Start implementing mbc1
This commit is contained in:
parent
29081f5f5e
commit
3ed0bed61c
|
@ -24,6 +24,9 @@ GBTimers *gb_timers_open(RIO *io);
|
||||||
void gb_timers_close(RIO *io, GBTimers *timers);
|
void gb_timers_close(RIO *io, GBTimers *timers);
|
||||||
void gb_timers_update(GBTimers *timers, ut32 cycles);
|
void gb_timers_update(GBTimers *timers, ut32 cycles);
|
||||||
|
|
||||||
|
int gb_mbc1_open(RIO *io, char *path);
|
||||||
|
|
||||||
extern RIOPlugin r_io_plugin_gb_timers;
|
extern RIOPlugin r_io_plugin_gb_timers;
|
||||||
|
extern RIOPlugin r_io_plugin_gb_mbc1;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
137
io/mbc1.c
Normal file
137
io/mbc1.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gb.h>
|
||||||
|
#include <r_io.h>
|
||||||
|
#include <r_util.h>
|
||||||
|
|
||||||
|
typedef struct gb_mbc1_data {
|
||||||
|
RIO *io;
|
||||||
|
ut32 *rombank_to_io_map;
|
||||||
|
ut32 *rambank_to_io_map;
|
||||||
|
ut64 seek;
|
||||||
|
ut32 size;
|
||||||
|
int file_fd;
|
||||||
|
int mem_fd;
|
||||||
|
ut8 n_rombanks;
|
||||||
|
ut8 n_rambanks;
|
||||||
|
ut8 rombank_mask;
|
||||||
|
ut8 rombank;
|
||||||
|
union {
|
||||||
|
ut8 high_rombank;
|
||||||
|
ut8 rambank;
|
||||||
|
};
|
||||||
|
bool ram_enable;
|
||||||
|
bool small_ram;
|
||||||
|
} MBC1;
|
||||||
|
|
||||||
|
ut8 mbc1_mask[] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x1f, 0x1f };
|
||||||
|
|
||||||
|
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) {
|
||||||
|
if (!r_str_startswith (pathname, "gb_mbc1://")) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!r_file_exists (&pathname[10]) || !r_file_is_regular (&pathname[10])) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
RIODesc *desc = r_io_desc_open (io, &pathname[10], R_PERM_R, 0);
|
||||||
|
if (!desc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ut8 mbc_info[3] = {0xfb, 0xff, 0xff};
|
||||||
|
r_io_desc_read_at (desc, 0x147, mbc_info, 3);
|
||||||
|
r_io_desc_close (desc);
|
||||||
|
if (R_UNLIKELY (!mbc_info[0] || (mbc_info[0] > 3) ||
|
||||||
|
(mbc_info[1] > 6) || (mbc_info[2] > 2))) {
|
||||||
|
//not a mbc1 game
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MBC1 *mbc = R_NEW0 (MBC1);
|
||||||
|
if (!mbc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mbc->n_rombanks = 0x1 << (mbc_info[1] + 1);
|
||||||
|
mbc->rombank_to_io_map = R_NEWS0 (ut32, mbc->n_rombanks);
|
||||||
|
if (!mbc->rombank_to_io_map) {
|
||||||
|
free (mbc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mbc->rombank_mask = mbc1_mask[mbc_info[1]];
|
||||||
|
if (mbc_info[0] != 1) {
|
||||||
|
switch (mbc_info[2]) {
|
||||||
|
case 0x1:
|
||||||
|
mbc->small_ram = true;
|
||||||
|
case 0x3:
|
||||||
|
mbc->n_rambanks = 4;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
mbc->n_rambanks = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mbc->rambank_to_io_map = R_NEWS0 (ut32, mbc->n_rambanks);
|
||||||
|
if (!mbc->rambank_to_io_map) {
|
||||||
|
free (mbc->rombank_to_io_map);
|
||||||
|
free (mbc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbc->io = r_io_new ();
|
||||||
|
if (!mbc->io) {
|
||||||
|
free (mbc->rombank_to_io_map);
|
||||||
|
free (mbc->rambank_to_io_map);
|
||||||
|
free (mbc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mbc->file_fd = r_io_fd_open (mbc->io, &pathname[10], R_PERM_R, 0);
|
||||||
|
{
|
||||||
|
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->file_fd < 0) || (mbc->mem_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;
|
||||||
|
ut32 i;
|
||||||
|
for (i = 1; i < mbc->n_rombanks; i++) {
|
||||||
|
map = r_io_map_add_bottom (mbc->io, mbc->file_fd, R_PERM_R,
|
||||||
|
0x4000 * i, 0x4000, 0x4000);
|
||||||
|
if (!map) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
mbc->rombank_to_io_map[i] = 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,
|
||||||
|
0ULL, 0xa000 + 0x800 * i, 0x800);
|
||||||
|
if (!map) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
mbc->rambank_to_io_map[i] = map->id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
map = r_io_map_add_bottom (mbc->io, mbc->mem_fd, R_PERM_RW,
|
||||||
|
0x2000 * i, 0xa000, 0x2000);
|
||||||
|
if (!map) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
mbc->rambank_to_io_map[i] = map->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbc->rombank = 1;
|
||||||
|
mbc->io->cache.mode = 0;
|
||||||
|
desc = r_io_desc_new (io, &r_io_plugin_gb_mbc1, pathname,
|
||||||
|
R_PERM_RWX, mode, mbc);
|
||||||
|
return desc;
|
||||||
|
fail:
|
||||||
|
r_io_free (mbc->io);
|
||||||
|
free (mbc->rombank_to_io_map);
|
||||||
|
free (mbc->rambank_to_io_map);
|
||||||
|
free (mbc);
|
||||||
|
return NULL;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user