/* radare - LGPL - 2013 - 2015 - condret@runas-racer.com */ #include #include #include #include #include #include "../format/nin/nin.h" static Sdb* get_sdb (RBinObject *o) { if (!o) return NULL; //struct r_bin_[NAME]_obj_t *bin = (struct r_bin_r_bin_[NAME]_obj_t *) o->bin_obj; //if (bin->kv) return kv; return NULL; } static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){ return R_NOTNULL; } static int check_bytes(const ut8 *buf, ut64 length) { ut8 lict[48]; if (!buf || length < (0x104+48)) return 0; memcpy (lict, buf + 0x104, 48); return (!memcmp (lict, lic, 48))? 1: 0; } static int check(RBinFile *arch) { const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL; ut64 sz = arch ? r_buf_size (arch->buf): 0; return check_bytes (bytes, sz); } static int load(RBinFile *arch) { const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL; ut64 sz = arch ? r_buf_size (arch->buf): 0; if (!arch || !arch->o) return false; arch->o->bin_obj = load_bytes (arch, bytes, sz, arch->o->loadaddr, arch->sdb); return check_bytes (bytes, sz); } static int destroy(RBinFile *arch) { r_buf_free (arch->buf); arch->buf = NULL; return true; } static ut64 baddr(RBinFile *arch) { return 0LL; } static RBinAddr* binsym(RBinFile *arch, int type) { if (type == R_BIN_SYM_MAIN && arch && arch->buf) { ut8 init_jmp[4]; RBinAddr *ret = R_NEW0 (RBinAddr); if (!ret) return NULL; r_buf_read_at (arch->buf, 0x100, init_jmp, 4); if (init_jmp[1] == 0xc3) { ret->paddr = ret->vaddr = init_jmp[3]*0x100 + init_jmp[2]; return ret; } free (ret); } return NULL; } static RList* entries(RBinFile *arch) { RList *ret = r_list_new (); RBinAddr *ptr = NULL; if (arch && arch->buf != NULL) { if (!ret) return NULL; ret->free = free; if (!(ptr = R_NEW0 (RBinAddr))) return ret; ptr->paddr = ptr->vaddr = 0x100; r_list_append (ret, ptr); } return ret; } static RList* sections(RBinFile *arch){ ut8 bank; int i; RList *ret; if (!arch) return NULL; ret = r_list_new(); if (!ret ) return NULL; r_buf_read_at (arch->buf, 0x148, &bank, 1); bank = gb_get_rombanks(bank); RBinSection *rombank[bank]; if (!arch->buf) { free (ret); return NULL; } ret->free = free; rombank[0] = R_NEW0 (RBinSection); strncpy (rombank[0]->name, "rombank00", R_BIN_SIZEOF_STRINGS); rombank[0]->paddr = 0; rombank[0]->size = 0x4000; rombank[0]->vsize = 0x4000; rombank[0]->vaddr = 0; rombank[0]->srwx = r_str_rwx ("mrx"); rombank[0]->add = true; r_list_append (ret, rombank[0]); for (i = 1; i < bank; i++) { rombank[i] = R_NEW0 (RBinSection); sprintf (rombank[i]->name,"rombank%02x",i); rombank[i]->paddr = i*0x4000; rombank[i]->vaddr = i*0x10000-0xc000; //spaaaaaaaaaaaaaaaace!!! rombank[i]->size = rombank[i]->vsize = 0x4000; rombank[i]->srwx = r_str_rwx ("mrx"); rombank[i]->add = true; r_list_append (ret,rombank[i]); } return ret; } static RList* symbols(RBinFile *arch) { RList *ret = NULL; RBinSymbol *ptr[13]; int i; if (!(ret = r_list_new())) return NULL; ret->free = free; for (i = 0; i < 8; i++) { if (!(ptr[i] = R_NEW0 (RBinSymbol))) { ret->free (ret); return NULL; } ptr[i]->name = r_str_newf ("rst_%i", i*8); ptr[i]->paddr = ptr[i]->vaddr = i*8; ptr[i]->size = 1; ptr[i]->ordinal = i; r_list_append (ret, ptr[i]); } if (!(ptr[8] = R_NEW0 (RBinSymbol))) return ret; ptr[8]->name = strdup ("Interrupt_Vblank"); ptr[8]->paddr = ptr[8]->vaddr = 64; ptr[8]->size = 1; ptr[8]->ordinal = 8; r_list_append (ret, ptr[8]); if (!(ptr[9] = R_NEW0 (RBinSymbol))) return ret; ptr[9]->name = strdup ("Interrupt_LCDC-Status"); ptr[9]->paddr = ptr[9]->vaddr = 72; ptr[9]->size = 1; ptr[9]->ordinal = 9; r_list_append (ret, ptr[9]); if (!(ptr[10] = R_NEW0 (RBinSymbol))) return ret; ptr[10]->name = strdup ("Interrupt_Timer-Overflow"); ptr[10]->paddr = ptr[10]->vaddr = 80; ptr[10]->size = 1; ptr[10]->ordinal = 10; r_list_append (ret, ptr[10]); if (!(ptr[11] = R_NEW0 (RBinSymbol))) return ret; ptr[11]->name = strdup ("Interrupt_Serial-Transfere"); ptr[11]->paddr = ptr[11]->vaddr = 88; ptr[11]->size = 1; ptr[11]->ordinal = 11; r_list_append (ret, ptr[11]); if (!(ptr[12] = R_NEW0 (RBinSymbol))) return ret; ptr[12]->name = strdup ("Interrupt_Joypad"); ptr[12]->paddr = ptr[12]->vaddr = 96; ptr[12]->size = 1; ptr[12]->ordinal = 12; r_list_append (ret, ptr[12]); return ret; } static RBinInfo* info(RBinFile *arch) { ut8 rom_header[76]; RBinInfo *ret = R_NEW0 (RBinInfo); if (!ret || !arch || !arch->buf) { free (ret); return NULL; } r_buf_read_at (arch->buf, 0x104, rom_header, 76); ret->file = calloc (1, 17); strncpy (ret->file, (const char*)&rom_header[48], 16); ret->type = malloc (128); ret->type[0] = 0; gb_get_gbtype (ret->type, rom_header[66], rom_header[63]); gb_add_cardtype (ret->type, rom_header[67]); // XXX ret->machine = strdup ("Gameboy"); ret->os = strdup ("any"); ret->arch = strdup ("gb"); ret->has_va = true; ret->bits = 16; ret->big_endian = 0; ret->dbg_info = 0; return ret; } RList *mem (RBinFile *arch) { RList *ret; RBinMem *m, *n; if (!(ret = r_list_new())) return NULL; ret->free = free; if (!(m = R_NEW0 (RBinMem))) { r_list_free (ret); return NULL; } m->name = strdup ("fastram"); m->addr = 0xff80LL; m->size = 0x80; m->perms = r_str_rwx ("rwx"); r_list_append (ret, m); if (!(m = R_NEW0 (RBinMem))) return ret; m->name = strdup ("ioports"); m->addr = 0xff00LL; m->size = 0x4c; m->perms = r_str_rwx ("rwx"); r_list_append (ret, m); if (!(m = R_NEW0 (RBinMem))) return ret; m->name = strdup ("oam"); m->addr = 0xfe00LL; m->size = 0xa0; m->perms = r_str_rwx ("rwx"); r_list_append (ret, m); if (!(m = R_NEW0 (RBinMem))) return ret; m->name = strdup ("videoram"); m->addr = 0x8000LL; m->size = 0x2000; m->perms = r_str_rwx ("rwx"); r_list_append (ret, m); if (!(m = R_NEW0 (RBinMem))) return ret; m->name = strdup ("iram"); m->addr = 0xc000LL; m->size = 0x2000; m->perms = r_str_rwx ("rwx"); r_list_append (ret, m); if (!(m->mirrors = r_list_new())) return ret; if (!(n = R_NEW0 (RBinMem))) { r_list_free (m->mirrors); m->mirrors = NULL; return ret; } n->name = strdup ("iram_echo"); n->addr = 0xe000LL; n->size = 0x1e00; n->perms = r_str_rwx ("rx"); r_list_append (m->mirrors, n); return ret; } struct r_bin_plugin_t r_bin_plugin_ningb = { .name = "ningb", .desc = "Gameboy format r_bin plugin", .license = "LGPL3", .get_sdb = &get_sdb, .load = &load, .load_bytes = &load_bytes, .destroy = &destroy, .check = &check, .check_bytes = &check_bytes, .baddr = &baddr, .binsym = &binsym, .entries = &entries, .sections = §ions, .symbols = &symbols, .info = &info, .mem = &mem, }; #ifndef CORELIB struct r_lib_struct_t radare_plugin = { .type = R_LIB_TYPE_BIN, .data = &r_bin_plugin_ningb, .version = R2_VERSION }; #endif