diff --git a/include/gb.h b/include/gb.h index 7422cd6..2208674 100644 --- a/include/gb.h +++ b/include/gb.h @@ -88,6 +88,7 @@ typedef struct gb_dma_t { int dma_fd; //fd representing the dma register int dma_bus_fd; //fd representing the memory bus while dma occupies it int oam_fd; //fd representing oam + ut32 oam_mapid; ut32 dma_bank_id; ut32 default_bank_id; // ut16 bus_occupancy_size; @@ -103,10 +104,10 @@ typedef struct gb_dma_t { #define GB_DMA_ACTIVE 0x60000 #define GB_DMA_CGB_MODE 0x80000 -GBDMA *gb_dma_open(RIO *io); +bool gb_dma_init(GBDMA *dma, RIO *io); //void gb_dma_enable_cgb(GBDMA *dma); void gb_dma_continue(GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec); -void gb_dma_close(GBDMA *dma, RIO *io); +void gb_dma_fini(GBDMA *dma, RIO *io); enum { GB_PPU_LCDC = 0, //0xff40 @@ -221,7 +222,6 @@ typedef struct gb_dmg_ppu_t { int reg_fd; int vram_fd; ut32 vram_mapid; - ut32 oam_mapid; } GBPPU; enum { @@ -239,7 +239,7 @@ typedef struct gameboy_t { GBTimers timers; GBJoypad joypad; GBInterrupts interrupts; - GBDMA *dma; + GBDMA dma; GBPPU *ppu; ut64 addr; int cartrigde_fd; diff --git a/io/dma.c b/io/dma.c index aba0438..85ac0d5 100644 --- a/io/dma.c +++ b/io/dma.c @@ -172,53 +172,77 @@ RIOPlugin r_io_plugin_gb_dma = { .write = __write, }; -GBDMA *gb_dma_open (RIO *io) { - GBDMA *dma = R_NEW0 (GBDMA); - if (!dma) { - return NULL; + +bool gb_dma_init (GBDMA *dma, RIO *io) { + if (!dma || !io) { + return false; } + dma[0] = (const GBDMA) {0}; dma->default_bank_id = io->bank; RIOBank *bank = r_io_bank_new ("dma bus"); if (!bank) { - free (dma); - return NULL; + return false; } if (!r_io_bank_add (io, bank)) { r_io_bank_free (bank); - free (dma); - return NULL; + return false; } dma->dma_bank_id = bank->id; -// strcpy (uri, "malloc://0xa0"); dma->oam_fd = r_io_fd_open (io, "malloc://0xa0", R_PERM_RWX, 0); if (dma->oam_fd < 0) { + r_io_bank_del (io, bank->id); r_io_bank_free (bank); - free (dma); - return NULL; + r_io_fd_close (io, dma->oam_fd); + return false; } + RIOMap *oam_map = r_io_map_add (io, dma->oam_fd, R_PERM_RWX, 0, 0xffe0, 0xa0); + if (!oam_map) { + r_io_bank_del (io, bank->id); + r_io_bank_free (bank); + r_io_fd_close (io, dma->oam_fd); + return false; + } + dma->oam_mapid = oam_map->id; char uri[64]; memset (uri, 0x00, sizeof (char) * 64); sprintf (uri, "gb_dma://%p", dma); RIODesc *desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_dma, uri, R_PERM_RWX, 0); if (!desc) { - r_io_fd_close (io, dma->oam_fd); + r_io_bank_del (io, bank->id); r_io_bank_free (bank); - free (dma); - return NULL; + r_io_fd_close (io, dma->oam_fd); + return false; + } + if (!r_io_map_add (io, dma->dma_fd, R_PERM_RWX, 0, 0xff46, 1)) { + r_io_bank_del (io, bank->id); + r_io_bank_free (bank); + r_io_fd_close (io, dma->oam_fd); + r_io_desc_close (desc); } dma->dma_fd = desc->fd; sprintf (uri, "gb_dma_bus://%p", dma); desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_dma_bus, uri, R_PERM_RWX, 0); if (!desc) { + r_io_bank_del (io, dma->dma_bank_id); + r_io_bank_free (bank); r_io_fd_close (io, dma->oam_fd); r_io_fd_close (io, dma->dma_fd); - r_io_bank_free (bank); - free (dma); - return NULL; + return false; } + r_io_bank_use (io, dma->dma_bank_id); + if (!r_io_map_add (io, desc->fd, R_PERM_RWX, 0, 0, 0xff80)) { + r_io_bank_use (io, dma->default_bank_id); + r_io_bank_del (io, dma->dma_bank_id); + r_io_bank_free (bank); + r_io_fd_close (io, dma->oam_fd); + r_io_fd_close (io, dma->dma_fd); + r_io_desc_close (desc); + return false; + } + r_io_bank_use (io, dma->default_bank_id); dma->dma_bus_fd = desc->fd; - return dma; + return true; } void gb_dma_continue (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { @@ -264,14 +288,15 @@ void gb_dma_continue (GBDMA *dma, RIO *io, ut32 cycles, bool pre_exec) { } } -void gb_dma_close (GBDMA *dma, RIO *io) { +void gb_dma_fini (GBDMA *dma, RIO *io) { if (!dma || !io) { return; } r_io_bank_use (io, dma->default_bank_id); - r_io_bank_del (io, dma->dma_bank_id); r_io_fd_close (io, dma->dma_bus_fd); r_io_fd_close (io, dma->dma_fd); r_io_fd_close (io, dma->oam_fd); - free (dma); + RIOBank *bank = r_io_bank_get (io, dma->dma_bank_id); + r_io_bank_del (io, dma->dma_bank_id); + r_io_bank_free (bank); } diff --git a/io/interrupts.c b/io/interrupts.c index eacee87..fce7f4a 100644 --- a/io/interrupts.c +++ b/io/interrupts.c @@ -107,6 +107,17 @@ bool gb_interrupts_init(GBInterrupts *ints, RIO *io, RReg *reg) { if (!desc) { return false; } + //map IF register + if (!r_io_map_add (io, desc->fd, R_PERM_RWX, 0, 0xff0f, 1)) { + r_io_desc_close (desc); + return false; + } + //map IE register + if (!r_io_map_add (io, desc->fd, R_PERM_RWX, 1, 0xffff, 1)) { + r_io_desc_close (desc); + //r_io will automatically remove the map for IF register + return false; + } ints->fd = desc->fd; return true; } diff --git a/io/joypad.c b/io/joypad.c index 807ee9e..5aaef77 100644 --- a/io/joypad.c +++ b/io/joypad.c @@ -93,6 +93,10 @@ bool gb_joypad_init (GBJoypad *joypad, RIO *io) { if (!desc) { return false; } + if (!r_io_map_add (io, desc->fd, R_PERM_RWX, 0, 0xff00, 1)) { + r_io_desc_close (desc); + return false; + } joypad->fd = desc->fd; const ut8 *keys = SDL_GetKeyboardState (NULL); memcpy (&joypad->keys, &keys, sizeof (ut8 *)); diff --git a/io/ppu.c b/io/ppu.c index 52869e2..6dde818 100644 --- a/io/ppu.c +++ b/io/ppu.c @@ -139,7 +139,7 @@ static ut32 gb_ppu_oam_scan_continue (GB *gb, ut32 cycles) { if (cycles & 0x1) { R_LOG_WARN ("Odd amount of cycles"); } - if (gb->dma->seek & GB_DMA_ACTIVE) { + 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; @@ -152,7 +152,7 @@ static ut32 gb_ppu_oam_scan_continue (GB *gb, ut32 cycles) { if (gb->ppu->ost.n_entries < 10) { ut8 yx[2]; //this is probably inaccurate - 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))) { gb->ppu->ost.data[gb->ppu->ost.n_entries] = (gb->ppu->ost.addr << 16) | (yx[0] << 8) | yx[1]; @@ -253,7 +253,7 @@ static void gb_pixel_fifo_fetch_continue (GB *gb) { fifo->fetcher[0].addr += (gb->ppu->buf[GB_PPU_LY] & 0x7) * 2; } } else { - read_obj_data (gb->ppu, gb->io, &tile, gb->dma->oam_fd); + read_obj_data (gb->ppu, gb->io, &tile, gb->dma.oam_fd); fifo->fetcher[1].addr = tile; } case 1: @@ -262,7 +262,7 @@ static void gb_pixel_fifo_fetch_continue (GB *gb) { if (fetch_obj) { 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); + 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; @@ -526,7 +526,7 @@ static ut32 gb_ppu_vblank_continue (GB *gb, ut32 cycles) { 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); + RIOMap *map = r_io_map_get (gb->io, gb->dma.oam_mapid); if (gb->ppu->buf[GB_PPU_LCDC] & GB_PPU_LCDC_ENABLE) { //lcd was switched on //launch oam scan @@ -568,7 +568,7 @@ void gb_ppu_continue (GB *gb, ut32 cycles) { 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); + RIOMap *map = r_io_map_get (gb->io, gb->dma.oam_mapid); map->perm = R_PERM_RWX; map = r_io_map_get (gb->io, gb->ppu->vram_mapid); map->perm = R_PERM_RWX; @@ -577,7 +577,7 @@ void gb_ppu_continue (GB *gb, ut32 cycles) { 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); + RIOMap *oam = r_io_map_get (gb->io, gb->dma.oam_mapid); oam->perm = 0; if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_OAM) { gb_interrupts_request (gb, GB_INTERRUPT_STAT); @@ -594,7 +594,7 @@ void gb_ppu_continue (GB *gb, ut32 cycles) { 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); + RIOMap *oam = r_io_map_get (gb->io, gb->dma.oam_mapid); oam->perm = 0; if (gb->ppu->buf[GB_PPU_STAT] & GB_PPU_STAT_INTR_OAM) { gb_interrupts_request (gb, GB_INTERRUPT_STAT); diff --git a/io/timers.c b/io/timers.c index 1680eb5..aa7fca0 100644 --- a/io/timers.c +++ b/io/timers.c @@ -112,7 +112,11 @@ bool gb_timers_init (GBTimers *timers, RIO *io) { RIODesc *desc = r_io_desc_open_plugin (io, &r_io_plugin_gb_timers, uri, R_PERM_RWX, 0); if (!desc) { - return NULL; + return false; + } + if (!r_io_map_add (io, desc->fd, R_PERM_RWX, 0, 0xff04, 4)) { + r_io_desc_close (desc); + return false; } timers->fd = desc->fd; return true;