From 4fe5bd2e151745a2fbc81e712a83d8fbdba19eed Mon Sep 17 00:00:00 2001 From: condret Date: Mon, 4 Nov 2024 03:07:34 +0100 Subject: [PATCH] Minor progress on gb_ppu_render_continue --- include/gb.h | 14 +++++++----- io/dma.c | 2 +- io/joypad.c | 2 +- io/ppu.c | 60 +++++++++++++++++++++++++++++++++++++++++++--------- io/timers.c | 2 +- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/include/gb.h b/include/gb.h index 1eb3efe..4c004bb 100644 --- a/include/gb.h +++ b/include/gb.h @@ -25,7 +25,7 @@ typedef struct gb_timers_t { } GBTimers; GBTimers *gb_timers_open(RIO *io); -void gb_timers_update(GBTimers *timers, ut32 cycles); +void gb_timers_continue(GBTimers *timers, ut32 cycles); void gb_timers_close(GBTimers *timers, RIO *io); typedef struct gb_joypad_t { @@ -44,7 +44,7 @@ typedef struct gb_joypad_t { } GBJoypad; GBJoypad *gb_joypad_open(RIO *io); -void gb_joypad_update(GBJoypad *joypad); +void gb_joypad_continue(GBJoypad *joypad); void gb_joypad_close(GBJoypad *joypad, RIO *io); typedef struct gb_dma_t { @@ -69,7 +69,7 @@ typedef struct gb_dma_t { GBDMA *gb_dma_open(RIO *io); //void gb_dma_enable_cgb(GBDMA *dma); -void gb_dma_update(GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec); +void gb_dma_continue(GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec); void gb_dma_close(GBDMA *dma, RIO *io); enum { @@ -121,6 +121,8 @@ typedef struct pixel_fifo_fetcher_t { #define GB_PIXEL_FIFO_FETCH_OBJECT 0x10 #define GB_PIXEL_FIFO_FETCH_WINDOW 0x20 #define GB_PIXEL_FIFO_FETCH_READY 0x40 +//specifies if scx & 0x7 and wy are copied into fifo +#define GB_PIXEL_FIFO_REG_DATA_LOADED 0x80 #define GB_OAM_PALLET 0x10 #define GB_OAM_FLIP_X 0x20 @@ -132,6 +134,7 @@ typedef struct pixel_fifo_fetcher_t { #define GB_FIFO_OAM_FLIP_Y (GB_OAM_FLIP_Y << 24) #define GB_FIFO_OAM_PRIORITY (GB_OAM_PRIORITY << 24) + typedef struct pixel_fifo_t { ut64 data; PixelFifoFetcher fetcher[2]; @@ -149,8 +152,9 @@ obj p1 - 11 ut8 flags; }; ut8 n_fpixel; //number of pixel that are currently in the fifo - ut8 wy; ut8 x; + ut8 wy; + ut8 dx; //discard x } PixelFifo; typedef struct gb_dmg_ppu_t { @@ -178,7 +182,7 @@ typedef struct gameboy_t { } GB; GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer); -void gb_ppu_update (GB *gb, ut32 cycles); +void gb_ppu_continue (GB *gb, ut32 cycles); void gb_ppu_close (GBPPU *ppu, RIO *io); extern RIOPlugin r_io_plugin_gb_timers; diff --git a/io/dma.c b/io/dma.c index 99f814c..aba0438 100644 --- a/io/dma.c +++ b/io/dma.c @@ -221,7 +221,7 @@ GBDMA *gb_dma_open (RIO *io) { return dma; } -void gb_dma_update (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { +void gb_dma_continue (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { if (!(dma->seek & GB_DMA_ACTIVE)) { return; } diff --git a/io/joypad.c b/io/joypad.c index ae4ffa0..a7dbb5b 100644 --- a/io/joypad.c +++ b/io/joypad.c @@ -108,7 +108,7 @@ GBJoypad *gb_joypad_open (RIO *io) { return joypad; } -void gb_joypad_update(GBJoypad *joypad) { +void gb_joypad_continue(GBJoypad *joypad) { joypad->odata &= 0xc0; joypad->odata |= joypad->data & 0x3f; SDL_PumpEvents (); diff --git a/io/ppu.c b/io/ppu.c index 0717448..6ff93e9 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -124,7 +124,7 @@ GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer) { return ppu; } -static ut32 gb_ppu_oam_scan_update (GB *gb, ut32 cycles) { +static ut32 gb_ppu_oam_scan_continue (GB *gb, ut32 cycles) { if (gb->ppu->ost.addr >= 0xa0) { gb->ppu->ost.addr = 0; gb->ppu->ost.n_entries = 0; @@ -279,6 +279,9 @@ static void gb_pixel_fifo_fetch_continue (GB *gb) { } } case 5: + if (!fetch_obj) { + fifo->flags |= GB_PIXEL_FIFO_FETCH_READY; + } break; case 6: if (fetch_obj) { @@ -311,37 +314,74 @@ static void gb_pixel_fifo_fetch_continue (GB *gb) { } break; case 7: - fifo->flags |= GB_PIXEL_FIFO_FETCH_READY; + if (fetch_obj) { + fifo->flags |= GB_PIXEL_FIFO_FETCH_READY; + } } fifo->fetcher[fetch_obj].state_ctr = (fifo->fetcher[fetch_obj].state_ctr + 1) & 0x7; } -static ut32 gb_ppu_render_update (GB *gb, ut32 cycles) { +static void gb_ppu_render_launch (GB *gb) { + RIOMap *vram = r_io_map_get (gb->io, gb->ppu->vram_mapid); + vram->perm = 0; //disable vram access for rendering + gb->ppu->fifo = (const PixelFifo){0}; + gb->ppu->fifo.remaining_cycles = 376; +} + +static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) { + PixelFifo *fifo = &gb->ppu->fifo; + if (R_UNLIKELY (!(fifo->flags & GB_PIXEL_FIFO_REG_DATA_LOADED))) { + fifo->dx = gb->ppu->buf[GB_PPU_SCX] & 0x7; + fifo->wy = gb->ppu->buf[GB_PPU_WY]; + fifo->flags |= GB_PIXEL_FIFO_REG_DATA_LOADED; + } + while (cycles) { + if (fifo->n_fpixel < 9) { + gb_pixel_fifo_fetch_continue (gb); + if (fifo->flags & GB_PIXEL_FIFO_FETCH_READY) { + if (!fifo->n_fpixel) { + fifo->data = ((ut64)fifo->fetcher[0].fetched) << 32; + } else { + fifo->data |= fifo->fetcher[0].fetched; + } + fifo->n_fpixel += 8; + //I suspect the initial 16 pixels fetch on each line only takes 12 cycles instead of 16, + //because the pixel fifo is empty + fifo->flags ^= GB_PIXEL_FIFO_FETCH_READY; + fifo->fetcher[0].state_ctr = 0; + } + } + fifo->remaining_cycles--; + cycles--; + } return 0; } -static ut32 gb_ppu_hblank_update (GB *gb, ut32 cycles) { +static ut32 gb_ppu_hblank_continue (GB *gb, ut32 cycles) { return 0; } -static ut32 gb_ppu_vblank_update (GB *gb, ut32 cycles) { +static ut32 gb_ppu_vblank_continue (GB *gb, ut32 cycles) { return 0; } -void gb_ppu_update (GB *gb, ut32 cycles) { +void gb_ppu_continue (GB *gb, ut32 cycles) { while (cycles) { switch (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) { case GB_PPU_STAT_MODE_OAM_SCAN: - cycles = gb_ppu_oam_scan_update (gb, cycles); + cycles = gb_ppu_oam_scan_continue (gb, cycles); + if ((gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) == GB_PPU_STAT_MODE_RENDER) { + gb_ppu_render_launch (gb); + } break; case GB_PPU_STAT_MODE_RENDER: - cycles = gb_ppu_render_update (gb, cycles); + cycles = gb_ppu_render_continue (gb, cycles); break; case GB_PPU_STAT_MODE_HBLANK: - cycles = gb_ppu_hblank_update (gb, cycles); + cycles = gb_ppu_hblank_continue (gb, cycles); break; case GB_PPU_STAT_MODE_VBLANK: - cycles = gb_ppu_vblank_update (gb, cycles); + cycles = gb_ppu_vblank_continue (gb, cycles); break; } } diff --git a/io/timers.c b/io/timers.c index e1bfcf0..d8a04a6 100644 --- a/io/timers.c +++ b/io/timers.c @@ -130,7 +130,7 @@ void gb_timers_close (GBTimers *timers, RIO *io) { free (timers); } -void gb_timers_update (GBTimers *timers, ut32 cycles) { +void gb_timers_continue (GBTimers *timers, ut32 cycles) { bool request_interrupt = false; do { //ensure all falling edges are detected