www.pudn.com > sn068s.zip > BG16O.NI


%define RO16x16_Local_Bytes 60 
%define RO16x16_Plotter_LeftEdge esp+56 
%define RO16x16_Plotter esp+52 
%define RO16x16_BG_Table esp+48 
%define RO16x16_Current_Line esp+44 
%define RO16x16_BaseDestPtr esp+40 
%define RO16x16_Lines esp+36 
 
; Same as LineAddress(Y), additional vars for offset change code 
%define RO16x16_LineAddressOffset  esp+32 
%define RO16x16_LineAddressOffsetY esp+28 
 
%define RO16x16_FirstTile esp+24 
 
; Base tile map address for offset change code 
%define RO16x16_MapAddress_Base    esp+20 
 
; Scroll-adjusted tile map address for offset 
;  change code when tile offset not changed 
%define RO16x16_MapAddress_Current esp+16 
 
; Current render line # for offset change layers 
; Used for vertical mosaic effect 
%define RO16x16_Current_Line_Offset esp+12 
 
%define RO16x16_TMapAddress esp+8 
%define RO16x16_BMapAddress esp+4 
%define RO16x16_RMapDifference esp 
 
; -Tile on left edge of screen not affected by V-offset change 
; -Offset change map is scrollable - always 16x16 
 
%macro Render_Offset_16x16 1 
ALIGNC 
EXPORT_C Render_Offset_16x16_C%1 
%ifndef NO_OFFSET_CHANGE 
%ifndef NO_OFFSET_CHANGE_DISABLE 
 cmp byte [_Offset_Change_Disable],0    ; Hack to disable offset change 
 jnz near _Render_16x16_C%1 
%endif  ; !NO_OFFSET_CHANGE_DISABLE 
%else   ; NO_OFFSET_CHANGE 
 jmp _Render_16x16_C%1 
%endif  ; NO_OFFSET_CHANGE 
 
%ifdef OFFSET_CHANGE_ELIMINATION 
%if %1 == 4     ;mode 2: 4-plane tiles, split offset table 
 mov cl,[OffsetChangeDetect3] 
 test cl,[OC_Flag+edx] 
 jz near _Render_16x16_C%1 
%else           ;mode 4: 2- and 8-plane tiles, unified offset table 
%if %1 == 2 
 mov ecx,[M0_Color+edx] 
 mov [Palette_Base],ecx 
%endif 
 mov cl,[OffsetChangeDetect1] 
 test cl,[OC_Flag+edx] 
 jz near _Render_16x16_C%1 
%endif 
%endif 
 
%ifndef NO_NP_RENDER 
 mov ecx,_Plot_Lines_Unclipped_NP_Offset_16x16_C%1 
 test al,al 
 mov eax,_Plot_Lines_Unclipped_NP_Offset_16x16_C%1.LeftEdge 
 jnz .have_plotter 
%endif 
 
%ifndef NO_PLOTTER_PER_PRIORITY 
 cmp byte [Tile_priority_bit],0 
 mov ecx,_Plot_Lines_Unclipped_H_Offset_16x16_C%1 
 mov eax,_Plot_Lines_Unclipped_H_Offset_16x16_C%1.LeftEdge 
 jz .have_plotter 
 mov ecx,_Plot_Lines_Unclipped_L_Offset_16x16_C%1 
 mov eax,_Plot_Lines_Unclipped_L_Offset_16x16_C%1.LeftEdge 
%else 
 mov ecx,_Plot_Lines_Unclipped_V_Offset_16x16_C%1 
 mov eax,_Plot_Lines_Unclipped_V_Offset_16x16_C%1.LeftEdge 
%endif 
.have_plotter: 
 jmp Render_Offset_16x16_Base 
%endmacro 
 
Render_Offset_16x16 2 
Render_Offset_16x16 4 
Render_Offset_16x16 8 
 
ALIGNC 
Render_Offset_16x16_Base: 
 push eax 
 push ecx 
 push edx ;BG_Table 
 push ebx ;Current_Line 
 push edi ;BaseDestPtr 
 push ebp ;Lines 
 sub esp,byte RO16x16_Local_Bytes-24 
 
