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

📄 bg8.asm

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

%define SNEeSe_ppu_bg8_asm

%include "misc.inc"
%include "ppu/ppu.inc"
%include "ppu/tiles.inc"
%include "ppu/screen.inc"


%define R8x8_Local_Bytes_H 56
%define R8x8_Local_Bytes 52
%define R8x8_Plotter_Table_NP esp+52
%define R8x8_Plotter_Table esp+48
%define R8x8_Clipped esp+44
%define R8x8_BG_Table esp+40
%define R8x8_Current_Line esp+36
%define R8x8_BaseDestPtr esp+32
%define R8x8_Lines esp+28
%define R8x8_Runs_Left esp+24
%define R8x8_Output esp+20
%define R8x8_RunListPtr esp+16
%define R8x8R_VMapOffset esp+12
%define R8x8R_Plotter esp+8
%define R8x8R_BG_Table R8x8_BG_Table
%define R8x8R_Next_Pixel esp+4
%define R8x8R_Pixel_Count esp
%define R8x8R_Inner (4)

;VMapOffset = bg_line_offset (vscroll + current line) / bg tile size *
; 32 words (per line)
;Plotter = background plotting handler, passed:
; ebx = VRAM screen address of first tile
;  cl = tile count to plot
; edi = pointer to destination surface, leftmost pixel of first tile
;  (even if clipped)
; uses qword TileClip1 (dword TileClip1Left, dword TileClip1Right)
;BG_Table = pointer to background structure
;Next_Pixel = first pixel in run to be plotted
;     (local) hscroll-adjusted pixel to be plotted next (not always updated)
;Pixel_Count = count of pixels in run to be plotted
;edx = pointer to background structure (same as passed on stack)
;edi = native pointer to destination surface, start of first line
; to be drawn in output

%if 0
C-pseudo code
void Render_8x8_Run
(BGTABLE *bgtable, UINT8 *output, int vmapoffset, int nextpixel,
 int numpixels,
 void (*plotter)(UINT16 *screen_address, UINT8 tilecount, UINT8 *output))
)
{
 UINT16 *screen_address;

 output += nextpixel;

 nextpixel += bgtable->hscroll & 0xFF;
 if (nextpixel < 0x100)
 {
  screen_address = (UINT16 *) (bgtable->vlmapaddress + vmapoffset +
   nextpixel / 8 * 2);
 }
 else
 {
  nextpixel -= 0x100;
  screen_address = (UINT16 *) (bgtable->vrmapaddress + vmapoffset +
   nextpixel / 8 * 2);
 }

 if (nextpixel & 7)
 {
  output -= nextpixel & 7;
  TileClip1Left = *(UINT32 *)(ClipLeftTable - (nextpixel & 7));
  TileClip1Right = *(UINT32 *)(ClipLeftTable - (nextpixel & 7) + 4);

  if (numpixels < 8 - (nextpixel & 7))
  {
   TileClip1Left &=
    *(UINT32 *)(ClipRightTable - ((nextpixel & 7) + numpixels));
   TileClip1Right &=
    *(UINT32 *)(ClipRightTable - ((nextpixel & 7) + numpixels) + 4);
  }

  plotter(screen_address, 1, output);

  if (numpixels <= 0) return;

  screen_address ++;
  output += 8;
  nextpixel += 8 - (nextpixel & 7);
  numpixels -= 8 - (nextpixel & 7);
 }

 TileClip1Left = TileClip1Right = -1;

 if (nextpixel != 0x100)
 {
  UINT8 runlength;
  if (numpixels < 0x100 - nextpixel)
  {
   runlength = numpixels & ~7;
   if (!runlength)
   {
    TileClip1Left &=
     *(UINT32 *)(ClipRightTable - numpixels);
    TileClip1Right &=
     *(UINT32 *)(ClipRightTable - numpixels + 4);
    plotter(screen_address, 1, output);
    return;
   }
  }
  else
  {
   runlength = 0x100 - nextpixel;
  }

  plotter(screen_address, runlength / 8, output);
  numpixels -= runlength;
  if (!numpixels) return;

  screen_address += runlength / 8;
  output += runlength;
  nextpixel += runlength;

  if (nextpixel < 0x100)
  {
   TileClip1Left &=
    *(UINT32 *)(ClipRightTable - numpixels);
   TileClip1Right &=
    *(UINT32 *)(ClipRightTable - numpixels + 4);
   plotter(screen_address, 1, output);
   return;
  }
 }

 screen_address = (UINT16 *) (bgtable->vrmapaddress + vmapoffset);
 if (numpixels >= 8)
 {
  plotter(screen_address, numpixels / 8, output);
  if (!(numpixels & 7)) return;
  screen_address += numpixels / 8;
  output += numpixels & ~7;
 }

 TileClip1Left &=
  *(UINT32 *)(ClipRightTable - (numpixels & 7));
 TileClip1Right &=
  *(UINT32 *)(ClipRightTable - (numpixels & 7) + 4);
 plotter(screen_address, 1, output);
}
%endif
ALIGNC
Render_8x8_Run:
 xor ecx,ecx

 mov eax,[R8x8R_Next_Pixel+R8x8R_Inner]
 mov cl,[HScroll+edx]
 add edi,eax    ;first pixel
 add ecx,eax

 mov eax,[VLMapAddress+edx]
 mov ebx,[R8x8R_VMapOffset+R8x8R_Inner]
 cmp ecx,0x100
 jb .do_before_wrap
 sub ecx,0x100
 mov eax,[VRMapAddress+edx]
.do_before_wrap:

 mov ebp,ecx
 add ebx,eax

 shr ebp,3      ;(nextpixel / 8)

 ;hscroll + first pixel, relative to screen of first tile to be plotted
 mov [R8x8R_Next_Pixel+R8x8R_Inner],ecx
 and ecx,byte 7
 lea ebx,[ebx+ebp*2]
 jz .do_unclipped_before_wrap

 sub edi,ecx
 sub ecx,byte 8

 sub [R8x8R_Next_Pixel+R8x8R_Inner],ecx ;nextpixel += 8 - (nextpixel & 7)
 mov esi,[R8x8R_Pixel_Count+R8x8R_Inner]
 add [R8x8R_Pixel_Count+R8x8R_Inner],ecx    ;count -= 8 - (nextpixel & 7)
 xor ecx,byte 7

 mov eax,[ClipLeftTable+ecx+1]      ;ClipLeftTable[-(nextpixel & 7)]
 mov [TileClip1Left],eax
 mov eax,[ClipLeftTable+ecx+1+4]
 mov [TileClip1Right],eax
 sub ecx,esi
 cmp dword [R8x8R_Pixel_Count+R8x8R_Inner],0
 jl .clippedboth
 jz .last_tile

 mov cl,1
 call [R8x8R_Plotter+R8x8R_Inner]

.do_unclipped_before_wrap:
 mov eax,-1
 mov ecx,0x100
 mov ebp,[R8x8R_Next_Pixel+R8x8R_Inner]
 mov [TileClip1Left],eax
 sub ecx,ebp
 mov [TileClip1Right],eax
 jz .do_unclipped_after_wrap

 mov eax,[R8x8R_Pixel_Count+R8x8R_Inner]
 cmp ecx,eax
 jbe .goodcountunclippedleft
 mov ecx,eax
 and ecx,byte ~7
 jz .clipped_last_before_wrap
.goodcountunclippedleft:

 sub eax,ecx    ;count -= pixels in unclipped tiles in left run
 add [R8x8R_Next_Pixel+R8x8R_Inner],ecx ;nextpixel += 8 - (nextpixel & 7)
 shr ecx,3

 test eax,eax
 jz .last_run
 mov [R8x8R_Pixel_Count+R8x8R_Inner],eax
 call [R8x8R_Plotter+R8x8R_Inner]

 mov ebp,[R8x8R_Next_Pixel+R8x8R_Inner]
 cmp ebp,0x100
 jae .do_unclipped_after_wrap

.clipped_last_before_wrap:
 mov ecx,[R8x8R_Pixel_Count+R8x8R_Inner]
 jmp .do_clipped_last_tile

.do_unclipped_after_wrap:
 mov edx,[R8x8R_BG_Table+R8x8R_Inner]
 mov eax,[R8x8R_Pixel_Count+R8x8R_Inner]
 mov esi,[R8x8R_VMapOffset+R8x8R_Inner]
 mov ecx,eax
 mov ebx,[VRMapAddress+edx]
 add ebx,esi
 shr eax,3
 jz .do_clipped_last_tile

 test ecx,7
 mov ecx,eax
 jz .last_run

 call [R8x8R_Plotter+R8x8R_Inner]

 mov ecx,[R8x8R_Pixel_Count+R8x8R_Inner]

.do_clipped_last_tile:
 and ecx,byte 7
 xor ecx,byte -1
.clippedboth:
 ; ClipRightTable[-((nextpixel & 7) + pixel_count)]
 mov eax,[ClipRightTable+ecx+1]
 and [TileClip1Left],eax
 mov eax,[ClipRightTable+ecx+1+4]
 and [TileClip1Right],eax

.last_tile:
 mov cl,1
.last_run:
 jmp [R8x8R_Plotter+R8x8R_Inner]

%macro Render_8x8 1
ALIGNC
EXPORT_C Render_8x8_C%1
 cmp byte [Mosaic+edx],0
 jnz C_LABEL(Render_8x8M_C%1)

%if %1 == 2
 mov ecx,[M0_Color+edx]
 mov [Palette_Base],ecx
%endif

 mov ecx,C_LABEL(Plot_Lines_V_8x8_Table_C%1)
 test al,al
 jnz .plotter_high

 cmp byte [Tile_priority_bit],0
 jnz Render_8x8_Low

.plotter_high:
 push dword C_LABEL(Plot_Lines_NP_8x8_Table_C%1)
 jmp Render_8x8_High
%endmacro

Render_8x8 2
Render_8x8 4
Render_8x8 8

;%1 = label, %2 = priority
%macro Render_8x8_Base 2
ALIGNC
%1:
 push ecx
 push esi
 push edx ;BG_Table
 push ebx ;Current_Line
 push edi ;BaseDestPtr
 push ebp ;Lines
 sub esp,byte R8x8_Local_Bytes-24

 mov eax,[SetAddress+edx]
 mov [TilesetAddress],eax

.next_line:
 mov edx,[R8x8_BG_Table]

 mov eax,[R8x8_Current_Line]

%if %2 > 0
 mov cl,[Priority_Unused+edx+eax*2]
 test cl,cl
 jz .no_plot
%endif

 call Sort_Screen_Height
                
%if %2 == 0
 xor eax,eax
 mov [Tile_Priority_Used],ax
%endif

 mov eax,[R8x8_Current_Line]
 SORT_TILES_8_TALL
 mov ebp,[R8x8_Lines] ;*
;cmp ebp,byte 1
;je .no_multi

 ;esi = 7 - ((VScroll + Current_Line) & 7)

 cmp esi,ebp
 jae .no_multi
 lea ebp,[esi+1]
.no_multi:
 mov edi,[R8x8_BaseDestPtr]
%if %2 > 0
 mov esi,[R8x8_Current_Line]
%endif
 mov eax,ebp
 shl eax,8
 lea ecx,[edi+ebp*GfxBufferLineSlack]
 add eax,ecx

%if %2 == 0
 mov ecx,[R8x8_Plotter_Table]
%else
 mov cl,[Priority_Used+edx+esi*2]
 cmp cl,1
 mov ecx,[R8x8_Plotter_Table_NP]
 jc .plotter_np
 mov ecx,[R8x8_Plotter_Table]
.plotter_np:
%endif
 mov [BGLineCount],ebp ;*
 cmp ebp,byte 1
 mov [R8x8_BaseDestPtr],eax
 sbb ebp,ebp
 mov eax,[C_LABEL(SNES_Screen8)]
 add edi,eax
 mov ecx,[ecx+ebp*4+4]

 mov esi,[R8x8_Clipped]
 mov al,[Win_Count+edx+esi]

 test al,al
 jz .done

 mov [R8x8_Runs_Left],eax
 lea edx,[Win_Bands+edx+esi]

 mov [R8x8_Output],edi
 mov [R8x8_RunListPtr],edx
 mov [R8x8R_VMapOffset],ebx ;vertical screen map address
 xor ebx,ebx
 mov [R8x8R_Plotter],ecx    ;renderer
 mov bl,[edx]

 xor ecx,ecx
 mov cl,[edx+1]
 mov edx,[R8x8_BG_Table]
 sub cl,bl
 setz ch

 mov [R8x8R_Next_Pixel],ebx
 mov [R8x8R_Pixel_Count],ecx

 dec al
 je .last_run

.not_last_run:
 mov [R8x8_Runs_Left],al
 call Render_8x8_Run

 mov edx,[R8x8_RunListPtr]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -