www.pudn.com > sn068s.zip > BG8O.NI
%define RO8x8_Local_Bytes 60 %define RO8x8_Plotter_LeftEdge esp+56 %define RO8x8_Plotter esp+52 %define RO8x8_BG_Table esp+48 %define RO8x8_Current_Line esp+44 %define RO8x8_BaseDestPtr esp+40 %define RO8x8_Lines esp+36 ; Same as LineAddress(Y), additional vars for offset change code %define RO8x8_LineAddressOffset esp+32 %define RO8x8_LineAddressOffsetY esp+28 %define RO8x8_FirstTile esp+24 ; Base tile map address for offset change code %define RO8x8_MapAddress_Base esp+20 ; Scroll-adjusted tile map address for offset ; change code when tile offset not changed %define RO8x8_MapAddress_Current esp+16 ; Current render line # for offset change layers ; Used for vertical mosaic effect %define RO8x8_Current_Line_Offset esp+12 %define RO8x8_TMapAddress esp+8 %define RO8x8_BMapAddress esp+4 %define RO8x8_RMapDifference esp ; -Tile on left edge of screen not affected by V-offset change ; -Offset change map is scrollable - always 8x8 %macro Render_Offset_8x8 1 ALIGNC EXPORT_C Render_Offset_8x8_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_8x8_C%1 %endif ; !NO_OFFSET_CHANGE_DISABLE %else ; NO_OFFSET_CHANGE jmp _Render_8x8_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_8x8_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_8x8_C%1 %endif %endif %ifndef NO_NP_RENDER mov ecx,_Plot_Lines_Unclipped_NP_Offset_8x8_C%1 test al,al mov eax,_Plot_Lines_Unclipped_NP_Offset_8x8_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_8x8_C%1 mov eax,_Plot_Lines_Unclipped_H_Offset_8x8_C%1.LeftEdge jz .have_plotter mov ecx,_Plot_Lines_Unclipped_L_Offset_8x8_C%1 mov eax,_Plot_Lines_Unclipped_L_Offset_8x8_C%1.LeftEdge %else mov ecx,_Plot_Lines_Unclipped_V_Offset_8x8_C%1 mov eax,_Plot_Lines_Unclipped_V_Offset_8x8_C%1.LeftEdge %endif .have_plotter: jmp Render_Offset_8x8_Base %endmacro Render_Offset_8x8 2 Render_Offset_8x8 4 Render_Offset_8x8 8 ALIGNC Render_Offset_8x8_Base: push eax push ecx push edx ;BG_Table push ebx ;Current_Line push edi ;BaseDestPtr push ebp ;Lines sub esp,byte RO8x8_Local_Bytes-24 .next_line: mov edx,[RO8x8_BG_Table] mov eax,[RO8x8_Current_Line] call Sort_Screen_Height_Mosaic mov eax,[RO8x8_Current_Line] Get_Current_Line mov [RO8x8_Current_Line_Offset],eax SORT_TILES_8_TALL [RO8x8_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,[RO8x8_Current_Line_Offset] mov edi,[BLMapAddress+edx] mov ebp,[VScroll+edx] mov [RO8x8_TMapAddress],eax add ecx,ebp mov [RO8x8_BMapAddress],edi mov ebp,[RO8x8_MapAddress_Base] and ch,1 ;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 [RO8x8_MapAddress_Current],eax shr ebp,3 xor eax,eax add ebp,ebp mov cl,[BGSC+edx] mov [RO8x8_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 [RO8x8_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 eax,[_SNES_Screen8] mov edi,[RO8x8_BaseDestPtr] mov ebx,[FirstPixel+edx] 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 [RO8x8_Plotter_LeftEdge] mov edx,[RO8x8_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 [RO8x8_Plotter] .no_second_run: %ifndef LAYERS_PER_LINE mov edi,[RO8x8_BaseDestPtr] inc dword [RO8x8_Current_Line] add edi,GfxBufferLinePitch dec dword [RO8x8_Lines] mov [RO8x8_BaseDestPtr],edi ; Point screen to next line jnz near .next_line %endif mov edx,[RO8x8_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 RO8x8_Local_Bytes ret %define RO8x8_Inner 4 ;%1 = label, %2 = priority - 0 = none, 1 = low, 2 = high %macro Plot_Lines_Unclipped_Offset_8x8_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,[RO8x8_FirstTile+RO8x8_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 add ebp,ebp .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,[RO8x8_Current_Line_Offset+RO8x8_Inner+8] add eax,edx .calc_v_offset: and ah,1 mov esi,[RO8x8_TMapAddress+RO8x8_Inner+8] jz .line_in_screen_map_top mov esi,[RO8x8_BMapAddress+RO8x8_Inner+8] .line_in_screen_map_top: ; al contains real Y offset for next tile mov ecx,0xF8 mov edx,7 and ecx,eax and eax,byte 7 sub edx,eax lea esi,[esi+ecx*8] ; Get screen offset jmp short .have_v_offset .LeftEdge: push ecx push eax mov ebp,[RO8x8_FirstTile+RO8x8_Inner+8] .No_VChange: mov eax,[LineAddress] mov esi,[RO8x8_MapAddress_Current+RO8x8_Inner+8] mov edx,[LineAddressY] .have_v_offset: add ebp,ebx add ebx,byte 2 ; Update X offset mov [RO8x8_LineAddressOffset+RO8x8_Inner+8],eax push ebx mov ebx,ebp and ebp,byte 31*2 ; X offset wrap mov [RO8x8_LineAddressOffsetY+RO8x8_Inner+12],edx add esi,ebp ; Combine X and Y offsets into tile map and ebx,byte 32*2 mov ebx,[RO8x8_RMapDifference+RO8x8_Inner+12] jz .tile_in_screen_map_left add esi,ebx .tile_in_screen_map_left: mov al,[esi+1] Check_Tile_Priority %2, near %1_check mov ebp,[RO8x8_LineAddressOffsetY+RO8x8_Inner+12] test al,al ; Check Y flip mov si,[esi] ; Get tile # js .flip_y mov ebp,[RO8x8_LineAddressOffset+RO8x8_Inner+12] .flip_y: shl esi,3 mov dl,al add esi,ebp mov ebp,[TilesetAddress] and esi,0x3FF * 8 + 7 ; Clip to tileset and edx,byte 7*4 ; Get palette add esi,ebp and esi,0xFFFF * 2 / 8 ; Clip to VRAM mov ebp,[palette_4bpl+edx] add al,al ; Get X flip (now in MSB) js near .xflip 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: 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_8x8_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,[RO8x8_FirstTile+RO8x8_Inner+8] mov eax,[RO8x8_Current_Line_Offset+RO8x8_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 add ebp,ebp jmp .No_VChange .calc_v_offset: mov dl,[esi] add eax,edx and ah,1 mov esi,[RO8x8_TMapAddress+RO8x8_Inner+8] jz .line_in_screen_map_top mov esi,[RO8x8_BMapAddress+RO8x8_Inner+8] .line_in_screen_map_top: ; al contains real Y offset for next tile mov ecx,0xF8 mov edx,7 and ecx,eax and eax,byte 7 sub edx,eax lea esi,[esi+ecx*8] ; Get screen offset jmp short .have_v_offset .LeftEdge: push ecx push eax mov ebp,[RO8x8_FirstTile+RO8x8_Inner+8] .No_VChange: mov eax,[LineAddress] mov esi,[RO8x8_MapAddress_Current+RO8x8_Inner+8] mov edx,[LineAddressY] .have_v_offset: add ebp,ebx add ebx,byte 2 ; Update X offset mov [RO8x8_LineAddressOffset+RO8x8_Inner+8],eax push ebx mov ebx,ebp and ebp,byte 31*2 ; X offset wrap mov [RO8x8_LineAddressOffsetY+RO8x8_Inner+12],edx add esi,ebp ; Combine X and Y offsets into tile map and ebx,byte 32*2 mov ebx,[RO8x8_RMapDifference+RO8x8_Inner+12] jz .tile_in_screen_map_left add esi,ebx .tile_in_screen_map_left: mov al,[esi+1] Check_Tile_Priority %2, near %1_check mov ebp,[RO8x8_LineAddressOffsetY+RO8x8_Inner+12] test al,al ; Check Y flip mov si,[esi] ; Get tile # js .flip_y mov ebp,[RO8x8_LineAddressOffset+RO8x8_Inner+12] .flip_y: shl esi,3 mov dl,al add esi,ebp mov ebp,[TilesetAddress] and esi,0x3FF * 8 + 7 ; Clip to tileset and edx,byte 7*4 ; Get palette add esi,ebp and esi,0xFFFF * 4 / 8 ; Clip to VRAM mov ebp,[palette_2bpl+edx] add al,al ; Get X flip (now in MSB) js near .xflip 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: 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_8x8_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,[RO8x8_FirstTile+RO8x8_Inner+8] mov eax,[RO8x8_Current_Line_Offset+RO8x8_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 add ebp,ebp jmp .No_VChange .calc_v_offset: mov dl,[esi] add eax,edx and ah,1 mov esi,[RO8x8_TMapAddress+RO8x8_Inner+8] jz .line_in_screen_map_top mov esi,[RO8x8_BMapAddress+RO8x8_Inner+8] .line_in_screen_map_top: ; al contains real Y offset for next tile mov ecx,0xF8 mov edx,7 and ecx,eax and eax,byte 7 sub edx,eax lea esi,[esi+ecx*8] ; Get screen offset jmp short .have_v_offset .LeftEdge: push ecx push eax mov ebp,[RO8x8_FirstTile+RO8x8_Inner+8] .No_VChange: mov eax,[LineAddress] mov esi,[RO8x8_MapAddress_Current+RO8x8_Inner+8] mov edx,[LineAddressY] .have_v_offset: add ebp,ebx add ebx,byte 2 ; Update X offset mov [RO8x8_LineAddressOffset+RO8x8_Inner+8],eax push ebx mov ebx,ebp and ebp,byte 31*2 ; X offset wrap mov [RO8x8_LineAddressOffsetY+RO8x8_Inner+12],edx add esi,ebp ; Combine X and Y offsets into tile map and ebx,byte 32*2 mov ebx,[RO8x8_RMapDifference+RO8x8_Inner+12] jz .tile_in_screen_map_left add esi,ebx .tile_in_screen_map_left: mov al,[esi+1] Check_Tile_Priority %2, near %1_check mov ebp,[RO8x8_LineAddressOffsetY+RO8x8_Inner+12] test al,al ; Check Y flip mov si,[esi] ; Get tile # js .flip_y mov ebp,[RO8x8_LineAddressOffset+RO8x8_Inner+12] .flip_y: shl esi,3 add esi,ebp mov ebp,[TilesetAddress] and esi,0x3FF * 8 + 7 ; Clip to tileset add esi,ebp and esi,0xFFFF / 8 ; Clip to VRAM add al,al ; Get X flip (now in MSB) js near .xflip 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: 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_8x8_C4 Plot_Lines_Unclipped_NP_Offset_8x8_C4,0 %endif %ifndef NO_PLOTTER_PER_PRIORITY Plot_Lines_Unclipped_Offset_8x8_C4 Plot_Lines_Unclipped_L_Offset_8x8_C4,1 Plot_Lines_Unclipped_Offset_8x8_C4 Plot_Lines_Unclipped_H_Offset_8x8_C4,2 %else Plot_Lines_Unclipped_Offset_8x8_C4 Plot_Lines_Unclipped_V_Offset_8x8_C4,3 %endif %ifndef NO_NP_RENDER Plot_Lines_Unclipped_Offset_8x8_C2 Plot_Lines_Unclipped_NP_Offset_8x8_C2,0 %endif %ifndef NO_PLOTTER_PER_PRIORITY Plot_Lines_Unclipped_Offset_8x8_C2 Plot_Lines_Unclipped_L_Offset_8x8_C2,1 Plot_Lines_Unclipped_Offset_8x8_C2 Plot_Lines_Unclipped_H_Offset_8x8_C2,2 %else Plot_Lines_Unclipped_Offset_8x8_C2 Plot_Lines_Unclipped_V_Offset_8x8_C2,3 %endif %ifndef NO_NP_RENDER Plot_Lines_Unclipped_Offset_8x8_C8 Plot_Lines_Unclipped_NP_Offset_8x8_C8,0 %endif %ifndef NO_PLOTTER_PER_PRIORITY Plot_Lines_Unclipped_Offset_8x8_C8 Plot_Lines_Unclipped_L_Offset_8x8_C8,1 Plot_Lines_Unclipped_Offset_8x8_C8 Plot_Lines_Unclipped_H_Offset_8x8_C8,2 %else Plot_Lines_Unclipped_Offset_8x8_C8 Plot_Lines_Unclipped_V_Offset_8x8_C8,3 %endif