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