.next_line: 
 mov edx,[RO16x16_BG_Table] 
 
 mov eax,[RO16x16_Current_Line] 
 call Sort_Screen_Height_Mosaic 
 
 mov eax,[RO16x16_Current_Line] 
 Get_Current_Line 
 mov [RO16x16_Current_Line_Offset],eax 
 SORT_TILES_16_TALL [RO16x16_MapAddress_Base] 
 ; This sets up the screen vert 2! 
 
 mov edi,[SetAddress+edx] 
 mov [TilesetAddress],edi 
 
 ; Corrupts eax,ecx,ebp 
 mov eax,[TLMapAddress+edx] 
 mov ecx,[RO16x16_Current_Line_Offset] 
 mov edi,[BLMapAddress+edx] 
 mov ebp,[VScroll+edx] 
 mov [RO16x16_TMapAddress],eax 
 add ecx,ebp 
 mov [RO16x16_BMapAddress],edi 
 mov ebp,[RO16x16_MapAddress_Base] 
 
 and ch,2 
;global Tile_Height 
;Tile_Height equ $-1    ; 1 = 8x8, 16x8, 2 = 16x16 
 jz .current_line_in_screen_map_top 
 mov eax,edi 
.current_line_in_screen_map_top: 
 add eax,ebp 
 
 mov ebp,[HScroll+edx] 
 mov [RO16x16_MapAddress_Current],eax 
 shr ebp,3 
 xor eax,eax 
 mov cl,[BGSC+edx] 
 mov [RO16x16_FirstTile],ebp   ;FirstTile = (HScroll / 8) * 2 
 
 and cl,1   ;BGSC & 1 
 jz .no_wide_screen_map 
 mov eax,32*32*2 
.no_wide_screen_map: 
 
 ; cl contains bit for determining planes to affect 
 mov cl,[OC_Flag+edx] 
 mov [RO16x16_RMapDifference],eax 
 
;if less background tiles than BG3 tiles + 1, use background tile count 
 mov al,[TileCount1BG3] 
 mov ch,[TileCount1+edx] 
 inc al 
 add ch,[TileCount2+edx] 
 cmp ch,al 
 jb .count_okay 
 
 mov ch,al 
 
.count_okay: 
 
 mov ebx,[FirstPixel+edx] 
 mov edi,[RO16x16_BaseDestPtr] 
 mov eax,[_SNES_Screen8] 
 and ebx,byte 7 
 add edi,eax 
 
 ; BG3 scroll affects offset-change map address 
 mov eax,[VLMapAddressBG3] 
 sub edi,ebx 
 mov ebx,[OffsetChangeMap_VOffset]  ; BG3VOFS adjusted 
 add eax,ebx 
 
 xor ebx,ebx 
 ; eax = linear offset map current tile address 
 ; ebx = tile address offset from first tile on line 
 ; ch = # tiles 
 call dword [RO16x16_Plotter_LeftEdge] 
 
 mov edx,[RO16x16_BG_Table] 
 mov al,[TileCount1BG3] 
 mov ch,[TileCount1+edx] 
 inc al 
 add ch,[TileCount2+edx] 
 sub ch,al 
 jbe .no_second_run 
 
 ; BG3 scroll affects offset-change map address 
 mov esi,[VRMapAddressBG3] 
 add esi,[OffsetChangeMap_VOffset]  ; BG3VOFS adjusted 
 
 call dword [RO16x16_Plotter] 
 
.no_second_run: 
 
%ifndef LAYERS_PER_LINE 
 mov edi,[RO16x16_BaseDestPtr] 
 inc dword [RO16x16_Current_Line] 
 add edi,GfxBufferLinePitch 
 dec dword [RO16x16_Lines] 
 mov [RO16x16_BaseDestPtr],edi ; Point screen to next line 
 jnz near .next_line 
%endif 
 
 mov edx,[RO16x16_BG_Table] 
 mov al,[Tile_Priority_Used] 
 mov [Priority_Used+edx],al 
 mov ah,[Tile_Priority_Unused] 
 mov [Priority_Unused+edx],ah 
 
 add esp,byte RO16x16_Local_Bytes 
 ret 
 
%define RO16x16_Inner 4 
 
;%1 = label, %2 = priority - 0 = none, 1 = low, 2 = high 
%macro Plot_Lines_Unclipped_Offset_16x16_C4 2 
%if %2 > 0 
%%return: 
 ret 
 
ALIGNC 
%1_check: 
 pop ebx 
 pop esi 
 pop ecx 
 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Unused],ch 
%endif 
 add edi,byte 8 
 dec ch 
 jz %%return 
%endif 
 
EXPORT_C %1     ; Define label, entry point 
.next_tile: 
 mov eax,esi 
 push ecx 
 add eax,byte 2 
 mov dh,[1+esi]     ; Horizontal offset change map 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 mov eax,[OffsetChangeVMap_VOffset] 
 test dh,cl         ; H-offset enabled? 
 jz .have_h_offset 
 mov dl,[esi] 
 mov ebp,edx 
 shr ebp,3 
