radare2/libr/bin/p/bin_sms.c
2017-04-13 11:54:28 +02:00

133 lines
3.2 KiB
C

/* radare - LGPL - Copyright 2015-2016 - shengdi */
#include <r_bin.h>
typedef struct gen_hdr {
ut8 HeaderID[8];
ut8 ReservedWord[2];
ut16 CheckSum;
ut8 ProductCode[2];
ut8 Version; //Low 4 bits version, Top 4 bits ProductCode
ut8 RegionRomSize; //Low 4 bits RomSize, Top 4 bits Region
} SMS_Header;
#define CMP8(o,x) strncmp((const char*)bs+o,x,8)
#define CMP4(o,x) strncmp((const char*)bs+o,x,4)
static bool check_bytes(const ut8 *bs, ut64 length) {
if (length > 0x2000 && !CMP8(0x1ff0, "TMR SEGA")) {
return true;
}
if (length > 0x4000 && !CMP8(0x3ff0, "TMR SEGA")) {
return true;
}
if (length > 0x8000 && !CMP8(0x7ff0, "TMR SEGA")) {
return true;
}
if (length > 0x9000 && !CMP8(0x8ff0, "TMR SEGA")) {
return true;
}
if (length > 0x8000 && !CMP4(0x7fe0, "SDSC")) {
return true;
}
return false;
}
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){
check_bytes (buf, sz);
return R_NOTNULL;
}
static RBinInfo* info(RBinFile *arch) {
const char *bs;
SMS_Header *hdr = NULL;
RBinInfo *ret = R_NEW0 (RBinInfo);
if (!ret || !arch || !arch->buf) {
free (ret);
return NULL;
}
ret->file = strdup (arch->file);
ret->type = strdup ("ROM");
ret->machine = strdup ("SEGA MasterSystem");
ret->os = strdup ("sms");
ret->arch = strdup ("z80");
ret->has_va = 1;
ret->bits = 8;
bs = (const char*)arch->buf->buf;
// TODO: figure out sections/symbols for this format and move this there
// also add SDSC headers..and find entry
if (!CMP8(0x1ff0, "TMR SEGA")) {
hdr = (SMS_Header*)(bs + 0x1ff0);
} else if (!CMP8(0x3ff0, "TMR SEGA")) {
hdr = (SMS_Header*)(bs + 0x3ff0);
} else if (!CMP8(0x7ff0, "TMR SEGA")) {
hdr = (SMS_Header*)(bs + 0x7ff0);
} else if (!CMP8(0x8ff0, "TMR SEGA")) {
hdr = (SMS_Header*)(bs + 0x8ff0);
} else {
eprintf ("Cannot find magic SEGA copyright\n");
free (ret);
return NULL;
}
eprintf ("Checksum: 0x%04x\n", (ut32)hdr->CheckSum);
eprintf ("ProductCode: %02d%02X%02X\n", (hdr->Version >> 4), hdr->ProductCode[1],
hdr->ProductCode[0]);
switch (hdr->RegionRomSize >> 4) {
case 3:
eprintf ("Console: Sega Master System\n");
eprintf ("Region: Japan\n");
break;
case 4:
eprintf ("Console: Sega Master System\n");
eprintf ("Region: Export\n");
break;
case 5:
eprintf ("Console: Game Gear\n");
eprintf ("Region: Japan\n");
break;
case 6:
eprintf ("Console: Game Gear\n");
eprintf ("Region: Export\n");
break;
case 7:
eprintf ("Console: Game Gear\n");
eprintf ("Region: International\n");
break;
}
int romsize = 0;
switch (hdr->RegionRomSize & 0xf) {
case 0xa: romsize = 8; break;
case 0xb: romsize = 16; break;
case 0xc: romsize = 32; break;
case 0xd: romsize = 48; break;
case 0xe: romsize = 64; break;
case 0xf: romsize = 128; break;
case 0x0: romsize = 256; break;
case 0x1: romsize = 512; break;
case 0x2: romsize = 1024; break;
}
eprintf ("RomSize: %dKB\n", romsize);
return ret;
}
RBinPlugin r_bin_plugin_sms = {
.name = "sms",
.desc = "SEGA MasterSystem/GameGear",
.license = "LGPL3",
.load_bytes = &load_bytes,
.check_bytes = &check_bytes,
.info = &info,
.minstrlen = 10,
.strfilter = 'U'
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_BIN,
.data = &r_bin_plugin_sms,
.version = R2_VERSION
};
#endif