⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmp3d.asm

📁 Cracker终结者——提供最优秀的软件保护技术
💻 ASM
📖 第 1 页 / 共 2 页
字号:
@@
	mov	dword [MpegPtr], 0
	cmp	dword [BufAddr], byte 0
	jz	@F

	VMMCall	_PageFree, dword [BufAddr], byte 0
	mov	dword [BufAddr], 0

@@
	retn


SetIndex:
; EAX = index
	push	edx

	mov	edx, [ListBuf]
	cmp	edx, byte 0
	jz	@F

	cmp	eax, [edx]
	jae	@F

	mov	[NextFile], eax

	pop	edx
	xor	eax, eax
	clc
	retn

@@
	pop	edx
	or	eax, byte -1
	stc
	retn


SetIndexNext:
	push	edx

	mov	edx, [ListBuf]
	cmp	edx, byte 0
	jnz	@F

	pop	edx
	or	eax, byte -1
	stc
	retn

@@
	inc	dword [NextFile]
	mov	eax, [NextFile]

	cmp	eax, [edx]
	jb	@F

	and	dword [NextFile], byte 0

@@
	pop	edx
	xor	eax, eax
	clc
	retn


SetIndexPrev:
	push	edx

	mov	edx, [ListBuf]
	cmp	edx, byte 0
	jnz	@F

	pop	edx
	or	eax, byte -1
	stc
	retn

@@
	sub	dword [NextFile], byte 1
	jnc	@F

	mov	eax, [edx]
	dec	eax
	mov	[NextFile], eax

@@
	pop	edx
	xor	eax, eax
	clc
	retn


PlayMpegIndex:
	pushad

	mov	esi, [ListBuf]
	mov	eax, [NextFile]
	lea	eax, [esi+eax*4+4]

	mov	esi, [eax]	; pointer to file name
	jmp	short PlayMpeg.NoRegs

PlayMpeg:
; ESI = filename
	pushad

.NoRegs:
; acquire wave device if not done yet
	cmp	word [hMMWave], 0
	jnz	.hasdevice

	VxDCall _SHELL_CallAtAppyTime, dword AppyWaveOpen, byte 0, byte 0, byte 0
	cmp	eax, byte 0
	jnz	@F

%if ADD_DEBUG = 1
	Trace_Out "Grab Wave appy event-schedule failed"
%endif

	mov	eax, -5
	jmp	.err_noclose

@@
; wait for appy to finish
;	mov	eax, [hMMSem]
;	mov	ecx, BLOCK_SVC_INTS | BLOCK_ENABLE_INTS
;	VMMCall	Wait_Semaphore
	VMMCall	_BlockOnID, dword hMMLib, dword BLOCK_SVC_INTS | BLOCK_ENABLE_INTS

	cmp	word [hMMWave], 0
	jnz	.hasdevice

	mov	eax, -5
	jmp	.err_noclose

.hasdevice:
	xor	eax, eax	; keep the device
	call	StopMpeg

; open file
	mov	eax, R0_OPENCREATFILE
	mov	ebx, 2040h		; read only|share:deny none|no INT24
	mov	ecx, 0020h		; archive
	mov	edx, 0001h		; open|fail
	VxDCall IFSMgr_Ring0_FileIO

%if ADD_DEBUG = 1
	Trace_OutC "Open file failed, code #EAX"
%endif	

	jc	near .err_noclose

; save handle for future
	mov	ebx, eax

	mov	eax, R0_GETFILESIZE
	VxDCall	IFSMgr_Ring0_FileIO
	jc	near .err_close

	mov	[FileSize], eax
	
	add	eax, 0fffh
	shr	eax, 12
	VMMCall	_PageAllocate, eax, byte PG_SYS, byte 0, byte 0, byte 0, byte 0, byte 0, dword PAGEFIXED
	cmp	eax, byte 0
	jnz	@F

