From 86904c13d5e365ecd498819ebf91b38610c0b655 Mon Sep 17 00:00:00 2001 From: Lowly Worm Date: Sat, 6 Jan 2018 16:33:49 -0800 Subject: [PATCH] add n64 (z64 format) loader (#9142) --- libr/bin/meson.build | 1 + libr/bin/p/Makefile | 2 +- libr/bin/p/bin_z64.c | 189 +++++++++++++++++++++++++++++++++++++++++++ libr/bin/p/z64.mk | 11 +++ libr/meson.build | 1 + plugins.nogpl.cfg | 1 + 6 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 libr/bin/p/bin_z64.c create mode 100644 libr/bin/p/z64.mk diff --git a/libr/bin/meson.build b/libr/bin/meson.build index a6ebb3f4d8..4b533be102 100644 --- a/libr/bin/meson.build +++ b/libr/bin/meson.build @@ -59,6 +59,7 @@ files=[ 'p/bin_xtr_dyldcache.c', 'p/bin_xtr_fatmach0.c', 'p/bin_zimg.c', +'p/bin_z64.c', 'format/bflt/bflt.c', 'format/coff/coff.c', diff --git a/libr/bin/p/Makefile b/libr/bin/p/Makefile index b05a141a7f..caef63b87b 100644 --- a/libr/bin/p/Makefile +++ b/libr/bin/p/Makefile @@ -21,7 +21,7 @@ FORMATS+=bios.mk mach064.mk fatmach0.mk dyldcache.mk java.mk FORMATS+=dex.mk fs.mk ningb.mk coff.mk ningba.mk xbe.mk zimg.mk FORMATS+=omf.mk cgc.mk dol.mk nes.mk mbn.mk psxexe.mk spc700.mk FORMATS+=vsf.mk nin3ds.mk xtr_dyldcache.mk bflt.mk wasm.mk sfc.mk -FORMATS+=mdmp.mk +FORMATS+=mdmp.mk z64.mk include $(FORMATS) all: ${ALL_TARGETS} diff --git a/libr/bin/p/bin_z64.c b/libr/bin/p/bin_z64.c new file mode 100644 index 0000000000..fb376324d4 --- /dev/null +++ b/libr/bin/p/bin_z64.c @@ -0,0 +1,189 @@ +/* radare2 - LGPL - Copyright 2018 - lowlyw */ + +/* + * info comes from here. + * https://github.com/mikeryan/n64dev + * http://en64.shoutwiki.com/wiki/N64_Memory + */ + +#include +#include +#include +#include +#include +#include + +#define N64_ROM_START 0x1000 + +// starting at 0 +/* +0000h (1 byte): initial PI_BSB_DOM1_LAT_REG value (0x80) +0001h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x37) +0002h (1 byte): initial PI_BSB_DOM1_PWD_REG value (0x12) +0003h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x40) +0004h - 0007h (1 dword): ClockRate +0008h - 000Bh (1 dword): Program Counter (PC) +000Ch - 000Fh (1 dword): Release +0010h - 0013h (1 dword): CRC1 +0014h - 0017h (1 dword): CRC2 +0018h - 001Fh (2 dwords): Unknown (0x0000000000000000) +0020h - 0033h (20 bytes): Image name + Padded with 0x00 or spaces (0x20) +0034h - 0037h (1 dword): Unknown (0x00000000) +0038h - 003Bh (1 dword): Manufacturer ID + 0x0000004E = Nintendo ('N') +003Ch - 003Dh (1 word): Cartridge ID +003Eh - 003Fh (1 word): Country code + 0x4400 = Germany ('D') + 0x4500 = USA ('E') + 0x4A00 = Japan ('J') + 0x5000 = Europe ('P') + 0x5500 = Australia ('U') +0040h - 0FFFh (1008 dwords): Boot code +*/ +typedef struct { + ut8 x1; /* initial PI_BSB_DOM1_LAT_REG value */ + ut8 x2; /* initial PI_BSB_DOM1_PGS_REG value */ + ut8 x3; /* initial PI_BSB_DOM1_PWD_REG value */ + ut8 x4; /* initial PI_BSB_DOM1_RLS_REG value */ + ut32 ClockRate; + ut32 BootAddress; + ut32 Release; + ut32 CRC1; + ut32 CRC2; + ut64 UNK1; + char Name[20]; + ut32 UNK2; + ut16 UNK3; + ut8 UNK4; + ut8 ManufacturerID; // 0x0000004E ('N') ? + ut16 CartridgeID; + char CountryCode; + ut8 UNK5; + // BOOT CODE? +} N64Header; + +static N64Header n64_header; + +static ut64 baddr(RBinFile *bf) { + return (ut64) r_read_be32(&n64_header.BootAddress); +} + +static bool check_bytes (const ut8 *buf, ut64 length) { + // XXX just based on size? we should validate the struct too + if (length < N64_ROM_START) { + return false; + } + return true; +} + +static void *load_bytes(RBinFile *bf, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) { + if (check_bytes (r_buf_buffer (bf->buf), sz)) { + return memcpy (&n64_header, buf, sizeof (N64Header)); + } + return NULL; +} + +static bool load(RBinFile *bf) { + const ut8 *bytes = bf ? r_buf_buffer (bf->buf) : NULL; + char *fname = bf->file; + ut64 sz = bf ? r_buf_size (bf->buf) : 0; + if (!bf || !bf->o) { + return false; + } + // XXX hack based on name? + if(strlen(fname) > 4 && !strcmp(fname + strlen(fname) - 4, ".z64")) { + bf->o->bin_obj = load_bytes (bf, bytes, sz, bf->o->loadaddr, bf->sdb); + return check_bytes (bytes, sz); + } else { + return false; + } +} + +static int destroy(RBinFile *bf) { + return true; +} + +static RList *entries(RBinFile *bf) { + RList /**/ *ret = r_list_new (); + RBinAddr *ptr = NULL; + if (!(ret = r_list_new ())) { + return NULL; + } + ret->free = free; + if ((ptr = R_NEW0 (RBinAddr))) { + ptr->paddr = N64_ROM_START; + ptr->vaddr = baddr (bf); + r_list_append (ret, ptr); + } + return ret; +} + +static RList *sections(RBinFile *bf) { + RList /**/ *ret = r_list_new (); + if (!ret) { + return NULL; + } + RBinSection *text = R_NEW0 (RBinSection); + if (!text) { + r_list_free (ret); + return NULL; + } + strncpy (text->name, "text", R_BIN_SIZEOF_STRINGS); + text->size = bf->buf->length - sizeof (N64Header); + text->vsize = text->size; + text->paddr = N64_ROM_START; + text->vaddr = baddr (bf); + text->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x + text->add = true; + r_list_append (ret, text); + return ret; +} + +static ut64 boffset(RBinFile *bf) { + return 0LL; +} + +static RBinInfo *info(RBinFile *bf) { + char GameName[21] = {0}; + RBinInfo *ret = R_NEW0 (RBinInfo); + if (!ret) { + return NULL; + } + memcpy (GameName, n64_header.Name, sizeof (n64_header.Name)); + ret->file = r_str_newf ("%s (%c)", GameName, n64_header.CountryCode); + ret->os = strdup ("n64"); + ret->arch = strdup ("mips"); + ret->machine = strdup ("Nintendo 64"); + ret->type = strdup ("ROM"); + ret->bits = 32; + ret->has_va = true; + ret->big_endian = true; + return ret; +} + +#if !R_BIN_Z64 + +RBinPlugin r_bin_plugin_z64 = { + .name = "z64", + .desc = "Nintendo 64 binaries big endian r_bin plugin", + .license = "LGPL2", + .load = &load, + .load_bytes = &load_bytes, + .destroy = &destroy, + .check_bytes = &check_bytes, + .baddr = baddr, + .boffset = &boffset, + .entries = &entries, + .sections = §ions, + .info = &info +}; + +#ifndef CORELIB +RLibStruct radare_plugin = { + .type = R_LIB_TYPE_BIN, + .data = &r_bin_plugin_z64, + .version = R2_VERSION +}; +#endif +#endif diff --git a/libr/bin/p/z64.mk b/libr/bin/p/z64.mk new file mode 100644 index 0000000000..7ce548cc8d --- /dev/null +++ b/libr/bin/p/z64.mk @@ -0,0 +1,11 @@ +OBJ_Z64=bin_z64.o + +STATIC_OBJ+=${OBJ_Z64} +TARGET_Z64=bin_z64.${EXT_SO} + +ALL_TARGETS+=${TARGET_Z64} + +${TARGET_Z64}: ${OBJ_Z64} + ${CC} $(call libname,bin_z64) ${CFLAGS} \ + ${OBJ_Z64} \ + $(LINK) $(LDFLAGS) diff --git a/libr/meson.build b/libr/meson.build index 39062b2aa2..b3b45e4d3a 100644 --- a/libr/meson.build +++ b/libr/meson.build @@ -129,6 +129,7 @@ bin = [ 'wasm', 'xbe', 'zimg', + 'z64', ] bin_xtr = [ diff --git a/plugins.nogpl.cfg b/plugins.nogpl.cfg index a6de629044..c9f9bfac36 100644 --- a/plugins.nogpl.cfg +++ b/plugins.nogpl.cfg @@ -80,6 +80,7 @@ bin.pebble bin.rar bin.te bin.xbe +bin.z64 bin_xtr.dyldcache bin_xtr.fatmach0 bp.arm