Immplement oam_scan

This commit is contained in:
condret 2024-11-01 02:24:47 +01:00
parent d1842269d4
commit e88697c773
3 changed files with 70 additions and 12 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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
}