📄 sprites.asm
字号:
%if 0
SNEeSe, an Open Source Super NES emulator.
Copyright (c) 1998-2004 Charles Bilyue'.
Portions Copyright (c) 2003-2004 Daniel Horchner.
This is free software. See 'LICENSE' for details.
You must read and accept the license prior to use.
%endif
;
; Sprite render functions
;
; In all the sprite renderers...
; eax = (internal)
; ebx = (internal)
; cl = sprite counter for priority (internal)
; ch = sprite counter for set (internal)
; dl = sprite priority identifier (input)
; dh = (internal)
; esi = current sprite (internal)
; edi = (internal)
;
; OAM decoder generates table with plot data per sprite tile-line
; (X position, line-in-tile cache address, palette, X-flip, priority for
; each sprite scanline, and time/range flags for each scanline)
; 14b address, 2bit XYflip, 3bit palette, 2bit priority, 9bit X pos
; (may pack priority, palette, X-flip, and bit 8 X pos in 1b)
; 4b/sprite line
; 34 sprite lines/scanline max + count + time/range + priority + pri flag
; (34 * 4b = 136b + 8b)
; count = total sprites/tiles, and total sprites only including last per
; priority
; 239 lines * 145b = 34,416b (~33.61k)
; However, with this, other tables can be removed (OAM_*, 1,664b (1.625k))
; Plotters will be greatly simplified, with less redundant handling
;#define Profile_Recache_OAM
%define ALT_CLEAR
%define SNEeSe_ppu_sprites_asm
%include "misc.inc"
%include "clear.inc"
%include "ppu/tiles.inc"
%include "ppu/screen.inc"
%include "ppu/ppu.inc"
section .text
EXPORT_C sprites_text_start
section .data
EXPORT_C sprites_data_start
section .bss
EXPORT_C sprites_bss_start
EXTERN Ready_Line_Render,BaseDestPtr
EXTERN_C SNES_Screen8
EXTERN HVBJOY
section .data
ALIGND
palette_obj:
dd 0x8F8F8F8F, 0x9F9F9F9F, 0xAFAFAFAF, 0xBFBFBFBF
dd 0xCFCFCFCF, 0xDFDFDFDF, 0xEFEFEFEF, 0xFFFFFFFF
; Sprite offset tables moved to ScreenL.S
; abc - a = X or Y, b = s(ize) or l(imit), c = s(mall) or l(arge)
; Xss, Xls, Xsl, Xll, Yss, Yls, Ysl, Yll
Sprite_Size_Table:
db 1, -7, 2,-15, 1, -7, 2,-15 ; 8x8, 16x16
db 1, -7, 4,-31, 1, -7, 4,-31 ; 8x8, 32x32
db 1, -7, 8,-63, 1, -7, 8,-63 ; 8x8, 64x64
db 2,-15, 4,-31, 2,-15, 4,-31 ; 16x16, 32x32
db 2,-15, 8,-63, 2,-15, 8,-63 ; 16x16, 64x64
db 4,-31, 8,-63, 4,-31, 8,-63 ; 32x32, 64x64
db 2,-15, 4,-31, 4,-31, 8,-63 ; 16x32, 32x64
db 2,-15, 4,-31, 4,-31, 4,-31 ; 16x32, 32x32
section .bss
ALIGNB
;Line counts when last OBJ of specified priority was added
EXPORT_C OAM_Count_Priority,skipl 240
;OBJ counts (low byte) and OBJ line counts (high byte)
EXPORT_C OAM_Count,skipw 240
;Time/range overflow flags
EXPORT_C OAM_TimeRange,skipb 240
;'Complex' priority in-use flags
EXPORT_C OAM_Low_Before_High,skipb 240
;Priorities for 'complex' priority detection
EXPORT_C OAM_Lowest_Priority,skipb 240
;Tail entry for ring buffers
EXPORT OAM_Tail,skipb 240
;239 ring buffers of 34 OBJ line descriptors (32-bit)
EXPORT_C OAM_Lines,skipl 34*239
; AAAA AAAA AAAA AAxx YXPP CCCX XXXX XXXX
; A - OAM sprite line-in-tile address
; YXPP CCC - bits 1-7 of OAM attribute word
; X - X position
ALIGNB
EXPORT_C OAM,skipb 512+32 ; Buffer for OAM
EXPORT SpriteCount,skipl
EXPORT_C HiSprite ,skipl
EXPORT_C HiSpriteCnt1,skipl ; First set size and bit offset
EXPORT_C HiSpriteCnt2,skipl ; Second set size and bit offset
EXPORT_C OBBASE,skipl ; VRAM location of sprite tiles 00-FF
EXPORT_C OBNAME,skipl ; VRAM location of sprite tiles 100-1FF
EXPORT_C OAMAddress,skipl
EXPORT_C OAMAddress_VBL,skipl ; Restore this at VBL
EXPORT_C HiSpriteAddr,skipl ; OAM address of sprite in 512b table
EXPORT_C HiSpriteBits,skipl ; OAM address of sprite in 32b table
ALIGNB
EXPORT Sprite_Size_Current_X,skipl
EXPORT_EQU sprsize_small_x,Sprite_Size_Current_X
EXPORT_EQU sprlim_small_x,Sprite_Size_Current_X+1
EXPORT_EQU sprsize_large_x,Sprite_Size_Current_X+2
EXPORT_EQU sprlim_large_x,Sprite_Size_Current_X+3
EXPORT Sprite_Size_Current_Y,skipl
EXPORT_EQU sprsize_small_y,Sprite_Size_Current_Y
EXPORT_EQU sprlim_small_y,Sprite_Size_Current_Y+1
EXPORT_EQU sprsize_large_y,Sprite_Size_Current_Y+2
EXPORT_EQU sprlim_large_y,Sprite_Size_Current_Y+3
OBJ_vflip_fixup:skipb ; value to XOR with OBJ current line for v-flip
; used for rectangular (undocumented) OBJ
EXPORT Redo_OAM,skipb
EXPORT SPRLatch ,skipb ; Sprite Priority Rotation latch flag
EXPORT_C OBSEL ,skipb ; sssnnxbb sss=sprite size,nn=upper 4k address,bb=offset
EXPORT OAMHigh ,skipb
EXPORT OAM_Write_Low,skipb
EXPORT Pixel_Allocation_Tag,skipb
section .text
%define PS_Local_Bytes 16
%define PS_Lines esp+12
%define PS_BaseDestPtr esp+8
%define PS_Current_Line esp+4
%define PS_Priority esp
ALIGNC
EXPORT Plot_Sprites
dec ebx
push ebp
and edx,byte 0x30
push edi
push ebx
push edx
%ifdef NO_EARLY_CLEAR
mov ebx,[PS_Current_Line]
mov ebp,1
inc ebx
call Clear_Lines
%endif
mov ebx,[PS_Current_Line]
mov edi,[PS_BaseDestPtr]
mov edx,[PS_Priority]
jmp .first_line
ALIGNC
.next_line:
%ifdef NO_EARLY_CLEAR
mov ebx,[PS_Current_Line]
mov ebp,1
add ebx,byte 2
call Clear_Lines
%endif
mov ebx,[PS_Current_Line]
mov edi,[PS_BaseDestPtr]
mov edx,[PS_Priority]
inc ebx
add edi,GfxBufferLinePitch
mov [PS_Current_Line],ebx
mov [PS_BaseDestPtr],edi
.first_line:
and edx,byte 0x30
shr edx,4
mov cl,[C_LABEL(OAM_Count_Priority)+ebx*4+edx]
shl edx,4
test cl,cl
jz .check_line_count
mov cl,[C_LABEL(OAM_Count)+ebx*2+1]
mov al,[C_LABEL(OAM_Low_Before_High)+ebx]
test al,al
jnz C_LABEL(Plot_Sprites_Low_Before_High).first_line
xor eax,eax
mov al,cl
cmp cl,34
jb .zero_head
mov al,[OAM_Tail+ebx]
test al,al
jnz .zero_head
mov al,34
.zero_head:
shl ebx,4
mov ch,cl
mov esi,[PS_Current_Line]
sub ch,al
shl eax,2
add ebx,esi
sub cl,ch
lea ebx,[C_LABEL(OAM_Lines)+eax+ebx*8-4]
.next_tile:
mov dh,0x30
mov eax,[ebx]
and dh,ah
sub ebx,byte 4
cmp dh,dl ; Check priority
jne .check_tile_count
mov esi,eax
mov edi,[PS_BaseDestPtr]
shl esi,23
add edi,[C_LABEL(SNES_Screen8)]
sar esi,23
add edi,esi ; X-adjust
mov esi,eax
mov dl,ah
shr esi,15
and edx,byte 7*2 ; Get palette
and esi,byte ~7 ; Tile line # address
mov ebp,[palette_obj+edx*2]
add esi,C_LABEL(TileCache4)
add ah,ah
js .flip_x
Plot_8_Paletted_Lines_noflip 0,esi,0
mov dl,[PS_Priority]
dec cl
jnz .next_tile
jmp .check_count
ALIGNC
.flip_x:
Plot_8_Paletted_Lines_Xflip 0,esi,0
mov dl,[PS_Priority]
.check_tile_count:
dec cl
jnz .next_tile
.check_count:
add ebx,34*4
add cl,ch
mov ch,0
jnz .next_tile
.check_line_count:
dec dword [PS_Lines]
jnz .next_line
.done:
add esp,byte PS_Local_Bytes
ret
ALIGNC
EXPORT_C Plot_Sprites_Low_Before_High
.first_line:
xor eax,eax
mov al,[OAM_Tail+ebx]
shl ebx,4
mov ch,al
shl eax,2
sub cl,ch
add ebx,[PS_Current_Line]
lea ebx,[C_LABEL(OAM_Lines)+eax+ebx*8]
.next_tile:
mov dh,0x30
mov eax,[ebx]
and dh,ah
add ebx,byte 4
push ebx
mov ebx,eax
shl ebx,23
push ecx
mov edi,[PS_BaseDestPtr+8]
sar ebx,23
add edi,[C_LABEL(SNES_Screen8)]
mov esi,eax
cmp dh,dl ; Check priority
jnz .bad_priority_plot
mov dh,ah
shr esi,15
add edi,ebx ; X-adjust
shl dh,3 ; Palette
and esi,byte ~7 ; Tile line # address
or dh,0x8F
add esi,C_LABEL(TileCache4)
add ebx,DisplayZ+8
add ah,ah
mov ah,[Pixel_Allocation_Tag]
js .flip_x
mov al,[esi]
and al,dh
jz .no_pixel_0
mov ch,[ebx]
test ch,ah
jnz .no_pixel_0
or ch,ah
mov [edi],al
mov [ebx],ch
.no_pixel_0:
mov al,[esi + 4]
and al,dh
jz .no_pixel_4
mov ch,[ebx + 4]
test ch,ah
jnz .no_pixel_4
or ch,ah
mov [edi + 4],al
mov [ebx + 4],ch
.no_pixel_4:
mov al,[esi + 1]
and al,dh
jz .no_pixel_1
mov ch,[ebx + 1]
test ch,ah
jnz .no_pixel_1
or ch,ah
mov [edi + 1],al
mov [ebx + 1],ch
.no_pixel_1:
mov al,[esi + 5]
and al,dh
jz .no_pixel_5
mov ch,[ebx + 5]
test ch,ah
jnz .no_pixel_5
or ch,ah
mov [edi + 5],al
mov [ebx + 5],ch
.no_pixel_5:
mov al,[esi + 2]
and al,dh
jz .no_pixel_2
mov ch,[ebx + 2]
test ch,ah
jnz .no_pixel_2
or ch,ah
mov [edi + 2],al
mov [ebx + 2],ch
.no_pixel_2:
mov al,[esi + 6]
and al,dh
jz .no_pixel_6
mov ch,[ebx + 6]
test ch,ah
jnz .no_pixel_6
or ch,ah
mov [edi + 6],al
mov [ebx + 6],ch
.no_pixel_6:
mov al,[esi + 3]
and al,dh
jz .no_pixel_3
mov ch,[ebx + 3]
test ch,ah
jnz .no_pixel_3
or ch,ah
mov [edi + 3],al
mov [ebx + 3],ch
.no_pixel_3:
mov al,[esi + 7]
and al,dh
jz .no_pixel_7
mov ch,[ebx + 7]
test ch,ah
jnz .no_pixel_7
or ch,ah
mov [edi + 7],al
mov [ebx + 7],ch
.no_pixel_7:
pop ecx
pop ebx
dec cl
jnz .next_tile
jmp .check_tag
ALIGNC
.flip_x:
mov al,[esi + 7]
and al,dh
jz .no_pixel_0_x
mov ch,[ebx]
test ch,ah
jnz .no_pixel_0_x
or ch,ah
mov [edi],al
mov [ebx],ch
.no_pixel_0_x:
mov al,[esi + 3]
and al,dh
jz .no_pixel_4_x
mov ch,[ebx + 4]
test ch,ah
jnz .no_pixel_4_x
or ch,ah
mov [edi + 4],al
mov [ebx + 4],ch
.no_pixel_4_x:
mov al,[esi + 6]
and al,dh
jz .no_pixel_1_x
mov ch,[ebx + 1]
test ch,ah
jnz .no_pixel_1_x
or ch,ah
mov [edi + 1],al
mov [ebx + 1],ch
.no_pixel_1_x:
mov al,[esi + 2]
and al,dh
jz .no_pixel_5_x
mov ch,[ebx + 5]
test ch,ah
jnz .no_pixel_5_x
or ch,ah
mov [edi + 5],al
mov [ebx + 5],ch
.no_pixel_5_x:
mov al,[esi + 5]
and al,dh
jz .no_pixel_2_x
mov ch,[ebx + 2]
test ch,ah
jnz .no_pixel_2_x
or ch,ah
mov [edi + 2],al
mov [ebx + 2],ch
.no_pixel_2_x:
mov al,[esi + 1]
and al,dh
jz .no_pixel_6_x
mov ch,[ebx + 6]
test ch,ah
jnz .no_pixel_6_x
or ch,ah
mov [edi + 6],al
mov [ebx + 6],ch
.no_pixel_6_x:
mov al,[esi + 4]
and al,dh
jz .no_pixel_3_x
mov ch,[ebx + 3]
test ch,ah
jnz .no_pixel_3_x
or ch,ah
mov [edi + 3],al
mov [ebx + 3],ch
.no_pixel_3_x:
mov al,[esi]
and al,dh
jz .no_pixel_7_x
mov ch,[ebx + 7]
test ch,ah
jnz .no_pixel_7_x
or ch,ah
mov [edi + 7],al
mov [ebx + 7],ch
.no_pixel_7_x:
.check_tile_count:
pop ecx
pop ebx
dec cl
jnz .next_tile
.check_tag:
sub ebx,34*4
add cl,ch
mov ch,0
jnz .next_tile
rol byte [Pixel_Allocation_Tag],1
jnc .check_line_count
; Clear pixel allocation tag table
mov edi,DisplayZ+8
xor eax,eax
mov ecx,256/32
call Do_Clear
.check_line_count:
dec dword [PS_Lines]
jnz Plot_Sprites.next_line
.done:
add esp,byte PS_Local_Bytes
ret
ALIGNC
.bad_priority_plot:
mov dh,ah
shr esi,15
add edi,ebx ; X-adjust
shl dh,3 ; Palette
and esi,byte ~7 ; Tile line # address
or dh,0x8F
add esi,C_LABEL(TileCache4)
add ebx,DisplayZ+8
add ah,ah
mov ah,[Pixel_Allocation_Tag]
js .bad_priority_flip_x
mov al,[esi]
and al,dh
jz .no_pixel_bp_0
mov ch,[ebx]
or ch,ah
mov [ebx],ch
.no_pixel_bp_0:
mov al,[esi + 4]
and al,dh
jz .no_pixel_bp_4
mov ch,[ebx + 4]
or ch,ah
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -