gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit a9ba2945eee0e69caf8e87aa85e788ebecb7b538 parent c2929d709cb8eeca3820e2029fe5663f98cfe15d Author: Toxa <56631470+untoxa@users.noreply.github.com> Date: Fri, 2 Sep 2022 12:42:48 +0300 Merge pull request #406 from michel-iwaniec/nes_refactor_bkg_functions NES: Refactor nametable writes to use indirect writes via the vram transfer buffer when screen is not blanked Diffstat:
| M | gbdk-lib/libc/targets/mos6502/nes/crt0.s | 116 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s | 9 | ++++----- |
| M | gbdk-lib/libc/targets/mos6502/nes/set_bk_ts.s | 67 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
3 files changed, 183 insertions(+), 9 deletions(-)
diff --git a/gbdk-lib/libc/targets/mos6502/nes/crt0.s b/gbdk-lib/libc/targets/mos6502/nes/crt0.s @@ -28,6 +28,8 @@ VRAM_HDR_LENGTH = 0 VRAM_HDR_DIRECTION = 1 VRAM_HDR_PPUHI = 2 VRAM_HDR_PPULO = 3 +VRAM_MAX_BYTES = 32 +VRAM_MAX_STRIPE_SIZE = VRAM_HDR_SIZEOF + VRAM_MAX_BYTES ; Number of 8-cycles available each frame for transfer buffer VRAM_DELAY_CYCLES_X8 = 170 @@ -630,6 +632,120 @@ _display_on:: ror *.crt0_forced_blanking rts +; +; Begin a horizontal stripe +; +.ppu_stripe_begin_horizontal:: + clc + jmp .ppu_stripe_begin + +; +; Begin a vertical stripe +; +.ppu_stripe_begin_vertical:: + sec + jmp .ppu_stripe_begin + +; +; Begin a stripe (carry indicates vertical stripe) +; +.ppu_stripe_begin:: + bit *.crt0_forced_blanking + bpl 1$ + ; Direct write + stx PPUADDR + sta PPUADDR + ; Set inc-by-32 bit in PPUCTRL as well + lda #0 + rol + asl + asl + lda *_shadow_PPUCTRL + sta PPUCTRL + rts +1$: + ; Indirect write via transfer buffer + sty *__crt0_textTemp + pha + txa + pha + lda #0 + rol + asl + asl + pha + ; Ensure there's at least VRAM_MAX_STRIPE_SIZE bytes remaining to write before progressing + ; This conservative limit simplifies conditions for rest of stripe in order to write single bytes with no checks +2$: + lda *__crt0_drawListPosW + cmp #128-VRAM_MAX_STRIPE_SIZE + bcs 2$ + ; Lock buffer and store current write pointer for later + VRAM_BUFFER_LOCK + ldy *__crt0_drawListPosW + sty *.crt0_textStringBegin + ; Write direction + pla + sta _vram_transfer_buffer+VRAM_HDR_DIRECTION,y + ; Write address + pla + sta _vram_transfer_buffer+VRAM_HDR_PPUHI,y + pla + sta _vram_transfer_buffer+VRAM_HDR_PPULO,y + tya + clc + adc #VRAM_HDR_SIZEOF + sta *__crt0_drawListPosW + ; __crt0_drawListNumDelayCycles_x8 -= 7 (assumes carry clear) + lda *__crt0_drawListNumDelayCycles_x8 + sbc #6 + sta *__crt0_drawListNumDelayCycles_x8 + ldy *__crt0_textTemp + rts + +; +; End a stripe (be it direct or via transfer buffer) +; +.ppu_stripe_end:: + bit *.crt0_forced_blanking + bpl 1$ + ; For direct writes there's nothing more to do + rts +1$: + sty *__crt0_textTemp + ldy *__crt0_drawListPosW + ; Write terminator byte + lda #0 + sta _vram_transfer_buffer,y + ; Write number of data bytes + tya + sec + sbc *.crt0_textStringBegin + sec + sbc #VRAM_HDR_SIZEOF + ldy *.crt0_textStringBegin + sta _vram_transfer_buffer+VRAM_HDR_LENGTH,y + VRAM_BUFFER_UNLOCK + ldy *__crt0_textTemp + rts + +; +; Writes a byte of an in-progress horizontal / vertical stripe (be it direct or via transfer buffer) +; +.ppu_stripe_write_byte:: + bit *.crt0_forced_blanking + bpl 1$ + sta PPUDATA ; Direct write + rts +1$: + sty *__crt0_textTemp + ldy *__crt0_drawListPosW + sta _vram_transfer_buffer,y + inc *__crt0_drawListPosW + dec *__crt0_drawListNumDelayCycles_x8 + ldy *__crt0_textTemp + rts + ; Interrupt / RESET vector table .area VECTORS (ABS) .org 0xfffa diff --git a/gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s b/gbdk-lib/libc/targets/mos6502/nes/set_bk_attributes.s @@ -18,7 +18,6 @@ .area _HOME -; TODO: Switch to use vram transfer buffer when screen not blanked .define .width "_set_bkg_attributes_PARM_3" .define .height "_set_bkg_attributes_PARM_4" .define .tiles "_set_bkg_attributes_PARM_5" @@ -543,22 +542,22 @@ _flush_shadow_attributes_end: ; ; Flushes all dirty rows of _attribute_shadow by writing them to PPU memory -; TODO: Support VRAM transfer buffer as well as direct mode. ; _flush_shadow_attributes_update_row: ; Update all 8 bytes of row for now, as each row in _attribute_row_dirty only stores 1 bit ; TODO: Could store 8 bytes and update range, at expense of 7 more bytes. lda *.tmp+1 - sta PPUADDR + tax lda *.tmp - sta PPUADDR + jsr .ppu_stripe_begin_horizontal ; Write 8 bytes i = 0 .rept 8 lda _attribute_shadow+i,y - sta PPUDATA + jsr .ppu_stripe_write_byte i = i + 1 .endm + jsr .ppu_stripe_end jmp _flush_shadow_attributes_next_row .attribute_set_dirty: diff --git a/gbdk-lib/libc/targets/mos6502/nes/set_bk_ts.s b/gbdk-lib/libc/targets/mos6502/nes/set_bk_ts.s @@ -12,7 +12,6 @@ .area _HOME _set_bkg_tiles:: - ; TODO: Switch to use vram transfer buffer when screen not blanked .define .width "_set_bkg_tiles_PARM_3" .define .height "_set_bkg_tiles_PARM_4" .define .tiles "_set_bkg_tiles_PARM_5" @@ -24,6 +23,11 @@ _set_bkg_tiles:: sta *.src_tiles+1 lda *.height sta *.num_rows + ; Prefer vertical stripes if height > width + cmp *.width + beq _set_bkg_tiles_horizontalStripes + bcs _set_bkg_tiles_verticalStripes +_set_bkg_tiles_horizontalStripes: 1$: lda #0 sta *.tmp+1 @@ -43,17 +47,18 @@ _set_bkg_tiles:: ; lda *.tmp+1 ora #0x20 - sta PPUADDR + tax lda *.tmp - sta PPUADDR + jsr .ppu_stripe_begin_horizontal ldx *.width ldy #0 2$: lda [*.src_tiles],y iny - sta PPUDATA + jsr .ppu_stripe_write_byte dex bne 2$ + jsr .ppu_stripe_end ; .src_tiles += y tya clc @@ -66,3 +71,57 @@ _set_bkg_tiles:: dec *.num_rows bne 1$ rts + +.define .num_cols ".num_rows" + +_set_bkg_tiles_verticalStripes:: + lda *.width + sta *.num_cols + ldy #0 +1$: + lda *.tiles + sta *.src_tiles + lda *.tiles+1 + sta *.src_tiles+1 + ; + lda #0 + sta *.tmp+1 + lda *.ypos + asl + rol *.tmp+1 + asl + rol *.tmp+1 + asl + rol *.tmp+1 + asl + rol *.tmp+1 + asl + rol *.tmp+1 + ora *.xpos + sta *.tmp + ; + lda *.tmp+1 + ora #0x20 + tax + lda *.tmp + jsr .ppu_stripe_begin_vertical + ldx *.height +2$: + lda [*.src_tiles],y + jsr .ppu_stripe_write_byte + ; .src_tiles += width + lda *.width + clc + adc *.src_tiles + sta *.src_tiles + lda #0 + adc *.src_tiles+1 + sta *.src_tiles+1 + dex + bne 2$ + jsr .ppu_stripe_end + iny + inc *.xpos + dec *.num_cols + bne 1$ + rts
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.