NES PPU 杂

.686 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

; 43210
; |||||
; |||++- Pixel value from tile data
; |++--- Palette number from attribute table or OAM
; +----- Background/Sprite select
; As in some second-generation game consoles, values in the NES palette are based on hue and brightness:
; 76543210
; ||||||||
; ||||++++- Hue (phase, determines NTSC/PAL chroma)
; ||++----- Value (voltage, determines NTSC/PAL luma)
; ++------- Unimplemented, reads back as 0
; Hue $0 is light gray, $1-$C are blue to red to green to cyan, $D is dark gray, and $E-$F are mirrors of $1D (black).
; The canonical code for "black" is $0F or $1D. $0D should not be used;
; it results in a "blacker than black" signal that may cause problems for some TVs.
; It works this way because of the way colors are represented in an NTSC or PAL signal,
; with the phase of a color subcarrier controlling the hue. For details, see NTSC video.
; The 2C03 RGB PPU used in the PlayChoice-10 and Famicom Titler renders hue $D as black, not dark gray. The 2C04 PPUs used in many Vs.
; System arcade games have completely different palettes as a copy protection measure.

DisplaySkew struct
dword X ?
dword Y ?
dword ScrLatch ?
DisplaySkew ends

AddressSkew struct
dword LowAddr ?
dword HighAddr ?
dword AddrLatch ?
AddressSkew ends

.data?

align 16

BGPal dd 16 dup (?) ; offset - 160 size : 64
SPPal dd 16 dup (?) ; offset - 96 size : 64
ppuREG dd 8 dup (?) ; offset - 32 size : 32
DisplaySkew ScreenOffset <> ; offset 0
AddressSkew AddressOffset <> ; offset 12
DisplaySkew CurLineOffset <> ; offset 24 size : 24
m_EleGun dd ? ; offset 36 size : 4
m_RollReg dd ? ; offset 40 size : 4
pNameTable dd ? ; offset 44 size : 4
VideoBuffer dd 15360 ?
SRAM dd 256 dup (?) ; offset : N/A unless Sprite RAM
.data

PPU_VBLANK_BIT equ 80h
PPU_SPHIT_BIT equ 40h
PPU_SP16_BIT equ 20h
PPU_BGTBL_BIT equ 10h
PPU_SPTBL_BIT equ 08h
PPU_INC32_BIT equ 04h
PPU_NAMETBL_BIT equ 03h
; 2001 mask
PPU_SHOWCOLOR equ 00h
PPU_NOCOLOR equ 01h
PPU_LEFT8COL equ 02h
PPU_SPRLEFT8COL equ 04h
PPU_SHOWBG equ 08h
PPU_SHOWSPR equ 10h
; 2002 mask
PPU_VBLANK_FLAG equ 80h
PPU_SPHIT_FLAG equ 40h
PPU_SPMAX_FLAG equ 20h
PPU_WENABLE_FLAG equ 10h

SP_VREVERT equ 80h
SP_HREVERT equ 40h
SP_LEVEL equ 20h
SP_HIGHCOLOR equ 03h

_PPU_ReadByte proc C _addr

option prologue:none, epilogue:none

movzx eax, word ptr[esp+4] ; - N
push edx
and eax, 03FFFh ; - decom mirror
mov edx, eax
shr eax, 8
jmp [PLTable+eax*4-08000h] ; -N/V
align 16
GX00:
GX01:
GX02:
GX03:
GX04:
GX05:
GX06:
GX07:
GX08:
GX09:
GX0A:
GX0B:
GX0C:
GX0D:
GX0E:
GX0F:
GX10:
GX11:
GX12:
GX13:
GX14:
GX15:
GX16:
GX17:
GX18:
GX19:
GX1A:
GX1B:
GX1C:
GX1D:
GX1E:
GX1F:
GX20:
GX21:
GX22:
GX23:
GX24:
GX25:
GX26:
GX27:
GX28:
GX29:
GX2A:
GX2B:
GX2C:
GX2D:
GX2E:
GX2F: ; 0x0010 1111
mov eax, edx ; - U
and edx, 03FFh ; - V
shr eax, 10 ; - U
mov eax, [PPU_MEM_BANK_INDEX+eax*4]
movzx eax, [eax+edx]
pop edx
ret
align 16
GX30:
GX31:
GX32:
GX33:
GX34:
GX35:
GX36:
GX37:
GX38:
GX39:
GX3A:
GX3B:
GX3C:
GX3D:
GX3E: ; $2000 - $2EFF's mirror
lea eax, [edx-01000h]
sub edx, 01000h
shr edx, 10 ; - U
and eax, 03FFh ; - V
mov edx, [PPU_MEM_BANK_INDEX+edx*4]
movzx eax, [eax+edx]
pop edx
ret
align 16
GX3F: ; palette/mirror
mov eax, edx ; - U save old frame
and edx, 15 ; - V limit bit for PAL mirror
and eax, 16 ; - U is SPPal ? Y: D5 == 1 : D5 == 0
lea eax, [eax*4] ; - U D5 is 0 ? edx == 0 : edx == 64
mov eax, [BGPal+eax+edx*4] ; N/V set val
pop edx
ret
align 16
PLTable dd GX00, GX01, GX02, GX03, GX04, GX05, GX06, GX07
dd GX08, GX09, GX0A, GX0B, GX0C, GX0D, GX0E, GX0F
dd GX10, GX11, GX12, GX13, GX14, GX15, GX16, GX17
dd GX18, GX19, GX1A, GX1B, GX1C, GX1D, GX1E, GX1F
dd GX20, GX21, GX22, GX23, GX24, GX25, GX26, GX27
dd GX28, GX29, GX2A, GX2B, GX2C, GX2D, GX2E, GX2F
dd GX30, GX31, GX32, GX33, GX34, GX35, GX36, GX37
dd GX38, GX39, GX3A, GX3B, GX3C, GX3D, GX3E, GX3F
_PPU_ReadByte endp

_PPU_WriteByte proc C _addr, _val

option prologue:none, epilogue:none