.have_h_offset: 
 
 mov dh,[1+esi+eax] ; Vertical offset change map 
 test dh,cl         ; V-offset enabled? 
 jz .No_VChange 
 mov dl,[esi+eax] 
 mov eax,[RO16x16_Current_Line_Offset+RO16x16_Inner+8] 
 add eax,edx 
 
.calc_v_offset: 
 and ah,2 
 mov esi,[RO16x16_TMapAddress+RO16x16_Inner+8] 
 jz .line_in_screen_map_top 
 mov esi,[RO16x16_BMapAddress+RO16x16_Inner+8] 
.line_in_screen_map_top: 
 
 ; al contains real Y offset for next tile 
 shl eax,2          ; Get screen offset 
 mov ecx,0x1F0*4    ; Current line + V scroll * 32words 
 and ecx,eax 
 and eax,byte 0x0F*4    ; Offset into table of line offsets 
 mov edx,16*8+7 
 mov eax,[Tile_Offset_Table_16_8+eax] 
 sub edx,eax 
 add esi,ecx 
 jmp short .have_v_offset 
 
.LeftEdge: 
 push ecx 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 
.No_VChange: 
 mov eax,[LineAddress] 
 mov esi,[RO16x16_MapAddress_Current+RO16x16_Inner+8] 
 mov edx,[LineAddressY] 
 
.have_v_offset: 
 add ebp,ebx 
 inc ebx            ; Update X offset 
 mov [RO16x16_LineAddressOffset+RO16x16_Inner+8],eax 
 push ebx 
 mov ebx,ebp 
 and ebp,byte 63    ; X offset wrap 
 and ebx,byte 64 
 mov [RO16x16_LineAddressOffsetY+RO16x16_Inner+12],edx 
 mov ebx,[RO16x16_RMapDifference+RO16x16_Inner+12] 
 jz  .tile_in_screen_map_left 
 add esi,ebx 
.tile_in_screen_map_left: 
 mov ebx,ebp 
 and ebp,byte ~1 
 
 mov al,[esi+ebp+1] ; Combine X and Y offsets into tile map 
 Check_Tile_Priority %2, near %1_check 
 
 mov si,[esi+ebp]   ; Get tile # 
 mov ebp,[RO16x16_LineAddressOffsetY+RO16x16_Inner+12] 
 test al,al         ; Check Y flip 
 js .flip_y 
 mov ebp,[RO16x16_LineAddressOffset+RO16x16_Inner+12] 
 
.flip_y: 
 shl esi,3 
 mov dl,al 
 add esi,ebp 
 and edx,byte 7*4   ; Get palette 
 and ebx,byte 1 
 add al,al      ; Get X flip (now in MSB) 
 mov ebp,[palette_4bpl+edx] 
 mov edx,[TilesetAddress] 
 js near .xflip 
 
 lea esi,[esi+ebx*8] 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF * 2 / 8 ; Clip to VRAM 
 
 Plot_8_Paletted_Lines_noflip 1,_TileCache4+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
 
ALIGNC 
.xflip: 
 shl ebx,3 
 add esi,byte 8 
 sub esi,ebx 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF * 2 / 8 ; Clip to VRAM 
 
 Plot_8_Paletted_Lines_Xflip 1,_TileCache4+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
%endmacro 
 
;%1 = label, %2 = priority - 0 = none, 1 = low, 2 = high 
%macro Plot_Lines_Unclipped_Offset_16x16_C2 2 
%if %2 > 0 
%%return: 
 ret 
 
ALIGNC 
%1_check: 
 pop ebx 
 pop esi 
 pop ecx 
 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Unused],ch 
%endif 
 add edi,byte 8 
 dec ch 
 jz %%return 
%endif 
 
EXPORT_C %1     ; Define label, entry point 
.next_tile: 
 mov eax,esi 
 push ecx 
 add eax,byte 2 
 mov dh,[1+esi]     ; Offset change map 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 mov eax,[RO16x16_Current_Line_Offset+RO16x16_Inner+8] 
 test dh,cl         ; Offset enabled? 
 jz .No_VChange 
 
 test dh,dh         ; vertical offset? 
 jnz .calc_v_offset 
 
 mov dl,[esi] 
 mov ebp,edx 
 shr ebp,3 
 jmp .No_VChange 
 
.calc_v_offset: 
 mov dl,[esi] 
 add eax,edx 
 
 and ah,2 
 mov esi,[RO16x16_TMapAddress+RO16x16_Inner+8] 
 jz  .line_in_screen_map_top 
 mov esi,[RO16x16_BMapAddress+RO16x16_Inner+8] 
