From fb0d9a9cc4bc2dde9335b138f3555cf4816f09bc Mon Sep 17 00:00:00 2001 From: condret Date: Sat, 12 Oct 2024 04:23:34 +0200 Subject: [PATCH] debug prints --- include/gb.h | 2 +- io/mbc1.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 196 insertions(+), 15 deletions(-) diff --git a/include/gb.h b/include/gb.h index ac2450f..362b10c 100644 --- a/include/gb.h +++ b/include/gb.h @@ -24,7 +24,7 @@ GBTimers *gb_timers_open(RIO *io); void gb_timers_close(RIO *io, GBTimers *timers); void gb_timers_update(GBTimers *timers, ut32 cycles); -int gb_mbc1_open(RIO *io, char *path); +//int gb_mbc1_open(RIO *io, char *path); extern RIOPlugin r_io_plugin_gb_timers; extern RIOPlugin r_io_plugin_gb_mbc1; diff --git a/io/mbc1.c b/io/mbc1.c index 4c805e6..dc9cd1c 100644 --- a/io/mbc1.c +++ b/io/mbc1.c @@ -8,22 +8,46 @@ typedef struct gb_mbc1_data { ut32 *rombank_to_io_map; ut32 *rambank_to_io_map; ut64 seek; - ut32 size; int file_fd; int mem_fd; + ut32 rombank0_map; ut8 n_rombanks; ut8 n_rambanks; ut8 rombank_mask; - ut8 rombank; + ut8 rombank_high; + ut8 rombank_low; union { ut8 high_rombank; ut8 rambank; }; bool ram_enable; + bool mode; bool small_ram; } MBC1; -ut8 mbc1_mask[] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x1f, 0x1f }; +static void disable_ram (MBC1 *mbc) { + ut32 i; + for (i = 0; i < mbc->n_rambanks; i++) { + RIOMap *map = r_io_map_get (mbc->io, mbc->rambank_to_io_map[i]); + map->perm = 0; + } + mbc->ram_enable = false; +} + +static void enable_ram (MBC1 *mbc) { + ut32 i; + for (i = 0; i < mbc->n_rambanks; i++) { + RIOMap *map = r_io_map_get (mbc->io, mbc->rambank_to_io_map[i]); + map->perm = R_PERM_RW; + } + mbc->ram_enable = true; +} + +static bool __check(RIO *io, const char *pathname, bool many) { + return r_str_startswith (pathname, "gb_mbc1://"); +} + +ut8 mbc1_mask[] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f }; static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (!r_str_startswith (pathname, "gb_mbc1://")) { @@ -54,6 +78,7 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { free (mbc); return NULL; } + eprintf ("%d rombanks\n", mbc->n_rombanks); mbc->rombank_mask = mbc1_mask[mbc_info[1]]; if (mbc_info[0] != 1) { switch (mbc_info[2]) { @@ -72,6 +97,9 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { free (mbc); return NULL; } + eprintf ("%d rambanks\n", mbc->n_rambanks); + } else { + eprintf ("no external ram\n", mbc->n_rombanks); } mbc->io = r_io_new (); if (!mbc->io) { @@ -80,30 +108,38 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { free (mbc); return NULL; } + mbc->io->va = true; mbc->file_fd = r_io_fd_open (mbc->io, &pathname[10], R_PERM_R, 0); - { + if (mbc->n_rambanks) { char *malloc_uri = r_str_newf ("malloc://0x%"PFMT64x, mbc->small_ram? 0x800: (0x2000 * mbc->n_rambanks)); mbc->mem_fd = r_io_fd_open (mbc->io, malloc_uri, R_PERM_RW, 0); free (malloc_uri); + if (mbc->mem_fd < 0) { + goto fail; + } } - if ((mbc->file_fd < 0) || (mbc->mem_fd < 0)) { + if (mbc->file_fd < 0) { goto fail; } - RIOMap *map = r_io_map_add (mbc->io, mbc->file_fd, R_PERM_R, 0ULL, 0ULL, 0x4000); - if (!map) { - goto fail; - } - mbc->rombank_to_io_map[0] = map->id; + RIOMap *map; ut32 i; - for (i = 1; i < mbc->n_rombanks; i++) { + for (i = 0; i < mbc->n_rombanks; i++) { map = r_io_map_add_bottom (mbc->io, mbc->file_fd, R_PERM_R, - 0x4000 * i, 0x4000, 0x4000); + 0x4000 * i, (i & 0x1f)? 0x4000: 0ULL, 0x4000); if (!map) { goto fail; } mbc->rombank_to_io_map[i] = map->id; } + if (mbc->n_rombanks < 32) { + map = r_io_map_add_bottom (mbc->io, mbc->file_fd, R_PERM_R, + 0ULL, 0x4000, 0x4000); + if (!map) { + goto fail; + } + mbc->rombank0_map = map->id; + } if (mbc->small_ram) { for (i = 0; i < 4; i++) { map = r_io_map_add (mbc->io, mbc->mem_fd, R_PERM_RW, @@ -113,7 +149,7 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { } mbc->rambank_to_io_map[i] = map->id; } - } else { + } else if (mbc->n_rambanks) { for (i = 0; i < 4; i++) { map = r_io_map_add_bottom (mbc->io, mbc->mem_fd, R_PERM_RW, 0x2000 * i, 0xa000, 0x2000); @@ -123,10 +159,15 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { mbc->rambank_to_io_map[i] = map->id; } } - mbc->rombank = 1; + mbc->rombank_high = 1; mbc->io->cache.mode = 0; desc = r_io_desc_new (io, &r_io_plugin_gb_mbc1, pathname, R_PERM_RWX, mode, mbc); + mbc->io->va = true; + if (!desc) { + goto fail; + } + disable_ram (mbc); return desc; fail: r_io_free (mbc->io); @@ -135,3 +176,143 @@ fail: free (mbc); return NULL; } + +static bool __close(RIODesc *desc) { + MBC1 *mbc = (MBC1 *)desc->data; + r_io_free (mbc->io); + free (mbc->rombank_to_io_map); + free (mbc->rambank_to_io_map); + R_FREE (desc->data); + return true; +} + +static ut64 __lseek(RIO* io, RIODesc *desc, ut64 offset, int whence) { + MBC1 *mbc = (MBC1 *)desc->data; + switch (whence) { + case R_IO_SEEK_SET: + return mbc->seek = R_MIN (0xc000, offset); + case R_IO_SEEK_CUR: + return mbc->seek = R_MIN (0xc000, mbc->seek + offset); + case R_IO_SEEK_END: + return mbc->seek = 0xc000; + } + return mbc->seek; +} + +static int __write(RIO *io, RIODesc *desc, const ut8 *buf, int len) { + MBC1 *mbc = (MBC1 *)desc->data; + len = R_MIN (len, 0xc000 - mbc->seek); + r_io_write_at (mbc->io, mbc->seek, buf, len); + ut64 endseek = mbc->seek + len; + ut8 rombank; + while ((mbc->seek < 0x8000) && (mbc->seek < endseek)) { + const ut32 i = mbc->seek - (endseek - len); + switch (mbc->seek & 0x6000) { + case 0ULL: + if ((buf[i] & 0x0f) == 0x0a) { + eprintf ("enabling external ram\n"); + enable_ram (mbc); + } else { + eprintf ("disabling external ram\n"); + disable_ram (mbc); + } + break; + case 0x2000: + eprintf ("switching banks (low bits)\n"); + rombank = buf[i] & 0x1f; + if (!rombank) { + rombank++; + } + rombank |= (mbc->high_rombank & 0x3) << 5; + rombank &= mbc->rombank_mask; + if (!rombank) { + r_io_map_priorize (mbc->io, mbc->rombank0_map); + mbc->rombank_high = 0; + } else if (R_LIKELY (rombank < mbc->n_rombanks)) { + r_io_map_priorize (mbc->io, mbc->rombank_to_io_map[rombank]); + mbc->rombank_high = rombank; + } + break; + case 0x4000: //rambank switch/high rombank bits switch + eprintf ("switching banks (high bits)\n"); + mbc->rambank = buf[i] & 0x3; + rombank = mbc->rombank_high & 0x1f; + rombank |= (mbc->high_rombank & 0x3) << 5; + rombank &= mbc->rombank_mask; + if (!rombank) { + r_io_map_priorize (mbc->io, mbc->rombank0_map); + mbc->rombank_high = 0; + } else if (R_LIKELY (rombank < mbc->n_rombanks)) { + r_io_map_priorize (mbc->io, mbc->rombank_to_io_map[rombank]); + mbc->rombank_high = rombank; + } + if (mbc->mode) { + if (!mbc->small_ram && mbc->n_rambanks > 1) { + r_io_map_priorize (mbc->io, + mbc->rambank_to_io_map[mbc->rambank]); + } + rombank = (mbc->high_rombank << 5) & mbc->rombank_mask; + r_io_map_priorize (mbc->io, mbc->rombank_to_io_map[rombank]); + mbc->rombank_low = rombank; + } + break; + case 0x6000: + eprintf ("switching mode\n"); + mbc->mode = !!(buf[i] & 0x1); + if (!mbc->mode) { + r_io_map_priorize (mbc->io, mbc->rombank_to_io_map[0]); + mbc->rombank_low = 0; + if (!mbc->small_ram && mbc->n_rambanks > 1) { + r_io_map_priorize (mbc->io, mbc->rambank_to_io_map[0]); + } + } else { + if (!mbc->small_ram && mbc->n_rambanks > 1) { + r_io_map_priorize (mbc->io, + mbc->rambank_to_io_map[mbc->rambank]); + } + rombank = (mbc->high_rombank << 5) & mbc->rombank_mask; + r_io_map_priorize (mbc->io, mbc->rombank_to_io_map[rombank]); + mbc->rombank_low = rombank; + } + break; + } + mbc->seek++; + } + mbc->seek = endseek; + return len; +} + +static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) { + MBC1 *mbc = (MBC1 *)desc->data; + len = R_MIN (len, 0xc000 - mbc->seek); + if (!r_io_read_at (mbc->io, mbc->seek, buf, len)) { + eprintf ("r_io_read_at failed\n"); + return -1; + } + eprintf ("read @ 0x%"PFMT64x" %d bytes\n", mbc->seek, len); + mbc->seek += len; + return len; +} + +RIOPlugin r_io_plugin_gb_mbc1 = { + .meta = { + .name = "gb_mbc1", + .desc = "gb_mbc1", + .license = "LGPL", + }, + .uris = "gb_mbc1://", + .open = __open, + .close = __close, + .read = __read, + .check = __check, + .seek = __lseek, + .write = __write, +}; + +#ifndef R2_PLUGIN_INCORE +R_API RLibStruct radare_plugin = { + .type = R_LIB_TYPE_IO, + .data = &r_io_plugin_gb_mbc1, + .version = R2_VERSION +}; +#endif