Progress on ppu
This commit is contained in:
parent
98eb21a9e2
commit
5d4d9e2bcb
12
include/gb.h
12
include/gb.h
|
@ -92,9 +92,12 @@ enum {
|
||||||
GB_PPU_N_REGS,
|
GB_PPU_N_REGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GB_PPU_LCDC_BGW_ENABLE 0x1
|
||||||
|
#define GB_PPU_LCDC_OBJ_ENABLE 0x2
|
||||||
#define GB_PPU_LCDC_BIG_OBJ 0x4
|
#define GB_PPU_LCDC_BIG_OBJ 0x4
|
||||||
#define GB_PPU_LCDC_BG_TILE_MAP 0x8
|
#define GB_PPU_LCDC_BG_TILE_MAP 0x8
|
||||||
#define GB_PPU_LCDC_TILE_BASE 0x10
|
#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
|
||||||
|
@ -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;
|
||||||
|
union {
|
||||||
ut8 dx; //discard x
|
ut8 dx; //discard x
|
||||||
|
ut8 flags1;
|
||||||
|
};
|
||||||
} PixelFifo;
|
} PixelFifo;
|
||||||
|
|
||||||
typedef struct gb_dmg_ppu_t {
|
typedef struct gb_dmg_ppu_t {
|
||||||
|
|
63
io/ppu.c
63
io/ppu.c
|
@ -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;
|
||||||
if (!(ppu->fifo.shift_out & 0x08)) {
|
|
||||||
//bg pallet
|
//bg pallet
|
||||||
|
if (!(ppu->fifo.shift_out & 0x08)) {
|
||||||
|
//check if window and bg are enabled
|
||||||
|
if (ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BGW_ENABLE) {
|
||||||
color = (ppu->buf[GB_PPU_BGP] & (0x3 << ((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);
|
((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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user