📄 cmd_cdplayer.asm
字号:
%include "util.mac"
%include "icedump.inc"
%include "vxdn.inc"
%include "wiat.inc"
%ifndef MAKEDEP
global Parse_CDPlayer
global Service_CDPlayer
extern sdata
extern Parser.error
extern Parser.errorMsg
extern Error_PMR0
extern SetCB
extern ParseExpression
bits 32
;-------------------------------------------------------------------------------
; CD [<track>]
;-------------------------------------------------------------------------------
segment _LTEXT
Parse_CDPlayer:
mov edi,Error_PMR0
mov ebp,[dClient_CS]
test byte [ebp],3 ; is client in ring-0?
jz near Parser.errorMsg
mov ebp,[dClient_EAX]
movb dword [ebp],SERVICE_CDPLAYER
call [pSkipWhiteSpace] ; skip to track#
jnz .GetTrack
mov al,-1 ; issue STOP
jmp short .SetCB
.GetTrack:
mov edi,.Error_Track
call ParseExpression ; parse <track>
jc near Parser.errorMsg
.SetCB:
mov ebp,[dClient_ECX] ; store track number
mov [ebp],eax
call SetCB
jc near Parser.error
xor eax,eax
inc eax
mov ebp,[fPAGEIN_InProgress] ; set internal Winice flag to 1
mov [ebp],eax
mov ebp,[fExecuteMoreCommands] ; set internal Winice flag to 0
mov [ebp],ah
popad
retn
segment _LDATA
.Error_Track db 'could not parse track.',0
;-------------------------------------------------------------------------------
; this is the actual CD Player code that's executed in ring-0.
; EBP = CRS
;-------------------------------------------------------------------------------
segment _LTEXT
Service_CDPlayer:
mov eax,[ebp+CRS.ECX] ; track number
mov [.Track],eax
mov [.CurES],es
VMMCall Begin_Nest_V86_Exec
; check for cdrom
mov [ebp+CRS.EAX],word 0x1500
movb dword [ebp+CRS.EBX],0
movb eax,0x2F
VMMCall Exec_Int
movzx ebx,word [ebp+CRS.EBX]
mov edi,.NoCdRom
or ebx,ebx
jz .PrintError
mov eax,[ebp+CRS.ECX]
mov [.CdRom],eax
call .GetDiskInfo
test eax,eax
jnz .Error
mov ecx,[.Track] ; track #
cmp cl,-1
jne .PlayTracks
; track == -1, it's a STOP
call .Stop
jmp short .ExitNested
.PlayTracks:
; check if this track exists on CD
cmp cl,bl
jb .BadTrack
cmp cl,bh
jbe .TrackOk
.BadTrack:
mov edi,.ValidMsg
movzx eax,bh
movzx ebx,bl
jmp short .PrintError
.TrackOk:
mov al,cl
call .GetTrackInfo
test eax,eax
jnz .Error
mov eax,ebx
call .Play
test eax,eax
jnz .Error
jmp short .ExitNested
.Error:
mov edi,.CdError
.PrintError:
push edi
VMMCall _Trace_Out_Service
.ExitNested:
VMMCall End_Nest_Exec
popfd
popad
retn
segment _LDATA
align 4
dw 0 ; dummy
.CurES dw 0
.DiscEnd dd 0
.CdRom dd 0 ; CD-Rom drive letter code
.Track dd 0
.NoCdRom db 'CD-Rom unavailable',CRLF0
.CdError db 'CD-Rom error #EAX',CRLF0
.ValidMsg db 'Valid tracks are #EBX to #EAX',CRLF0
;.TestMsg db 'Someone wants to hear track #ECX. Amazing, SoftICE is still alive =)',CRLF0
segment _LTEXT
.Stop:
movb ecx,CdReq_size
call .AllocV86
jc .AllocError
mov ebx,133 ; STOP AUDIO
xor ecx,ecx
call .CdCommand
call .FreeV86
retn
; EAX = track start
.Play:
movb ecx,CdReq_size+CdPlayReq_size
call .AllocV86
jc .AllocError
mov ebx,132 ; PLAY AUDIO
movb ecx,CdPlayReq_size
mov [edi+CdReq_size+CdPlayReq.AddrMode],byte 0
mov [edi+CdReq_size+CdPlayReq.Sector],eax
sub eax,[.DiscEnd]
neg eax
mov [edi+CdReq_size+CdPlayReq.Count],eax
call .CdCommand
call .FreeV86
retn
; AL = track#
; returns track start in EBX
.GetTrackInfo:
movb ecx,CdIoctlReq_size+CdTrackInfo_size
call .AllocV86
jc .AllocError
movb ebx,0x0B ; IOCTLI/TRACK_INFO
movb ecx,CdTrackInfo_size
mov [edi+CdIoctlReq_size+CdTrackInfo.Track],al
call .CdIoCtl
mov ebx,[edi+CdIoctlReq_size+CdTrackInfo.Start]
call .RedBook2HSG
call .FreeV86
retn
.AllocError:
mov al,0xFF
jmp .DrvErr
; returns Lo-Hi track #s in BX
.GetDiskInfo:
movb ecx,CdIoctlReq_size+CdDiskInfo_size
call .AllocV86
jc .AllocError
movb ebx,0x0A ; IOCTLI/AUDIO_INFO
movb ecx,CdDiskInfo_size
call .CdIoCtl
mov ebx,[edi+CdIoctlReq_size+CdDiskInfo.LeadOut]
call .RedBook2HSG
mov [.DiscEnd],ebx
mov ebx,[edi+CdIoctlReq_size+CdDiskInfo.TrackLo]
call .FreeV86
retn
; BX = driver command, ECX = extra request data length
.CdCommand:
mov edx,ecx
movb ecx,CdReq_size ; 0-init the req structure
push edi
xor al,al
rep stosb
pop edi
add edx,byte CdReq_size
mov [edi+CdReq.Len],dl
mov [edi+CdReq.Cmd],bx
jmp short .CdCallExt
; BX = I/O + control code, ECX = control block data length
.CdIoCtl:
mov [edi+CdIoctlReq.CtrlCode],bl
mov edx,ecx
movb ecx,CdIoctlReq_size ; 0-init the req structure
push edi
xor al,al
rep stosb
pop edi
; setup the IOCTL req structure
movb eax,3 ; IOCTLI
test bh,0x80
jz .notO
movb eax,12 ; IOCTLO
.notO:
mov [edi+CdIoctlReq.Cmd],ax
mov [edi+CdIoctlReq.Len],byte CdIoctlReq_size
mov [edi+CdIoctlReq.XferSize],dx
; setup IOCTL transfer address
lea eax,[edi+CdIoctlReq_size]
shl eax,12
shr ax,12
mov [edi+CdIoctlReq.XferOfs],eax
.CdCallExt:
; setup es:bx pair
mov eax,edi
ror eax,4
mov [ebp+CRS.ES],ax
shr eax,28
mov [ebp+CRS.EBX],ax
mov [ebp+CRS.EAX],word 0x1510
mov eax,[.CdRom]
mov [ebp+CRS.ECX],eax
movb eax,0x2F
push es
mov es,[.CurES]
VMMCall Exec_Int
pop es
movzx eax,word [ebp+CRS.EAX]
mov ebx,[ebp+CRS.EFlags] ; test CF
and ebx,byte 1
jnz .DrvNotCalled ; there was CF
movzx eax,word [edi+CdReq.Status]
test ah,0x80
jnz .DrvErr
xor eax,eax
.DrvErr:
movzx eax,al
.DrvNotCalled:
retn
; !!! always call Free after Alloc if alloc succeeded
.AllocV86:
push eax
VMMCall Get_Cur_VM_Handle
clc
VxDCall V86MMGR_Allocate_Buffer
mov [.BufSizeV86],ecx
jc ._allocerr
; calc linear v86 addr
mov eax,edi
shr edi,16
shl edi,4
movzx eax,ax
add edi,eax
VxDCall V86MMGR_Get_VM_Flat_Sel
mov es,eax
._allocerr:
pop eax
retn
.FreeV86:
push ebx
mov es,[.CurES]
mov ecx,[.BufSizeV86]
VMMCall Get_Cur_VM_Handle
clc
VxDCall V86MMGR_Free_Buffer
pop ebx
retn
segment _LDATA
align 4
.BufSizeV86 dd 0
; HSG = (Min * 60 + Sec) * 75 + Frame - 150
segment _LTEXT
.RedBook2HSG:
mov edx,ebx
shr ebx,16
imul ebx,byte 60
movzx ecx,dh
add ebx,ecx
imul ebx,byte 75
movzx ecx,dl
lea ebx,[ebx+ecx-150]
retn
%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -