📄 cmd_mp3player.asm
字号:
%include "util.mac"
%define WIN403SERVICES
%include "vxdn.inc"
%include "icedump.inc"
%include "vmp3d.inc"
%include "wiat.inc"
global Parse_MP3Player
global MP3MainHook
global Service_MP3Player
extern sdata
extern Parser.error
extern Parser.errorMsg
extern SetCB
extern ParseExpression
bits 32
;-------------------------------------------------------------------------------
; MP3 <0,n,+,->
; stop,play,next,prev
;-------------------------------------------------------------------------------
segment _LTEXT
Parse_MP3Player:
push byte SERVICE_MP3PLAYER
mov ebp,[dClient_EAX]
pop dword [ebp]
mov edi,.Error_NoPlayer
cmp byte [sdata+MP3.PlayerPresent],1
jne near Parser.errorMsg
; parse params
call [pSkipWhiteSpace] ; skip to command/track#
mov edi,.Error_NoParam
jz near Parser.errorMsg
cmp byte [esi],'+'
jz @F
cmp byte [esi],'-'
jnz .parseTrack
@@
movzx eax,byte [esi]
mov ebp,[dClient_EBX]
mov [ebp],eax
jmp short .setCB
.parseTrack:
mov edi,.Error_Track
call ParseExpression ; parse 0,n
jc near Parser.errorMsg
mov ebp,[dClient_ECX]
mov [ebp],eax
mov ebp,[dClient_EBX]
mov dword [ebp],0
.setCB:
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_NoPlayer: db 'MP3 player not loaded.',0
.Error_NoParam: db 'no params specified',0
.Error_Track: db 'could not parse track',0
;-------------------------------------------------------------------------------
; inside-winice IRQ handler
;-------------------------------------------------------------------------------
segment _STEXT
StaticSoundCardIntProc:
cld
push edi
mov edi,[cs:sdata+s_fWiniceIsActive]
cmp byte [cs:edi],0
pop edi
jnz @F ; yes: delegate to winice
push dword [cs:sdata+OldSoundCardIntProc.sel]
push dword [cs:sdata+OldSoundCardIntProc.off]
retf
@@
pushad
push es
push ds
mov eax,0x30 ; ring-0 data selector
mov ds,eax
mov es,eax
VxDCall VMP3D_On_SoftIce_IRQ
; send EOI
movzx eax,byte [sdata+MP3.nIRQ]
call [sdata+s_pSendSpecificEOI]
pop ds
pop es
popad
iretd
;-------------------------------------------------------------------------------
; WiniceMain hook
;-------------------------------------------------------------------------------
segment _LTEXT
MP3MainHook:
cmp byte [sdata+MP3.PlayerPresent],1
je .present
; reinit VxDCall, since VMM will replace our code
mov word [.checkmp3],0x20CD ; VxDCall
GetDeviceServiceOrdinal dword [.checkmp3+2],VMP3D_Get_Version
.checkmp3:
VxDCall VMP3D_Get_Version
jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_VMP3DNotFound
call [pPrintToCommandWindow]
debug_end
retn
@@
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_VMP3DFound
call [pPrintToCommandWindow]
debug_end
mov byte [sdata+MP3.PlayerPresent],1
.present:
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_VMP3DPresent
call [pPrintToCommandWindow]
debug_end
; Hook IRQx, our strategy is to install first level handlers (that is, directly
; into the IDT) into whatever IDT happens to be active at the time winice came
; up, this will eventually install it everywhere
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_IRQHooking
call [pPrintToCommandWindow]
debug_end
VxDCall VMP3D_Get_IRQ
mov [sdata+MP3.nIRQ],al
call [pIRQ2INT]
push eax
sidt [esp-2]
pop edi
lea edi,[edi+8*eax] ; edi: IDT descriptor offset
mov bx,[edi+6] ; get old gate offset
shl ebx,16
mov bx,[edi]
cmp ebx,StaticSoundCardIntProc ; already hooked?
jnz @F
cmp word [edi+2],0x28
jz .hooked
@@
cmp [sdata+OldSoundCardIntProc.off],byte 0
jz @F
cmp [sdata+OldSoundCardIntProc.off],ebx
jz @F
mov esi,.Msg_DifferentHandler
call [pPrintToCommandWindow]
@@
mov [sdata+OldSoundCardIntProc.off],ebx
movzx ebx,word [edi+2] ; get old gate selector
mov [sdata+OldSoundCardIntProc.sel],ebx
mov ebx,StaticSoundCardIntProc ; write new gate offset
mov [edi],bx
shr ebx,16
mov [edi+6],bx
mov word [edi+2],0x28 ; write new gate selector
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_IRQHooked
call [pPrintToCommandWindow]
debug_end
.hooked:
; test if VMP3D is playing a song already, and enable IRQ handling
; otherwise silence... until user exits winice
VxDCall VMP3D_Need_SoftIce_IRQ
jnz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_IRQNotEnabled
call [pPrintToCommandWindow]
debug_end
retn
@@
; ok, let's rock ;-)
movzx eax,byte [sdata+MP3.nIRQ]
call [pEnableIRQ]
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_MP3
mov esi,.Msg_IRQEnabled
call [pPrintToCommandWindow]
debug_end
retn
segment _LDATA
.Msg_VMP3DNotFound: db 'VMP3D not found',0
.Msg_VMP3DFound: db 'VMP3D found',0
.Msg_VMP3DPresent: db 'VMP3D present',0
.Msg_IRQHooking: db 'hooking IRQ',0
.Msg_IRQHooked: db 'hooked IRQ',0
.Msg_IRQNotEnabled: db 'did not enable IRQ',0
.Msg_IRQEnabled: db 'enabled IRQ',0
.Msg_DifferentHandler: db 'ERROR: old first level handler is different',0
;-------------------------------------------------------------------------------
; this is the actual MP3 Player code that's executed in ring-0.
; EBP = CRS
;-------------------------------------------------------------------------------
segment _LTEXT
Service_MP3Player:
cmp dword [ebp+CRS.EBX],byte '+'
jnz @F
VxDCall VMP3D_Play_Next
jmp short .ret
@@
cmp dword [ebp+CRS.EBX],byte '-'
jnz @F
VxDCall VMP3D_Play_Prev
jmp short .ret
@@
cmp dword [ebp+CRS.EBX],byte 0
jnz .ret
cmp dword [ebp+CRS.ECX],byte 0
jnz @F
VxDCall VMP3D_Stop
jmp short .ret
@@
mov eax,[ebp+CRS.ECX]
dec eax
VxDCall VMP3D_Play
.ret:
popfd
popad
retn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -