main
Jay 2 months ago
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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -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…
Cancel
Save