1 /* radare - LGPL - 2013 - 2017 - condret@runas-racer.com */
2 
3 #include <r_types.h>
4 #include <r_util.h>
5 #include <r_lib.h>
6 #include <r_bin.h>
7 #include <string.h>
8 #include "../format/nin/nin.h"
9 
check_buffer(RBuffer * b)10 static bool check_buffer(RBuffer *b) {
11 	ut8 lict[sizeof (lic)];
12 	if (r_buf_read_at (b, 0x104, lict, sizeof (lict)) == sizeof (lict)) {
13 		return !memcmp (lict, lic, sizeof (lict));
14 	}
15 	return false;
16 }
17 
load_buffer(RBinFile * bf,void ** bin_obj,RBuffer * buf,ut64 loadaddr,Sdb * sdb)18 static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
19 	return check_buffer (buf);
20 }
21 
baddr(RBinFile * bf)22 static ut64 baddr(RBinFile *bf) {
23 	return 0LL;
24 }
25 
binsym(RBinFile * bf,int type)26 static RBinAddr* binsym(RBinFile *bf, int type) {
27 	if (type == R_BIN_SYM_MAIN && bf && bf->buf) {
28 		ut8 init_jmp[4];
29 		RBinAddr *ret = R_NEW0 (RBinAddr);
30 		if (!ret) {
31 			return NULL;
32 		}
33 		r_buf_read_at (bf->buf, 0x100, init_jmp, 4);
34 		if (init_jmp[1] == 0xc3) {
35 			ret->paddr = ret->vaddr = init_jmp[3]*0x100 + init_jmp[2];
36 			return ret;
37 		}
38 		free (ret);
39 	}
40 	return NULL;
41 }
42 
entries(RBinFile * bf)43 static RList* entries(RBinFile *bf) {
44 	RList *ret = r_list_new ();
45 	RBinAddr *ptr = NULL;
46 
47 	if (bf && bf->buf != NULL) {
48 		if (!ret) {
49 			return NULL;
50 		}
51 		ret->free = free;
52 		if (!(ptr = R_NEW0 (RBinAddr))) {
53 			return ret;
54 		}
55 		ptr->paddr = ptr->vaddr = ptr->hpaddr = 0x100;
56 		r_list_append (ret, ptr);
57 	}
58 	return ret;
59 }
60 
sections(RBinFile * bf)61 static RList* sections(RBinFile *bf){
62 	ut8 bank;
63 	int i;
64 	RList *ret;
65 
66 	if (!bf) {
67 		return NULL;
68 	}
69 
70 	ret = r_list_new ();
71 	if (!ret) {
72 		return NULL;
73 	}
74 
75 	r_buf_read_at (bf->buf, 0x148, &bank, 1);
76 	bank = gb_get_rombanks(bank);
77 #ifdef _MSC_VER
78 	RBinSection **rombank = (RBinSection**) malloc (sizeof (RBinSection*) * bank);
79 #else
80 	RBinSection *rombank[bank];
81 #endif
82 
83 	if (!bf->buf) {
84 		free (ret);
85 #ifdef _MSC_VER
86 		free (rombank);
87 #endif
88 		return NULL;
89 	}
90 
91 	ret->free = free;
92 
93 	rombank[0] = R_NEW0 (RBinSection);
94 	rombank[0]->name = strdup ("rombank00");
95 	rombank[0]->paddr = 0;
96 	rombank[0]->size = 0x4000;
97 	rombank[0]->vsize = 0x4000;
98 	rombank[0]->vaddr = 0;
99 	rombank[0]->perm = r_str_rwx ("rx");
100 	rombank[0]->add = true;
101 
102 	r_list_append (ret, rombank[0]);
103 
104 	for (i = 1; i < bank; i++) {
105 		rombank[i] = R_NEW0 (RBinSection);
106 		rombank[i]->name = r_str_newf ("rombank%02x", i);
107 		rombank[i]->paddr = i*0x4000;
108 		rombank[i]->vaddr = i*0x10000-0xc000;			//spaaaaaaaaaaaaaaaace!!!
109 		rombank[i]->size = rombank[i]->vsize = 0x4000;
110 		rombank[i]->perm = r_str_rwx ("rx");
111 		rombank[i]->add = true;
112 		r_list_append (ret,rombank[i]);
113 	}
114 #ifdef _MSC_VER
115 	free (rombank);
116 #endif
117 	return ret;
118 }
119 
symbols(RBinFile * bf)120 static RList* symbols(RBinFile *bf) {
121 	RList *ret = NULL;
122 	RBinSymbol *ptr[13];
123 	int i;
124 	if (!(ret = r_list_new ())) {
125 		return NULL;
126 	}
127 	ret->free = free;
128 
129 	for (i = 0; i < 8; i++) {
130 		if (!(ptr[i] = R_NEW0 (RBinSymbol))) {
131 			ret->free (ret);
132 			return NULL;
133 		}
134 		ptr[i]->name = r_str_newf ("rst_%i", i*8);
135 		ptr[i]->paddr = ptr[i]->vaddr = i*8;
136 		ptr[i]->size = 1;
137 		ptr[i]->ordinal = i;
138 		r_list_append (ret, ptr[i]);
139 	}
140 
141 	if (!(ptr[8] = R_NEW0 (RBinSymbol))) {
142 		return ret;
143 	}
144 
145 	ptr[8]->name = strdup ("Interrupt_Vblank");
146 	ptr[8]->paddr = ptr[8]->vaddr = 64;
147 	ptr[8]->size = 1;
148 	ptr[8]->ordinal = 8;
149 	r_list_append (ret, ptr[8]);
150 
151 	if (!(ptr[9] = R_NEW0 (RBinSymbol))) {
152 		return ret;
153 	}
154 
155 	ptr[9]->name = strdup ("Interrupt_LCDC-Status");
156 	ptr[9]->paddr = ptr[9]->vaddr = 72;
157 	ptr[9]->size = 1;
158 	ptr[9]->ordinal = 9;
159 	r_list_append (ret, ptr[9]);
160 
161 	if (!(ptr[10] = R_NEW0 (RBinSymbol))) {
162 		return ret;
163 	}
164 
165 	ptr[10]->name = strdup ("Interrupt_Timer-Overflow");
166 	ptr[10]->paddr = ptr[10]->vaddr = 80;
167 	ptr[10]->size = 1;
168 	ptr[10]->ordinal = 10;
169 	r_list_append (ret, ptr[10]);
170 
171 	if (!(ptr[11] = R_NEW0 (RBinSymbol))) {
172 		return ret;
173 	}
174 
175 	ptr[11]->name = strdup ("Interrupt_Serial-Transfere");
176 	ptr[11]->paddr = ptr[11]->vaddr = 88;
177 	ptr[11]->size = 1;
178 	ptr[11]->ordinal = 11;
179 	r_list_append (ret, ptr[11]);
180 
181 	if (!(ptr[12] = R_NEW0 (RBinSymbol))) {
182 		return ret;
183 	}
184 
185 	ptr[12]->name = strdup ("Interrupt_Joypad");
186 	ptr[12]->paddr = ptr[12]->vaddr = 96;
187 	ptr[12]->size = 1;
188 	ptr[12]->ordinal = 12;
189 	r_list_append (ret, ptr[12]);
190 
191 	return ret;
192 }
193 
info(RBinFile * bf)194 static RBinInfo* info(RBinFile *bf) {
195 	ut8 rom_header[76];
196 	RBinInfo *ret = R_NEW0 (RBinInfo);
197 	if (!ret || !bf || !bf->buf) {
198 		free (ret);
199 		return NULL;
200 	}
201 	r_buf_read_at (bf->buf, 0x104, rom_header, 76);
202 	ret->file = r_str_ndup ((const char*)&rom_header[48], 16);
203 	ret->type = malloc (128);
204 	ret->type[0] = 0;
205 	gb_get_gbtype (ret->type, rom_header[66], rom_header[63]);
206 	gb_add_cardtype (ret->type, rom_header[67]); // XXX
207 	ret->machine = strdup ("Gameboy");
208 	ret->os = strdup ("any");
209 	ret->arch = strdup ("gb");
210 	ret->has_va = true;
211 	ret->bits = 16;
212 	ret->big_endian = 0;
213 	ret->dbg_info = 0;
214 	return ret;
215 }
216 
mem(RBinFile * bf)217 RList *mem (RBinFile *bf) {
218 	RList *ret;
219 	RBinMem *m, *n;
220 	if (!(ret = r_list_new ())) {
221 		return NULL;
222 	}
223 	ret->free = free;
224 	if (!(m = R_NEW0 (RBinMem))) {
225 		r_list_free (ret);
226 		return NULL;
227 	}
228 	m->name = strdup ("fastram");
229 	m->addr = 0xff80LL;
230 	m->size = 0x80;
231 	m->perms = r_str_rwx ("rwx");
232 	r_list_append (ret, m);
233 
234 	if (!(m = R_NEW0 (RBinMem))) {
235 		return ret;
236 	}
237 	m->name = strdup ("ioports");
238 	m->addr = 0xff00LL;
239 	m->size = 0x4c;
240 	m->perms = r_str_rwx ("rwx");
241 	r_list_append (ret, m);
242 
243 	if (!(m = R_NEW0 (RBinMem))) {
244 		return ret;
245 	}
246 	m->name = strdup ("oam");
247 	m->addr = 0xfe00LL;
248 	m->size = 0xa0;
249 	m->perms = r_str_rwx ("rwx");
250 	r_list_append (ret, m);
251 
252 	if (!(m = R_NEW0 (RBinMem))) {
253 		return ret;
254 	}
255 	m->name = strdup ("videoram");
256 	m->addr = 0x8000LL;
257 	m->size = 0x2000;
258 	m->perms = r_str_rwx ("rwx");
259 	r_list_append (ret, m);
260 
261 	if (!(m = R_NEW0 (RBinMem))) {
262 		return ret;
263 	}
264 	m->name = strdup ("iram");
265 	m->addr = 0xc000LL;
266 	m->size = 0x2000;
267 	m->perms = r_str_rwx ("rwx");
268 	r_list_append (ret, m);
269 	if (!(m->mirrors = r_list_new ())) {
270 		return ret;
271 	}
272 	if (!(n = R_NEW0 (RBinMem))) {
273 		r_list_free (m->mirrors);
274 		m->mirrors = NULL;
275 		return ret;
276 	}
277 	n->name = strdup ("iram_echo");
278 	n->addr = 0xe000LL;
279 	n->size = 0x1e00;
280 	n->perms = r_str_rwx ("rx");
281 	r_list_append (m->mirrors, n);
282 
283 	return ret;
284 }
285 
286 RBinPlugin r_bin_plugin_ningb = {
287 	.name = "ningb",
288 	.desc = "Gameboy format r_bin plugin",
289 	.license = "LGPL3",
290 	.load_buffer = &load_buffer,
291 	.check_buffer = &check_buffer,
292 	.baddr = &baddr,
293 	.binsym = &binsym,
294 	.entries = &entries,
295 	.sections = &sections,
296 	.symbols = &symbols,
297 	.info = &info,
298 	.mem = &mem,
299 };
300 
301 #ifndef R2_PLUGIN_INCORE
302 R_API RLibStruct radare_plugin = {
303 	.type = R_LIB_TYPE_BIN,
304 	.data = &r_bin_plugin_ningb,
305 	.version = R2_VERSION
306 };
307 #endif
308