; ************************************** ;*** SNAPSHOT MOD for DOAX *** ;*** by Alucard of the Neotaku Boards *** ; ************************************** BITS32 ORG0x10B40
; Parameters of the framebuffer (depth = 32bits) WIDTHequ768 WIDTH2equ720 HEIGHTequ480 ; NVidia GPU: Framebuffer address NV_CRTC_FB_ADDRequ0xFD600800 ; Addresses of various NT Kernel routines in DOAX's import table NtCreateFileequ0x00239620 NtWriteFileequ0x00239628 NtCloseequ 0x00239634 MmAllocateContiguousMemoryequ0x002396E0 MmFreeContiguousMemoryequ 0x002396B4 ; Address of the pad polling function of DOAX PadPollequ 0x0023308F SnapshotFunc: ; We start by making a copy of all arguments of DOAX's pad polling function popdword [ReturnAddr] popdword [hHandle] popdword [pState]
; Put the args back in place and call the pad polling function ourselves pushdword [pState]; Obviously a structure that contain's the pad's state pushdword [hHandle]; Probably a handle to the pad device callPadPoll ; Put the return address back in place so when we use 'ret' DOAX will continue its ; execution pushdword [ReturnAddr] ; Save all registers pushad
movedi, dword [pState] ; Check if START and BACK are pressed. ; This is to avoid taking a snapshot when someone use EvoX's reset function ; (L+R+BACK+START) movax, [edi +4] andax, 0x30 cmpax, 0x30 jne.NoReset jmpExit .NoReset: ; The position of the LEFT trigger is at offset 12 in the pad state structure. addedi, 12 moval, [edi] cmpal, 128 ja.LeftTriggerPressed jmpExitUnlock .LeftTriggerPressed: ; Test our 'previous state', this is used to save only one picture each time ; the LEFT trigger is pressed. xoreax, eax cmpdword [PreviousState], eax je.DoSnapshot jmpExit .DoSnapshot: incdword [PreviousState] incdword [Number] movedi, NumA + 7 xoreax, eax movebx, dword [Number] movecx, 8 movedx, ITOA ConvASCII: moval, bl andal, 0xF moval, [edx + eax] movbyte [edi], al decedi shrebx, 4 loopConvASCII
; Create / Overwrite a file xoreax, eax pushdword 0x00000060; FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT pushdword 0x00000005; FILE_OVERWRITE_IF inceax pusheax; FILE_SHARE_READ pushdword 0x00000080; FILE_ATTRIBUTE_NORMAL deceax pusheax; NULL pushIoStatusBlock pushObjectAttributes pushdword 0x40000000; GENERIC_WRITE pushFileHandle call[NtCreateFile] ; Allocate two memory buffers pushdword (WIDTH * HEIGHT * 4) call[MmAllocateContiguousMemory] pusheax pushdword (WIDTH * HEIGHT * 4) call[MmAllocateContiguousMemory] pusheax ; Get the framebuffer address from the GPU movesi, dword [NV_CRTC_FB_ADDR] oresi, 0x80000000 ; Make a copy of the framebuffer as fast as we can cli movedi, [esp] movecx, (WIDTH * HEIGHT) repmovsd sti ; Decode the framebuffer callUnSwizzle ; Copy lines from the decode buffer to the final bitmap, cropping to a width of 720 movesi, [esp + 4] movedi, [esp] movecx, HEIGHT CopyLine: pushecx movecx, (WIDTH2 * 3 / 4) repmovsd popecx addesi, ((WIDTH - WIDTH2) * 3) loopCopyLine ; Write the BMP header xoreax, eax pusheax; NULL pushdword 0x36; size pushBmpHeader; buffer pushIoStatusBlock; StatusBlock pusheax; NULL pusheax; NULL pusheax; NULL pushdword [FileHandle]; FileHandle call[NtWriteFile] ; Write bitmap data xoreax, eax movebx, [esp] pusheax; NULL pushWIDTH2 * HEIGHT * 3; size pushebx; buffer pushIoStatusBlock; StatusBlock pusheax; NULL pusheax; NULL pusheax; NULL pushdword [FileHandle]; FileHandle call[NtWriteFile]
; Close the file pushdword [FileHandle] call[NtClose] ; Discard the two buffers call[MmFreeContiguousMemory] call[MmFreeContiguousMemory] Exit: popad ret ExitUnlock: xoreax,eax movdword [PreviousState], eax jmpExit
align4 ;VOID UnSwizzle(PVOID Src, PVOID Dest); UnSwizzle: .Bequ0 .Aequ4 .OFFSETequ8 .INDEXequ12 .Lequ16 .Kequ20 .Jequ24 .Iequ28 .SRCequ36 .DSTequ40 subesp, 32 ;a = InBuffer; moveax, [esp + .SRC] mov[esp + .A], eax ;b = OutBuffer + ((HEIGHT-1) * WIDTH * 3); moveax, [esp + .DST] addeax, ((HEIGHT-1) * WIDTH * 3) mov[esp + .B], eax ;index = 0; xoreax, eax mov[esp + .INDEX], eax ;for(i=0;imovdword [esp + .I], HEIGHT / 16 .ILoop: moveax, [esp + .I] oreax, eax jnz.0 jmp.EndILoop .0: ;for(j=0;jmovdword [esp + .J], WIDTH / 64 .JLoop: moveax, [esp + .J] oreax, eax jnz.1 jmp.EndJLoop .1: ;if (i & 1) testdword [esp + .I], 1 jz.2 ;if (j & 1) testdword [esp + .J], 1 jz.3 ;b -= 192; subdword [esp + .B], 192 ;else jmp.2 .3: ;b += 192; adddword [esp + .B], 192 .2: ;for(l=0;l<4;l++) movdword [esp + .L], 4 .LLoop: moveax, [esp + .L] oreax, eax jnz.4 jmp.EndLLoop .4: ;for(k=0;k<16;k++) movdword [esp + .K], 16 .KLoop: moveax, [esp + .K] oreax, eax jnz.5 jmp.EndKLoop .5: ;offset = (((BlockNo[index]&0xFFFFFFFE)>>2) * 256) + ((BlockNo[index]&3) * 16); xorebx, ebx moveax, [esp + .INDEX] addeax, BlockNo movbl, [eax] moveax, ebx andeax, 3 shleax, 4 andebx, 0xFFFFFFFE shrebx, 2 shlebx, 8 addeax, ebx mov[esp + .OFFSET], eax ;index = (index + 1) & 63; moveax, [esp + .INDEX] inceax andeax, 63 mov[esp + .INDEX], eax ;b[WIDTH * -3 * 0 + 0] = a[offset + 64 * 0 + 0]; (0 to 11) movedi, [esp + .B] movesi, [esp + .A] addesi, [esp + .OFFSET] movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb ;b[WIDTH * -3 * 1 + 0] = a[offset + 64 * 1 + 0]; (0 to 11) movedi, [esp + .B] addedi, WIDTH * -3 * 1 movesi, [esp + .A] addesi, [esp + .OFFSET] addesi, 64 * 1 movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb ;b[WIDTH * -3 * 2 + 0] = a[offset + 64 * 2 + 0]; (0 to 11) movedi, [esp + .B] addedi, WIDTH * -3 * 2 movesi, [esp + .A] addesi, [esp + .OFFSET] addesi, 64 * 2 movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb ;b[WIDTH * -3 * 3 + 0] = a[offset + 64 * 3 + 0]; (0 to 11) movedi, [esp + .B] addedi, WIDTH * -3 * 3 movesi, [esp + .A] addesi, [esp + .OFFSET] addesi, 64 * 3 movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb incesi movsb movsb movsb ;b += 12; adddword [esp + .B], 12 ;} (KLoop) decdword [esp + .K] jmp.KLoop .EndKLoop: ;b = b - 192 - (WIDTH * 12); subdword [esp + .B], 192 + WIDTH * 12 ;} (LLoop) decdword [esp + .L] jmp.LLoop .EndLLoop: ;b = b + (WIDTH * 48) + 192; adddword [esp + .B], (WIDTH * 48) + 192 ;a += 4096; adddword [esp + .A], 4096 ;if (i & 1) testdword [esp + .I], 1 jz.6 ;if (j & 1) testdword [esp + .J], 1 jz.7 ;b += 192; adddword [esp + .B], 192 ;else jmp.6 .7: ;b -= 192; subdword [esp + .B], 192 .6: ;} (JLoop) decdword [esp + .J] jmp.JLoop .EndJLoop: ;b = b - (WIDTH * 51); subdword [esp + .B], WIDTH * 51 ;} (ILoop) decdword [esp + .I] jmp.ILoop .EndILoop: addesp, 32 ret align4 ObjectAttributes:; (OBJECT ATTRIBUTES) dd0; HANDLE RootDirectory ddObjectName; PANSI_STRING ObjectName dd0x00000040; ULONG Attributes ObjectName:; (PANSI_STRING) dw31; USHORT Length dw31; USHORT MaximumLength ddFileName; PCHAR Buffer
BmpHeader: db0x42, 0x4d, 0x36, 0xd2, 0x0f, 0x00, 0x00, 0x00 db0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00 db0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0xe0, 0x01 db0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00 db0x00, 0x00, 0x00, 0xd2, 0x0f, 0x00, 0x12, 0x0b db0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00 db0x00, 0x00, 0x00, 0x00, 0x00, 0x00 BlockNo: db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 db18, 19, 16, 17, 22, 23, 20, 21, 26, 27, 24, 25, 30, 31, 28, 29 db33, 34, 35, 32, 37, 38, 39, 36, 41, 42, 43, 40, 45, 46, 47, 44 db51, 48, 49, 50, 55, 52, 53, 54, 59, 56, 57, 58, 63, 60, 61, 62 FileName: db"??D:framebuffer_" NumA: db"00000000.bmp",0 ITOA: db"0123456789ABCDEF" align4 Number: dd0 PreviousState: dd0 ReturnAddr: dd0 hHandle: dd0 pState: dd0 FileHandle: dd0 IoStatusBlock: dd0 dd0
|