; push edx
mov eax, [esp+8] ; - U val
push esi ; - V
mov esi, [esp+8] ; - N addr
push edx ; - V
mov edx, esi ; - U
and esi, 03FFFh ; - V decom mirror
shr esi, 8 ; - U
jmp [WLTable+esi*4-08000h] ; -N/V
align 16
ZX00:
ZX01:
ZX02:
ZX03:
ZX04:
ZX05:
ZX06:
ZX07:
ZX08:
ZX09:
ZX0A:
ZX0B:
ZX0C:
ZX0D:
ZX0E:
ZX0F:
ZX10:
ZX11:
ZX12:
ZX13:
ZX14:
ZX15:
ZX16:
ZX17:
ZX18:
ZX19:
ZX1A:
ZX1B:
ZX1C:
ZX1D:
ZX1E:
ZX1F:
ZX20:
ZX21:
ZX22:
ZX23:
ZX24:
ZX25:
ZX26:
ZX27:
ZX28:
ZX29:
ZX2A:
ZX2B:
ZX2C:
ZX2D:
ZX2E:
ZX2F: ; 0x0010 1111
and edx, 03FFFh ; - U
nop ; - V spare
mov esi, edx ; - U
and edx, 03FFh ; - V
shr esi, 10 ; - U
mov esi, [PPU_MEM_BANK_INDEX+esi*4]
mov [esi+edx], al
pop edx
pop esi
ret
align 16
ZX30:
ZX31:
ZX32:
ZX33:
ZX34:
ZX35:
ZX36:
ZX37:
ZX38:
ZX39:
ZX3A:
ZX3B:
ZX3C:
ZX3D:
ZX3E: ; $2000 - $2EFF's mirror
and edx, 03FFFh ; - U
nop ; - V
sub edx, 01000h ; - U
nop ; - V spare
mov esi, edx ; - U
and edx, 03FFh ; - V
shr esi, 10 ; - U
mov esi, [PPU_MEM_BANK_INDEX+esi*4]
mov [esi+edx], al
pop edx
pop esi
ret
align 16
ZX3F: ; palette/mirror
lea esi, [BGPal]
and eax, 63 ; limit PAL index
jmp [PALAddrIndex+edx*4-0FC00h]
align 16
AC00:
AC10:
AC20:
AC30:
AC40:
AC50:
AC60:
AC70:
AC80:
AC90:
ACA0:
ACB0:
ACC0:
ACD0:
ACE0:
ACF0:
mov [esi], eax ; disp 32 .. maybe unaligned pipe ...
mov [esi+64], eax
pop edx
pop esi
ret
align 16
AC01:
AC02:
AC03:
AC04:
AC05:
AC06:
AC07:
AC08:
AC09:
AC0A:
AC0B:
AC0C:
AC0D:
AC0E:
AC0F:
AC21:
AC22:
AC23:
AC24:
AC25:
AC26:
AC27:
AC28:
AC29:
AC2A:
AC2B:
AC2C:
AC2D:
AC2E:
AC2F:
AC41:
AC42:
AC43:
AC44:
AC45:
AC46:
AC47:
AC48:
AC49:
AC4A:
AC4B:
AC4C:
AC4D:
AC4E:
AC4F:
AC61:
AC62:
AC63:
AC64:
AC65:
AC66:
AC67:
AC68:
AC69:
AC6A:
AC6B:
AC6C:
AC6D:
AC6E:
AC6F:
AC81:
AC82:
AC83:
AC84:
AC85:
AC86:
AC87:
AC88:
AC89:
AC8A:
AC8B:
AC8C:
AC8D:
AC8E:
AC8F:
ACA1:
ACA2:
ACA3:
ACA4:
ACA5:
ACA6:
ACA7:
ACA8:
ACA9:
ACAA:
ACAB:
ACAC:
ACAD:
ACAE:
ACAF:
ACC1:
ACC2:
ACC3:
ACC4:
ACC5:
ACC6:
ACC7:
ACC8:
ACC9:
ACCA:
ACCB:
ACCC:
ACCD:
ACCE:
ACCF:
ACE1:
ACE2:
ACE3:
ACE4:
ACE5:
ACE6:
ACE7:
ACE8:
ACE9:
ACEA:
ACEB:
ACEC:
ACED:
ACEE:
ACEF:
and edx, 15
mov [esi+edx*4], eax
pop edx
pop esi
ret
align 16
AC11:
AC12:
AC13:
AC14:
AC15:
AC16:
AC17:
AC18:
AC19:
AC1A:
AC1B:
AC1C:
AC1D:
AC1E:
AC1F:
AC31:
AC32:
AC33:
AC34:
AC35:
AC36:
AC37:
AC38:
AC39:
AC3A:
AC3B:
AC3C:
AC3D:
AC3E:
AC3F:
AC51:
AC52:
AC53:
AC54:
AC55:
AC56:
AC57:
AC58:
AC59:
AC5A:
AC5B:
AC5C:
AC5D:
AC5E:
AC5F:
AC71:
AC72:
AC73:
AC74:
AC75:
AC76:
AC77:
AC78:
AC79:
AC7A:
AC7B:
AC7C:
AC7D:
AC7E:
AC7F:
AC91:
AC92:
AC93:
AC94:
AC95:
AC96:
AC97:
AC98:
AC99:
AC9A:
AC9B:
AC9C:
AC9D:
AC9E:
AC9F:
ACB1:
ACB2:
ACB3:
ACB4:
ACB5:
ACB6:
ACB7:
ACB8:
ACB9:
ACBA:
ACBB:
ACBC:
ACBD:
ACBE:
ACBF:
ACD1:
ACD2:
ACD3:
ACD4:
ACD5:
ACD6:
ACD7:
ACD8:
ACD9:
ACDA:
ACDB:
ACDC:
ACDD:
ACDE:
ACDF:
ACF1:
ACF2:
ACF3:
ACF4:
ACF5:
ACF6:
ACF7:
ACF8:
ACF9:
ACFA:
ACFB:
ACFC:
ACFD:
ACFE:
ACFF:
and edx, 15
mov [esi+edx*4+64], eax
pop edx
pop esi
ret
; $3F00 Universal background color
; $3F01-$3F03 Background palette 0
; $3F05-$3F07 Background palette 1
; $3F09-$3F0B Background palette 2
; $3F0D-$3F0F Background palette 3
; $3F11-$3F13 Sprite palette 0
; $3F15-$3F17 Sprite palette 1
; $3F19-$3F1B Sprite palette 2
; $3F1D-$3F1F Sprite palette 3

