gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 0bd8c2d6d9ede29c59458c4a96f1b593fed9f876 parent 7d8b5bdb058d3be47c218cdef3aa3a4f30d43aee Author: Michel Iwaniec <46843052+michel-iwaniec@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:00:51 +0100 Merge pull request #642 from michel-iwaniec/nes_optimize_crt0_zp NES: Simplify VRAM update loop NES: Optimize crt0 ROM space by 16 bytes by simplifying NMI handler NES: Refactor NMI handler NES: Optimize CRT0 zeropage usage Diffstat:
| M | gbdk-lib/libc/targets/mos6502/nes/crt0.s | 119 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
| M | gbdk-lib/libc/targets/mos6502/nes/global.s | 2 | +- |
2 files changed, 50 insertions(+), 71 deletions(-)
diff --git a/gbdk-lib/libc/targets/mos6502/nes/crt0.s b/gbdk-lib/libc/targets/mos6502/nes/crt0.s @@ -67,8 +67,6 @@ _sys_time:: .ds 2 _shadow_PPUCTRL:: .ds 1 _shadow_PPUMASK:: .ds 1 __crt0_spritePageValid: .ds 1 -__crt0_NMI_insideNMI: .ds 1 -__crt0_ScrollHV: .ds 1 _bkg_scroll_x:: .ds 1 _bkg_scroll_y:: .ds 1 _attribute_row_dirty:: .ds 1 @@ -199,28 +197,58 @@ ProcessDrawList: rts __crt0_NMI: - ; Prevent NMI re-entry - bit *__crt0_NMI_insideNMI - bpl NotInsideNMI - rti -NotInsideNMI: pha txa pha tya pha - - lda #0x80 - sta *__crt0_NMI_insideNMI - + + ; Skip graphics updates if blanked, to allow main code to do VRAM address / scroll updates + lda *_shadow_PPUMASK + and #(PPUMASK_SHOW_BG | PPUMASK_SHOW_SPR) + beq __crt0_NMI_skip + ; Do Sprite DMA or delay equivalent cycles jsr __crt0_doSpriteDMA - jsr __crt0_NMI_doUpdateVRAM + ; Update VRAM + lda PPUSTATUS + lda #PPUCTRL_SPR_CHR + sta PPUCTRL + jsr DoUpdateVRAM + ; Set scroll address + lda _bkg_scroll_x + sta PPUSCROLL + lda _bkg_scroll_y + sta PPUSCROLL + + ; Re-write PPUCTRL (clobbered by vram transfer buffer code) + lda *_shadow_PPUCTRL + sta PPUCTRL - nop - ; Enable screen to get normal dot crawl pattern + ; Write shadow_PPUMASK to PPUMASK, in case it was disabled lda *_shadow_PPUMASK sta PPUMASK + ; Call fake LCD isr if present (0x60 = RTS means no LCD) and + lda .jmp_to_LCD_isr + cmp #0x60 + beq __crt0_NMI_skip + ; First delay until end-of-vblank, depending on transfer buffer contents... + ; (X set to correct delay value by DoUpdateVRAM) +1$: + lda *0x00 + dex + bne 1$ + ; ...then delay for desired number of scanlines + ldx *__lcd_scanline + jsr .delay_to_lcd_scanline + ; Additional alignment + nop + nop + ; Call the handler + jsr .jmp_to_LCD_isr +__crt0_NMI_skip: + + ; Update frame counter lda *_sys_time clc adc #1 @@ -228,81 +256,32 @@ NotInsideNMI: lda *(_sys_time+1) adc #0 sta *(_sys_time+1) - - lda *_shadow_PPUCTRL - ora *__crt0_ScrollHV - sta PPUCTRL - - ; Call fake LCD isr - ldx *__lcd_scanline - beq 1$ - jsr .delay_to_lcd_scanline -1$: - ; Adjust to align to just-before-hblank - nop - nop - nop - lda #0x00 - lda 0x0000 - ; Call the handler - jsr .jmp_to_LCD_isr pla tay pla tax pla - asl *__crt0_NMI_insideNMI rti -__crt0_NMI_doUpdateVRAM: - lda *_shadow_PPUMASK - and #(PPUMASK_SHOW_BG | PPUMASK_SHOW_SPR) - beq __crt0_NMI_doUpdateVRAM_blanked - ; Not manually blanked - do updates - lda PPUSTATUS - lda #PPUCTRL_SPR_CHR - sta PPUCTRL - lda #0 - sta PPUMASK - jsr DoUpdateVRAM - ; Set scroll address - lda _bkg_scroll_x - sta PPUSCROLL - lda _bkg_scroll_y - sta PPUSCROLL - rts -__crt0_NMI_doUpdateVRAM_blanked: - ; Early-out if blanked to allow main code to do VRAM address / scroll updates - nop - nop - nop - rts - DoUpdateVRAM: WRITE_PALETTE_SHADOW bit *__vram_transfer_buffer_valid bmi DoUpdateVRAM_drawListValid DoUpdateVRAM_drawListInvalid: - ; Delay for remaining cycles to keep timing consistent - ldx #(VRAM_DELAY_CYCLES_X8+7) -DoUpdateVRAM_invalid_loop: - lda *__vram_transfer_buffer_num_cycles_x8 - dex - bne DoUpdateVRAM_invalid_loop + ; Delay for all unused cycles and ProcessDrawList overhead to keep timing consistent + lda *0x00 nop - rts + ldx #(VRAM_DELAY_CYCLES_X8+6) + bne DoUpdateVRAM_end DoUpdateVRAM_drawListValid: jsr ProcessDrawList - ; Delay for remaining cycles to keep timing consistent - ; ...plus fixed-cost of 56 cycles + ; Delay for remaining unused cycles to keep timing consistent ldx *__vram_transfer_buffer_num_cycles_x8 -DoUpdateVRAM_valid_loop: - stx *__vram_transfer_buffer_num_cycles_x8 - dex - bne DoUpdateVRAM_valid_loop + ; Reset available cycles to initial value lda #VRAM_DELAY_CYCLES_X8 sta *__vram_transfer_buffer_num_cycles_x8 +DoUpdateVRAM_end: rts __crt0_IRQ: diff --git a/gbdk-lib/libc/targets/mos6502/nes/global.s b/gbdk-lib/libc/targets/mos6502/nes/global.s @@ -1,7 +1,7 @@ ;; Transfer buffer (lower half of hardware stack) __vram_transfer_buffer = 0x100 ;; Number of 8-cycles available each frame for transfer buffer - VRAM_DELAY_CYCLES_X8 = 167 + VRAM_DELAY_CYCLES_X8 = 174 ;; Keypad .UP = 0x08
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.