commit fd9eed9706b8950d974ae1736ad40a32766ab18e Author: dewdude Date: Mon Nov 4 22:20:38 2024 -0500 Hello. diff --git a/GETCD.ASM b/GETCD.ASM new file mode 100644 index 0000000..c0aea3e --- /dev/null +++ b/GETCD.ASM @@ -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. + diff --git a/GETCD.COM b/GETCD.COM new file mode 100644 index 0000000..bd51b21 Binary files /dev/null and b/GETCD.COM differ diff --git a/GETCD.IMG b/GETCD.IMG new file mode 100644 index 0000000..d3df19e Binary files /dev/null and b/GETCD.IMG differ diff --git a/GETCD.zip b/GETCD.zip new file mode 100644 index 0000000..cc6d57c Binary files /dev/null and b/GETCD.zip differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ff2017c --- /dev/null +++ b/LICENSE @@ -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. \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..65f6803 --- /dev/null +++ b/README.MD @@ -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. \ No newline at end of file