%if ADD_DEBUG = 1
	Trace_Out "File buffer alloc failed"
%endif	
	mov	eax, 8			; Not enough mem
	jmp	.err_close

@@
	mov	[BufAddr], eax

; read entire file in
	mov	esi, eax		; buffer
	mov	eax, R0_READFILE
	mov	ecx, [FileSize]		; bytes to read
	xor	edx, edx		; file ofs
	VxDCall	IFSMgr_Ring0_FileIO

%if ADD_DEBUG = 1
	Trace_OutC "Read file failed, code #EAX"
%endif	

	jc	near .err_close

	mov	eax, R0_CLOSEFILE
	VxDCall	IFSMgr_Ring0_FileIO
	
; reset vars
	mov	ecx, [FileSize]
	mov	[FileLeft], ecx
	xor	ecx, ecx
	mov	[CurBlock], ecx
	mov	[cBlocks], ecx
	mov	[BufPtr], ecx
	
	call	InitMpeg
	jc	near .err_noclose

	call	MpegNextBlock
	call	MpegNextBlock

; init DMA for auto-init xfer
	VxDCall	VDSPD_Get_DMA
	mov	ebx, [DmaPhysAddr]
	mov	ecx, 10000h
	call	DmaInit

	mov	byte [IsPlaying], 1

	mov	eax, [hIrq]
	VxDCall	VPICD_Physically_Unmask

	mov	eax, [LastFrame + FrameInfo.SampFreq]
	mov	ebx, [LastFrame + FrameInfo.Chans]
	shr	ebx, 1		; set mono/stereo bit
	mov	edx, [LastFrame + FrameInfo.BitsPerSample]
	shr	edx, 4
	shl	edx, 1
	or	ebx, edx	; set 16bit-play bit
	mov	ecx, 8000h
	VxDCall	VDSPD_Play

	xor	eax, eax
	mov	[esp + CRS.EAX], eax

	popad
	clc
	retn		

.err_close:
	push	eax
	mov	eax, R0_CLOSEFILE
	VxDCall	IFSMgr_Ring0_FileIO
	pop	eax

.err_noclose:
	mov	[esp + CRS.EAX], eax

	popad
	stc
	retn


WAVE_MAPPER	EQU	-1

struc WaveOpenArgs
woa_fdwOpen	resd 1
woa_dwInstance	resd 1
woa_dwCB	resd 1
woa_lpWaveFmt	resd 1
woa_uDeviceID	resw 1
woa_lphWaveOut	resd 1
endstruc

struc WaveCloseArgs
wca_hWaveOut	resw 1
endstruc


AppyWaveOpen:
; PROC C Public, dwRefData:DWORD, dwFlags:DWORD
; setup call stack
	mov	eax, [hMMmem]
	mov	[woa + woa_lpWaveFmt], eax
	add	eax, byte WaveFormatEx_size
	mov	[woa + woa_lphWaveOut], eax
	
; init hWaveOut in case call fails
	mov	edx, [LinMMmem]
	mov	word [edx + WaveFormatEx_size], 0
        push	edx
	VxDCall	_SHELL_CallDll, byte 0, dword [waveOutOpen], byte WaveOpenArgs_size, dword woa
	pop	edx
	mov	cx, [edx + WaveFormatEx_size]

%if ADD_DEBUG = 1
	cmp	eax, byte 0
	jnz	@F

	cmp	cx, 0
	jnz	@F

	Trace_Out "waveOutOpen failed"
@@
%endif

	mov	[hMMWave], cx

%if ADD_DEBUG = 1
	Trace_Out "waveOutOpen succeeded at AppyTime"
%endif

;	mov	eax, [hMMSem]
;	VMMCall	Signal_Semaphore
	VMMCall	_SignalID, dword hMMLib
	retn


segment _LDATA
	align 4
