Progress on ppu

This commit is contained in:
condret 2024-11-07 04:04:51 +01:00
parent 98eb21a9e2
commit 5d4d9e2bcb
2 changed files with 72 additions and 17 deletions

View File

@ -92,9 +92,12 @@ enum {
GB_PPU_N_REGS, GB_PPU_N_REGS,
}; };
#define GB_PPU_LCDC_BIG_OBJ 0x4 #define GB_PPU_LCDC_BGW_ENABLE 0x1
#define GB_PPU_LCDC_BG_TILE_MAP 0x8 #define GB_PPU_LCDC_OBJ_ENABLE 0x2
#define GB_PPU_LCDC_TILE_BASE 0x10 #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_ENABLE 0x20
#define GB_PPU_LCDC_WIN_TILE_MAP 0x40 #define GB_PPU_LCDC_WIN_TILE_MAP 0x40
enum { enum {
@ -123,12 +126,18 @@ typedef struct pixel_fifo_fetcher_t {
ut8 state_ctr; ut8 state_ctr;
} PixelFifoFetcher; } PixelFifoFetcher;
// flags
#define GB_PIXEL_FIFO_FETCH_OBJECT 0x10 #define GB_PIXEL_FIFO_FETCH_OBJECT 0x10
#define GB_PIXEL_FIFO_FETCH_WINDOW 0x20 #define GB_PIXEL_FIFO_FETCH_WINDOW 0x20
#define GB_PIXEL_FIFO_FETCH_READY 0x40 #define GB_PIXEL_FIFO_FETCH_READY 0x40
//specifies if scx & 0x7 and wy are copied into fifo //specifies if scx & 0x7 and wy are copied into fifo
#define GB_PIXEL_FIFO_REG_DATA_LOADED 0x80 #define GB_PIXEL_FIFO_REG_DATA_LOADED 0x80
//flags1
//window x condition triggered
#define GB_PIXEL_FIFO_WXC_TRIGGERED 0x8
#define GB_OAM_PALLET 0x10 #define GB_OAM_PALLET 0x10
#define GB_OAM_FLIP_X 0x20 #define GB_OAM_FLIP_X 0x20
#define GB_OAM_FLIP_Y 0x40 #define GB_OAM_FLIP_Y 0x40
@ -144,7 +153,7 @@ typedef struct pixel_fifo_t {
ut64 data; ut64 data;
PixelFifoFetcher fetcher[2]; PixelFifoFetcher fetcher[2];
ut32 remaining_cycles; ut32 remaining_cycles;
ut32 obj; //object ut32 obj; //object
union { union {
ut8 shift_out; //lower nibble is sourch info, pallet, color ut8 shift_out; //lower nibble is sourch info, pallet, color
// 0b....spcc // 0b....spcc
@ -159,7 +168,10 @@ obj p1 - 11
ut8 n_fpixel; //number of pixel that are currently in the fifo ut8 n_fpixel; //number of pixel that are currently in the fifo
ut8 x; ut8 x;
ut8 wy; ut8 wy;
ut8 dx; //discard x union {
ut8 dx; //discard x
ut8 flags1;
};
} PixelFifo; } PixelFifo;
typedef struct gb_dmg_ppu_t { typedef struct gb_dmg_ppu_t {

View File

@ -197,18 +197,30 @@ static void read_obj_data (GBPPU *ppu, RIO *io, ut8 *tile, int oam_fd) {
} }
} }
static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf) { static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
ut32 pixels = pxf->data >> 32; ut32 pixels = pxf->data >> 32;
ut32 newpixels = 0; ut64 newpixels = 0;
ut32 i; ut32 i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (!(pixels & (0x3 << 28))) { //check for transparency const ut8 bg_pixel = (pixels & (0xf << ((7 - i) << 2))) >> ((7 - i) << 2);
newpixels = (newpixels << 4) | const ut8 fg_pixel = (pxf->fetcher[1].fetched & (0xf << ((7 - i) << 2))) >> ((7 - i) << 2);
((pxf->fetcher[1].fetched & (0xf << (i << 2))) >> (i << 2)); newpixels <<= 4;
pixels = pixels << 4; //background always wins if obj is transparent or bg is obj
if ((!(fg_pixel & 0x3)) || ((bg_pixel & 0xc) == 0x4) || (bg_pixel & 0x8)) {
newpixels |= bg_pixel;
continue; continue;
} }
if ((bg_pixel & 0xc) == 0x4) {
//bg is window
//TODO: check for window priority
}
if (!priority && (bg_pixel & 0x3)) {
newpixels |= bg_pixel;
continue;
}
newpixels |= fg_pixel;
} }
pxf->data = (pxf->data & 0xffffffff) | (newpixels << 32);
} }
static void gb_pixel_fifo_fetch_continue (GB *gb) { static void gb_pixel_fifo_fetch_continue (GB *gb) {
@ -351,16 +363,22 @@ static void shit_out_pixel (GBPPU *ppu) {
ppu->fifo.shift_out = (ppu->fifo.shift_out & 0xf0) | ppu->fifo.data >> 60; ppu->fifo.shift_out = (ppu->fifo.shift_out & 0xf0) | ppu->fifo.data >> 60;
ppu->fifo.data = ppu->fifo.data << 4; ppu->fifo.data = ppu->fifo.data << 4;
ppu->fifo.n_fpixel--; ppu->fifo.n_fpixel--;
if (ppu->fifo.dx) { if (ppu->fifo.dx & 0x7) {
//discard pixel //discard pixel
ppu->fifo.dx--; ppu->fifo.dx = (ppu->fifo.dx & 0xf8) | ((ppu->fifo.dx & 0x7) - 1);
return; return;
} }
ut8 color; ut8 color;
//bg pallet
if (!(ppu->fifo.shift_out & 0x08)) { if (!(ppu->fifo.shift_out & 0x08)) {
//bg pallet //check if window and bg are enabled
color = (ppu->buf[GB_PPU_BGP] & (0x3 << ((ppu->fifo.shift_out & 0x3) << 1))) >> if (ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BGW_ENABLE) {
((ppu->fifo.shift_out & 0x3) << 1); color = (ppu->buf[GB_PPU_BGP] & (0x3 << ((ppu->fifo.shift_out & 0x3) << 1))) >>
((ppu->fifo.shift_out & 0x3) << 1);
} else {
//white
color = 0;
}
} else { } else {
const ut8 pal = !!(ppu->fifo.shift_out & 0x04); const ut8 pal = !!(ppu->fifo.shift_out & 0x04);
color = (ppu->buf[GB_PPU_OBP0 + pal] & (0x3 << ((ppu->fifo.shift_out & 0x3) << 1))) >> color = (ppu->buf[GB_PPU_OBP0 + pal] & (0x3 << ((ppu->fifo.shift_out & 0x3) << 1))) >>
@ -390,6 +408,29 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) {
fifo->flags |= GB_PIXEL_FIFO_REG_DATA_LOADED; fifo->flags |= GB_PIXEL_FIFO_REG_DATA_LOADED;
} }
while (cycles) { while (cycles) {
#if 1
if (fifo->flags & GB_PIXEL_FIFO_FETCH_WINDOW) {
//this is probably insufficient,
//but the actual behaviour of deactivating the window mid fetch is not really documented
if (!(gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_WIN_ENABLE)) {
fifo->flags ^= GB_PIXEL_FIFO_FETCH_WINDOW;
}
} else {
if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_WIN_ENABLE) {
if ((fifo->wy <= gb->ppu->buf[GB_PPU_LY]) &&
((fifo->flags1 & GB_PIXEL_FIFO_WXC_TRIGGERED) ||
(gb->ppu->buf[GB_PPU_WX] >= fifo->x))) {
//when window starts at 0, we don't need to discard pixels anyway
fifo->flags1 = GB_PIXEL_FIFO_WXC_TRIGGERED;
fifo->flags |= GB_PIXEL_FIFO_FETCH_WINDOW;
//clear the fetcher
fifo->fetcher[0] = (const PixelFifoFetcher) {0};
//clear the pipe
fifo->n_fpixel = 0;
}
}
}
#endif
if (fifo->n_fpixel < 9) { if (fifo->n_fpixel < 9) {
//initial phase on each line //initial phase on each line
//also when window starts? //also when window starts?
@ -422,7 +463,9 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) {
} else { } else {
gb_pixel_fifo_fetch_continue (gb); gb_pixel_fifo_fetch_continue (gb);
if (fifo->flags & GB_PIXEL_FIFO_FETCH_READY) { if (fifo->flags & GB_PIXEL_FIFO_FETCH_READY) {
gb_ppu_pixel_fifo_merge_opixels (fifo); if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_OBJ_ENABLE) {
gb_ppu_pixel_fifo_merge_opixels (fifo, !!(fifo->obj & GB_FIFO_OAM_PRIORITY));
}
fifo->flags ^= GB_PIXEL_FIFO_FETCH_OBJECT | GB_PIXEL_FIFO_FETCH_READY; fifo->flags ^= GB_PIXEL_FIFO_FETCH_OBJECT | GB_PIXEL_FIFO_FETCH_READY;
} }
} }