;??????????????????????????????????????????????????????????????????????????????
;?? RCS (Revision Control System) Version Log ??
;??????????????????????????????????????????????????????????????????????????????
;
; $Log: 0cd.asm $
; Revision 1.40 1995/12/06 22:13:29 Lasse
; Fixed so that -a was disabled if mscdex was loaded.
;
; Revision 1.39 1995/12/05 22:11:53 Lasse
; Adjusted the revision messages
;
; Revision 1.38 1995/12/05 22:00:45 Lasse
; Version 7.0; Removes data segment when going resident, shrinked down to
; 6.5 Kb of memory from 8.7 Kb. Also, fixed a bug when allocating more
; drives than available consecutively. Also, inserted rcs keywords in a
; message
;
; Revision 1.37 1995/12/05 09:05:14 Lasse
; Version 6.7; now co-exists with mscdex, and also enables audio through-
; put.
;
; Revision 1.36 1995/12/04 00:56:07 Lasse
; Version 6.6; Now works with worms too, and simulates the following new
; device requests:
; Play
; Stop
; also, the AudioStatus function has been augmented to react on the Play
; and Stop functions, and the HeadLocation function will return different
; values, as though the cd was playing or moving around.
; Also, the -a option will make 0cd simulate FakeCD.
;
; Revision 1.35 1995/12/03 02:35:45 Lasse
; Version 6.5; Fixed the root-directory subst problem which came back :(
;
; Revision 1.34 1995/11/26 09:46:54 Lasse
; Version 6.4; Fixed several bugs with the DiskFree function
;
; Revision 1.33 1995/11/16 06:36:22 Lasse
; Fixed a bug in the makecd program, and an inconsistency in 0cd
;
; Revision 1.32 1995/11/16 06:14:39 Lasse
; Put Decrunch into 0cd.asm for maximum distributability
;
; Revision 1.31 1995/11/16 06:04:28 Lasse
; Version 6.2
;
; Revision 1.30 1995/11/16 05:24:59 Lasse
; Commented all code; Done some minor cosmetic changes, tidied up the
; code a bit
;
; Revision 1.29 1995/11/14 22:04:22 Lasse
; If last character in directory was \ then redirection failed; fixed!
;
; Revision 1.28 1995/11/14 21:57:59 Lasse
; Removed the "Unmangling" of filename
;
; Revision 1.27 1995/11/14 21:46:19 Lasse
; Version 6.2; Fixed so that magic carpet works; Fixed so that DiskFree(d:)
; where d: is a cd-rom now returns correct data
;
; Revision 1.26 1995/11/14 19:50:33 Lasse
; Bug in previous revision concerning the drive letter in speed messages;
; fixed
;
; Revision 1.25 1995/11/14 19:48:43 Lasse
; Fixed so that speed message included correct drive letter
;
; Revision 1.24 1995/11/14 19:29:30 Lasse
; Version 6.1; Super speed emulation enabled
;
; Revision 1.23 1995/11/14 19:02:11 Lasse
; Updated the usage message, and renamed VTC to data
;
; Revision 1.22 1995/11/14 18:51:36 Lasse
; Version 6.0; Now simulates speed of cd-rom; Also read sector 16 (system
; data)
;
; Revision 1.21 1995/11/12 21:52:52 Lasse
; Version 5.0; fixed a couple of bugs with the audio track information
;
; Revision 1.20 1995/11/12 08:14:22 Lasse
; Version 4.1
;
; Revision 1.19 1995/11/12 08:09:58 Lasse
; Removed some old dummy-stuff
;
; Revision 1.18 1995/11/12 06:44:56 Lasse
; Audio Status now responds music paused; fix necessary for MechWarrior 2
;
; Revision 1.17 1995/11/12 03:39:43 Lasse
; Fixed the return to directory bug
;
; Revision 1.16 1995/11/12 03:24:55 Lasse
; Bug-fix; couldn't supply more than name.ext, no dir to run
;
; Revision 1.15 1995/11/12 03:21:29 Lasse
; Version 4; supply name of program to run
;
; Revision 1.14 1995/11/12 02:34:58 Lasse
; Fixed so that it reads audio data also
;
; Revision 1.13 1995/11/11 22:51:03 Lasse
; Fixed so cd-roms could be redirected to the root of a drive
;
; Revision 1.12 1995/11/11 22:48:52 Lasse
; Fixed a bug which caused strange symbols in 'dir' listings
;
; Revision 1.11 1995/11/11 22:39:32 Lasse
; Fixed so it didn't automatically write protect cd-roms unless the user
; asked for it
;
; Revision 1.10 1995/11/11 20:50:50 Lasse
; DiskFree function now clears carry flag
;
; Revision 1.9 1995/11/11 20:44:24 Lasse
; Version 3.1; added option to supply name of .vtc file
;
; Revision 1.8 1995/11/11 20:15:29 Lasse
; Returns dummy filenames, and uses CD0.VTC - CD7.VTC instead of DIR.VTC
; so that the same directory may be used for different cd's.
;
; Revision 1.7 1995/11/11 05:55:23 Lasse
; Fixed so it reads the VTOC into memory and returns it upon request.
;
; Revision 1.6 1995/11/10 23:14:47 Lasse
; Fixed the volume label bug that appeared in the last revision.
;
; Revision 1.5 1995/11/10 23:05:40 Lasse
; Fixed a bug when checking more than 8 drives past the first emulated
; cd-rom drive.
;
; Revision 1.4 1995/11/07 22:15:01 Lasse
; Version 2.0
;
; Revision 1.3 1995/11/07 22:13:19 Lasse
; Now saves current drive and directory and restores them when the sub-
; process exits. Also has self-installed check code now.
;
; Revision 1.2 1995/11/07 21:50:29 Lasse
; Moved all string procedures into 0cd.asm itself. Tidied up some of the
; code. Replace the uppercase functions. Fixed so that the GetDirEntry call
; to MSCDEX will go through (possibly returning garbage, but...) and some
; other stuff.
;
; Revision 1.1 1995/11/07 20:15:56 Lasse
; Initial revision
;
;
;??????????????????????????????????????????????????????????????????????????????
;?? Assembler options and directives ??
;??????????????????????????????????????????????????????????????????????????????
ideal ; IDEAL assembly mode
stacksize = 60h ; Size of stack (words)
p386 ; Select the processor
p387 ; Support for math coprocessor
model tiny, pascal ; Always must be TINY model
;??????????????????????????????????????????????????????????????????????????????
;?? Initialized data segment ??
;??????????????????????????????????????????????????????????????????????????????
dataseg ; Initialized data segment
MaxCDs = 8
HookMsg db '0cd: installed', 13, 10, 0
MSCDEX db '0cd error: mscdex already installed', 13, 10, 0
Installed db '0cd error: already installed', 13, 10, 0
NoRedirs db '0cd error: no redirections specified', 13, 10, 0
UnknownOp db '0cd error: unknown command line parameter: ', 0
InvOption db '0cd: invalid option ',0
TooManyCDs db '0cd error: cannot handle more than ',48+MaxCDs
db ' drives', 13, 10, 0
No66Msg db '0cd error: int 66h not available', 13, 10, 0
NoDrives db '0cd error: no drives available', 13, 10, 0
NotRoom db '0cd error: no more drive letters available', 13, 10, 0
CDSize db '0cd: host drive(s) and cd-rom(s) report host drive(s) size', 13, 10, 0
CD0 db '0cd: host drive(s) and cd-rom(s) report 0 bytes free', 13, 10, 0
IsProt db '0cd: cd-rom(s) are write protected', 13, 10, 0
NotProt db '0cd: cd-rom(s) are not write protected', 13, 10, 0
DataTooBig db '0cd error: data file is too big (>65535 bytes)', 13, 10, 0
DataNoMem db '0cd error: no memory for data file', 13, 10, 0
RunProg db '0cd: program to run is ', 0
UnknownSpd db '0cd error: unknown speed option ', 0
InvDrive db '0cd warning: can only adjust drive letter before redirections', 13, 10, 0
SuccessMsg db '0cd: functions will succeed with dummy data', 13, 10, 0
FailMsg db '0cd: functions will fail with no data', 13, 10, 0
AltMsg db '0cd: alternate simulation enabled', 13, 10, 0
TruMsg db '0cd: audio through-put enabled', 13, 10, 0
NoMSCDEX db '0cd warning: no mscdex detected, audio through-put not enabled', 13, 10, 0
CoMsg db '0cd: mscdex co-existance enabled', 13, 10, 0
UnknownMSC db '0cd error: unknown mscdex option ',0
TooFew db '0cd error: not enough consecutive drive letters, use the /lx option', 13, 10, 0
UnknownSim db '0cd error: unknown simulation option ',0
SimMsg1 db '0cd: drive '
SimDrv db 'E'
db ': simulates a ',0
SimMsg2 db 'physical drive', 13, 10, 0
SimMsg3 db 'substed drive', 13, 10, 0
SimMsg4 db 'remote or cd-rom drive', 13, 10, 0
SpeedMsg1 db '0cd: drive '
SpeedDrv db 'E'
db ': is a',0
SpeedMsg2 db ' drive', 13, 10, 0
SingleMsg db ' single speed',0
DoubleMsg db ' double speed',0
TripleMsg db ' triple speed',0
QuadraMsg db ' quadra speed',0
SexaMsg db ' sexa speed',0
OctaMsg db 'n octa speed',0
SuperMsg db ' super speed',0
ReadData1 db '0cd: data for drive '
ReadData2 db '?'
ReadData3 db ': read into memory from ', 0
Prompt1 db '0cd: mounted ', 0
Prompt2 db ': in ', 0
DriveID db 0, 0
AnyRedir db 0
CSEnv db 'COMSPEC=',0
UsageMsg db '0cd usage: 0cd [options] <directory> [<directory> ... ]', 13, 10
db '0cd options: -q = quiet; no messages except for error messages', 13, 10
db ' -0 = host and cd-rom drives report 0 bytes free', 13, 10
db ' -w = cd-rom drives are write protected', 13, 10
db ' -dfilename = supply name of data file', 13, 10
db ' -rfilename = supply name of program to run',13,10
db ' -sx = supply speed of drive (x=s, 1, 2, 3, 4, 6 or 8)', 13, 10
db ' -i0 = simulate physical drive', 13, 10
db ' -i1 = simulate substed drive', 13, 10
db ' -i2 = simulate remote or cd-rom drive (default)', 13, 10
db ' -f = failure if no cd-rom data', 13, 10
db ' -a = alternate simulation', 13, 10
db ' -mx = mscdex co-existance level (x=0-3, default=0)', 13, 10
db ' -v = show revision information', 13, 10, 0
CRLF db 13, 10, 0
Line db 30 dup (0)
PathName db 128 dup (0)
DataName db 128 dup (0)
RevMsg db '0cd: revision $Revision: 1.40 $', 13, 10
db '0cd: state $State: Exp $', 13, 10
db '0cd: source $Source: D:/ASM/PROJECTS/0CD/RCS/0cd.asm $', 13, 10
db '0cd: rcsfile $RCSfile: 0cd.asm $', 13, 10
db 0
Label EndOfData word
;??????????????????????????????????????????????????????????????????????????????
;?? Uninitialized data segment ??
;??????????????????????????????????????????????????????????????????????????????
;??????????????????????????????????????????????????????????????????????????????
;?? Code segment ??
;??????????????????????????????????????????????????????????????????????????????
assume cs:@code,
ds:@data,
es:@data
codeseg ; Code segment
;??????????????????????????????????????????????????????????????????????????????
;?? Macro declarations ??
;??????????????????????????????????????????????????????????????????????????????
macro iCLC
push bp ; Preserve BP register
mov bp,sp ; Set BP to stack pointer
and [word ptr bp+6],0fffeh ; Modify flags on the stack
pop bp ; Restore BP register
endm
macro iSTC
push bp ; Preserve BP register
mov bp,sp ; Set BP to stack pointer
or [word ptr bp+6],0001h ; Modify flags on the stack
pop bp ; Restore BP register
endm
;??????????????????????????????????????????????????????????????????????????????
;?? Program initialization ??
;??????????????????????????????????????????????????????????????????????????????
StartUpCode ; Insert startup code
mov sp,offset TheStack ; Fix stack pointers
mov bx,offset EndOfData ; Get end of data segment
shr bx,4 ; Make segment count
add bx,1 ; Make last segment count
mov ah,4ah ; Fn 4ah = Resize memory block
int 21h ; Call dos interrupt
push cs ; Point ds to
pop ds ; data segment (after code)
push cs ; Point es to
pop es ; data segment (after code)
;??????????????????????????????????????????????????????????????????????????????
;?? User-code ??
;??????????????????????????????????????????????????????????????????????????????
call SaveDir
call GetCOMSPEC
call Init
call Report
call Hook
call MinMem
call Exec, cs offset ProgName, cs offset Params
call UnHook
call ReturnDir
;??????????????????????????????????????????????????????????????????????????????
;?? Exit program here, returning 0000h as ExitCode (ERRORLEVEL in DOS) ??
;??????????????????????????????????????????????????????????????????????????????
ExitCode 0000h ; Return to dos, clear up heap
;??????????????????????????????????????????????????????????????????????????????
;?? Procedure/function declarations ??
;??????????????????????????????????????????????????????????????????????????????
; Code segment variables
OldDir db 79 dup (0)
OldDrive db 0
ProgName db 128 dup (0)
Params db '/C '
RunName db '0CDSTART.BAT',0
db 115 dup (0)
SimType db 2
SimFlag dw 0100000010000000b
CoMSCDEX db 0
FirstRealCD db 0
AudioTru db 0
AltSimul db 0
DoFailure db 0
CDPlaying dw 0001h
CDPos dw 0010h
CurSpeed db 2
CurDelay dw 6200
UnHookMsg db '0cd: removed', 13, 10, 0
InitMsg db '0cd: version 7.1', 13, 10, 0
Inited db 0
Datas db 2*MaxCDs dup (0)
FirstID db 0
LastID db 0
IsRun db 0
RetZero db 0
WriteProt db 0
Quiet db 0
DriveCount db 0
DriveSpeeds dw MaxCDs dup (0)
DeviceHdr dw -1, -1
dw 0100100001000000b
dw Strategy
dw Strategy ; No interrupt
db '0CD-CDx',0
db 0,0
dw stacksize dup (0) ; Set up space for stack
Label TheStack Word ; Here begins the stack
; Strategy procedure
proc Strategy far
ret ; Return to caller
endp
; MinMem procedure
proc MinMem
mov ah,62h ; Dos Fn 62h = Get PSP in bx
int 21h ; Call dos interrupt
mov es,bx ; Store in es for realloc
mov ah,4ah ; Dos Fn 4ah = Realloc
lea bx,[HookMsg] ; Get offset of data
shr bx,4 ; Calculate segments
inc bx ; Adjust for last segment
int 21h ; Reallocate memory
ret ; Return to caller
endp
; GetCDData procedure
; returns segment in es, or 0-segment if failure
proc GetCDData
arg @@DriveID:word
local @@Handle:word, @@NewSeg:word, @@Size:word
uses ax, bx, si
mov [@@NewSeg],0 ; No segment yet
cmp [byte ptr ds:DataName],0 ; Got a filename of datafile ?
je @@Exit ; No --> @@Exit
mov ah,3dh ; Dos Fn 3dh = Open file
lea dx,[DataName] ; Filename in dx:dx
mov al,00h ; Open mode in al
int 21h ; Call DOS interrupt
jc @@Exit ; Error --> @@Exit
mov [@@Handle],ax ; Save file handle
mov ax,4202h ; Dos Fn 42 = LSeek
mov bx,[@@Handle] ; Filehandle in bx
xor cx,cx ; High 16 bits of position
xor dx,dx ; Low 16 bits of position
int 21h ; Call DOS interrupt
test dx,dx ; File larger than 64K ?
jz @@OkSize ; No --> @@OkSize
mov ah,3eh ; Dos Fn 3eh = Close file
mov bx,[@@Handle] ; Filehandle in bx
int 21h ; Call DOS interrupt
mov [cs:Quiet],00h ; Turn of quiet mode
call LStrWrite, offset DataTooBig ; Write error msg
call CleanUp ; Clean up
ExitCode 0001h ; Exit to DOS
@@OkSize:
mov [@@Size],ax ; Save size of file
shr ax,4 ; Divide by 16
inc ax ; And add 1
mov bx,ax ; Number of segments in bx
mov ah,48h ; Dos Fn 48h = AllocMem
int 21h ; Call DOS interrupt
jc @@NoMem ; Error --> @@NoMem
mov es,ax ; Segment in es
mov [@@NewSeg],ax ; Store new segment
mov ax,4200h ; Dos Fn 42 = LSeek
mov bx,[@@Handle] ; Filehandle in bx
xor cx,cx ; High 16 bits of position
xor dx,dx ; Low 16 bits of position
int 21h ; Call DOS interrupt
mov ah,3fh ; Dos Fn 3fh = Read file
mov bx,[@@Handle] ; Filehandle in bx
push ds ; Save ds
push es ; Put ds ...
pop ds ; ... in es
xor dx,dx ; High 16 bits of size in dx
mov cx,[@@Size] ; Low 16 bits of size in cx
int 21h ; Call DOS interrupt
pop ds ; Restore ds
mov al,[byte ptr @@DriveID] ; Get driveletter
mov [ReadData2],al ; Update message text
call LStrWrite, offset ReadData1 ; Write text
call LStrWrite, offset DataName ; Write filename
call LStrWrite, offset CRLF ; Newline
mov bx,[@@Handle] ; Filehandle in bx
mov ah,3eh ; Dos Fn 3eh = Close file
int 21h ; Call DOS interrupt
jmp @@Exit ; Exit
@@NoMem:
mov bx,[@@Handle] ; Filehandle in bx
mov ah,3eh ; Dos Fn 3eh = Close file
int 21h ; Call DOS interrupt
mov [cs:Quiet],00h ; Turn off quiet mode
call LStrWrite, offset DataNoMem ; Write error msg
call CleanUp ; Clean up
ExitCode 0001h ; Exit to dos
@@Exit:
lea si,[Datas] ; ds:si point to Datas
mov cx,[@@DriveID] ; Get drive letter
sub cl,[cs:FirstID] ; Make 0-based
cmp cl,0 ; First drive ?
je @@DoExit ; Yes --> @@DoExit
@@Loop:
add si,2 ; Next data index
dec cl ; One less to skip
jnz @@Loop ; More --> @@Loop
@@DoExit:
mov es,[@@NewSeg] ; Return segment in es
mov [ds:si],es ; Save segment in Datas
ret ; Return to caller
endp
; Report procedure
proc Report
cmp [cs:CoMSCDEX],01h ; MSCDEX co-existance ?
jne @@NoCoEXIST
call LStrWrite, offset CoMsg ; Write message
@@NoCoExist:
cmp [cs:AudioTru],00h ; Audio throughput ?
je @@NoTru ; No --> @@NoTru
call LStrWrite, offset TruMsg ; Write message
@@NoTru:
cmp [cs:AltSimul],00h ; Alternate simulation ?
je @@NoAlt ; No --> @@NoAlt
call LStrWrite, offset AltMsg ; Write message
@@NoAlt:
cmp [cs:DoFailure],00h ; Failure or success ?
je @@Success
call LStrWrite, offset FailMsg ; Write message
jmp @@OkFail
@@Success:
call LStrWrite, offset SuccessMsg ; Write message
@@OkFail:
cmp [cs:WriteProt],00h ; Write-protected ?
je @@NotProt ; No --> @@NotProt
call LStrWrite, offset IsProt ; Write message
jmp @@Size ; --> @@Size
@@NotProt:
call LStrWrite, offset NotProt ; Write message
@@Size:
cmp [cs:RetZero],00h ; Zero disk free ?
je @@NotZero ; No --> @@NotZero
call LStrWrite, offset CD0 ; Write message
jmp @@Exit ; Exit
@@NotZero:
call LStrWrite, offset CDSize ; Write message
@@Exit:
call LStrWrite, offset CRLF ; Write an empty line
ret ; Return to caller
endp
; SaveDir procedure
proc SaveDir
uses ax, si, dx
mov ah,47h ; Dos Fn 47h = GetCurDir
lea si,[OldDir+1] ; Destination in ds:si
push ds
push cs
pop ds
mov [byte ptr ds:si-1],'\' ; Make \ relative
mov dl,00h ; Set to current drive
int 21h ; Call DOS interrupt
pop ds
mov ah,19h ; Dos Fn 19h = GetCurDrive
int 21h ; Call DOS interrupt
mov [cs:OldDrive],al ; Save drive
ret ; Return to caller
endp
; ReturnDir procedure
proc ReturnDir
uses ax, dx
mov ah,0eh ; Dos Fn 0eh = SetCurDrive
mov dl,[cs:OldDrive] ; Drive no in dl
int 21h ; Call DOS interrupt
mov ah,3bh ; Dos Fn 3bh = SetCurDir
lea dx,[OldDir] ; Directory in ds:dx
push ds
push cs
pop ds
int 21h ; Call DOS interrupt
pop ds
ret ; Return to caller
endp
; LStrWrite procedure
proc LStrWrite
arg @@Str:word
cmp [cs:Quiet],1 ; Quiet mode ?
je @@Exit ; Yes --> @@Exit
cmp [cs:Inited],0 ; Already shown version ?
jne @@Ok ; Yes --> @@Ok
mov [cs:Inited],1 ; Set version shown flag
call StrWrite, cs offset InitMsg ; Show version message
@@Ok:
call StrWrite, [@@Str] ; Write text
@@Exit:
ret ; Return to caller
endp
; Init procedure
proc Init
call GetFirstDrive
call ReadDescription
call Needed
call CheckMSCDEX
ret
endp
; GetCOMSPEC procedure
proc GetCOMSPEC
uses ax, si, di, es, ds
mov ah,62h ; Dos Fn 62h = Get PSP
int 21h ; Call DOS interrupt
mov es,bx ; Segment of PSP in es
mov es,[es:002ch] ; Get environment segment
xor si,si ; Start of environment
@@Loop:
call StrLIComp, es si, ds offset CSEnv, 8 ; COMSPEC=xxx ?
jc @@Next ; No --> @@Next
add si,8 ; Skip to xxx
call StrCopy, cs offset ProgName, es si ; Save program name
jmp @@Exit ; Exit
@@Next:
inc si ; Next character
cmp [byte ptr es:si],0 ; At end of string ?
jne @@Next ; No --> @@Next
inc si ; Skip end-of-string char
cmp [byte ptr es:si],0 ; End of environment ?
jne @@Loop ; No --> @@Loop
@@Exit:
ret ; Return to caller
endp
; Needed procedure
proc Needed
cmp [AnyRedir],1 ; Any redirections at all ?
je @@Exit ; Yes --> @@Exit
call LStrWrite, offset NoRedirs ; Write error message
call CleanUp ; Clean up
ExitCode 0001h ; Exit to dos
@@Exit:
call CheckFile ; Check for program to run
ret ; Return to caller
endp
; CheckFile procedure
proc CheckFile
mov ax,3d00h ; Dos Fn 3d = Open file
push ds
push cs
pop ds
lea dx,[RunName] ; Filename in ds:dx
int 21h ; Call DOS interrupt
pop ds
jc @@NoFile ; Error --> @@NoFile
mov bx,ax ; Filehandle in bx
mov ah,3eh ; Dos Fn 3eh = Close file
int 21h ; Call DOS interrupt
call LStrWrite, offset RunProg ; Show run message
push ds cs ; Save ds and put cs ...
pop ds ; ... into ds
call LStrWrite, offset RunName ; Show name of program
pop ds ; Restore ds
call LStrWrite, offset CRLF ; Newline
jmp @@Exit ; Exit
@@NoFile:
mov [byte ptr cs:Params],0 ; No parameters to COMSPEC
@@Exit:
ret ; Return to caller
endp
; GetCDS procedure
; Returns pointer in es:bx, and carry set if success, or 0:0 in es:bx and
; carry clear if failure
proc GetCDS
arg @@DriveID:word
uses ax
call UpCase, [@@DriveID] ; Make letter uppercase
mov [@@DriveID],ax ; Store in @@DriveID
mov ah,52h ; Dos Fn 52h = Get DosSysVars
int 21h ; Call DOS interrupt
add bx,16h ; Skip to CDS entry
les bx,[dword ptr es:bx] ; Get pointer to CDS in es:bx
mov al,'A' ; First drive letter in CDS
@@Loop:
cmp al,[byte ptr @@DriveID