Rizin
unix-like reverse engineering framework and cli tools
bin_nes.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015-2019 maijin <maijin21@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_bin.h>
5 #include <rz_lib.h>
6 #include "nes/nes_specs.h"
7 
8 static bool check_buffer(RzBuffer *b) {
9  if (rz_buf_size(b) > 4) {
10  ut8 buf[4];
11  rz_buf_read_at(b, 0, buf, sizeof(buf));
12  return (!memcmp(buf, INES_MAGIC, sizeof(buf)));
13  }
14  return false;
15 }
16 
17 static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
18  return check_buffer(buf);
19 }
20 
21 static RzBinInfo *info(RzBinFile *bf) {
22  RzBinInfo *ret = NULL;
23  ines_hdr ihdr;
24  memset(&ihdr, 0, INES_HDR_SIZE);
25  int reat = rz_buf_read_at(bf->buf, 0, (ut8 *)&ihdr, INES_HDR_SIZE);
26  if (reat != INES_HDR_SIZE) {
27  RZ_LOG_ERROR("Truncated Header\n");
28  return NULL;
29  }
30  if (!(ret = RZ_NEW0(RzBinInfo))) {
31  return NULL;
32  }
33  ret->file = strdup(bf->file);
34  ret->type = strdup("ROM");
35  ret->machine = strdup("Nintendo NES");
36  ret->os = strdup("nes");
37  ret->arch = strdup("6502");
38  ret->bits = 8;
39  ret->has_va = 1;
40  return ret;
41 }
42 
43 static void addsym(RzList *ret, const char *name, ut64 addr, ut32 size) {
45  if (!ptr) {
46  return;
47  }
48  ptr->name = strdup(name ? name : "");
49  ptr->paddr = ptr->vaddr = addr;
50  ptr->size = size;
51  ptr->ordinal = 0;
52  rz_list_append(ret, ptr);
53 }
54 
55 static RzList *symbols(RzBinFile *bf) {
56  RzList *ret = NULL;
58  return NULL;
59  }
60  addsym(ret, "NMI_VECTOR_START_ADDRESS", NMI_VECTOR_START_ADDRESS, 2);
61  addsym(ret, "RESET_VECTOR_START_ADDRESS", RESET_VECTOR_START_ADDRESS, 2);
62  addsym(ret, "IRQ_VECTOR_START_ADDRESS", IRQ_VECTOR_START_ADDRESS, 2);
63  addsym(ret, "PPU_CTRL_REG1", PPU_CTRL_REG1, 0x1);
64  addsym(ret, "PPU_CTRL_REG2", PPU_CTRL_REG2, 0x1);
65  addsym(ret, "PPU_STATUS", PPU_STATUS, 0x1);
66  addsym(ret, "PPU_SPR_ADDR", PPU_SPR_ADDR, 0x1);
67  addsym(ret, "PPU_SPR_DATA", PPU_SPR_DATA, 0x1);
68  addsym(ret, "PPU_SCROLL_REG", PPU_SCROLL_REG, 0x1);
69  addsym(ret, "PPU_ADDRESS", PPU_ADDRESS, 0x1);
70  addsym(ret, "PPU_DATA", PPU_DATA, 0x1);
71  addsym(ret, "SND_REGISTER", SND_REGISTER, 0x15);
72  addsym(ret, "SND_SQUARE1_REG", SND_SQUARE1_REG, 0x4);
73  addsym(ret, "SND_SQUARE2_REG", SND_SQUARE2_REG, 0x4);
74  addsym(ret, "SND_TRIANGLE_REG", SND_TRIANGLE_REG, 0x4);
75  addsym(ret, "SND_NOISE_REG", SND_NOISE_REG, 0x2);
76  addsym(ret, "SND_DELTA_REG", SND_DELTA_REG, 0x4);
77  addsym(ret, "SND_MASTERCTRL_REG", SND_MASTERCTRL_REG, 0x5);
78  addsym(ret, "SPR_DMA", SPR_DMA, 0x2);
79  addsym(ret, "JOYPAD_PORT", JOYPAD_PORT, 0x1);
80  addsym(ret, "JOYPAD_PORT1", JOYPAD_PORT1, 0x1);
81  addsym(ret, "JOYPAD_PORT2", JOYPAD_PORT2, 0x1);
82  return ret;
83 }
84 
85 static RzList *sections(RzBinFile *bf) {
86  RzList *ret = NULL;
87  RzBinSection *ptr = NULL;
88  ines_hdr ihdr;
89  memset(&ihdr, 0, INES_HDR_SIZE);
90  int reat = rz_buf_read_at(bf->buf, 0, (ut8 *)&ihdr, INES_HDR_SIZE);
91  if (reat != INES_HDR_SIZE) {
92  RZ_LOG_ERROR("Truncated Header\n");
93  return NULL;
94  }
95  if (!(ret = rz_list_new())) {
96  return NULL;
97  }
98  if (!(ptr = RZ_NEW0(RzBinSection))) {
99  return ret;
100  }
101  ptr->name = strdup("ROM");
102  ptr->paddr = INES_HDR_SIZE;
103  ptr->size = ihdr.prg_page_count_16k * PRG_PAGE_SIZE;
104  bool mirror = ROM_START_ADDRESS + ptr->size <= ROM_MIRROR_ADDRESS; // not a 256bit ROM, mapper 0 mirrors the complete ROM in this case
105  ptr->vaddr = ROM_START_ADDRESS;
106  ptr->vsize = mirror ? ROM_MIRROR_ADDRESS - ROM_START_ADDRESS : ROM_SIZE; // make sure the ROM zero excess does not overlap the mirror
107  ptr->perm = RZ_PERM_RX;
108  rz_list_append(ret, ptr);
109  if (mirror) {
110  if (!(ptr = RZ_NEW0(RzBinSection))) {
111  return ret;
112  }
113  ptr->name = strdup("ROM_MIRROR");
114  ptr->paddr = INES_HDR_SIZE;
115  ptr->size = ihdr.prg_page_count_16k * PRG_PAGE_SIZE;
116  ptr->vaddr = ROM_MIRROR_ADDRESS;
117  ptr->vsize = ROM_MIRROR_SIZE;
118  ptr->perm = RZ_PERM_RX;
119  rz_list_append(ret, ptr);
120  }
121  return ret;
122 }
123 
124 static RzList *mem(RzBinFile *bf) {
125  RzList *ret;
126  RzBinMem *m, *n;
127  if (!(ret = rz_list_new())) {
128  return NULL;
129  }
130  ret->free = free;
131  if (!(m = RZ_NEW0(RzBinMem))) {
132  rz_list_free(ret);
133  return NULL;
134  }
135  m->name = strdup("RAM");
136  m->addr = RAM_START_ADDRESS;
137  m->size = RAM_SIZE;
138  m->perms = rz_str_rwx("rwx");
139  rz_list_append(ret, m);
140  if (!(n = RZ_NEW0(RzBinMem))) {
141  return ret;
142  }
143  m->mirrors = rz_list_new();
144  n->name = strdup("RAM_MIRROR_2");
145  n->addr = RAM_MIRROR_2_ADDRESS;
146  n->size = RAM_MIRROR_2_SIZE;
147  n->perms = rz_str_rwx("rwx");
148  rz_list_append(m->mirrors, n);
149  if (!(n = RZ_NEW0(RzBinMem))) {
150  rz_list_free(m->mirrors);
151  m->mirrors = NULL;
152  return ret;
153  }
154  n->name = strdup("RAM_MIRROR_3");
155  n->addr = RAM_MIRROR_3_ADDRESS;
156  n->size = RAM_MIRROR_3_SIZE;
157  n->perms = rz_str_rwx("rwx");
158  rz_list_append(m->mirrors, n);
159  if (!(m = RZ_NEW0(RzBinMem))) {
160  rz_list_free(ret);
161  return NULL;
162  }
163  m->name = strdup("PPU_REG");
164  m->addr = PPU_REG_ADDRESS;
165  m->size = PPU_REG_SIZE;
166  m->perms = rz_str_rwx("rwx");
167  rz_list_append(ret, m);
168  m->mirrors = rz_list_new();
169  int i;
170  for (i = 1; i < 1024; i++) {
171  if (!(n = RZ_NEW0(RzBinMem))) {
172  rz_list_free(m->mirrors);
173  m->mirrors = NULL;
174  return ret;
175  }
176  n->name = rz_str_newf("PPU_REG_MIRROR_%d", i);
177  n->addr = PPU_REG_ADDRESS + i * PPU_REG_SIZE;
178  n->size = PPU_REG_SIZE;
179  n->perms = rz_str_rwx("rwx");
180  rz_list_append(m->mirrors, n);
181  }
182  if (!(m = RZ_NEW0(RzBinMem))) {
183  rz_list_free(ret);
184  return NULL;
185  }
186  m->name = strdup("APU_AND_IOREGS");
188  m->size = APU_AND_IOREGS_SIZE;
189  m->perms = rz_str_rwx("rwx");
190  rz_list_append(ret, m);
191  if (!(m = RZ_NEW0(RzBinMem))) {
192  rz_list_free(ret);
193  return NULL;
194  }
195  m->name = strdup("SRAM");
196  m->addr = SRAM_START_ADDRESS;
197  m->size = SRAM_SIZE;
198  m->perms = rz_str_rwx("rwx");
199  rz_list_append(ret, m);
200  return ret;
201 }
202 
203 static RzList *entries(RzBinFile *bf) { // Should be 3 offsets pointed by NMI, RESET, IRQ after mapping && default = 1st CHR
204  RzList *ret;
205  RzBinAddr *ptr = NULL;
206  if (!(ret = rz_list_new())) {
207  return NULL;
208  }
209  if (!(ptr = RZ_NEW0(RzBinAddr))) {
210  return ret;
211  }
212  ptr->paddr = INES_HDR_SIZE;
213  ptr->vaddr = ROM_START_ADDRESS;
214  rz_list_append(ret, ptr);
215  return ret;
216 }
217 
218 static ut64 baddr(RzBinFile *bf) {
219  // having this we make rz -B work, otherwise it doesnt works :??
220  return 0;
221 }
222 
224  .name = "nes",
225  .desc = "NES",
226  .license = "MIT",
227  .load_buffer = &load_buffer,
228  .baddr = &baddr,
229  .check_buffer = &check_buffer,
230  .entries = &entries,
232  .sections = sections,
233  .symbols = &symbols,
234  .info = &info,
235  .mem = &mem,
236 };
237 
238 #ifndef RZ_PLUGIN_INCORE
241  .data = &rz_bin_plugin_nes,
243 };
244 #endif
lzma_index ** i
Definition: index.h:629
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API RZ_OWN RzList * rz_bin_maps_of_file_sections(RZ_NONNULL RzBinFile *binfile)
Create a list of RzBinMap from RzBinSections queried from the given file.
Definition: bin.c:1040
static RzList * mem(RzBinFile *bf)
Definition: bin_nes.c:124
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_nes.c:17
static RzList * symbols(RzBinFile *bf)
Definition: bin_nes.c:55
RzBinPlugin rz_bin_plugin_nes
Definition: bin_nes.c:223
static void addsym(RzList *ret, const char *name, ut64 addr, ut32 size)
Definition: bin_nes.c:43
RZ_API RzLibStruct rizin_plugin
Definition: bin_nes.c:239
static bool check_buffer(RzBuffer *b)
Definition: bin_nes.c:8
static RzBinInfo * info(RzBinFile *bf)
Definition: bin_nes.c:21
static ut64 baddr(RzBinFile *bf)
Definition: bin_nes.c:218
static RzList * entries(RzBinFile *bf)
Definition: bin_nes.c:203
static RzList * sections(RzBinFile *bf)
Definition: bin_nes.c:85
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int n
Definition: mipsasm.c:19
#define SRAM_START_ADDRESS
Definition: nes_specs.h:33
#define SPR_DMA
Definition: nes_specs.h:63
#define SRAM_SIZE
Definition: nes_specs.h:34
#define RAM_MIRROR_3_SIZE
Definition: nes_specs.h:25
#define RAM_MIRROR_2_ADDRESS
Definition: nes_specs.h:21
#define PPU_REG_SIZE
Definition: nes_specs.h:28
#define PPU_CTRL_REG2
Definition: nes_specs.h:47
#define PRG_PAGE_SIZE
Definition: nes_specs.h:11
#define NMI_VECTOR_START_ADDRESS
Definition: nes_specs.h:42
#define PPU_CTRL_REG1
Definition: nes_specs.h:46
#define RAM_MIRROR_3_ADDRESS
Definition: nes_specs.h:24
#define PPU_SPR_DATA
Definition: nes_specs.h:50
#define JOYPAD_PORT2
Definition: nes_specs.h:66
#define APU_AND_IOREGS_START_ADDRESS
Definition: nes_specs.h:30
#define SND_DELTA_REG
Definition: nes_specs.h:60
#define APU_AND_IOREGS_SIZE
Definition: nes_specs.h:31
#define ROM_MIRROR_ADDRESS
Definition: nes_specs.h:39
#define SND_SQUARE2_REG
Definition: nes_specs.h:57
#define PPU_REG_ADDRESS
Definition: nes_specs.h:27
#define SND_SQUARE1_REG
Definition: nes_specs.h:56
#define JOYPAD_PORT1
Definition: nes_specs.h:65
#define RAM_MIRROR_2_SIZE
Definition: nes_specs.h:22
#define PPU_ADDRESS
Definition: nes_specs.h:52
#define RESET_VECTOR_START_ADDRESS
Definition: nes_specs.h:43
#define INES_MAGIC
Definition: nes_specs.h:9
#define RAM_SIZE
Definition: nes_specs.h:16
#define PPU_SCROLL_REG
Definition: nes_specs.h:51
#define IRQ_VECTOR_START_ADDRESS
Definition: nes_specs.h:44
#define ROM_MIRROR_SIZE
Definition: nes_specs.h:40
#define SND_TRIANGLE_REG
Definition: nes_specs.h:58
#define PPU_SPR_ADDR
Definition: nes_specs.h:49
#define ROM_SIZE
Definition: nes_specs.h:37
#define PPU_DATA
Definition: nes_specs.h:53
#define JOYPAD_PORT
Definition: nes_specs.h:64
#define RAM_START_ADDRESS
Definition: nes_specs.h:15
#define INES_HDR_SIZE
Definition: nes_specs.h:13
#define PPU_STATUS
Definition: nes_specs.h:48
#define SND_NOISE_REG
Definition: nes_specs.h:59
#define SND_REGISTER
Definition: nes_specs.h:55
#define ROM_START_ADDRESS
Definition: nes_specs.h:36
#define SND_MASTERCTRL_REG
Definition: nes_specs.h:61
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int rz_str_rwx(const char *str)
Definition: str.c:318
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_RX
Definition: rz_types.h:97
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
Definition: z80asm.h:102
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
XX curplugin == o->plugin.
Definition: rz_bin.h:298
char * file
Definition: rz_bin.h:299
RzBuffer * buf
Definition: rz_bin.h:303
int has_va
Definition: rz_bin.h:228
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * machine
Definition: rz_bin.h:216
char * file
Definition: rz_bin.h:210
char * arch
Definition: rz_bin.h:214
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
char * name
Definition: rz_bin.h:619
char * name
Definition: rz_bin.h:675
ut32 ordinal
Definition: rz_bin.h:692
RzListFree free
Definition: rz_list.h:21
Definition: sdb.h:63
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58