Hello.
commit
fd9eed9706
@ -0,0 +1,268 @@
|
||||
;GETCD V 1.0 | 3-NOV-2024 Jay Moore/dewdude@pickmy.org
|
||||
;Finds CDROM drive letter and places in CDROM
|
||||
;environment variable
|
||||
;
|
||||
;A replacement for FINDCD.EXE written in NASM Assembly and
|
||||
;manipulates a lot of memory directly. Not a drop-in
|
||||
;replacement, but close. Designed as a .BAT utility, the
|
||||
;only user interaction is feeding it a path/filename and
|
||||
;checking the environment variable. Default returns first
|
||||
;CDROM drive that has a disc.
|
||||
;
|
||||
;GETCD [/?] SEARCHSTRING
|
||||
;
|
||||
;SEARCHSTRING can be a file, directory name, path, or wildcard.
|
||||
;Not specifying a file does a wildcard search on root of CD.
|
||||
;You do not need to add a leading \ to the string.
|
||||
;/? displays the usual help, except poorly written.
|
||||
;
|
||||
;CDROM=E:
|
||||
;
|
||||
;Is how the variable will be set. If you desire a trailing \;
|
||||
;just have your script 'set CDROM=%CDROM%\'
|
||||
;
|
||||
;This will absolutely overwrite any existing CDROM= contents with
|
||||
;the above format; and will also shift data around to make it the
|
||||
;exact length. It will also create an environment variable if none
|
||||
;exists. This is contrast with FINDCD.EXE; which not only needs
|
||||
;you to set the CDROM= variable first, but requires patching the
|
||||
;.exe to change the file search. Gross.
|
||||
;
|
||||
;Displayed output is minimal. The only error displayed is if the
|
||||
;environment block is full. A lack of CDROM drives will exit with
|
||||
;errorlevel 255. Anything else just doesn't change (or create) the
|
||||
;CDROM variable. You'll need to do that after execution in your script.
|
||||
;
|
||||
;argument section of PSP starts at 80h; byte count, bytes, terminator.
|
||||
;term is 0x0D, but it's not included in byte count. this can include
|
||||
;spaces if full name.ext is used or user just hit space.
|
||||
;the pointer to parent's PSP lives at 16h; env-block pointer is 2Ch
|
||||
;offset 3 one segment back is the block allocation size.
|
||||
;this means I initialize di to 10h now and just leave es where it is
|
||||
;as all counts are relative from di's initialization
|
||||
|
||||
[CPU 8086]
|
||||
[BITS 16]
|
||||
org 100h
|
||||
|
||||
section .text
|
||||
global start
|
||||
|
||||
start:
|
||||
xor cx, cx ; clear out cx
|
||||
mov si, 80h ; move si to psp argument count
|
||||
mov cl, [si] ; load argument byte count
|
||||
|
||||
argproc:
|
||||
jcxz varinit ; stop if cx is 0
|
||||
inc si ; increment si
|
||||
cmp byte [si], 20h ; Invalid char/space check
|
||||
jbe skipit ; jump to loop if <20h
|
||||
cmp byte [si], 5ch ; is it backslash
|
||||
jz skipit ; jump if it is
|
||||
cmp word [si], 3f2fh ; check for /?
|
||||
jz hllp ; jump if it is
|
||||
jmp ldfile ; land here when done
|
||||
skipit:
|
||||
loop argproc ; dec cx, jmp argproc ;)
|
||||
|
||||
ldfile:
|
||||
lea di, filename ; load filename to di
|
||||
repe movsb ; copy argument to filename
|
||||
mov byte [di], 0 ; null for good measure
|
||||
|
||||
varinit:
|
||||
mov es, [16h] ; parent psp pointer
|
||||
mov ax, [es:2ch] ; load block segment
|
||||
dec ax ; segment one below
|
||||
mov es, ax ; go back a segment
|
||||
mov ax, [es:3h] ; this is the size
|
||||
mov cl, 4 ; load 4 to cl for shl
|
||||
shl ax, cl ; bit shift left 4
|
||||
mov [blocksize], ax ; store
|
||||
mov di, 10h ; move di up to env blk
|
||||
|
||||
readblock:
|
||||
cmp word [es:di], 0 ; end of block?
|
||||
jz endofblock ; variiable missing
|
||||
lea si, envname ; load envname address
|
||||
mov cx, 6 ; load six
|
||||
repe cmpsb ; repe compare string
|
||||
jnz readblock ; if not variable, go back up
|
||||
sub di, 6 ; subtract 6
|
||||
mov [envstart], di ; write starting location
|
||||
add di, 6 ; place it back
|
||||
|
||||
findend:
|
||||
inc di ; now to find the end
|
||||
cmp word [es:di], 0 ; is it the end?
|
||||
jnz findend ; jump back up if not
|
||||
|
||||
endofblock:
|
||||
inc di ; actual end of block
|
||||
mov [blockend], di ; write that down
|
||||
cmp word [envstart], 0 ; did we find a var
|
||||
jz noenv ; jump if novar
|
||||
mov di, [envstart] ; go back to the env start
|
||||
mov ax, 1212h ; get the asciz length
|
||||
int 2fh ; in to cx
|
||||
cmp cx, 9 ; and see if it's 9
|
||||
jb envtoosmall ; jump to envtosmall if too small
|
||||
ja envtoobig ; jump to envtoobig if too big
|
||||
|
||||
envokay:
|
||||
add di, 6 ; drive letter is six in
|
||||
jmp drivego ; es:di ready for letter
|
||||
|
||||
envtoobig:
|
||||
mov si, di ; duplicate pointers
|
||||
mov word [es:di+7], 0x003A ; write : and null
|
||||
add si, 9 ; put si where i need di
|
||||
call endcheck ; check relative position
|
||||
call bytesize ; get byte count to copy
|
||||
xchg di, si ; now we swap
|
||||
cld ; clear that direction
|
||||
call copybytes ; copy byte routine
|
||||
mov word [es:di], 0 ; double null new end
|
||||
mov di, [envstart] ; go back to the env
|
||||
jmp envokay ; might as well jump
|
||||
|
||||
noenv:
|
||||
call envfree ; check free space
|
||||
mov di, [blockend] ; go to block end
|
||||
|
||||
|
||||
newenv:
|
||||
lea si, envname ; load address of envname
|
||||
mov cx, 8 ; we want 8 bytes
|
||||
repe movsb ; write 'em
|
||||
mov word [es:di], 0000h ; double null new term
|
||||
sub di, 2 ; back di up two
|
||||
jmp drivego ; es:di is ready
|
||||
|
||||
envtoosmall:
|
||||
mov byte [oneornine], 01h ; change envfree's cmp value
|
||||
call envfree ; check environment space
|
||||
call endcheck ; check relative position
|
||||
call bytesize ; call for byte count
|
||||
add cx, 3 ; add three to that count
|
||||
mov si, [blockend] ; load the end of block offset to si
|
||||
mov di, [blockend] ; load it again to di
|
||||
inc di ; move it up one
|
||||
std ; set direction flag
|
||||
call copybytes ; copybytes routine
|
||||
mov word [es:di+1], 0x003A ; write the : and null one byte up
|
||||
|
||||
drivego:
|
||||
mov ax, 2524h ; Ignore Critical Errors
|
||||
lea dx, [new24] ; pointer to new handler
|
||||
int 21h ; interrupt to change ivt
|
||||
mov ax, 1500h ; function to get drive info
|
||||
int 2Fh ; from int 2f
|
||||
xchg bx, cx ; swap count and starting number
|
||||
jcxz nodrives ; see if we have drives
|
||||
add bl, 41h ; convert number to letter
|
||||
|
||||
loadltr:
|
||||
push cx ; push drive count to stack
|
||||
mov [drivevar], bl ; copy drive letter to ram
|
||||
lea dx, drivevar ; load address of drivevar
|
||||
mov ah, 4Eh ; load find first file
|
||||
mov cl, 17h ; all the options
|
||||
int 21h ; call the interrupt
|
||||
jnc envset ; found file, go on
|
||||
pop cx ; pop drive count back in to CX
|
||||
inc bl ; increment to next drive
|
||||
loop loadltr ; loop back around
|
||||
jmp exit ; no match, leave
|
||||
|
||||
envset:
|
||||
lea si, drivevar ; loads address to si
|
||||
movsb ; moves ds:si to es:di
|
||||
jmp exit ; we're done, go home
|
||||
|
||||
nodrives:
|
||||
mov al, 0FFh ; load errorlevel 255 to al
|
||||
|
||||
exit:
|
||||
mov ax, 4c00h ; standard dos kernel terminate
|
||||
int 21h ; bye.
|
||||
|
||||
endcheck:
|
||||
push cx ; push cx to stack
|
||||
add cx, di ; add di to cx
|
||||
sub cx, [blockend] ; subtract blockend from cx
|
||||
jcxz fakenew ; jump if zero
|
||||
pop cx ; invert cx (it should be neg)
|
||||
ret ; go back to moving bytes
|
||||
|
||||
fakenew:
|
||||
sub sp, 04h ; reset the stack you animal
|
||||
mov di, [envstart] ; load di
|
||||
jmp newenv ; pretend it's new
|
||||
|
||||
copybytes:
|
||||
push ds ; push ds on to the stack
|
||||
push es ; push es on to the stack
|
||||
pop ds ; pop es in to ds for this
|
||||
repe movsb ; copy ds:si to es:di till cx is 0
|
||||
pop ds ; pop ds's original value back out
|
||||
ret
|
||||
|
||||
envfree:
|
||||
mov ax, [blocksize] ; load size
|
||||
sub ax, [blockend] ; calculate free
|
||||
cmp al, [oneornine] ; need n free
|
||||
jz blockfull ; not enough space
|
||||
ret ; return if ok
|
||||
|
||||
bytesize:
|
||||
add di, cx ; place di at next variable
|
||||
mov cx, [blockend] ; load the end of the block
|
||||
sub cx, di ; subtract the actual usage
|
||||
ret ; return from subroutine
|
||||
|
||||
hllp:
|
||||
lea dx, hlptxt ; address of $-terminated strong
|
||||
mov ah, 09h ; display string function
|
||||
int 21h ; dos interrupt
|
||||
jmp exit ; exit
|
||||
|
||||
new24:
|
||||
mov al, 3 ; FAIL! (Hitting F, but faster)
|
||||
iret ; Return from interrupt.
|
||||
|
||||
section .data
|
||||
|
||||
hlptxt:
|
||||
db 'GETCD 1.0 | 4-NOV-2024 | dewdude@pickmy.org | Freeware/MIT', 0x0d, 0x0a
|
||||
db 'Sets "CDROM=[driveletter]:" by searching CD-ROM drives', 0x0d, 0x0a
|
||||
db 'USAGE: GETCD [/?] [FILE/OR/PATH/TO/FILE.EXT]', 0x0d, 0x0a
|
||||
db 'Finds file on CD-ROM drives. Returns first match. Allows wildcards.', 0x0d, 0x0a
|
||||
db 'Creates/adjusts variable. Default search is wildcard.$', 0x0d, 0x0a
|
||||
blockfull: db 'NO ENV FREE $'
|
||||
blocksize: db 0, 0 ; holds block size
|
||||
envstart: db 0, 0 ; start of cdrom=
|
||||
blockend: db 0, 0 ; end of used block
|
||||
oneornine: db 09h ; default 9
|
||||
envname: db 'CDROM=' ; variable name
|
||||
drivevar: db '0:\' ; variable's variable
|
||||
filename: db '*', 0x00 ; (default) filename
|
||||
|
||||
;MIT No Attribution
|
||||
;
|
||||
;Copyright 2024 Jay Moore
|
||||
;
|
||||
;Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
;software and associated documentation files (the "Software"), to deal in the Software
|
||||
;without restriction, including without limitation the rights to use, copy, modify,
|
||||
;merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
;permit persons to whom the Software is furnished to do so.
|
||||
;
|
||||
;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
;INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
;PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
;OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
;SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@ -0,0 +1,16 @@
|
||||
MIT No Attribution
|
||||
|
||||
Copyright 2024 Jay Moore
|
||||
|
||||
Permission is hereby granted, free of charge, to any p
|
||||
software and associated documentation files (the "Soft
|
||||
without restriction, including without limitation the
|
||||
merge, publish, distribute, sublicense, and/or sell co
|
||||
permit persons to whom the Software is furnished to do
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHAN
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SH
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF O
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,164 @@
|
||||
# GETCD: MS-DOS .BAT Utility For Locating CD-ROM Drive
|
||||
|
||||
`GETCD.COM` is "batch utility" for MS-DOS to assist in locating a
|
||||
CD-ROM drive based on file search. It is similar to `FINDCD.EXE`
|
||||
with the following exceptions
|
||||
- it takes an argument to specify a file
|
||||
- automatically creates/manages the CDROM= variable
|
||||
|
||||
It is written in NASM assembler; and is mostly the thing I wrote
|
||||
while ~~attempting to learn~~ learning assembler.
|
||||
|
||||
## Usage
|
||||
|
||||
`GETCD.COM` does not display much in the way of user output. The
|
||||
largest chunk can be seen by calling the basic help:
|
||||
|
||||
`getcd /?`
|
||||
|
||||
If you were to "place a CD" in a "CD drive" with the file what.txt
|
||||
on it and ran this:
|
||||
|
||||
`getcd what.txt`
|
||||
|
||||
It looks like nothing happened. However, if you call `set` from the
|
||||
command prompt to see the current variables; you should see `CDROM=D:`
|
||||
(or whatever the actual drive letter is) now exists.
|
||||
|
||||
`getcd` on it's own will default to a wildcard (*) search. This has
|
||||
the effect of returning the first CD drive that has a disc in it, or
|
||||
doesn't return some kind of error.
|
||||
|
||||
Wildcards are allowed in the search string; as well as just directory
|
||||
names. The first drive that doesn't fail search is returned.
|
||||
|
||||
`NO ENV FREE` is the only displayed error message if you don't have
|
||||
enough environment space free. Most failures should result in nothing
|
||||
being changed. This plays well with being a batch utility:
|
||||
|
||||
```
|
||||
@echo off
|
||||
set CDROM=0:
|
||||
getcd what.txt
|
||||
if %CDROM%=0: goto nocd
|
||||
(do stuff)
|
||||
goto exit
|
||||
nocd:
|
||||
(stuff for no cd)
|
||||
exit:
|
||||
```
|
||||
|
||||
Additionally, you can look for errorlevel 255, which is returned if
|
||||
there are no CDROM drives.
|
||||
|
||||
### Adapting scripts for FINDCD.EXE
|
||||
|
||||
You'll just need to modify `FINDCD` to `GETCD [file]`
|
||||
|
||||
### My scripts want a \ in the variable
|
||||
|
||||
`GETCD` is kind of picky in that it will make the CDROM variable
|
||||
a drive letter, a colon, and no backslash. I may change this by
|
||||
assuming an extra character is a backslash an not delete it.
|
||||
|
||||
But, for now; just do this in your .bat
|
||||
|
||||
```
|
||||
set CDROM=%CDROM%\
|
||||
```
|
||||
|
||||
|
||||
|
||||
## What does this do?
|
||||
|
||||
- It lets you specify a file to search CD-ROM drives for and puts
|
||||
that drive letter in to the CDROM= environment variable. Then
|
||||
fancy .BAT scripts can go `call %CDROM%\install.bat` and
|
||||
run the .bat off the CD.
|
||||
|
||||
## How does it differ from other utilities?
|
||||
|
||||
- The only utility I've actually found has been FINDCD.EXE. The
|
||||
alternative is apparently for loops. I've seen mentions of other
|
||||
utlities on sites devoted to .bat scripting; but never found an
|
||||
exe.
|
||||
The differences from FINDCD are passing a filename as an argument
|
||||
and the automatic management of the variable. FINDCD used a hard
|
||||
coded file in the binary as well as requiring you to preset the
|
||||
variable.
|
||||
I decided to just toss all that aside and assume the user might
|
||||
not do it right; or in the case of FINDCD; the variable length
|
||||
pre-set is longer than necessary. I have no clue what FINDCD is
|
||||
doing with the variable.
|
||||
|
||||
## Building
|
||||
|
||||
`nasm -o getcd.com getcd.asm`
|
||||
|
||||
The build system was FreeDOS with WatcomC, DJGPP, IA16, and a few other things on it.
|
||||
|
||||
It was tested on MS-DOS 6.22 under an 86Box emulated 486/DX4 100.
|
||||
|
||||
## Random Things Passed As FAQ:
|
||||
|
||||
**Why a .COM and not a .EXE?**
|
||||
|
||||
- We didn't need any of the fancy options a .exe gave us. Our binary is not over 65kB in size and doesn't have to be relocated to run. That is primarily what .exe would give me; the ability to relocate my code once loaded. I could have assembled this to an object file then linked it to an .EXE, but I still wouldn't be using any "EXE features"
|
||||
|
||||
**What are the minimum requirements?**
|
||||
|
||||
- DOS 3.3 and a CD-ROM drive. The program doesn't use much ram and
|
||||
while will technically run on an 8088, the lack of CD-ROM drivers
|
||||
are a bigger issue.
|
||||
|
||||
**Will this work on FreeDOS?**
|
||||
|
||||
- Yes, it's been known to. I have not tested the memory manipulating
|
||||
version; but early versions worked.
|
||||
|
||||
**What about n-DOS?**
|
||||
|
||||
- No comment. It *should*, but it will depend if your CD-ROM extensions
|
||||
respond to the interrupts I use.
|
||||
|
||||
**Why did you do this?**
|
||||
|
||||
- I'd wanted to see if I could write x86 ASM for quite some time. I
|
||||
hadn't learned ASM beyond knowing how CPU's work at a low level
|
||||
and what ASM was. I had an incorrect assumption that I didn't know
|
||||
the levels of math required to make it work that I'd held for years.
|
||||
Anyway; I'd also incorrectly assumed after diving in that the magic
|
||||
of low-level would give me a secret way to look at drives without
|
||||
triggering errors. It did; but changing the interrupt vector isn't
|
||||
ASM specific..it was, like most things; a concept I'd heard about
|
||||
but really didn't undertand back in my teens when I first tried.
|
||||
I almost gave up and went to C when I was just trying to get the
|
||||
byte in the env block realizing that's why people have libaries.
|
||||
And, no; what little I read about the subject involved inline ASM.
|
||||
My most optimized version was 98 bytes. Yes, 98. It had no file
|
||||
argument or memory management. You had to make the environment;
|
||||
variable, it put the letter at the byte after =, and that was it.
|
||||
Then I decided to add features for the sake of stability and users;
|
||||
plus what good is a clone if you don't improve it.
|
||||
So despite serving no real purpose and being a huge time-sink for
|
||||
something only I'll probably use; I'm at least better in ASM than
|
||||
when I started. Huge bar given I started at almost zero.
|
||||
|
||||
## License
|
||||
|
||||
MIT No Attribution
|
||||
|
||||
Copyright 2024 Jay Moore
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Loading…
Reference in New Issue