woa:
istruc WaveOpenArgs
  at woa_fdwOpen,	dd 0
  at woa_dwInstance,	dd 0
  at woa_dwCB,		dd 0
  at woa_lpWaveFmt,	dd 0
  at woa_uDeviceID,	dw WAVE_MAPPER
  at woa_lphWaveOut,	dd 0
iend


segment _LTEXT
AppyWaveClose:
; PROC C Public, dwRefData:DWORD, dwFlags:DWORD
	mov	ax, [hMMWave]
	mov	[wca + wca_hWaveOut], ax
	VxDCall	_SHELL_CallDll, byte 0, dword [waveOutClose], byte WaveCloseArgs_size, dword wca
	mov	word [hMMWave], 0

%if ADD_DEBUG = 1
	Trace_Out "waveOutClose succeeded at AppyTime"
%endif

;	mov	eax, [hMMSem]
;	VMMCall	Signal_Semaphore
	VMMCall	_SignalID, dword hMMLib
	retn


segment _LDATA
	align 4
wca:
istruc WaveCloseArgs
iend


segment _LTEXT
InitMpeg:
	VxDCall	VDSPD_Is_Stereo
	mov	edi, eax
	xor	edi, byte 1		; not

	VxDCall	VDSPD_Is_16bit
	mov	esi, eax
	xor	esi, byte 1		; not

	xor	ebx, ebx

.loop1:
	push	byte 0
	push	edi
	push	esi
	push	ebx
	push	dword 1234h		; dummy file handle
	call	_MpegBegin@20
	and	eax, 0C0000000h
	cmp	eax, 0C0000000h
	je	.err1

	call	NextFrame
	jc	.err1

	VxDCall	VDSPD_Get_Rate

	cmp	eax, [LastFrame + FrameInfo.SampFreq]
	jae	.ret1			; card freq supported, ok

	push	dword 1234h
	call	_MpegEnd@4
	inc	ebx
	mov	dword [MpegPtr], 0
	mov	dword [BufPtr], 0
	jmp	short .loop1

.ret1:
	clc
	retn

.err1:
	stc
	retn


NextFrame:
	push	edi
	mov	edi, [MpegBuf]
	add	edi, [MpegPtr]

@@
	push	dword LastFrame
	push	dword MpegLastBytes
	push	edi
	call	_MpegNextFrame@12
	mov	edx, eax
	and	edx, 0C0000000h
	cmp	edx, 0C0000000h 	; check for error
	jz	@F

	cmp	eax, MPEG_ENDOFTRACK
	je	@F

	cmp	dword [MpegLastBytes], byte 0
	jz	@B

	mov	eax, [MpegLastBytes]
	add	[MpegPtr], eax
	clc
	pop	edi
	retn

@@
	stc
	pop	edi
	retn


MpegNextBlock:
@@
	call	NextFrame
	jc	near .err1

	cmp	dword [MpegPtr], 0x8000
	jb	@B

	mov	edx, [MpegPtr]
	mov	ecx, 8000h
	sub	edx, ecx
	mov	[MpegPtr], edx

; copy wave-form to DMA Buffer
	mov	edi, [DmaLinAddr]
	mov	esi, [MpegBuf]
	add	edi, [CurBlock]
	xor	[CurBlock], ecx	; update current block

	cld
	shr	ecx, 2
	rep	movsd

	inc	dword [cBlocks]
	
; move wave-form leftovers (above 8000h) to the begining
	mov	edi, [MpegBuf]
	mov	ecx, edx
	and	edx, 3
	shr	ecx, 2
	rep	movsd
	cmp	edx, byte 0
	jz	@F

	mov	ecx, edx
	rep movsb

@@
	retn

.err1:
; end the stream
	mov	dword [FileLeft], 0
	mov	ecx, [FileSize]
	inc	ecx
	mov	[BufPtr], ecx
	retn


	align 4
DspHwIntProc:
	pushad

	call	OnDspIrq
	jnc	@F

	popad
	jmp	dword [OrgHwIntProc]

