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