Finish implementing gb_pixel_fifo_fetch_continue
This commit is contained in:
parent
5d113adc77
commit
feb59859ef
35
include/gb.h
35
include/gb.h
|
@ -102,33 +102,54 @@ enum {
|
||||||
#define GB_PPU_STAT_MODE_MASK 0x3
|
#define GB_PPU_STAT_MODE_MASK 0x3
|
||||||
|
|
||||||
typedef struct oam_scan_table {
|
typedef struct oam_scan_table {
|
||||||
ut16 data[10]; //low byte is x coordinate of sprite; high byte is addr of entry (0xffe0 + high byte)
|
ut32 data[10];
|
||||||
|
//low byte is x coordinate of sprite;
|
||||||
|
//second lowest byte is y coordinate
|
||||||
|
//second highest byte is addr of entry (0xffe0 + addr)
|
||||||
|
//highest byte is used for attributes, which is read by the fetcher, not during oam scan
|
||||||
ut8 n_entries; //max 10
|
ut8 n_entries; //max 10
|
||||||
ut8 addr;
|
ut8 addr;
|
||||||
} OAMScanTable;
|
} OAMScanTable;
|
||||||
|
|
||||||
typedef struct pixel_fifo_fetch_t {
|
typedef struct pixel_fifo_fetcher_t {
|
||||||
ut32 fetched;
|
ut32 fetched;
|
||||||
ut16 addr;
|
ut16 addr;
|
||||||
ut8 data[2];
|
ut8 data[2];
|
||||||
ut8 state_ctr;
|
ut8 state_ctr;
|
||||||
} PixelFifoFetch;
|
} PixelFifoFetcher;
|
||||||
|
|
||||||
#define GB_PIXEL_FIFO_FETCH_SELECT 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_OAM_PALLET 0x10
|
||||||
|
#define GB_OAM_FLIP_X 0x20
|
||||||
|
#define GB_OAM_FLIP_Y 0x40
|
||||||
|
#define GB_OAM_PRIORITY 0x80
|
||||||
|
|
||||||
|
#define GB_FIFO_OAM_PALLET (GB_OAM_PALLET << 24)
|
||||||
|
#define GB_FIFO_OAM_FLIP_X (GB_OAM_FLIP_X << 24)
|
||||||
|
#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 {
|
typedef struct pixel_fifo_t {
|
||||||
ut64 data;
|
ut64 data;
|
||||||
PixelFifoFetch fetch[2];
|
PixelFifoFetcher fetcher[2];
|
||||||
ut8 shift_out; //lower nibble is sourch info, pallet, color
|
ut32 remaining_cycles;
|
||||||
// 0b....spcc
|
ut32 obj; //object
|
||||||
|
union {
|
||||||
|
ut8 shift_out; //lower nibble is sourch info, pallet, color
|
||||||
|
// 0b....spcc
|
||||||
#if 0
|
#if 0
|
||||||
bg - 00
|
bg - 00
|
||||||
win - 01
|
win - 01
|
||||||
obj p0 - 10
|
obj p0 - 10
|
||||||
obj p1 - 11
|
obj p1 - 11
|
||||||
#endif
|
#endif
|
||||||
|
ut8 flags;
|
||||||
|
};
|
||||||
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 wy;
|
||||||
ut8 x;
|
ut8 x;
|
||||||
} PixelFifo;
|
} PixelFifo;
|
||||||
|
|
||||||
|
|
140
io/ppu.c
140
io/ppu.c
|
@ -147,7 +147,7 @@ static ut32 gb_ppu_oam_scan_update (GB *gb, ut32 cycles) {
|
||||||
r_io_fd_read_at (gb->io, gb->dma->oam_fd, (ut64)gb->ppu->ost.addr, 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)) && yx[1]) {
|
if ((yx[0] <= ly) && (ly < (yx[0] + height)) && yx[1]) {
|
||||||
gb->ppu->ost.data[gb->ppu->ost.n_entries] =
|
gb->ppu->ost.data[gb->ppu->ost.n_entries] =
|
||||||
(gb->ppu->ost.addr << 8) | yx[1];
|
(gb->ppu->ost.addr << 16) | (yx[0] << 8) | yx[0];
|
||||||
gb->ppu->ost.n_entries++;
|
gb->ppu->ost.n_entries++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,24 +164,36 @@ beach:
|
||||||
return cycles;
|
return cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_tile_data (GB *gb, ut8 *tile) {
|
static void read_tile_data (GBPPU *ppu, RIO *io, ut8 *tile) {
|
||||||
const bool use_window = !!(gb->ppu->fifo.shift_out & GB_PIXEL_FIFO_FETCH_WINDOW);
|
const bool use_window = !!(ppu->fifo.flags & GB_PIXEL_FIFO_FETCH_WINDOW);
|
||||||
ut64 addr;
|
ut64 addr;
|
||||||
if (use_window) {
|
if (use_window) {
|
||||||
const ut8 x = ((gb->ppu->fifo.x + ((!!gb->ppu->fifo.n_fpixel) << 3)) -
|
const ut8 x = ((ppu->fifo.x + ((!!ppu->fifo.n_fpixel) << 3)) -
|
||||||
gb->ppu->buf[GB_PPU_WX]) & 0xf8;
|
ppu->buf[GB_PPU_WX]) & 0xf8;
|
||||||
//maybe store this at begin of line
|
//maybe store this at begin of line
|
||||||
const ut8 y = (gb->ppu->buf[GB_PPU_LY] - gb->ppu->buf[GB_PPU_WY]) & 0xf8;
|
#if 0
|
||||||
addr = ((gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_WIN_TILE_MAP)?
|
const ut8 y = (ppu->buf[GB_PPU_LY] - ppu->buf[GB_PPU_WY]) & 0xf8;
|
||||||
|
#else
|
||||||
|
const ut8 y = (ppu->buf[GB_PPU_LY] - ppu->fifo.wy) & 0xf8;
|
||||||
|
#endif
|
||||||
|
addr = ((ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_WIN_TILE_MAP)?
|
||||||
0x1800: 0x1c00) + y * 32 + x;
|
0x1800: 0x1c00) + y * 32 + x;
|
||||||
} else {
|
} else {
|
||||||
const ut8 x = (gb->ppu->fifo.x + gb->ppu->buf[GB_PPU_SCX] +
|
const ut8 x = (ppu->fifo.x + ppu->buf[GB_PPU_SCX] +
|
||||||
((!!gb->ppu->fifo.n_fpixel) << 3)) & 0xf8;
|
((!!ppu->fifo.n_fpixel) << 3)) & 0xf8;
|
||||||
const ut8 y = (gb->ppu->buf[GB_PPU_LY] + gb->ppu->buf[GB_PPU_SCY]) & 0xf8;
|
const ut8 y = (ppu->buf[GB_PPU_LY] + ppu->buf[GB_PPU_SCY]) & 0xf8;
|
||||||
addr = ((gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BG_TILE_MAP)?
|
addr = ((ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BG_TILE_MAP)?
|
||||||
0x1800: 0x1c00) + y * 32 + x;
|
0x1800: 0x1c00) + y * 32 + x;
|
||||||
}
|
}
|
||||||
r_io_fd_read_at (gb->io, gb->ppu->vram_fd, addr, tile, 1);
|
r_io_fd_read_at (io, ppu->vram_fd, addr, tile, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_obj_data (GBPPU *ppu, RIO *io, ut8 *tile, int oam_fd) {
|
||||||
|
ut8 addr = (ppu->fifo.obj >> 16) & 0xff;
|
||||||
|
r_io_fd_read_at (io, oam_fd, (ut64)(addr + 2), tile, 1);
|
||||||
|
if (ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BIG_OBJ) {
|
||||||
|
tile[0] &= 0xfe;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
|
static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
|
||||||
|
@ -191,7 +203,7 @@ static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (!(pixels & (0x3 << 28))) { //check for transparency
|
if (!(pixels & (0x3 << 28))) { //check for transparency
|
||||||
newpixels = (newpixels << 4) |
|
newpixels = (newpixels << 4) |
|
||||||
((pxf->fetch[1].fetched & (0xf << ((i - 1) << 2))) >> ((i - 1) << 2));
|
((pxf->fetcher[1].fetched & (0xf << (i << 2))) >> (i << 2));
|
||||||
pixels = pixels << 4;
|
pixels = pixels << 4;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -200,26 +212,108 @@ static void gb_ppu_pixel_fifo_merge_opixels (PixelFifo *pxf, bool priority) {
|
||||||
|
|
||||||
static void gb_pixel_fifo_fetch_continue (GB *gb) {
|
static void gb_pixel_fifo_fetch_continue (GB *gb) {
|
||||||
PixelFifo *fifo = &gb->ppu->fifo;
|
PixelFifo *fifo = &gb->ppu->fifo;
|
||||||
ut8 fetcher = !!(fifo->shift_out & GB_PIXEL_FIFO_FETCH_SELECT);
|
ut8 fetch_obj = !!(fifo->flags & GB_PIXEL_FIFO_FETCH_OBJECT);
|
||||||
ut8 tile;
|
ut8 tile;
|
||||||
switch (fifo->fetch[fetcher].state_ctr) {
|
switch (fifo->fetcher[fetch_obj].state_ctr) {
|
||||||
case 0:
|
case 0:
|
||||||
read_tile_data (gb, &tile);
|
if (!fetch_obj) {
|
||||||
if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_TILE_BASE) {
|
read_tile_data (gb->ppu, gb->io, &tile);
|
||||||
fifo->fetch[fetcher].addr = tile * 16;
|
if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_TILE_BASE) {
|
||||||
|
fifo->fetcher[0].addr = tile * 16;
|
||||||
|
} else {
|
||||||
|
st8 s_tile = (st8)tile;
|
||||||
|
fifo->fetcher[0].addr = 0x1000 + s_tile * 16;
|
||||||
|
}
|
||||||
|
if (fifo->flags & GB_PIXEL_FIFO_FETCH_WINDOW) {
|
||||||
|
fifo->fetcher[0].addr +=
|
||||||
|
((gb->ppu->buf[GB_PPU_LY] - fifo->wy) & 0x7) * 2;
|
||||||
|
} else {
|
||||||
|
fifo->fetcher[0].addr += (gb->ppu->buf[GB_PPU_LY] & 0x7) * 2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
st8 stile = (st8)tile;
|
read_obj_data (gb->ppu, gb->io, &tile, gb->dma->oam_fd);
|
||||||
fifo->fetch[fetcher].addr = 0x1000 + stile * 16;
|
fifo->fetcher[1].addr = tile;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
if (fetch_obj) {
|
||||||
break;
|
ut8 addr = (fifo->obj >> 16) & 0xff;
|
||||||
|
//read object attributes
|
||||||
|
r_io_fd_read_at (gb->io, gb->dma->oam_fd, (ut64)(addr + 3), &tile, 1);
|
||||||
|
fifo->obj = (fifo->obj & 0xffffff) | (tile << 24);
|
||||||
|
//tile idx
|
||||||
|
tile = fifo->fetcher[1].addr & 0xff;
|
||||||
|
//object_y - line_y
|
||||||
|
addr = ((fifo->obj >> 8) & 0xff) - gb->ppu->buf[GB_PPU_LY];
|
||||||
|
fifo->fetcher[1].addr = tile * 16;
|
||||||
|
if (fifo->obj & GB_FIFO_OAM_FLIP_Y) {
|
||||||
|
//perform y flip
|
||||||
|
addr ^= (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_BIG_OBJ)? 0xf: 0x7;
|
||||||
|
}
|
||||||
|
fifo->fetcher[1].addr += addr * 2;
|
||||||
|
} else {
|
||||||
|
r_io_fd_read_at (gb->io, gb->ppu->vram_fd, fifo->fetcher[0].addr,
|
||||||
|
&fifo->fetcher[0].data[0], 1);
|
||||||
|
fifo->fetcher[0].addr++;
|
||||||
|
}
|
||||||
case 3:
|
case 3:
|
||||||
fifo->fetch[fetcher].addr++;
|
break;
|
||||||
|
case 4:
|
||||||
|
r_io_fd_read_at (gb->io, gb->ppu->vram_fd, fifo->fetcher[fetch_obj].addr,
|
||||||
|
&fifo->fetcher[fetch_obj].data[!fetch_obj], 1);
|
||||||
|
fifo->fetcher[fetch_obj].addr++;
|
||||||
|
if (!fetch_obj) {
|
||||||
|
ut8 *p = &fifo->fetcher[0].data[0];
|
||||||
|
fifo->fetcher[0].fetched =
|
||||||
|
((p[1] & 0x80) << 22) | ((p[0] & 0x80) << 21) |
|
||||||
|
((p[1] & 0x40) << 19) | ((p[0] & 0x40) << 18) |
|
||||||
|
((p[1] & 0x20) << 16) | ((p[0] & 0x20) << 15) |
|
||||||
|
((p[1] & 0x10) << 13) | ((p[0] & 0x10) << 12) |
|
||||||
|
((p[1] & 0x8) << 10) | ((p[0] & 0x8) << 9) |
|
||||||
|
((p[1] & 0x4) << 7) | ((p[0] & 0x4) << 6) |
|
||||||
|
((p[1] & 0x2) << 4) | ((p[0] & 0x2) << 3) |
|
||||||
|
((p[1] & 0x1) << 1) | (p[0] & 0x1);
|
||||||
|
if (fifo->flags & GB_PIXEL_FIFO_FETCH_WINDOW) {
|
||||||
|
fifo->fetcher[0].fetched |= 0x44444444;
|
||||||
|
}
|
||||||
|
}
|
||||||
case 5:
|
case 5:
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if (fetch_obj) {
|
||||||
|
r_io_fd_read_at (gb->io, gb->ppu->vram_fd, fifo->fetcher[1].addr,
|
||||||
|
&fifo->fetcher[1].data[1], 1);
|
||||||
|
ut8 *p = &fifo->fetcher[1].data[0];
|
||||||
|
if (fifo->obj & GB_FIFO_OAM_FLIP_X) {
|
||||||
|
fifo->fetcher[1].fetched =
|
||||||
|
((p[1] & 0x80) >> 6) | ((p[0] & 0x80) >> 7) |
|
||||||
|
((p[1] & 0x40) >> 1) | ((p[0] & 0x40) >> 2) |
|
||||||
|
((p[1] & 0x20) << 4) | ((p[0] & 0x20) << 3) |
|
||||||
|
((p[1] & 0x10) << 9) | ((p[0] & 0x10) << 8) |
|
||||||
|
((p[1] & 0x8) << 14) | ((p[0] & 0x8) << 13) |
|
||||||
|
((p[1] & 0x4) << 19) | ((p[0] & 0x4) << 18) |
|
||||||
|
((p[1] & 0x2) << 24) | ((p[0] & 0x2) << 23) |
|
||||||
|
((p[1] & 0x1) << 29) | ((p[0] & 0x1) << 28);
|
||||||
|
} else {
|
||||||
|
fifo->fetcher[1].fetched =
|
||||||
|
((p[1] & 0x80) << 22) | ((p[0] & 0x80) << 21) |
|
||||||
|
((p[1] & 0x40) << 19) | ((p[0] & 0x40) << 18) |
|
||||||
|
((p[1] & 0x20) << 16) | ((p[0] & 0x20) << 15) |
|
||||||
|
((p[1] & 0x10) << 13) | ((p[0] & 0x10) << 12) |
|
||||||
|
((p[1] & 0x8) << 10) | ((p[0] & 0x8) << 9) |
|
||||||
|
((p[1] & 0x4) << 7) | ((p[0] & 0x4) << 6) |
|
||||||
|
((p[1] & 0x2) << 4) | ((p[0] & 0x2) << 3) |
|
||||||
|
((p[1] & 0x1) << 1) | (p[0] & 0x1);
|
||||||
|
}
|
||||||
|
fifo->fetcher[1].fetched |= (fifo->obj & GB_FIFO_OAM_PALLET)?
|
||||||
|
0xcccccccc: 0x88888888;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
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 ut32 gb_ppu_render_update (GB *gb, ut32 cycles) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user