From e88697c7733954353a56a4cba50157e72a7de2c3 Mon Sep 17 00:00:00 2001 From: condret Date: Fri, 1 Nov 2024 02:24:47 +0100 Subject: [PATCH] Immplement oam_scan --- include/gb.h | 27 +++++++++++++++++---------- io/dma.c | 4 ++-- io/ppu.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/include/gb.h b/include/gb.h index fcc090a..ced4190 100644 --- a/include/gb.h +++ b/include/gb.h @@ -87,24 +87,30 @@ enum { GB_PPU_N_REGS, }; +enum { + GB_PPU_STAT_MODE_HBLANK = 0, + GB_PPU_STAT_MODE_VBLANK, + GB_PPU_STAT_MODE_OAM_SCAN, + GB_PPU_STAT_MODE_RENDER, +}; + +#define GB_PPU_STAT_MODE_MASK 0x3 + +typedef struct oam_scan_table { + ut16 data[10]; //low byte is x coordinate of sprite; high byte is addr of entry (0xffe0 + high byte) + ut8 n_entries; //max 10 + ut8 addr; +} OAMScanTable; + typedef struct gb_dmg_ppu_t { GBPixBuf *pixbuf; ut64 seek; ut8 buf[GB_PPU_N_REGS]; + OAMScanTable ost; int reg_fd; int vram_fd; } GBPPU; -//these are in STAT -#define GB_PPU_MODE0 0 -#define GB_PPU_MODE1 1 -#define GB_PPU_MODE2 2 -#define GB_PPU_MODE3 3 -#define GB_PPU_MODE_MASK 3 - -//this is in seek -#define GB_PPU_DOUBLE_SPEED 0x10000 - typedef struct gameboy_t { RIO *io; RArch *arch; @@ -114,6 +120,7 @@ typedef struct gameboy_t { GBPPU *ppu; ut64 addr; int cartrigde_fd; + bool double_speed; } GB; GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer); diff --git a/io/dma.c b/io/dma.c index 7b3fe6f..99f814c 100644 --- a/io/dma.c +++ b/io/dma.c @@ -60,10 +60,10 @@ static int __bus_write(RIO *io, RIODesc *desc, const ut8 *buf, int len) { int _len = R_MIN (len, 0xa0 - ((ut32)dma->dst + (st32)dma->frontrun)); // memcpy (buf, &dma->buf[dma->dst + dma->frontrun], _len); dma->frontrun += _len; -#if 0 +#if 1 if (len != _len) { ut64 vseek = r_io_p2v (io, seek + _len); - r_io_bank_write_at (io, dma->default_bank_id, &buf[_len], len - _len) + r_io_bank_write_at (io, dma->default_bank_id, vseek, &buf[_len], len - _len); } #endif seek += len; diff --git a/io/ppu.c b/io/ppu.c index ff05720..353665f 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -124,7 +124,58 @@ GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer) { return ppu; } +static ut32 gb_ppu_oam_scan_update (GB *gb, ut32 cycles) { + if (gb->ppu->ost.addr >= 0xa0) { + gb->ppu->ost.addr = 0; + gb->ppu->ost.n_entries = 0; + } + if (cycles & 0x1) { + R_LOG_WARN ("Odd amount of cycles"); + } + if (gb->dma->seek & GB_DMA_ACTIVE) { + const ut8 running_cycles = R_MIN (cycles, (0xa0 - gb->ppu->ost.addr) >> 1); + //every oam entry costs 2 cycles + gb->ppu->ost.addr += running_cycles << 1; + cycles -= running_cycles; + goto beach; + } + const ut8 height = gb->ppu->buf[GB_PPU_LCDC] & 0x3? 16: 8; + const ut8 ly = gb->ppu->buf[GB_PPU_LY] + 16; + while (cycles && gb->ppu->ost.addr <= 0xa0) { + if (gb->ppu->ost.n_entries < 10) { + ut8 yx[2]; + r_io_fd_read_at (gb->io, gb->dma->oam_fd, (ut64)gb->ppu->ost.addr, yx, 2); + if ((yx[0] <= ly) && (ly < (yx[0] + height))) { + gb->ppu->ost.data[gb->ppu->ost.n_entries] = + (gb->ppu->ost.addr << 8) | yx[1]; + gb->ppu->ost.n_entries++; + } + } + gb->ppu->ost.addr += 4; + cycles -= 2; + } +beach: + if (gb->ppu->ost.addr == 0xa0) { + //indicate next mode + gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_RENDER; + } + return cycles; +} + void gb_ppu_update (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); + break; + case GB_PPU_STAT_MODE_RENDER: + break; + case GB_PPU_STAT_MODE_HBLANK: + break; + case GB_PPU_STAT_MODE_VBLANK: + break; + } + } //TODO }