; Addresses $3F04/$3F08/$3F0C can contain unique data,
; though these values are not used by the PPU when normally rendering
; They can still be shown using the background palette hack, explained below.
; Addresses $3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C.
align 16
WLTable dd ZX00, ZX01, ZX02, ZX03, ZX04, ZX05, ZX06, ZX07
dd ZX08, ZX09, ZX0A, ZX0B, ZX0C, ZX0D, ZX0E, ZX0F
dd ZX10, ZX11, ZX12, ZX13, ZX14, ZX15, ZX16, ZX17
dd ZX18, ZX19, ZX1A, ZX1B, ZX1C, ZX1D, ZX1E, ZX1F
dd ZX20, ZX21, ZX22, ZX23, ZX24, ZX25, ZX26, ZX27
dd ZX28, ZX29, ZX2A, ZX2B, ZX2C, ZX2D, ZX2E, ZX2F
dd ZX30, ZX31, ZX32, ZX33, ZX34, ZX35, ZX36, ZX37
dd ZX38, ZX39, ZX3A, ZX3B, ZX3C, ZX3D, ZX3E, ZX3F

PALAddrIndex dd AC00, AC01, AC02, AC03, AC04, AC05, AC06, AC07
dd AC08, AC09, AC0A, AC0B, AC0C, AC0D, AC0E, AC0F
dd AC10, AC11, AC12, AC13, AC14, AC15, AC16, AC17
dd AC18, AC19, AC1A, AC1B, AC1C, AC1D, AC1E, AC1F
dd AC20, AC21, AC22, AC23, AC24, AC25, AC26, AC27
dd AC28, AC29, AC2A, AC2B, AC2C, AC2D, AC2E, AC2F
dd AC30, AC31, AC32, AC33, AC34, AC35, AC36, AC37
dd AC38, AC39, AC3A, AC3B, AC3C, AC3D, AC3E, AC3F
dd AC40, AC41, AC42, AC43, AC44, AC45, AC46, AC47
dd AC48, AC49, AC4A, AC4B, AC4C, AC4D, AC4E, AC4F
dd AC50, AC51, AC52, AC53, AC54, AC55, AC56, AC57
dd AC58, AC59, AC5A, AC5B, AC5C, AC5D, AC5E, AC5F
dd AC60, AC61, AC62, AC63, AC64, AC65, AC66, AC67
dd AC68, AC69, AC6A, AC6B, AC6C, AC6D, AC6E, AC6F
dd AC70, AC71, AC72, AC73, AC74, AC75, AC76, AC77
dd AC78, AC79, AC7A, AC7B, AC7C, AC7D, AC7E, AC7F
dd AC80, AC81, AC82, AC83, AC84, AC85, AC86, AC87
dd AC88, AC89, AC8A, AC8B, AC8C, AC8D, AC8E, AC8F
dd AC90, AC91, AC92, AC93, AC94, AC95, AC96, AC97
dd AC98, AC99, AC9A, AC9B, AC9C, AC9D, AC9E, AC9F
dd ACA0, ACA1, ACA2, ACA3, ACA4, ACA5, ACA6, ACA7
dd ACA8, ACA9, ACAA, ACAB, ACAC, ACAD, ACAE, ACAF
dd ACB0, ACB1, ACB2, ACB3, ACB4, ACB5, ACB6, ACB7
dd ACB8, ACB9, ACBA, ACBB, ACBC, ACBD, ACBE, ACBF
dd ACC0, ACC1, ACC2, ACC3, ACC4, ACC5, ACC6, ACC7
dd ACC8, ACC9, ACCA, ACCB, ACCC, ACCD, ACCE, ACCF
dd ACD0, ACD1, ACD2, ACD3, ACD4, ACD5, ACD6, ACD7
dd ACD8, ACD9, ACDA, ACDB, ACDC, ACDD, ACDE, ACDF
dd ACE0, ACE1, ACE2, ACE3, ACE4, ACE5, ACE6, ACE7
dd ACE8, ACE9, ACEA, ACEB, ACEC, ACED, ACEE, ACEF
dd ACF0, ACF1, ACF2, ACF3, ACF4, ACF5, ACF6, ACF7
dd ACF8, ACF9, ACFA, ACFB, ACFC, ACFD, ACFE, ACFF
; BGPAL[0x04] = BGPAL[0x08] = BGPAL[0x0C] = BGPAL[0x00];
; SPPAL[0x00] = SPPAL[0x04] = SPPAL[0x08] = SPPAL[0x0C] = BGPAL[0x00];
_PPU_WriteByte endp