@@
	mov	eax, [esp+CRS.EAX]
	VxDCall	VPICD_Phys_EOI

	popad
	clc
	retn


;
; this mess simulates a HOOK_PROC
;
	jmp	short HookedMaskIRQ	; *MUST* assemble to EB,06 or EB,0A
	jmp	[OrgMaskIRQProc]

%if ADD_DEBUG = 1
	dd 0
%endif

HookedMaskIRQ: 
; LOCKED, HOOK_PROC, OrgMaskIRQProc
; prevents our irq from being masked
;Assume	eax:PTR VID_IRQ_Struct

	cmp	byte [IsPlaying], 1
	jne	IgnoreIRQ

	push	ecx
	mov	ecx, [eax + VID_IRQ_Struct.CtrlBlock]
	mov	ecx, [ecx + VID_IRQCB.nIRQ]
	cmp	ecx, [IrqNum]
	pop	ecx

	jne	IgnoreIRQ

	retn	; do nothing

IgnoreIRQ:
	jmp	[OrgMaskIRQProc]


HookIrq:
; EAX = irq #
; EBX = hVM
; EBP = CRS

	mov	[IrqNum], eax

; get PIC addr
	mov	ecx, eax
	shl	cl, 5
	mov	ch, 40h
	rcr	ch, 1
	shr	cl, 5
	mov	[PicReg], ch

; get PIC mask
	mov	ah, 1
	shl	ah, cl
	mov	[PicMask], ah

; hook VPICD_Physically_Mask to prevent masking of our irq
	GetDeviceServiceOrdinal eax, VPICD_Physically_Mask
	mov	esi, HookedMaskIRQ
	VMMCall	Hook_Device_Service

%if ADD_DEBUG = 1
	Trace_OutC "Hooking VPICD_Physically_Mask failed"
%endif

	jnc	@F

	retn

@@
; lookup virtualized irq handle
	mov	edi, [IrqTab]
        mov	eax, [IrqNum]
	mov	edi, [edi+eax*4]	; get VID_IRQCB ptr
	mov	eax, [edi + VID_IRQCB.hIrqOwner]

	cmp	dword [eax + VID_IRQ_Struct.DbgStr], 51524953h	; 'SIRQ'
	jne	.cleanup1

; we got our int, now hook Hw_Int_Proc
	mov	[hIrq], eax
	pushfd
	cli
	mov	ecx, [eax + VID_IRQ_Struct.Hw_Int_Proc]
	mov	[OrgHwIntProc], ecx
	mov	ecx, DspHwIntProc
	mov	[eax + VID_IRQ_Struct.Hw_Int_Proc], ecx
	popfd

        clc
	retn

.cleanup1:

%if ADD_DEBUG = 1
	Trace_Out "VPICD hack failed, invalid or unknown struct"
%endif

; unhook VPICD_Physically_Mask
	GetDeviceServiceOrdinal eax, VPICD_Physically_Mask
	mov	esi, HookedMaskIRQ
	VMMCall	Unhook_Device_Service
	
	stc
	retn


UnhookIrq:
; unhook Hw_Int_Proc
	pushfd
	cli
	mov	edx, [hIrq]
	mov	eax, [OrgHwIntProc]
	mov	[edx + VID_IRQ_Struct.Hw_Int_Proc], eax
	popfd

; unhook VPICD_Physically_Mask
	GetDeviceServiceOrdinal eax, VPICD_Physically_Mask
	mov	esi, HookedMaskIRQ
	VMMCall	Unhook_Device_Service

%if ADD_DEBUG = 1
	Trace_OutC "Unhooking VPICD_Physically_Mask failed"
%endif

	retn


	align 4
OnDspIrq:
	cmp	byte [IsPlaying], 1
	je	@F

	stc
	retn

@@
	VxDCall	VDSPD_Check_Int
	jnc	@F

	stc
	retn

