📄 c4proc.asm
字号:
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach );;http://www.zsnes.com;http://sourceforge.net/projects/zsnes;https://zsnes.bountysource.com;;This program is free software; you can redistribute it and/or;modify it under the terms of the GNU General Public License;version 2 as published by the Free Software Foundation.;;This program is distributed in the hope that it will be useful,;but WITHOUT ANY WARRANTY; without even the implied warranty of;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;GNU General Public License for more details.;;You should have received a copy of the GNU General Public License;along with this program; if not, write to the Free Software;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.%include "macros.mac"EXTSYM C4TransfWireFrame2,snesmmap,pressed,romdata,vidbufferEXTSYM C4WFXVal,C4WFYVal,C4WFX2Val,C4WFY2Val,C4CalcWireFrameEXTSYM C4WFDist,C4WFScale,C4TransfWireFrame,C4WFZValEXTSYM C41FXVal,C41FYVal,C41FAngleRes,C41FDist,C4Op1F,C4Op15EXTSYM C41FDistVal,C4Op0D,C4Op22,SinTable,CosTableEXTSYM regaccessbankr8,regaccessbankr16,regaccessbankw8,regaccessbankw16EXTSYM memaccessbankr16,memaccessbankr8,memaccessbankw16,memaccessbankw8; ******************************************************; C4 Emulation, reverse engineered & written by zsKnight; ******************************************************SECTION .text%macro RouteAccess 1 test ecx,8000h jnz memaccessbank%1 cmp ecx,6000h jb regaccessbank%1%endmacroNEWSYM C4Read8b RouteAccess r8 push ecx sub ecx,6000h and ecx,1fffh mov ebx,[C4RamR] call dword near [ebx+ecx*4] xor ebx,ebx pop ecx retNEWSYM C4Read16b RouteAccess r16 push ecx sub ecx,6000h and ecx,1fffh mov ebx,[C4RamR] inc ecx call dword near [ebx+ecx*4] dec ecx mov ah,al call dword near [ebx+ecx*4] xor ebx,ebx pop ecx retNEWSYM C4Write8b RouteAccess w8 push ecx sub ecx,6000h and ecx,1fffh mov ebx,[C4RamW] call dword near [ebx+ecx*4] xor ebx,ebx pop ecx retNEWSYM C4Write16b RouteAccess w16 push ecx sub ecx,6000h and ecx,1fffh; mov ebx,[C4Ram]; mov [ebx+ecx],ax mov ebx,[C4RamW] push eax call dword near [ebx+ecx*4] inc ecx mov al,ah call dword near [ebx+ecx*4] pop eax xor ebx,ebx pop ecx retC4ProcessVectors: mov esi,[C4Ram] mov edi,esi add edi,1F8Ch movzx edx,word[esi+1F8Ah] cmp dx,128 ja .ret cmp dx,0 jne .nozero.ret ret.nozero cmp dx,10h jb .less mov dx,10h.less mov esi,[C4Ram] add esi,800h.loop mov ecx,100h xor ebx,ebx xor eax,eax movsx bx,byte[edi].spotloop add ah,80h mov [esi],ah sub ah,80h add ax,bx inc esi dec ecx jnz .spotloop add edi,3 dec dx jnz .loop retsection .dataC4ColRot db 1SECTION .bssNEWSYM C4RamR, resd 1NEWSYM C4RamW, resd 1NEWSYM C4Ram, resd 1C4ObjDisp resd 1NEWSYM C4ObjSelec, resb 1NEWSYM C4SObjSelec, resb 1NEWSYM C4Pause, resb 1C4DataCopy resb 64CObjNum resw 1C4Temp resd 1section .textC4Edit: ; C4 editing routines ; Register keyboard presses ; [ = prev object, ] = next object ; p = pause/unpause cmp byte[pressed+1Ah],0 je .notpressed mov byte[pressed+1Ah],0 inc byte[C4ObjSelec] inc byte[C4Temp].notpressed cmp byte[pressed+1Bh],0 je .notpressed2 mov byte[pressed+1Bh],0 dec byte[C4ObjSelec] dec byte[C4Temp].notpressed2 cmp byte[pressed+19h],0 je .notpressed3 mov byte[pressed+19h],0 xor byte[C4Pause],1.notpressed3 ; Setup variables mov esi,[C4Ram] add byte[C4ColRot],16 mov al,[esi+620h] cmp byte[C4ObjSelec],0FFh jne .notneg dec al mov [C4ObjSelec],al jmp .notof.notneg cmp byte[C4ObjSelec],al jb .notof xor al,al mov [C4ObjSelec],al.notof ; Draw the dots on-screen movzx eax,byte[C4ObjSelec] shl eax,4 add eax,[C4Ram] add eax,220h mov byte[.flipped],0 test byte[eax+6],40h jz .notflip mov byte[.flipped],1.notflip; 00/01 - x position relative to BG scroll value; 02/03 - y position relative to BG scroll value; 04 - palette/priority settings; 05 - OAM pointer value; 06 - flip settings : b6 = flipx, b7 = flipy; 07 - looks like some sprite displacement values; 08/09 - ???; 0A-0F - unused movzx ebx,word[eax+8] mov [CObjNum],bx cmp bx,4096 jae near .skipall shl ebx,6 add ebx,[C4Data] ; t,f,g,h = move current object ; q = copy current object structure, w = paste current object structure cmp byte[pressed+14h],0 je .notmove mov byte[pressed+14h],0 pushad mov ecx,15.next add ebx,4 dec byte[ebx+1] dec ecx jnz .next popad.notmove cmp byte[pressed+21h],0 je .notmove2 mov byte[pressed+21h],0 pushad mov ecx,15.next2 add ebx,4 cmp byte[.flipped],0 je .noflipx add byte[ebx],2.noflipx dec byte[ebx] dec ecx jnz .next2 popad.notmove2 cmp byte[pressed+22h],0 je .notmove3 mov byte[pressed+22h],0 pushad mov ecx,15.next3 add ebx,4 inc byte[ebx+1] dec ecx jnz .next3 popad.notmove3 cmp byte[pressed+23h],0 je .notmove4 mov byte[pressed+23h],0 pushad mov ecx,15.next4 add ebx,4 cmp byte[.flipped],0 je .noflipx2 sub byte[ebx],2.noflipx2 inc byte[ebx] dec ecx jnz .next4 popad.notmove4 cmp byte[pressed+10h],0 je .notcopy mov byte[pressed+10h],0 pushad mov edx,C4DataCopy mov ecx,64.copylp mov al,[ebx] mov [edx],al inc ebx inc edx dec ecx jnz .copylp popad.notcopy cmp byte[pressed+11h],0 je .notpaste mov byte[pressed+11h],0 pushad mov edx,C4DataCopy mov ecx,64.pastelp mov al,[edx] mov [ebx],al inc ebx inc edx dec ecx jnz .pastelp popad.notpaste ; - = remove sub-object, + = add sub-object ; ; = previous sub-object, ' = next sub-object cmp byte[pressed+0Ch],0 je .notpressed4 mov byte[pressed+0Ch],0 cmp byte[ebx],0 je .notpressed4 dec byte[ebx].notpressed4 cmp byte[pressed+0Dh],0 je .notpressed5 mov byte[pressed+0Dh],0 cmp byte[ebx],15 je .notpressed5 inc byte[ebx].notpressed5 cmp byte[pressed+27h],0 je .notpressed6 mov byte[pressed+27h],0 dec byte[C4SObjSelec].notpressed6 cmp byte[pressed+28h],0 je .notpressed7 mov byte[pressed+28h],0 inc byte[C4SObjSelec].notpressed7 ; get current sub-object displacement (0 if no sub-objects) xor ecx,ecx cmp byte[ebx],0 je near .nosubobjs mov cl,[ebx] cmp byte[C4ObjSelec],0FFh jne .sobjokay2 dec cl mov [C4SObjSelec],cl jmp .sobjokay.sobjokay2 cmp byte[C4SObjSelec],cl jb .sobjokay mov byte[C4SObjSelec],0.sobjokay movzx ecx,byte[C4SObjSelec] shl ecx,2 add ebx,ecx add ebx,4 ; i,j,k,l = move current sub-object (17,24,25,26) ; u = toggle between 8x8 and 16x16 tiles ; o = toggle between high/low oam value ; . = decrease oam value, / = increase oam value of sub-object cmp byte[pressed+17h],0 je .notpressed8 mov byte[pressed+17h],0 dec byte[ebx+1].notpressed8 cmp byte[pressed+24h],0 je .notpressed9 mov byte[pressed+24h],0 dec byte[ebx] cmp byte[.flipped],0 je .notpressed9 add byte[ebx],2.notpressed9 cmp byte[pressed+26h],0 je .notpressed11 mov byte[pressed+26h],0 inc byte[ebx] cmp byte[.flipped],0 je .notpressed11 sub byte[ebx],2.notpressed11 cmp byte[pressed+25h],0 je .notpressed10 mov byte[pressed+25h],0 inc byte[ebx+1].notpressed10 cmp byte[pressed+16h],0 je .notpressed12 mov byte[pressed+16h],0 xor byte[ebx+3],2.notpressed12 cmp byte[pressed+18h],0 je .notpressed13 mov byte[pressed+18h],0 xor byte[ebx+3],1.notpressed13 cmp byte[pressed+34h],0 je .notpressed14 mov byte[pressed+34h],0 dec byte[ebx+2].notpressed14 cmp byte[pressed+35h],0 je .notpressed15 mov byte[pressed+35h],0 inc byte[ebx+2].notpressed15 mov cl,[ebx] mov ch,[ebx+1].nosubobjs mov edx,ecx movzx ebx,byte[eax] sub bl,[esi+621h] add bl,dl movzx ecx,byte[eax+2] sub cl,[esi+623h] add cl,dh mov esi,[vidbuffer] add esi,16*2+256*2+32*2 add esi,ebx add esi,ebx mov ebx,ecx shl ebx,9 shl ecx,6 add esi,ebx add esi,ecx mov al,[C4ColRot] mov ah,al xor ah,0FFh mov [esi],ax mov [esi+16],ax mov [esi+288*8*2],ax mov [esi+16+288*8*2],ax.skipall retSECTION .bss.flipped resb 1SECTION .textC4AddSprite: cmp dword[C4count],0 je near .nosprite mov [edi],ax mov [edi+2],bx mov ebx,[C4usprptr] and [ebx],dl mov al,dl xor al,0FFh and dh,al or [ebx],dh add edi,4 rol dl,2 rol dh,2 dec dword[C4count] cmp dl,0FCh jne .nosprite inc dword[C4usprptr].nosprite retC4ConvOAM: mov esi,[C4Ram] mov edi,esi movzx ecx,byte[esi+620h] mov bx,[esi+621h] mov [.addx],bx mov bx,[esi+623h] mov [.addy],bx mov [C4usprptr],esi add dword[C4usprptr],200h mov eax,[C4ObjDisp] add edi,eax shr eax,4 add dword[C4usprptr],eax add esi,220h ; Convert from esi to edi mov dl,0FCh push ecx mov cl,[C4sprites] and cl,3 add cl,cl rol dl,cl pop ecx cmp cl,0 je near .none mov dword[C4count],128 mov eax,[C4sprites] sub dword[C4count],eax.loop push ecx push esi; 00/01 - x position relative to BG scroll value; 02/03 - y position relative to BG scroll value; 04 - palette/priority settings; 05 - OAM pointer value; 06 - flip settings : b6 = flipx, b7 = flipy; 07 - ???; 08/09 - Pointer to Sprite Structure; 0A-0F - unused;bit 1-3 = palette number bit 4,5 = playfield priority;bit 6 = horizontal flip bit 7 = horizonal flip mov ax,[esi] sub ax,[.addx] mov [C4SprX],ax mov ax,[esi+2] sub ax,[.addy] mov [C4SprY],ax mov al,[esi+5] mov [C4SprOAM],al mov al,[esi+4] mov ah,al and ah,0Eh mov [C4SprAttr],al mov al,[esi+6] or [C4SprAttr],al; mov [C4SprFlip],al movzx ecx,byte[esi+9] shl ecx,16 mov cx,[esi+7] add cx,cx shr ecx,1 add ecx,[romdata] mov al,[ecx] or al,al jz near .singlespr mov [C4SprCnt],al inc ecx.nextspr xor ebx,ebx movsx bx,byte[ecx+1] test byte[C4SprAttr],40h jz .notflipx neg bx sub bx,8.notflipx add bx,[C4SprX] xor dh,dh test byte[ecx],20h jz .no16x16 or dh,10101010b test byte[C4SprAttr],40h jz .no16x16 sub bx,8.no16x16 cmp bx,-16 jl near .nosprite cmp bx,272 jg near .nosprite mov al,bl test bx,100h jz .not512b or dh,01010101b.not512b xor ebx,ebx movsx bx,byte[ecx+2] test byte[C4SprAttr],80h jz .notflipy neg bx sub bx,8.notflipy add bx,[C4SprY] test byte[ecx],20h jz .no16x16b test byte[C4SprAttr],80h jz .no16x16b sub bx,8.no16x16b cmp bx,-16 jl near .nosprite cmp bx,224 jg near .nosprite mov ah,bl mov bh,[C4SprAttr] mov bl,[ecx] and bl,0C0h xor bh,bl mov bl,[C4SprOAM] add bl,[ecx+3] call C4AddSprite.nosprite add ecx,4 dec byte[C4SprCnt] jnz near .nextspr jmp .donemultispr.singlespr mov dh,10101010b test byte[C4SprX+1],1 jz .not512 or dh,01010101b.not512 mov al,[C4SprX] mov ah,[C4SprY] mov bl,[C4SprOAM] mov bh,[C4SprAttr] call C4AddSprite.donemultispr pop esi pop ecx add esi,16 dec cl jnz near .loop.none retsection .bss.addx resw 1.addy resw 1C4count resd 1C4usprptr resd 1C4SprX resw 1C4SprY resw 1C4SprCnt resb 1C4SprAttr resb 1C4SprOAM resb 1C4SprFlip resb 1section .textNEWSYM C4VBlank retNEWSYM C4ProcessSprites push ecx push esi push edi push ebx push edx; call C4ProcessVectors; call C4Edit mov esi,[C4Ram] mov dword[C4count],8 mov cl,[esi+626h] mov [C4sprites],cl mov ecx,[C4sprites] shl ecx,2 mov [C4ObjDisp],ecx mov ecx,128; cmp byte[esi+65],50h; jne .noincdisp mov dword[C4count],32 sub ecx,[C4sprites].noincdisp add esi,[C4ObjDisp] ; Clear OAM to-be ram.next mov byte[esi+1],0E0h add esi,4 dec ecx jnz .next call C4ConvOAM pop edx pop ebx pop edi pop esi pop ecx retsection .bssC4Data resd 1C4sprites resd 1SECTION .textNEWSYM InitC4 pushad mov esi,[romdata] add esi,4096*1024 mov [C4Data],esi add dword[C4Data],128*1024 mov [C4RamR],esi mov [C4RamW],esi mov [C4Ram],esi add dword[C4RamW],8192*4 add dword[C4Ram],8192*8 mov ecx,8192.c4loop mov dword[esi],C4ReadReg mov dword[esi+8192*4],C4WriteReg mov dword[esi+8192*8],0 add esi,4 dec ecx jnz .c4loop mov esi,[C4RamW] mov dword[esi+1F4Fh*4],C4RegFunction mov esi,[C4Data] mov ecx,16*4096.c4loopb mov dword[esi],0 add esi,4 dec ecx jnz .c4loopb popad retC4ClearSpr: mov esi,ebx mov edi,eax shl ch,3.scloop2 mov cl,[C4SprPos] shl cl,2.scloop mov byte[edi],0 mov byte[edi+2000h],0 inc edi dec cl jnz .scloop dec ch jnz .scloop2 retC4SprBitPlane: mov edi,eax shl ebx,2.scloop3 mov ch,[C4SprPos] push esi.scloop4 push esi mov cl,8.loop mov dh,8 mov dl,80h mov eax,[esi].nextd test al,1 jz .not0 or byte[edi],dl.not0 test al,2 jz .not1 or byte[edi+1],dl.not1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -