📄 0cd.asm
字号:
cmp al,[cs:FirstID] ; < First ID ?
jb @@Nope ; Yes --> @@Nope
cmp al,[cs:LastID] ; > Last ID ?
ja @@Nope ; Yes --> @@Nope
jmp @@GotIt ; Got it
@@CheckIt:
mov al,[cs:FirstID] ; Get first emulated id
@@GetLoop:
call GetCDS,ax ; Get CDS entry
mov bl,[es:bx] ; Get host drive letter
cmp bl,[byte ptr @@DriveID] ; Id to check ?
je @@GotIt ; Yes --> @@GotIt
inc al ; Next drive
cmp al,[cs:LastID] ; Our drive ?
jbe @@GetLoop ; Yes --> @@GetLoop
@@Nope:
clc ; Signal external drive
jmp @@Exit ; Exit
@@GotIt:
stc ; Signal own drive
@@Exit:
ret ; Return to caller
endp
; NewInt21
OldInt21 dw 0,0
proc NewInt21 far
cmp ah,4eh ; FindFirst function ?
je @@FindFirst ; Yes --> @@FindFirst
cmp ah,36h ; DiskFree function ?
je @@DiskFree ; Yes --> @@DiskFree
cmp [cs:WriteProt],00h ; Writeprotect flag ?
je @@NotWriteProtected ; No --> @@NotWriteProtected
cmp ah,3ch ; CreateFile function ?
je @@DoKillSomething ; Yes --> @@DoKillSomething
cmp ah,0fh ; Open FCB function ?
je @@DoFCB ; Yes --> @@DoFCB
cmp ah,16h ; Create FCB function ?
je @@DoFCB ; Yes --> @@DoFCB
cmp ah,17h ; Rename FCB function ?
je @@DoFCB ; Yes --> @@DoFCB
cmp ah,39h ; MkDir function ?
je @@DoKillSomething ; Yes --> @@DoKillSomething
cmp ah,3ah ; RmDir function ?
je @@DoKillSomething ; Yes --> @@DoKillSomething
cmp ah,41h ; Delete file function ?
je @@DoKillSomething ; Yes --> @@DoKillSomething
@@NotWriteProtected:
jmp @@CallOld ; Call old interrupt handler
@@DoKillSomething:
push si ; Save si
mov si,dx ; ds:dx = Filename
cmp [byte ptr ds:si+1],':' ; Contains drive letter ?
je @@HasDriveToKill ; Yes --> @@HasDriveToKill
push ax ; Save ax
mov ah,19h ; Dos Fn 19h = GetCurDrive
int 21h ; Call DOS interrupt
mov [@@TempB],al ; Save drive letter
pop ax ; Restore ax
mov al,[@@TempB] ; Drive letter in al
pop si ; Restore si
add al,'A' ; Convert to A-Z
jmp @@KillIt ; --> @@KillIt
@@HasDriveToKill:
mov al,[ds:si] ; Get drive letter
pop si ; Restore si
@@KillIt:
call IsOwn, ax, 0000h ; Our drive ?
jnc @@CallOld ; No --> @@CallOld
iSTC ; Signal error
mov ax,0013h ; Write protected error
iret ; Return to interrupt caller
@@DoFCB:
push si ; Save si
mov si,dx ; Filename in ds:si
mov al,[ds:si] ; Get drive no
pop si ; Restore si
call ZeroDefault, ax ; Calculate drive letter
call IsOwn, ax, 0001h ; Our drive ?
jnc @@CallOld ; No --> @@CallOld
mov al,0ffh ; Signal error
iret ; Return to interrupt caller
@@DiskFree:
cmp [cs:RetZero],1 ; Return zero free ?
jne @@CallOld ; No --> @@CallOld
push ax bx cx dx ; Save registers
call ZeroDefault, dx ; Calculate drive letter
call IsOwn, ax, 0000h ; Our drive ?
jc @@FakeIt ; Yes --> @@FakeIt
call IsOwn, ax, 0001h ; Our drive ?
jnc @@NotFree ; No --> @@NotFree
@@GotIt:
pop dx cx bx ax ; Restore registers
int 66h ; Call old interrupt handler
cmp ax,0ffffh ; Error ?
je @@DiskFreeError ; No --> @@NoDiskFreeError
xor bx,bx ; 0 clusters free
@@DiskFreeError:
iret ; Return to interrupt caller
@@FakeIt:
pop dx cx bx ax ; Restore registers
push ax dx ds si ; Save registers
call ZeroDefault, dx ; Calculate drive id
call GetData, ax ; Get cd data structure
jc @@NoFreeData ; Error --> @@NoFreeData
mov ax,[ds:si+153] ; Get sectors per cluster
mov bx,[ds:si+155] ; Get available clusters
mov cx,[ds:si+157] ; Get bytes per sector
mov dx,[ds:si+159] ; Get total clusters
pop si ds ; Restore registers
add sp,4 ; Remove two words from stack
iCLC ; Signal ok
iret ; Return to interrupt caller
@@NoFreeData:
pop si ds dx ax ; Restore registers
mov ax,0001h ; 1 sector per cluster
mov bx,0000h ; 0 sectors free
mov cx,0800h ; 2048 bytes per sector
mov dx,0ffffh ; 65535 total clusters
iCLC ; Signal ok
iret ; Return to interrupt caller
@@NotFree:
pop dx cx bx ax ; Restore registers
jmp @@CallOld ; Call old interrutp handler
@@FindFirst:
test cx,0008h ; Volume label search ?
jz @@CallOld ; No --> @@CallOld
@@CheckLabel:
push es bx ds si ax dx ; Save registers
mov si,dx ; Filename in ds:si
cmp [byte ptr ds:si+1],':' ; Contains drive letter ?
je @@OkDrive ; Yes --> @@OkDrive
push ax ; Save ax
mov ah,19h ; Dos Fn 19h = GetCurDrive
int 21h ; Call DOS interrupt
mov [@@TempB],al ; Save drive letter
pop ax ; Restore ax
mov al,[@@TempB] ; Get drive letter
mov bl,al ; Put drive letter in bl
jmp @@CheckDrive ; --> @@CheckDrive
@@OkDrive:
mov bl,[ds:si] ; Get drive letter
push ax ; Save ax
call UpCase, bx ; Convert to uppercase
mov bx,ax ; Put new letter in bx
pop ax ; Restore ax
@@CheckDrive:
cmp bl,[cs:FirstID] ; Our drive ?
jb @@DoCallOld ; No --> @@DoCallOld
cmp bl,[cs:LastID] ; Our drive ?
ja @@DoCallOld ; No --> @@DoCallOld
jmp @@CheckOk ; --> @@CheckOk
@@DoCallOld:
pop dx ax si ds bx es ; Restore registers
jmp @@CallOld ; Call old interrupt handler
@@CheckOk:
call GetData, bx ; Get cd data
jc @@NoLabel ; No data --> @@NoLabel
add si,141 ; Adjust offset
cmp [byte ptr ds:si],0 ; Label ?
je @@NoLabel ; No --> @@NoLabel
mov ah,2fh ; Get DTA pointer
int 21h ; Call DOS interrupt
mov [byte ptr es:bx+15h],08h ; Set attribute
mov [word ptr es:bx+16h],0000h ; Zero time
mov [word ptr es:bx+18h],0000h ; Zero date
mov [word ptr es:bx+1ah],0000h ; Zero size low
mov [word ptr es:bx+1ch],0000h ; Zero size high
add bx,001eh ; Adjust offset
@@Loop:
mov al,[ds:si] ; Get character
inc si ; Skip character read
mov [es:bx],al ; Store character
inc bx ; Skip character stored
test al,al ; End of label ?
jnz @@Loop ; No --> @@Loop
pop dx ax si ds bx es ; Restore registers
iCLC ; Signal success
jmp @@Exit ; Exit
@@NoLabel:
pop dx ax si ds bx es ; Restore registers
iSTC ; Signal failure
mov ax,0002h ; File not found error
iret ; Return to interrupt caller
@@CallOld:
jmp [dword ptr cs:OldInt21] ; Call old interrupt handler
@@Exit:
iret ; Return to interrupt caller
@@TempB db 1
@@TempW dw 0
endp
; GetData procedure
proc GetData
uses cx
arg @@DriveID:word
mov cx,[@@DriveID] ; Get drive ID
cmp cl,[cs:FirstID] ; Our drive ?
jb @@NoData ; No --> @@NoData
cmp cl,[cs:LastID] ; Our drive ?
ja @@NoData ; No --> @@NoData
lea si,[Datas] ; ds:si --> Datas
sub cl,[cs:FirstID] ; Make drive id 0-based
cmp cl,0 ; First id ?
je @@OkData ; Yes --> @@OkData
@@NextData:
add si,2 ; Next index in Datas
dec cl ; Next drive
jnz @@NextData ; More --> @@NextData
@@OkData:
mov si,[cs:si] ; Get segment of data
test si,si ; Data there ?
jz @@NoData ; No --> @@NoData
mov ds,si ; Put segment in ds
xor si,si ; Zero offset
clc ; Signal success
jmp @@Exit ; Exit
@@NoData:
stc ; Signal failure
@@Exit:
ret ; Return to caller
endp
; NewInt2F
OldInt2F dw 0,0
proc NewInt2f far
mov [cs:@@OldAX],ax
cmp ax,1100h ; MSCDEX check ?
je @@CheckMSCDEX ; Yes --> @@CheckMSCDEX
cmp ax,1500h ; Installation check ?
je @@CheckInstall ; Yes --> @@CheckInstall
cmp ax,1501h ; DeviceList function ?
je @@DeviceList ; Yes --> @@DeviceList
cmp ax,1502h ; GetCopyright function ?
je @@GetFileName ; Yes --> @@GetFileName
cmp ax,1503h ; GetAbstract function ?
je @@GetFilename ; Yes --> @@GetFileName
cmp ax,1504h ; GetBibliographical function ?
je @@GetFilename ; Yes --> @@GetFileName
cmp [cs:AltSimul],01h ; Alternate simulation ?
je @@AltSimul
cmp ax,1505h ; VTOC read function ?
je @@ReadVTOC ; Yes --> @@ReadVTOC
cmp ax,1508h ; Absolute read function ?
je @@AbsRead ; Yes --> @@AbsRead
cmp ax,1509h ; Absolute write function ?
je @@Dummy ; Yes --> @@Dummy
cmp ax,150bh ; DriveCheck function ?
je @@DriveCheck ; Yes --> @@DriveCheck
cmp ax,150ch ; Version check function ?
je @@GetVersion ; Yes --> @@CheckVersion
cmp ax,150eh ; Descriptor function ?
je @@GetDescriptorPreference ; Yes --> @@GetDescriptorPreference
cmp ax,150fh ; Get directory entry ?
je @@GetDirEntry ; Yes --> @@GetDirEntry
cmp ax,1510h ; Device request ?
je @@DeviceRqz ; Yes --> @@DeviceRqz
cmp ax,150dh ; DriveList function ?
je @@DriveList ; Yes --> @@DriveList
@@CallOld:
mov ax,[cs:@@OldAX]
jmp [dword ptr cs:OldInt2F] ; Call old interrupt handler
@@AltSimul:
cmp ax,150bh ; DriveCheck function ?
je @@DriveCheck ; Yes --> @@DriveCheck
cmp ax,150ch ; Version check function ?
je @@GetVersion ; Yes --> @@CheckVersion
cmp ax,150dh ; DriveList function ?
je @@DriveList ; Yes --> @@DriveList
cmp ax,1510h ; Device request ?
je @@SuccessDev ; Yes --> @@SuccessDev
jmp @@CallOld ; Call old
@@AbsRead:
test dx,dx ; Sector count > 0 ?
jz @@ReadFinished ; Yes --> @@ReadFinished
push cx ds si ; Save registers
add cl,'A' ; Convert drive letter to A-Z
push ax ; Save ax
call GetSpeed, cx ; Get drive speed
mov [@@DelaySize],ax ; Save speed of delay
pop ax ; Restore ax
call GetData, cx ; Get cd data
jc @@NoAbsRead ; Error --> @@NoAbsRead
mov si,[ds:si+2] ; Adjust offset
cmp si,0ffffh ; Sector data ?
je @@NoAbsRead ; No --> @@NoAbsRead
push bx dx ; Save registers
@@ReadDataLoop:
push ds si es bx ; Save registers
call DeCrunch, ds si, es bx ; Decrunch sector data
pop bx es si ds ; Restore registers
add bx,2048 ; Next sector offset
dec dx ; One less sector to read
jnz @@ReadDataLoop ; More --> @@ReadDataLoop
pop dx bx si ds cx ; Restore registers
@@ReadFinished:
push ax cx dx ; Save registers
cmp [@@DelaySize],0 ; Any delay ?
je @@NoDelay ; No --> @@NoDelay
@@DelayLoop:
test dx,dx ; Sectors = 0 ?
jz @@NoDelay ; Yes --> @@NoDelay
push dx ; Save dx
mov ah,86h ; AT Fn 86h = Wait
mov cx,0 ; High 16 bit of delay
mov dx,[@@DelaySize] ; Low 16 bit of delay
int 15h ; Call AT interrupt
pop dx ; Restore dx
dec dx ; One less delay to perform
jmp @@DelayLoop ; Loop
@@NoDelay:
pop dx cx ax ; Restore registers
iCLC ; Signal success
iret ; Return to interrupt caller
@@NoAbsRead:
pop si ds cx ; Restore registers
cmp [cs:DoFailure],01h ; Failure on exit ?
jne @@Dummy ; No --> @@Dummy
iSTC ; Signal failure
mov ax,0015h ; Drive not ready error
iret ; Return to interrupt caller
@@GetDescriptorPreference:
cmp bx,0 ; Get function ?
je @@GetPreference ; Yes --> @@GetPreference
iCLC ; Signal success
iret ; Return to interrupt caller
@@GetPreference:
mov dx,0100h ; Set return bits
iCLC ; Signal success
iret ; Return to interrupt caller
@@Dummy:
iCLC ; Signal success
iret ; Return to interrupt caller
@@ReadVTOC:
push ds si ; Save registers
add cl,'A' ; Convert id to A-Z
call GetData, cx ; Get cd data
jc @@HasNoVTOC ; Error --> @@HasNoVTOC
mov si,[ds:si] ; Adjust offset
@@GetVTOC:
cmp [word ptr ds:si],0ffffh ; Last sector ?
je @@ReadFlags ; Yes --> @@ReadFlags
cmp [ds:si],dx ; Sector wanted ?
je @@ReadTheVTOC ; Yes --> @@ReadFlags
add si,2 ; Skip index word
add si,[word ptr ds:si] ; Skip _ax+_flags+data
jmp @@GetVTOC ; Loop
@@ReadTheVTOC:
push ax cx si ; Save registers
add si,8 ; Adjust offset
call DeCrunch, ds si, es bx ; Decrunch sector
pop si cx ax ; Restore registers
@@ReadFlags:
mov ax,[word ptr ds:si+6] ; Get flags to return
push bp ; Save bp
mov bp,sp ; Point bp to sp in stack
mov [word ptr bp+10],ax ; Adjust flags on stack
pop bp ; Restore bp
mov ax,[word ptr ds:si+4] ; Get ax to return
pop si ds ; Restore registers
cmp [cs:DoFailure],01h ; Failure on exit ?
jne @@Dummy ; No --> @@Dummy
mov al,17h
iSTC ; Signal failure
iret ; Return to interrupt caller
@@HasNoVTOC:
pop si ds ; Restore registers
@@NoVTOC:
cmp [cs:DoFailure],01h ; Failure on exit ?
jne @@Dummy ; No --> @@Dummy
iSTC ; Signal failure
mov al,17h ; Error code
iret ; Return to interrupt caller
@@DeviceRqz:
mov cl,[cs:FirstRealCD] ; Get the real cd-drive
mov al,[byte ptr es:bx+2] ; Get device command code
cmp al,1 ; Media check function ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,2 ; Build BPB ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,3 ; IOCTL input ?
je @@IOCTLI ; Yes --> @@IOCTLI
cmp al,4 ; Input ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,5 ; Nondestructive read ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,6 ; Input status ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,8 ; Output ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,9 ; Output with verify ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,10 ; Output status ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,11 ; Output flush ?
je @@ErrRqz ; Yes --> @@ErrRqz
cmp al,12 ; IOCTL output ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -