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 = §ions,
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