_ReadPpuPort proc C _addr

` option prologue:none, epilogue:none

movzx eax, word ptr[esp+4] ; - N
jmp [PORT_INDEX_TABLE+eax*4-08000h] ; -N/V
align 16
PORT_INDEX_TABLE dd REG2000, REG2001, REG2002, REG2003
dd REG2004, REG2005, REG2006, REG2007
REG2000:
REG2001:
REG2003:
REG2005:
REG2006:
movzx eax, byte ptr [ppuREG+eax*4-08000h] ; - N
ret ; - N
align 16
REG2002:
push ecx ; - U save old frame
push ebx ; - V save old frame
lea ecx, ScreenOffset ; - U lea base index
nop ; - V spare
mov [ecx+8], 0 ; - U ScrLatch = 0 (<-->)
mov ebx, [ecx-24] ; - V load REG[2]
mov [ecx+20], 1 ; - U AddrLatch = 1 (high bit)
mov eax, ebx ; - V save old frame
and ebx, 07Fh ; - U clr V_BLANK Enable
nop ; - V spare
mov [ecx-24], ebx ; - U write REG[2]
pop ebx ; - V
pop ecx ; - U
ret ; - N
align 16
REG2004:
push ecx ; - U - save old frame
lea ecx, ppuREG ; - V/N - decom reg
mov eax, [ecx+12] ; - U
inc eax ; - U ++ addr
mov [ecx+12], eax ; - N
and eax, 0FFh
pop ecx
movzx eax, byte ptr [SRAM+eax*4-4] ; - N
ret
align 16
REG2007:
push ebx ; - U save old frame
lea ebx, ScreenOffset ; - V/N - decom reg
push ecx ; - U save old frame
mov ecx, [ebx] ; - V load low bit
push edx ; - U save old frame
mov ch, [ebx+4] ; - V load high bit
mov edx, ecx ; - U save old frame VRAM's address
push ecx ; - V call NES_READ_BYTE
call dword ptr [_PPU_ReadByte] ; - N
add esp, 4 ; - U call type __cdcel ++ stack
mov ecx, [ebx-4] ; - V save old frame REG[7]
mov [ebx-4], eax ; - U write REG[7]
and edx, 0FFFFh ; - V
lea eax, [edx-03F00h] ; - U
nop ; - V spare
cmp eax, 0FFh ; - U address >= 0x3F00 && address < 0x4000 ?
ja no_palette ; - V Y: set palette/mirror ... N: next step ...
mov eax, edx ; - U save old frame
mov ecx, edx ; - V save old frame
and eax, 16 ; - U is SPPal ? Y: D5 == 1 : D5 == 0
and ecx, 15 ; - V limit bit for PAL mirror
lea eax, [eax*4] ; - U D5 is 0 ? edx == 0 : edx == 64
mov eax, [BGPal+eax+ecx*4] ; N/V set val
mov ecx, eax ; - U
neg eax ; - N
no_palette:
mov eax, ecx ; - U set return val eax <- REG[7]
mov ecx, [ebx-32] ; - V load REG[0]
shr ecx, 3 ; - U shift PPU_INC32_BIT is setted ? C_flag == 1 : C_flag == 0
mov ebx, 1 ; - V reset 32 to be use
adc ecx, 0 ; - U if C_flag == 1 ? edx == 1 : edx == 0
nop ; - V spare
and ecx, 1 ; - U limit bit
nop ; - V spare
lea ecx, [ecx*2+ecx] ; - U 3 or 0 myabe delay
ror bl, cl ; - N 1 or 32
add edx, ebx ; - U add sum
pop ecx ; - V
lea ebx, ScreenOffset ; - U index base
mov [ebx+4], dl ; - V/N
mov [ebx], dh ; - U
pop edx ; - V
pop ebx ; - U
ret ; - N
_ReadPpuPort endp

_WritePpuPort proc C _addr, _val

` option prologue:none, epilogue:none

mov eax, [esp+4] ; - U load addr
push ebx ; - V save old frame
and eax, 0FFFFh ; - U limit bit
push ecx ; - V
lea ebx, [ppuREG]; - U
mov ecx, [esp+16]; - V load val
jmp [_PORT_INDEX_TABLE+eax*4-08000h] ; -N/V
align 16
_PORT_INDEX_TABLE dd _REG2000, _REG2001, _REG2002, _REG2003
dd _REG2004, _REG2005, _REG2006, _REG2007
_REG2000: ; revise nametable addr
push edx ; - U save old frame
mov edx, ecx ; - V save old frame
shl ecx, 10 ; - U shift opr
mov eax, [ebx+76] ; - V load pNameTable
and ecx, 0C00h ; - U switch nametable index
and eax, 0F3FFh ; - V clear ora nametable index
or eax, ecx ; - U get current nametable index
mov ecx, [ebx] ; - V load REG[0]
mov [ebx+68], eax ; - U write nametable pointer
xor ecx, 080h ; - V neg VBLANK status
mov eax, [ebx+76] ; - U load REG[2]
and ecx, edx ; - V test status
and eax, ecx ; - U test status
mov [ebx], edx ; - V write REG[0]
shr eax, 7 ; - U shift
pop edx ; - V recover old frame
and eax, 1 ; - U clr bit
mov ebx, INT_WARNING ; - V/N
pop ecx ; - U recover old frame
or eax, ebx ; - V test set NMI_FLAG
pop ebx ; - U recover old frame
mov INT_WARNING, eax ; - V write back
ret ; - N child ret
align 16
_REG2001:
mov [ebx+4], ecx ; - U write val
pop ecx ; - V
pop ebx ; - U
ret ; - N
_REG2002:
mov [ebx+8], ecx ; - U write val
pop ecx ; - V
pop ebx ; - U
ret ; - N
_REG2003:
mov [ebx+12], ecx ; - U write val
pop ecx ; - V
pop ebx ; - U
ret ; - N
align 16
_REG2005:
mov eax, [ebx+40] ; - U load ScrLatch
nop ; - V spare
mov [ebx+32+eax*4], ecx; - U write val to current scr direction
xor eax, 1 ; - V switch now's direction
and ecx, 0FFh ; - U clr bit
mov [ebx+40], eax ; - V write ScrLatch
jmp [_REG2005_SCROLL_DIRECT_TABLE+eax*4]; V/N select table do frame
align 16
_X_HIT:
shr ecx, 3 ; - U get Tile X
mov eax, [ebx+24] ; - V load REG[6]
and ecx, 01Fh ; - U clr bit
and eax, 0FFE0h ; - V clr bit
or eax, ecx ; - U set bit
pop ecx ; - V recover old frame
mov [ebx+24], eax ; - U REG[6]
pop ebx ; - V/N recover old frame
ret ; - return ...
_Y_HIT:
ror ecx, 3 ; - U get Tile Y 0x0000 0111 and Y Tile offset
mov eax, [ebx+24] ; - V load REG[6]
shl cx, 5 ; - U/N ...
and eax, 08C1Fh ; - V clr bit 1000 1100 0001 1111
or eax, ecx ; - U set bit
nop ; - V spare 1110 0000 0000 0000 0NNN 0000 0000 0000
shr ecx, 14 ; - U
nop ; - V spare
or eax, ecx ; - U set bit
pop ecx ; - V recover old frame
mov [ebx+24], eax ; - U write REG[6]
pop ebx ; - V/N recover old frame
ret ; - return ...
align 16
_REG2006:
mov eax, [ebx+52] ; - U load AddrLatch
nop ; - V spare
mov [ebx+44+eax*4], ecx; - U/N write val to current addr
xor eax, 1 ; - V switch now's addr write mode
mov [ebx+52], eax ; - U write AddrLatch
mov [ebx+72+eax], cl ; - V write mem high|low bit (byte)...
mov ecx, [ebx+72+eax] ; - U load m_RollReg
IF 0
and [ebx+73], 03Fh ; - V clr bit load mem-> opr -> write back maybe terribe ..
ELSE
nop ; - V spare
ENDIF
mov [ebx+68+eax*4], ecx; - U/N
pop ecx ; - V/U recover old frame
pop ebx ; - U/V recover old frame
ret ; - return .
align 16
_REG2004:
movzx eax, [ebx+12] ; - N load REG[3]
mov [SRAM+eax*4], ecx ; - U/N write val to spram
inc eax ; - V/N
mov [ebx+12], eax ; - U
pop ecx ; - V
pop ebx ; - U
ret ; - N
align 16
_REG2007:
push ecx ; - U arg1 -> _val
mov al, [ebx+44] ; - V/N get low bit
mov ecx, [ebx] ; - U load REG[0]
mov ah, [ebx+48] ; - V/N get high bit
and ecx, 4 ; - U PPU_INC32_BIT is setted ?
push eax ; - V arg2 -> address
add eax, [_REG2000_INC_TABLE+ecx*4] ; - U PPU_INC32_BIT is setted ?
mov [ebx+44], al
mov [ebx+48], ah
call dword ptr [_WritePpuPort] ; - N
add esp, 8
pop ecx ; - V
pop ebx ; - U
ret ; - N
_REG2005_SCROLL_DIRECT_TABLE dd _Y_HIT, _X_HIT
_REG2000_INC_TABLE dd 1,1,1,1,32
_WritePpuPort endp

_ResetPPU proc C
option prologue:none, epilogue:none


_ResetPPU endp

_FrameStart proc C
option prologue:none, epilogue:none

test [ppuREG+4], 018h
jne _use_render
ret
_use_render:
mov eax, dword ptr [m_RollReg]
mov dword ptr [m_EleGun], eax
ret
_FrameStart endp

_VBlankStart proc C
option prologue:none, epilogue:none
and [ppuREG+12], 10000000b
test dword ptr [ppuREG], 128
je _NORMAL_P
; NMI PROC
_NORMAL_P:
ret
_VBlankStart endp

_VBlankEnd proc C
option prologue:none, epilogue:none
and [ppuREG+12], 00111111b
ret
_VBlankEnd endp

_StructCopy proc _des, _src, _num
_StructCopy endp

_ScanlineStart proc C
option prologue:none, epilogue:none

lea eax, [ScreenOffset]
nop ; sapre
test dword ptr [eax+28], 24
jne _set_render
ret
_set_render:
push ebx
push ecx
mov ebx, [eax]
mov ecx, [eax+4]
mov [eax+24], ebx
mov [eax+28], ecx
mov ebx, [eax+36]
mov ecx, [eax+40]
and ebx, 0F3E0h
and ecx, 00C1Fh
and ebx, ecx
pop ecx
mov [eax+36], ebx
pop ebx
ret

_ScanlineStart endp

_ScanlineNext proc C
option prologue:none, epilogue:none

test dword ptr [eax+28], 24
jne _set_renderX
ret
align 16
_set_renderX:
mov eax, [m_EleGun] ;
push ebx
mov ebx, eax
and eax, 07000h
cmp eax, 07000h ; cross a Tile's whole Y Offset ? 8 ...
jne _inc_Now_Tile_Offset_Y
and ebx, 08FFFh
mov eax, ebx
and eax, 03E0h
cmp eax, 03A0h ; Tile Y Offset == 29 ?
jne _Not_29
xor ebx, 0800h ; switch vertical nametable
__RET:
and ebx, 0FC1F ; set Tile Y Offset = 0
mov [m_EleGun], ebx
pop ebx
ret
align 16
_Not_29:
cmp eax, 03E0h ; Tile Y Offset == 31 ?
jne _inc_Now_Tile
jmp __RET
_inc_Now_Tile:
lea eax, [ebx+32]
jmp _pXRet
_inc_Now_Tile_Offset_Y: ; ++ Tile's Y Offset
lea eax, [ebx+1000h]
_pXRet:
pop ebx
mov [m_EleGun], eax
ret

_ScanlineNext endp

你可能感兴趣的:(n/a)