Huge progress on ppu
This commit is contained in:
parent
e94520f6cd
commit
f8d11cacc9
|
@ -127,6 +127,7 @@ enum {
|
|||
#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_ENABLE 0x80
|
||||
|
||||
enum {
|
||||
GB_PPU_STAT_MODE_HBLANK = 0,
|
||||
|
@ -169,6 +170,8 @@ typedef struct pixel_fifo_fetcher_t {
|
|||
//flags1
|
||||
//window x condition triggered
|
||||
#define GB_PIXEL_FIFO_WXC_TRIGGERED 0x8
|
||||
//indicates that LCDC_ENABLE bit was fliped
|
||||
#define GB_PIXEL_FIFO_LCDC_SWITCH 0x10
|
||||
|
||||
#define GB_OAM_PALLET 0x10
|
||||
#define GB_OAM_FLIP_X 0x20
|
||||
|
|
|
@ -8,14 +8,16 @@ typedef struct gb_pixel_buffer_t {
|
|||
SDL_Texture *texture;
|
||||
ut8 *buf; //buffer containing pixeldata
|
||||
ut32 color[4]; //rgb colors
|
||||
ut32 clear_color;
|
||||
ut16 w; //x size in pixel
|
||||
ut16 h; //y size in pixel
|
||||
// ut16 xsf; //x scale factor for projecting onto the texture
|
||||
// ut16 ysf; //y scale factor for projecting onto the texture
|
||||
} GBPixBuf;
|
||||
|
||||
GBPixBuf *gb_pix_buf_new(SDL_Renderer *renderer, ut16 w, ut16 h);
|
||||
GBPixBuf *gb_pix_buf_new(SDL_Renderer *renderer, ut16 w, ut16 h, ut32 clear_color);
|
||||
void gb_pix_buf_free(GBPixBuf *pb);
|
||||
void gb_pix_buf_set_pixel(GBPixBuf *pb, ut16 x, ut16 y, ut8 pixval);
|
||||
void gb_pix_buf_set_color(GBPixBuf *pb, ut8 color_idx, ut32 rgb);
|
||||
void gb_pix_buf_clear(GBPixBuf *pb);
|
||||
#endif
|
||||
|
|
100
io/ppu.c
100
io/ppu.c
|
@ -53,9 +53,15 @@ static int __write(RIO *io, RIODesc *desc, const ut8 *buf, int len) {
|
|||
for (i = 0; i < len; i++) {
|
||||
switch (seek) {
|
||||
case GB_PPU_STAT:
|
||||
ppu->buf[GB_PPU_STAT] = (buf[i] & 0xf8) | (ppu->buf[GB_PPU_STAT] & 0x7);
|
||||
ppu->buf[GB_PPU_STAT] = (buf[i] & 0xf8) |
|
||||
(ppu->buf[GB_PPU_STAT] & 0x7);
|
||||
case GB_PPU_LY:
|
||||
break;
|
||||
case GB_PPU_LCDC:
|
||||
if ((ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_ENABLE) !=
|
||||
(buf[i] & GB_PPU_LCDC_ENABLE)) {
|
||||
ppu->fifo.flags1 |= GB_PIXEL_FIFO_LCDC_SWITCH;
|
||||
}
|
||||
default:
|
||||
ppu->buf[seek] = buf[i];
|
||||
break;
|
||||
|
@ -114,7 +120,8 @@ GBPPU *gb_ppu_open (RIO *io, SDL_Renderer *renderer) {
|
|||
return NULL;
|
||||
}
|
||||
ppu->reg_fd = desc->fd;
|
||||
ppu->pixbuf = gb_pix_buf_new (renderer, 160, 144);
|
||||
//TODO: use proper clear color
|
||||
ppu->pixbuf = gb_pix_buf_new (renderer, 160, 144, 0xabcdef);
|
||||
if (!ppu->pixbuf) {
|
||||
r_io_desc_close (desc);
|
||||
r_io_fd_close (io, ppu->vram_fd);
|
||||
|
@ -480,14 +487,70 @@ static ut32 gb_ppu_render_continue (GB *gb, ut32 cycles) {
|
|||
}
|
||||
|
||||
static ut32 gb_ppu_hblank_continue (GB *gb, ut32 cycles) {
|
||||
if (cycles >= gb->ppu->fifo.remaining_cycles) {
|
||||
gb->ppu->buf[GB_PPU_LY]++;
|
||||
gb->ppu->buf[GB_PPU_STAT] &= ~GB_PPU_STAT_MODE_MASK;
|
||||
if (gb->ppu->buf[GB_PPU_LY] == 144) {
|
||||
//launch vblank
|
||||
gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_VBLANK;
|
||||
return cycles - gb->ppu->fifo.remaining_cycles;
|
||||
}
|
||||
//launch oam scan
|
||||
gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_OAM_SCAN;
|
||||
return cycles - gb->ppu->fifo.remaining_cycles;
|
||||
}
|
||||
gb->ppu->fifo.remaining_cycles -= cycles;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ut32 gb_ppu_vblank_continue (GB *gb, ut32 cycles) {
|
||||
const ut32 m = gb->ppu->fifo.remaining_cycles % 456;
|
||||
if (m && m < cycles) {
|
||||
gb->ppu->buf[GB_PPU_LY]++;
|
||||
if (gb->ppu->buf[GB_PPU_LY] == 156) {
|
||||
gb->ppu->buf[GB_PPU_STAT] &= ~GB_PPU_STAT_MODE_MASK;
|
||||
gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_OAM_SCAN;
|
||||
return cycles - gb->ppu->fifo.remaining_cycles;
|
||||
}
|
||||
}
|
||||
gb->ppu->fifo.remaining_cycles -= cycles;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gb_ppu_continue (GB *gb, ut32 cycles) {
|
||||
if (gb->ppu->fifo.flags1 & GB_PIXEL_FIFO_LCDC_SWITCH) {
|
||||
gb->ppu->fifo.flags1 ^= GB_PIXEL_FIFO_LCDC_SWITCH;
|
||||
RIOMap *map = r_io_map_get (gb->io, gb->ppu->oam_mapid);
|
||||
if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_ENABLE) {
|
||||
//lcd was switched on
|
||||
//launch oam scan
|
||||
gb->ppu->buf[GB_PPU_LY] = 0;
|
||||
//disable oam access
|
||||
map->perm = 0;
|
||||
gb->ppu->buf[GB_PPU_STAT] &= ~GB_PPU_STAT_MODE_MASK;
|
||||
gb->ppu->buf[GB_PPU_STAT] |= GB_PPU_STAT_MODE_OAM_SCAN;
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_OAM) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
} else {
|
||||
//lcd was switched off
|
||||
//enable oam and vram access
|
||||
map->perm = R_PERM_RWX;
|
||||
map = r_io_map_get (gb->io, gb->ppu->vram_mapid);
|
||||
map->perm = R_PERM_RWX;
|
||||
//clear screen
|
||||
gb_pix_buf_clear (gb->ppu->pixbuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!(gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_ENABLE)) {
|
||||
return;
|
||||
}
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_LYC) {
|
||||
if (gb->ppu->buf[GB_PPU_LY] == gb->ppu->buf[GB_PPU_LYC]) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
}
|
||||
while (cycles) {
|
||||
switch (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) {
|
||||
case GB_PPU_STAT_MODE_OAM_SCAN:
|
||||
|
@ -498,16 +561,47 @@ void gb_ppu_continue (GB *gb, ut32 cycles) {
|
|||
break;
|
||||
case GB_PPU_STAT_MODE_RENDER:
|
||||
cycles = gb_ppu_render_continue (gb, cycles);
|
||||
if ((gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) == GB_PPU_STAT_MODE_HBLANK) {
|
||||
RIOMap *map = r_io_map_get (gb->io, gb->ppu->oam_mapid);
|
||||
map->perm = R_PERM_RWX;
|
||||
map = r_io_map_get (gb->io, gb->ppu->vram_mapid);
|
||||
map->perm = R_PERM_RWX;
|
||||
}
|
||||
break;
|
||||
case GB_PPU_STAT_MODE_HBLANK:
|
||||
cycles = gb_ppu_hblank_continue (gb, cycles);
|
||||
if ((gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) == GB_PPU_STAT_MODE_OAM_SCAN) {
|
||||
RIOMap *oam = r_io_map_get (gb->io, gb->ppu->oam_mapid);
|
||||
oam->perm = 0;
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_OAM) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
} else if ((gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) == GB_PPU_STAT_MODE_VBLANK) {
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_VBLANK) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_VBLANK);
|
||||
gb->ppu->fifo.remaining_cycles = 4560;
|
||||
}
|
||||
break;
|
||||
case GB_PPU_STAT_MODE_VBLANK:
|
||||
cycles = gb_ppu_vblank_continue (gb, cycles);
|
||||
if ((gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_MODE_MASK) == GB_PPU_STAT_MODE_OAM_SCAN) {
|
||||
gb->ppu->buf[GB_PPU_LY] = 0;
|
||||
RIOMap *oam = r_io_map_get (gb->io, gb->ppu->oam_mapid);
|
||||
oam->perm = 0;
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_OAM) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//TODO
|
||||
if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_LYC) {
|
||||
if (gb->ppu->buf[GB_PPU_LY] == gb->ppu->buf[GB_PPU_LYC]) {
|
||||
gb_interrupts_request (gb, GB_INTERRUPT_STAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gb_ppu_close (GBPPU *ppu, RIO *io) {
|
||||
|
|
15
sdl/pixbuf.c
15
sdl/pixbuf.c
|
@ -2,7 +2,7 @@
|
|||
#include <r_util.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
GBPixBuf *gb_pix_buf_new (SDL_Renderer *renderer, ut16 w, ut16 h) {
|
||||
GBPixBuf *gb_pix_buf_new (SDL_Renderer *renderer, ut16 w, ut16 h, ut32 clear_color) {
|
||||
if (!renderer || !w || !h) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ GBPixBuf *gb_pix_buf_new (SDL_Renderer *renderer, ut16 w, ut16 h) {
|
|||
}
|
||||
pb->w = w;
|
||||
pb->h = h;
|
||||
pb->clear_color = clear_color;
|
||||
return pb;
|
||||
}
|
||||
|
||||
|
@ -62,3 +63,15 @@ void gb_pix_buf_set_color (GBPixBuf *pb, ut8 color_idx, ut32 rgb) {
|
|||
}
|
||||
pb->color[color_idx & 0x3] = rgb;
|
||||
}
|
||||
|
||||
void gb_pix_buf_clear (GBPixBuf *pb) {
|
||||
if (!pb) {
|
||||
return;
|
||||
}
|
||||
SDL_Texture *target = SDL_GetRenderTarget (pb->renderer);
|
||||
SDL_SetRenderTarget (pb->renderer, pb->texture);
|
||||
SDL_SetRenderDrawColor (pb->renderer, (pb->clear_color >> 16) & 0xff,
|
||||
(pb->clear_color >> 8) & 0xff, pb->clear_color & 0xff, 0xff);
|
||||
SDL_RenderClear (pb->renderer);
|
||||
SDL_SetRenderTarget (pb->renderer, target);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user