@@
; save fpu state (save TS)
	mov	eax, cr0
	push	eax
	clts
	sub	esp, byte FPU_Status_PM32_size + FPU_STx_size
	fnsave	[esp]

	fninit
	call	MpegNextBlock

; now restore FPU state, first clear possible pending exceptions
	xor	al, al
	xchg	al, [esp + FPU_Status_PM32.StatusLo]
	frstor	[esp]

; now restore status with possible pending exceptions
	xchg	al, [esp + FPU_Status_PM32.StatusLo]
	fldenv	[esp]
	add	esp, byte FPU_Status_PM32_size + FPU_STx_size
	pop	eax
	mov	cr0, eax	; restore CR0.TS
	
	dec	dword [cBlocks]
	jnz	.nostop

	VxDCall	VDSPD_Stop

.nostop:
	clc
	retn


	align 4
ReadStreamData:
; returns number of bytes read or MPEG_ENDOFSTREAM
; PROC Stdcall, hFile:DWORD, Buffer:PTR BYTE, BufferSize:DWORD

%define hFile esp+4+12
%define Buffer esp+8+12
%define BufferSize esp+12+12

	push	esi
	push	edi
	push	ebx

	mov	ecx, [FileLeft]
	cmp	ecx, byte 0
	jnz	@F

	mov	eax, MPEG_ENDOFTRACK
	pop	ebx
	pop	edi
	pop	esi
	retn    12

@@
	mov	eax, [BufferSize]
	cmp	ecx, eax
	jb	.block_ok

	mov	ecx, eax

.block_ok:
	sub	[FileLeft], ecx

	mov	esi, [BufAddr]	; calc next block ptr
	add	esi, [BufPtr]
	add	[BufPtr], ecx	; update buffer ptr
	mov	edi, [Buffer]

	mov	eax, ecx

	cld
	shr	ecx, 2
	rep	movsd
	mov	ecx, eax
	and	ecx, 3
	cmp	ecx, byte 0
	jz	@F

	rep	movsb
	
@@
	pop	ebx
	pop	edi
	pop	esi
	retn	12


VMP3D_Get_Version:
	mov	eax, 0100h
	clc
	retn


VMP3D_Get_IRQ:
	VxDCall	VDSPD_Get_IRQ
	retn


VMP3D_On_SoftIce_IRQ:
	pushad
	call	OnDspIrq
	popad
	clc
	retn


VMP3D_Need_SoftIce_IRQ:
	cmp	byte [IsPlaying], 0
	retn


VMP3D_Play:
	bts	dword [IsBusy], 0
	jc	@F

	pushad
	call	SetIndex		; eax: index
	jc	@F

	call	PlayMpegIndex

	btr	dword [IsBusy], 0

@@
	popad
	retn


VMP3D_Play_Next:
	bts	dword [IsBusy], 0
	jc	@F

	pushad
	call	SetIndexNext
	jc	@F

	call	PlayMpegIndex

	btr	dword [IsBusy], 0

@@
	popad
	retn


VMP3D_Play_Prev:
	bts	dword [IsBusy], 0
	jc	@F

	pushad
	call	SetIndexPrev
	jc	@F

	call	PlayMpegIndex

	btr	dword [IsBusy], 0

@@
	popad
	retn


VMP3D_Stop:
	pushad
	cmp	byte [IsPlaying], 0
	jz	@F

	bts	dword [IsBusy], 0
	jc	@F

	mov	eax, 1
	call	StopMpeg

	btr	dword [IsBusy], 0

@@
	popad
	clc
	retn


VMP3D_Pause:
	retn		; NOT READY YET

	pushad
	cmp	byte [IsPlaying], 0
	jz	@F

	VxDCall	VDSPD_Pause

@@
	popad
	retn


VMP3D_Resume:
	retn		; NOT READY YET

	pushad
	cmp	byte [IsPlaying], 0
	jz	@F

	VxDCall	VDSPD_Resume

@@
	popad
	retn

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -