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

📄 sprites.asm

📁 NES game Emulator in Linux.c and asm codes.
💻 ASM
📖 第 1 页 / 共 3 页
字号:
%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 + -