.line_in_screen_map_top: 
 
 ; al contains real Y offset for next tile 
 shl eax,2          ; Get screen offset 
 mov ecx,0x1F0*4    ; Current line + V scroll * 32words 
 and ecx,eax 
 and eax,byte 0x0F*4    ; Offset into table of line offsets 
 mov edx,16*8+7 
 mov eax,[Tile_Offset_Table_16_8+eax] 
 sub edx,eax 
 add esi,ecx 
 jmp short .have_v_offset 
 
.LeftEdge: 
 push ecx 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 
.No_VChange: 
 mov eax,[LineAddress] 
 mov esi,[RO16x16_MapAddress_Current+RO16x16_Inner+8] 
 mov edx,[LineAddressY] 
 
.have_v_offset: 
 add ebp,ebx 
 inc ebx            ; Update X offset 
 mov [RO16x16_LineAddressOffset+RO16x16_Inner+8],eax 
 push ebx 
 mov ebx,ebp 
 and ebp,byte 63    ; X offset wrap 
 and ebx,byte 64 
 mov [RO16x16_LineAddressOffsetY+RO16x16_Inner+12],edx 
 mov ebx,[RO16x16_RMapDifference+RO16x16_Inner+12] 
 jz  .tile_in_screen_map_left 
 add esi,ebx 
.tile_in_screen_map_left: 
 mov ebx,ebp 
 and ebp,byte ~1 
 
 mov al,[esi+ebp+1] ; Combine X and Y offsets into tile map 
 Check_Tile_Priority %2, near %1_check 
 
 mov si,[esi+ebp]   ; Get tile # 
 mov ebp,[RO16x16_LineAddressOffsetY+RO16x16_Inner+12] 
 test al,al         ; Check Y flip 
 js .flip_y 
 mov ebp,[RO16x16_LineAddressOffset+RO16x16_Inner+12] 
 
.flip_y: 
 shl esi,3 
 mov dl,al 
 add esi,ebp 
 and edx,byte 7*4   ; Get palette 
 and ebx,byte 1 
 add al,al      ; Get X flip (now in MSB) 
 mov ebp,[palette_2bpl+edx] 
 mov edx,[TilesetAddress] 
 js near .xflip 
 
 lea esi,[esi+ebx*8] 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF * 4 / 8 ; Clip to VRAM 
 
 Plot_8_Paletted_Lines_noflip 1,_TileCache2+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
 
ALIGNC 
.xflip: 
 shl ebx,3 
 add esi,byte 8 
 sub esi,ebx 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF * 4 / 8 ; Clip to VRAM 
 
 Plot_8_Paletted_Lines_Xflip 1,_TileCache2+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
%endmacro 
 
;%1 = label, %2 = priority - 0 = none, 1 = low, 2 = high 
%macro Plot_Lines_Unclipped_Offset_16x16_C8 2 
%if %2 > 0 
%%return: 
 ret 
 
ALIGNC 
%1_check: 
 pop ebx 
 pop esi 
 pop ecx 
 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Unused],ch 
%endif 
 add edi,byte 8 
 dec ch 
 jz %%return 
%endif 
 
EXPORT_C %1     ; Define label, entry point 
.next_tile: 
 mov eax,esi 
 push ecx 
 add eax,byte 2 
 mov dh,[1+esi]     ; Offset change map 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 mov eax,[RO16x16_Current_Line_Offset+RO16x16_Inner+8] 
 test dh,cl         ; Offset enabled? 
 jz .No_VChange 
 
 test dh,dh         ; vertical offset? 
 jnz .calc_v_offset 
 
 mov dl,[esi] 
 mov ebp,edx 
 shr ebp,3 
 jmp .No_VChange 
 
.calc_v_offset: 
 mov dl,[esi] 
 add eax,edx 
 
 and ah,2 
 mov esi,[RO16x16_TMapAddress+RO16x16_Inner+8] 
 jz  .line_in_screen_map_top 
 mov esi,[RO16x16_BMapAddress+RO16x16_Inner+8] 
.line_in_screen_map_top: 
 
 ; al contains real Y offset for next tile 
 shl eax,2          ; Get screen offset 
 mov ecx,0x1F0*4    ; Current line + V scroll * 32words 
 and ecx,eax 
 and eax,byte 0x0F*4    ; Offset into table of line offsets 
 mov edx,16*8+7 
 mov eax,[Tile_Offset_Table_16_8+eax] 
 sub edx,eax 
 add esi,ecx 
 jmp short .have_v_offset 
 
