diff --git a/include/gb.h b/include/gb.h index 63c03ab..fbc449a 100644 --- a/include/gb.h +++ b/include/gb.h @@ -87,6 +87,11 @@ enum { GB_PPU_N_REGS, }; +#define GB_PPU_LCDC_BIG_OBJ 0x4 +#define GB_PPU_LCDC_BG_TILE_MAP 0x8 +#define GB_PPU_LCDC_TILE_BASE 0x10 +#define GB_PPU_LCDC_WIN_TILE_MAP 0x40 + enum { GB_PPU_STAT_MODE_HBLANK = 0, GB_PPU_STAT_MODE_VBLANK, @@ -102,10 +107,19 @@ typedef struct oam_scan_table { ut8 addr; } OAMScanTable; +typedef struct pixel_fifo_fetch_t { + ut32 fetched; + ut16 addr; + ut8 data[2]; + ut8 state_ctr; +} PixelFifoFetch; + +#define GB_PIXEL_FIFO_FETCH_SELECT 0x10 +#define GB_PIXEL_FIFO_FETCH_WINDOW 0x20 + typedef struct pixel_fifo_t { ut64 data; - ut32 fetch; - ut32 obj_fetch; + PixelFifoFetch fetch[2]; ut8 shift_out; //lower nibble is sourch info, pallet, color // 0b....spcc #if 0 @@ -114,9 +128,8 @@ win - 01 obj p0 - 10 obj p1 - 11 #endif - ut8 n_fpixel; //number of pixel that are currently in the upper half of the fifo - 1 + ut8 n_fpixel; //number of pixel that are currently in the fifo ut8 x; - ut8 y; } PixelFifo; typedef struct gb_dmg_ppu_t { diff --git a/io/ppu.c b/io/ppu.c index 63a4e89..6d4f8a9 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -139,7 +139,7 @@ static ut32 gb_ppu_oam_scan_update (GB *gb, ut32 cycles) { cycles -= running_cycles; goto beach; } - const ut8 height = gb->ppu->buf[GB_PPU_LCDC] & 0x3? 16: 8; + const ut8 height = (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BIG_OBJ)? 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) { @@ -164,20 +164,64 @@ beach: return cycles; } +static void read_tile_data (GB *gb, ut8 *tile) { + const bool use_window = !!(gb->ppu->fifo.shift_out & GB_PIXEL_FIFO_FETCH_WINDOW); + ut64 addr; + if (use_window) { + const ut8 x = ((gb->ppu->fifo.x + ((!!gb->ppu->fifo.n_fpixel) << 3)) - + gb->ppu->buf[GB_PPU_WX]) & 0xf8; + //maybe store this at begin of line + const ut8 y = (gb->ppu->buf[GB_PPU_LY] - gb->ppu->buf[GB_PPU_WY]) & 0xf8; + addr = ((gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_WIN_TILE_MAP)? + 0x1800: 0x1c00) + y * 32 + x; + } else { + const ut8 x = (gb->ppu->fifo.x + gb->ppu->buf[GB_PPU_SCX] + + ((!!gb->ppu->fifo.n_fpixel) << 3)) & 0xf8; + const ut8 y = (gb->ppu->buf[GB_PPU_LY] + gb->ppu->buf[GB_PPU_SCY]) & 0xf8; + addr = ((gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BG_TILE_MAP)? + 0x1800: 0x1c00) + y * 32 + x; + } + r_io_fd_read_at (gb->io, gb->ppu->vram_fd, addr, tile, 1); +} + static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) { ut32 pixels = pxf->data >> 32; ut32 newpixels = 0; ut32 i; for (i = 0; i < 8; i++) { - if (!(pixels & (0x3 << 28))) { + if (!(pixels & (0x3 << 28))) { //check for transparency newpixels = (newpixels << 4) | - ((pxf->obj_fetch & (0xf << ((i - 1) << 2))) >> ((i - 1) << 2)); + ((pxf->fetch[1].fetched & (0xf << ((i - 1) << 2))) >> ((i - 1) << 2)); pixels = pixels << 4; continue; } } } +static void gb_pixel_fifo_fetch_continue (GB *gb) { + PixelFifo *fifo = &gb->ppu->fifo; + ut8 fetcher = !!(fifo->shift_out & GB_PIXEL_FIFO_FETCH_SELECT); + ut8 tile; + switch (fifo->fetch[fetcher].state_ctr) { + case 0: + read_tile_data (gb, &tile); + if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_TILE_BASE) { + fifo->fetch[fetcher].addr = tile * 16; + } else { + st8 stile = (st8)tile; + fifo->fetch[fetcher].addr = 0x1000 + stile * 16; + } + case 1: + break; + case 2: + case 4: + break; + case 3: + fifo->fetch[fetcher].addr++; + case 5: + } +} + static ut32 gb_ppu_render_update (GB *gb, ut32 cycles) { return 0; }