1 /* radare - LGPL - Copyright 2015-2018 - shengdi */
2
3 #include <r_bin.h>
4
5 typedef struct gen_hdr {
6 ut8 HeaderID[8];
7 ut8 ReservedWord[2];
8 ut16 CheckSum;
9 ut8 ProductCode[2];
10 ut8 Version; //Low 4 bits version, Top 4 bits ProductCode
11 ut8 RegionRomSize; //Low 4 bits RomSize, Top 4 bits Region
12 } SMS_Header;
13
14 static ut32 cb = 0;
15
check_buffer(RBuffer * b)16 static bool check_buffer(RBuffer *b) {
17 ut32 *off, offs[] = { 0x2000, 0x4000, 0x8000, 0x9000, 0 };
18 ut8 signature[8];
19 for (off = (ut32*)&offs; *off; off++) {
20 r_buf_read_at (b, *off - 16, (ut8*)&signature, 8);
21 if (!strncmp ((const char *)signature, "TMR SEGA", 8)) {
22 cb = *off - 16;
23 return true; // int)(*off - 16);
24 }
25 if (*off == 0x8000) {
26 if (!strncmp ((const char *)signature, "SDSC", 4)) {
27 cb = *off - 16;
28 return true; // (int)(*off - 16);
29 }
30 }
31 }
32 return false;
33 }
34
load_buffer(RBinFile * bf,void ** bin_obj,RBuffer * buf,ut64 loadaddr,Sdb * sdb)35 static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
36 return check_buffer (buf);
37 }
38
info(RBinFile * bf)39 static RBinInfo *info(RBinFile *bf) {
40 RBinInfo *ret = R_NEW0 (RBinInfo);
41 if (!ret || !bf || !bf->buf) {
42 free (ret);
43 return NULL;
44 }
45 ret->file = strdup (bf->file);
46 ret->type = strdup ("ROM");
47 ret->machine = strdup ("SEGA MasterSystem");
48 ret->os = strdup ("sms");
49 ret->arch = strdup ("z80");
50 ret->has_va = 1;
51 ret->bits = 8;
52 if (!check_buffer (bf->buf)) {
53 eprintf ("Cannot find magic SEGA copyright\n");
54 free (ret);
55 return NULL;
56 }
57 SMS_Header hdr = {{0}};
58 r_buf_read_at (bf->buf, cb, (ut8*)&hdr, sizeof (hdr));
59 hdr.CheckSum = r_read_le16 (&hdr.CheckSum);
60
61 eprintf ("Checksum: 0x%04x\n", (ut32)hdr.CheckSum); // use endian safe apis here
62 eprintf ("ProductCode: %02d%02X%02X\n", (hdr.Version >> 4), hdr.ProductCode[1],
63 hdr.ProductCode[0]);
64 switch (hdr.RegionRomSize >> 4) {
65 case 3:
66 eprintf ("Console: Sega Master System\n");
67 eprintf ("Region: Japan\n");
68 break;
69 case 4:
70 eprintf ("Console: Sega Master System\n");
71 eprintf ("Region: Export\n");
72 break;
73 case 5:
74 eprintf ("Console: Game Gear\n");
75 eprintf ("Region: Japan\n");
76 break;
77 case 6:
78 eprintf ("Console: Game Gear\n");
79 eprintf ("Region: Export\n");
80 break;
81 case 7:
82 eprintf ("Console: Game Gear\n");
83 eprintf ("Region: International\n");
84 break;
85 }
86 int romsize = 0;
87 switch (hdr.RegionRomSize & 0xf) {
88 case 0xa: romsize = 8; break;
89 case 0xb: romsize = 16; break;
90 case 0xc: romsize = 32; break;
91 case 0xd: romsize = 48; break;
92 case 0xe: romsize = 64; break;
93 case 0xf: romsize = 128; break;
94 case 0x0: romsize = 256; break;
95 case 0x1: romsize = 512; break;
96 case 0x2: romsize = 1024; break;
97 }
98 eprintf ("RomSize: %dKB\n", romsize);
99 return ret;
100 }
101
102 RBinPlugin r_bin_plugin_sms = {
103 .name = "sms",
104 .desc = "SEGA MasterSystem/GameGear",
105 .license = "LGPL3",
106 .load_buffer = &load_buffer,
107 .check_buffer = &check_buffer,
108 .info = &info,
109 .minstrlen = 10,
110 .strfilter = 'U'
111 };
112
113 #ifndef R2_PLUGIN_INCORE
114 R_API RLibStruct radare_plugin = {
115 .type = R_LIB_TYPE_BIN,
116 .data = &r_bin_plugin_sms,
117 .version = R2_VERSION
118 };
119 #endif
120