.LeftEdge: 
 push ecx 
 push eax 
 
 mov ebp,[RO16x16_FirstTile+RO16x16_Inner+8] 
 
.No_VChange: 
 mov eax,[LineAddress] 
 mov esi,[RO16x16_MapAddress_Current+RO16x16_Inner+8] 
 mov edx,[LineAddressY] 
 
.have_v_offset: 
 add ebp,ebx 
 inc ebx            ; Update X offset 
 mov [RO16x16_LineAddressOffset+RO16x16_Inner+8],eax 
 push ebx 
 mov ebx,ebp 
 and ebp,byte 63    ; X offset wrap 
 and ebx,byte 64 
 mov [RO16x16_LineAddressOffsetY+RO16x16_Inner+12],edx 
 mov ebx,[RO16x16_RMapDifference+RO16x16_Inner+12] 
 jz  .tile_in_screen_map_left 
 add esi,ebx 
.tile_in_screen_map_left: 
 mov ebx,ebp 
 and ebp,byte ~1 
 
 mov al,[esi+ebp+1] ; Combine X and Y offsets into tile map 
 Check_Tile_Priority %2, near %1_check 
 
 mov si,[esi+ebp]   ; Get tile # 
 mov ebp,[RO16x16_LineAddressOffsetY+RO16x16_Inner+12] 
 test al,al         ; Check Y flip 
 js .flip_y 
 mov ebp,[RO16x16_LineAddressOffset+RO16x16_Inner+12] 
 
.flip_y: 
 shl esi,3 
 add esi,ebp 
 and ebx,byte 1 
 add al,al      ; Get X flip (now in MSB) 
 mov edx,[TilesetAddress] 
 js near .xflip 
 
 lea esi,[esi+ebx*8] 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF / 8 ; Clip to VRAM 
 
 Plot_8_Lines_noflip 1,_TileCache8+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
 
ALIGNC 
.xflip: 
 shl ebx,3 
 add esi,byte 8 
 sub esi,ebx 
 and esi,0x3FF * 8 + 7  ; Clip to tileset 
 add esi,edx 
 and esi,0xFFFF / 8 ; Clip to VRAM 
 
 Plot_8_Lines_Xflip 1,_TileCache8+esi*8,0 
 
 pop ebx 
 pop esi 
 pop ecx 
 
 add edi,byte 8 
%if %2 == 1 || %2 == 3 
 mov [Tile_Priority_Used],ch 
%endif 
 dec ch 
 jnz near .next_tile 
 
 ret 
%endmacro 
 
%ifndef NO_NP_RENDER 
 Plot_Lines_Unclipped_Offset_16x16_C4 Plot_Lines_Unclipped_NP_Offset_16x16_C4,0 
%endif 
%ifndef NO_PLOTTER_PER_PRIORITY 
 Plot_Lines_Unclipped_Offset_16x16_C4 Plot_Lines_Unclipped_L_Offset_16x16_C4,1 
 Plot_Lines_Unclipped_Offset_16x16_C4 Plot_Lines_Unclipped_H_Offset_16x16_C4,2 
%else 
 Plot_Lines_Unclipped_Offset_16x16_C4 Plot_Lines_Unclipped_V_Offset_16x16_C4,3 
%endif 
 
%ifndef NO_NP_RENDER 
 Plot_Lines_Unclipped_Offset_16x16_C2 Plot_Lines_Unclipped_NP_Offset_16x16_C2,0 
%endif 
%ifndef NO_PLOTTER_PER_PRIORITY 
 Plot_Lines_Unclipped_Offset_16x16_C2 Plot_Lines_Unclipped_L_Offset_16x16_C2,1 
 Plot_Lines_Unclipped_Offset_16x16_C2 Plot_Lines_Unclipped_H_Offset_16x16_C2,2 
%else 
 Plot_Lines_Unclipped_Offset_16x16_C2 Plot_Lines_Unclipped_V_Offset_16x16_C2,3 
%endif 
 
%ifndef NO_NP_RENDER 
 Plot_Lines_Unclipped_Offset_16x16_C8 Plot_Lines_Unclipped_NP_Offset_16x16_C8,0 
%endif 
%ifndef NO_PLOTTER_PER_PRIORITY 
 Plot_Lines_Unclipped_Offset_16x16_C8 Plot_Lines_Unclipped_L_Offset_16x16_C8,1 
 Plot_Lines_Unclipped_Offset_16x16_C8 Plot_Lines_Unclipped_H_Offset_16x16_C8,2 
%else 
 Plot_Lines_Unclipped_Offset_16x16_C8 Plot_Lines_Unclipped_V_Offset_16x16_C8,3 
%endif