mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 21:29:49 +00:00
Adds VSF (VICE Snapshot File) support as a bin format
VICE is the most popular C64/C128 emulator and allows users to save snapshots of the games. Analyzing VICE snapshots are more useful than analyzing .prg (the "standard" c64 program) because usually all .prg are compressed, and are decompressed in runtime. commit 796297c6cd3a099fd17ad3715b4ed5646a6a9e65 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Fri Nov 27 12:28:58 2015 -0800 no sbd for the moment commit c785b22318c3cacf7771ab21198aa759777224af Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Fri Nov 27 10:06:12 2015 -0800 bank 0 and bank 1 commit 63304876b6f84df001c39f5b35084ff6e61bc01b Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Fri Nov 27 09:47:12 2015 -0800 c128 includes basic, monitor and editor sections commit 1a8995a644df6d9e871a586e57c3cd8e00cce7ae Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Thu Nov 26 14:45:36 2015 -0800 c128 roms... uses sdb which is not used at all more vic symbols commit 8a29c3c7736fcf689b9248e65093277347ae38bc Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Nov 24 10:39:44 2015 -0800 ram last entry commit fca46301b2fd68e230cf547047a5278e098c9340 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Tue Nov 24 00:10:20 2015 -0800 more tidy code commit 03b8a12b319bd0eb9f21b60d882da2030c2c35f1 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Mon Nov 23 22:52:20 2015 -0800 VSF works for C64... still many things to fix commit a118a930cb40441b412db916deb4c0ca30e30309 Author: Ricardo Quesada <ricardoquesada@gmail.com> Date: Mon Nov 23 13:37:32 2015 -0800 initial commit... compiles and detects VICE but nothing more
This commit is contained in:
parent
4e9916942c
commit
f5c65f5da8
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2015 - condret, Ricardo Quesada, qnix */
|
||||
/* radare - LGPL - Copyright 2015 - condret, riq, qnix */
|
||||
#include <r_asm.h>
|
||||
#include <r_lib.h>
|
||||
#include <string.h>
|
||||
|
74
libr/bin/format/vsf/vsf_specs.h
Normal file
74
libr/bin/format/vsf/vsf_specs.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* radare - LGPL - Copyright 2015 riq */
|
||||
#ifndef VSF_SPECS_H
|
||||
#define VSF_SPECS_H
|
||||
|
||||
#include <r_types_base.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
|
||||
/* Snapshot format for VICE: http://vice-emu.sourceforge.net/ */
|
||||
struct vsf_hdr {
|
||||
char id[19]; /* "VICE Snapshot File" */
|
||||
char major;
|
||||
char minor;
|
||||
char machine[16]; /* "C64" or "C128" or... */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_module {
|
||||
char module_name[16]; /* looking for "C64MEM", ... */
|
||||
char major;
|
||||
char minor;
|
||||
ut32 length; /* little endian */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_maincpu {
|
||||
ut32 clk; /* CPU clock value */
|
||||
ut8 ac; /* A */
|
||||
ut8 xr; /* X */
|
||||
ut8 yr; /* Y */
|
||||
ut8 sp; /* stack pointer */
|
||||
ut16 pc; /* program counter */
|
||||
ut8 st; /* Status register */
|
||||
ut32 lastopcode; /* ? */
|
||||
ut32 ba_low_flags; /* ? */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_c64mem {
|
||||
ut8 cpudata; /* CPU port data byte */
|
||||
ut8 cpudir; /* CPU port direction byte */
|
||||
ut8 exrom; /* state of the EXROM line (?) */
|
||||
ut8 game; /* state of the GAME line (?) */
|
||||
ut8 ram[1024 * 64]; /* 64k RAM dump */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_c64rom {
|
||||
ut8 kernal[1024 * 8]; /* Kernal ROM */
|
||||
ut8 basic[1024 * 8]; /* BASIC ROM */
|
||||
ut8 chargen[1024 * 4]; /* Charset */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_c128mem {
|
||||
ut8 mmu[12]; /* dump of the 12 MMU registers */
|
||||
ut8 ram[1024 * 128]; /* 128k RAM dump: banks 0 and 1 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vsf_c128rom {
|
||||
ut8 kernal[1024 * 8]; /* Kernal ROM */
|
||||
ut8 basic[1024 * 32]; /* BASIC ROM */
|
||||
ut8 editor[1024 * 4]; /* Dump of the editor ROM */
|
||||
ut8 chargen[1024 * 4]; /* Charset */
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* Internal structure */
|
||||
struct r_bin_vsf_obj {
|
||||
int machine_idx; /* 0=C64, 1=C128, ... see bin_vsf.c */
|
||||
void* rom; /* ptr to C64/C128 rom */
|
||||
void* mem; /* ptr to C64/C128 ram */
|
||||
struct vsf_maincpu* maincpu;
|
||||
Sdb *kv;
|
||||
};
|
||||
|
||||
#endif /* VSF_SPECS_H */
|
||||
|
@ -12,7 +12,7 @@ ALL_TARGETS=
|
||||
FORMATS=any.mk elf.mk elf64.mk pe.mk pe64.mk te.mk mach0.mk
|
||||
FORMATS+=bios.mk mach064.mk fatmach0.mk dyldcache.mk java.mk
|
||||
FORMATS+=dex.mk fs.mk ningb.mk coff.mk ningba.mk xbe.mk zimg.mk
|
||||
FORMATS+=omf.mk cgc.mk dol.mk nes.mk mbn.mk psxexe.mk spc700.mk
|
||||
FORMATS+=omf.mk cgc.mk dol.mk nes.mk mbn.mk psxexe.mk spc700.mk vsf.mk
|
||||
include $(FORMATS)
|
||||
|
||||
all: ${ALL_TARGETS}
|
||||
|
474
libr/bin/p/bin_vsf.c
Normal file
474
libr/bin/p/bin_vsf.c
Normal file
@ -0,0 +1,474 @@
|
||||
/* radare - LGPL3 - 2015 - riq */
|
||||
|
||||
/* VICE Snapshot File loader: http://vice-emu.sourceforge.net/ */
|
||||
|
||||
#include <r_bin.h>
|
||||
#include "vsf/vsf_specs.h"
|
||||
|
||||
static const char VICE_MAGIC[] = "VICE Snapshot File\032";
|
||||
static const int VICE_MAGIC_LEN = sizeof(VICE_MAGIC)-1;
|
||||
static const char VICE_MAINCPU[] = "MAINCPU";
|
||||
static const char VICE_C64MEM[] = "C64MEM";
|
||||
static const char VICE_C64ROM[] = "C64ROM";
|
||||
static const char VICE_C128MEM[] = "C128MEM";
|
||||
static const char VICE_C128ROM[] = "C128ROM";
|
||||
|
||||
static const struct {
|
||||
const char* name;
|
||||
const char* desc;
|
||||
const int offset_mem;
|
||||
const int ram_size;
|
||||
} _machines[] = {
|
||||
{"C64", "Commodore 64", r_offsetof(struct vsf_c64mem, ram), 64 * 1024},
|
||||
{"C128", "Commodore 128", r_offsetof(struct vsf_c128mem, ram), 128 * 1024},
|
||||
};
|
||||
static const int MACHINES_MAX = sizeof(_machines) / sizeof(_machines[0]);
|
||||
|
||||
static int check(RBinFile *arch);
|
||||
static int check_bytes(const ut8 *buf, ut64 length);
|
||||
|
||||
//static Sdb* get_sdb (RBinObject *o) {
|
||||
// if (!o || !o->bin_obj) return NULL;
|
||||
// struct r_bin_vsf_obj* bin = (struct r_bin_vsf_obj*) o->bin_obj;
|
||||
// if (bin->kv) return bin->kv;
|
||||
// return NULL;
|
||||
//}
|
||||
|
||||
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb) {
|
||||
|
||||
struct r_bin_vsf_obj* res = NULL;
|
||||
if (check_bytes (buf, sz)) {
|
||||
|
||||
if (!(res = R_NEW0 (struct r_bin_vsf_obj)))
|
||||
return NULL;
|
||||
|
||||
const unsigned char* machine = arch->buf->buf + r_offsetof(struct vsf_hdr, machine);
|
||||
|
||||
int i=0;
|
||||
for (; i<MACHINES_MAX; i++) {
|
||||
if (strncmp((const char*)machine, _machines[i].name, strlen(_machines[i].name)) == 0) {
|
||||
res->machine_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= MACHINES_MAX) {
|
||||
eprintf("invalid machine: %s\n", machine);
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read all VSF modules
|
||||
int offset = sizeof(struct vsf_hdr);
|
||||
while (offset < sz) {
|
||||
struct vsf_module module;
|
||||
int read = r_buf_fread_at (arch->buf, offset, (ut8*)&module, "16ccci", 1);
|
||||
if (read != sizeof(module)) {
|
||||
eprintf ("Truncated Header\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(module.module_name, VICE_C64MEM, sizeof(VICE_C64MEM)-1) == 0 && module.major == 0) {
|
||||
res->mem = &arch->buf->buf[offset + read];
|
||||
|
||||
} else if (memcmp(module.module_name, VICE_C64ROM, sizeof(VICE_C64ROM)-1) == 0 && module.major == 0) {
|
||||
res->rom = &arch->buf->buf[offset + read];
|
||||
|
||||
} else if (memcmp(module.module_name, VICE_C128MEM, sizeof(VICE_C128MEM)-1) == 0 && module.major == 0) {
|
||||
res->mem = &arch->buf->buf[offset + read];
|
||||
|
||||
} else if (memcmp(module.module_name, VICE_C128ROM, sizeof(VICE_C128ROM)-1) == 0 && module.major == 0) {
|
||||
res->rom = &arch->buf->buf[offset + read];
|
||||
|
||||
} else if (memcmp(module.module_name, VICE_MAINCPU, sizeof(VICE_MAINCPU)-1) == 0 && module.major == 1) {
|
||||
res->maincpu = (struct vsf_maincpu*)&arch->buf->buf[offset + read];
|
||||
} else {
|
||||
eprintf("unkown module: %s\n", module.module_name);
|
||||
}
|
||||
|
||||
offset += module.length;
|
||||
}
|
||||
}
|
||||
|
||||
// if (res) {
|
||||
// res->kv = sdb_new0 ();
|
||||
// sdb_ns_set (sdb, "info", res->kv);
|
||||
// }
|
||||
|
||||
// res will be assigned to arch->o->bin_obj by the callee
|
||||
return res;
|
||||
}
|
||||
|
||||
static int check(RBinFile *arch) {
|
||||
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
|
||||
ut64 sz = arch ? r_buf_size (arch->buf): 0;
|
||||
return check_bytes (bytes, sz);
|
||||
}
|
||||
|
||||
static int check_bytes(const ut8 *buf, ut64 length) {
|
||||
if (!buf || length < VICE_MAGIC_LEN) return false;
|
||||
return (!memcmp (buf, VICE_MAGIC, VICE_MAGIC_LEN));
|
||||
}
|
||||
|
||||
static RList *mem(RBinFile *arch) {
|
||||
|
||||
// FIXME: What does Mem do? Should I remove it ?
|
||||
struct r_bin_vsf_obj* vsf_obj = (struct r_bin_vsf_obj*) arch->o->bin_obj;
|
||||
if (!vsf_obj) return NULL;
|
||||
|
||||
RList *ret;
|
||||
RBinMem *m, *n;
|
||||
if (!(ret = r_list_new()))
|
||||
return NULL;
|
||||
ret->free = free;
|
||||
if (!(m = R_NEW0 (RBinMem))) {
|
||||
r_list_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
m->name = strdup ("RAM");
|
||||
m->addr = 0; // start address
|
||||
m->size = _machines[vsf_obj->machine_idx].ram_size;
|
||||
m->perms = r_str_rwx ("mrwx");
|
||||
r_list_append (ret, m);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList* sections(RBinFile* arch) {
|
||||
struct r_bin_vsf_obj* vsf_obj = (struct r_bin_vsf_obj*) arch->o->bin_obj;
|
||||
if (!vsf_obj) return NULL;
|
||||
|
||||
RList *ret = NULL;
|
||||
RBinSection *ptr = NULL;
|
||||
if (!(ret = r_list_new ()))
|
||||
return NULL;
|
||||
|
||||
const int m_idx = vsf_obj->machine_idx;
|
||||
|
||||
// Radare doesn't support BANK switching.
|
||||
// But by adding the ROM sections first, and then the RAM
|
||||
// it kind of simulate bank switching since users can remove existing sections
|
||||
// and the RAM section won't overwrite the ROM since it was added last.
|
||||
if (vsf_obj->rom) {
|
||||
if (vsf_obj->machine_idx == 0) {
|
||||
// Commodore 128 ROMS
|
||||
// BASIC (0xa000 - 0xbfff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "BASIC");
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c64rom, basic)) - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 8; // (8k)
|
||||
ptr->vaddr = 0xa000;
|
||||
ptr->vsize = 1024 * 8; // BASIC size (8k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// KERNAL (0xe000 - 0xffff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "KERNAL");
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c64rom, kernal)) - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 8; // (8k)
|
||||
ptr->vaddr = 0xe000;
|
||||
ptr->vsize = 1024 * 8; // KERNAL size (8k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// CHARGEN section ignored
|
||||
} else {
|
||||
// Commodore 128 ROMS
|
||||
// BASIC (0x4000 - 0xafff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "BASIC");
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c128rom, basic)) - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 28; // (28k)
|
||||
ptr->vaddr = 0x4000;
|
||||
ptr->vsize = 1024 * 28; // BASIC size (28k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// MONITOR (0xb000 - 0xbfff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "MONITOR");
|
||||
// skip first 28kb since "BASIC" and "MONITOR" share the same section in VSF
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c128rom, basic)) + 1024 * 28 - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 4; // (4k)
|
||||
ptr->vaddr = 0xb000;
|
||||
ptr->vsize = 1024 * 4; // BASIC size (4k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// EDITOR (0xc000 - 0xcfff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "EDITOR");
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c128rom, editor)) - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 4; // (4k)
|
||||
ptr->vaddr = 0xc000;
|
||||
ptr->vsize = 1024 * 4; // BASIC size (4k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// KERNAL (0xe000 - 0xffff)
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "KERNAL");
|
||||
ptr->paddr = (vsf_obj->rom + r_offsetof(struct vsf_c128rom, kernal)) - (void*) arch->buf->buf;
|
||||
ptr->size = 1024 * 8; // (8k)
|
||||
ptr->vaddr = 0xe000;
|
||||
ptr->vsize = 1024 * 8; // KERNAL size (8k)
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// CHARGEN section ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (vsf_obj->mem) {
|
||||
|
||||
int offset = _machines[m_idx].offset_mem;
|
||||
|
||||
if (vsf_obj->machine_idx == 0) {
|
||||
// RAM C64 (0x0000 - 0xffff)
|
||||
int size = _machines[m_idx].ram_size;
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "RAM");
|
||||
ptr->paddr = (vsf_obj->mem + offset) - (void*) arch->buf->buf;
|
||||
ptr->size = size;
|
||||
ptr->vaddr = 0x0;
|
||||
ptr->vsize = size;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_WRITABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
} else {
|
||||
// RAM C128 (0x0000 - 0xffff): Bank 0
|
||||
// RAM C128 (0x0000 - 0xffff): Bank 1
|
||||
|
||||
// size of each bank: 64k
|
||||
int size = 1024 * 64;
|
||||
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "RAM BANK 0");
|
||||
ptr->paddr = (vsf_obj->mem + offset) - (void*) arch->buf->buf;
|
||||
ptr->size = size;
|
||||
ptr->vaddr = 0x0;
|
||||
ptr->vsize = size;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_WRITABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
return ret;
|
||||
strcpy (ptr->name, "RAM BANK 1");
|
||||
ptr->paddr = (vsf_obj->mem + offset) + size - (void*) arch->buf->buf;
|
||||
ptr->size = size;
|
||||
ptr->vaddr = 0x0;
|
||||
ptr->vsize = size;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_WRITABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RBinInfo* info(RBinFile *arch) {
|
||||
|
||||
struct r_bin_vsf_obj* vsf_obj = (struct r_bin_vsf_obj*) arch->o->bin_obj;
|
||||
if (!vsf_obj) return NULL;
|
||||
|
||||
const int m_idx = vsf_obj->machine_idx;
|
||||
|
||||
RBinInfo *ret = NULL;
|
||||
struct vsf_hdr hdr;
|
||||
memset (&hdr, 0, sizeof(hdr));
|
||||
int read = r_buf_read_at (arch->buf, 0, (ut8*)&hdr, sizeof(hdr));
|
||||
if (read != sizeof(hdr)) {
|
||||
eprintf ("Truncated Header\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret = R_NEW0 (RBinInfo)))
|
||||
return NULL;
|
||||
ret->file = strdup (arch->file);
|
||||
ret->type = strdup ("Snapshot");
|
||||
ret->machine = strdup (_machines[m_idx].desc);
|
||||
ret->os = strdup (_machines[m_idx].name);
|
||||
ret->arch = strdup ("6502");
|
||||
ret->bits = 8;
|
||||
ret->has_va = true;
|
||||
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_a", vsf_obj->maincpu->ac, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_x", vsf_obj->maincpu->xr, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_y", vsf_obj->maincpu->yr, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_sp", vsf_obj->maincpu->sp, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_pc", vsf_obj->maincpu->pc, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.reg_st", vsf_obj->maincpu->st, 0);
|
||||
// sdb_num_set (vsf_obj->kb, "vsf.clock", vsf_obj->maincpu->clk, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList* symbols(RBinFile *arch) {
|
||||
|
||||
static const struct {
|
||||
const ut16 address;
|
||||
const char* symbol_name;
|
||||
} _symbols[] = {
|
||||
{0xfffa, "NMI_VECTOR_LSB"},
|
||||
{0xfffb, "NMI_VECTOR_MSB"},
|
||||
{0xfffe, "IRQ_VECTOR_LSB"},
|
||||
{0xffff, "IRQ_VECTOR_MSB"},
|
||||
|
||||
// VIC macros. Taken from c64.inc from cc65
|
||||
{0xd000, "VIC_SPR0_X"},
|
||||
{0xd001, "VIC_SPR0_Y"},
|
||||
{0xd002, "VIC_SPR1_X"},
|
||||
{0xd003, "VIC_SPR1_Y"},
|
||||
{0xd004, "VIC_SPR2_X"},
|
||||
{0xd005, "VIC_SPR2_Y"},
|
||||
{0xd006, "VIC_SPR3_X"},
|
||||
{0xd007, "VIC_SPR3_Y"},
|
||||
{0xd008, "VIC_SPR4_X"},
|
||||
{0xd009, "VIC_SPR4_Y"},
|
||||
{0xd00a, "VIC_SPR5_X"},
|
||||
{0xd00b, "VIC_SPR5_Y"},
|
||||
{0xd00c, "VIC_SPR6_X"},
|
||||
{0xd00d, "VIC_SPR6_Y"},
|
||||
{0xd00e, "VIC_SPR7_X"},
|
||||
{0xd00f, "VIC_SPR7_Y"},
|
||||
{0xd010, "VIC_SPR_HI_X"},
|
||||
{0xd015, "VIC_SPR_ENA"},
|
||||
{0xd017, "VIC_SPR_EXP_Y"},
|
||||
{0xd01d, "VIC_SPR_EXP_X"},
|
||||
{0xd01c, "VIC_SPR_MCOLOR"},
|
||||
{0xd01b, "VIC_SPR_BG_PRIO"},
|
||||
|
||||
{0xd025, "VIC_SPR_MCOLOR0"},
|
||||
{0xd026, "VIC_SPR_MCOLOR1"},
|
||||
|
||||
{0xd027, "VIC_SPR0_COLOR"},
|
||||
{0xd028, "VIC_SPR1_COLOR"},
|
||||
{0xd029, "VIC_SPR2_COLOR"},
|
||||
{0xd02A, "VIC_SPR3_COLOR"},
|
||||
{0xd02B, "VIC_SPR4_COLOR"},
|
||||
{0xd02C, "VIC_SPR5_COLOR"},
|
||||
{0xd02D, "VIC_SPR6_COLOR"},
|
||||
{0xd02E, "VIC_SPR7_COLOR"},
|
||||
|
||||
{0xd011, "VIC_CTRL1"},
|
||||
{0xd016, "VIC_CTRL2"},
|
||||
|
||||
{0xd012, "VIC_HLINE"},
|
||||
|
||||
{0xd013, "VIC_LPEN_X"},
|
||||
{0xd014, "VIC_LPEN_Y"},
|
||||
|
||||
{0xd018, "VIC_VIDEO_ADR"},
|
||||
|
||||
{0xd019, "VIC_IRR"},
|
||||
{0xd01a, "VIC_IMR"},
|
||||
|
||||
{0xd020, "VIC_BORDERCOLOR"},
|
||||
{0xd021, "VIC_BG_COLOR0"},
|
||||
{0xd022, "VIC_BG_COLOR1"},
|
||||
{0xd023, "VIC_BG_COLOR2"},
|
||||
{0xd024, "VIC_BG_COLOR3"},
|
||||
|
||||
// 128 stuff
|
||||
{0xd02F, "VIC_KBD_128"},
|
||||
{0xd030, "VIC_CLK_128"},
|
||||
|
||||
|
||||
};
|
||||
|
||||
static const int SYMBOLS_MAX = sizeof(_symbols) / sizeof(_symbols[0]);
|
||||
|
||||
struct r_bin_vsf_obj* vsf_obj = (struct r_bin_vsf_obj*) arch->o->bin_obj;
|
||||
if (!vsf_obj) return NULL;
|
||||
|
||||
const int m_idx = vsf_obj->machine_idx;
|
||||
int offset = _machines[m_idx].offset_mem;
|
||||
|
||||
RList *ret = NULL;
|
||||
RBinSymbol *ptr;
|
||||
if (!(ret = r_list_new()))
|
||||
return NULL;
|
||||
ret->free = free;
|
||||
|
||||
for (int i=0; i<SYMBOLS_MAX; i++)
|
||||
{
|
||||
if (!(ptr = R_NEW0 (RBinSymbol)))
|
||||
return ret;
|
||||
if (!ptr->name) {
|
||||
ptr->name = calloc(1, R_BIN_SIZEOF_STRINGS);
|
||||
}
|
||||
strncpy (ptr->name, _symbols[i].symbol_name, R_BIN_SIZEOF_STRINGS);
|
||||
ptr->vaddr = _symbols[i].address;
|
||||
ptr->size = 2;
|
||||
ptr->paddr = (vsf_obj->mem + offset) - (void*) arch->buf->buf + _symbols[i].address;
|
||||
ptr->ordinal = i;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int destroy(RBinFile *arch) {
|
||||
free(arch->o->bin_obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static RList* entries(RBinFile *arch) {
|
||||
struct r_bin_vsf_obj* vsf_obj = (struct r_bin_vsf_obj*) arch->o->bin_obj;
|
||||
if (!vsf_obj) return NULL;
|
||||
const int m_idx = vsf_obj->machine_idx;
|
||||
|
||||
RList *ret;
|
||||
RBinAddr *ptr = NULL;
|
||||
if (!(ret = r_list_new ()))
|
||||
return NULL;
|
||||
|
||||
int offset = _machines[m_idx].offset_mem;
|
||||
|
||||
// PC
|
||||
if (!(ptr = R_NEW0 (RBinAddr)))
|
||||
return ret;
|
||||
ptr->paddr = (vsf_obj->mem + offset) - (void*) arch->buf->buf;
|
||||
ptr->vaddr = vsf_obj->maincpu ? vsf_obj->maincpu->pc : 0;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
// IRQ: 0xFFFE or 0x0314 ?
|
||||
if (!(ptr = R_NEW0 (RBinAddr)))
|
||||
return ret;
|
||||
ptr->paddr = (vsf_obj->mem + offset) - (void*) arch->buf->buf;
|
||||
ptr->vaddr = 0x314; // or 0xfffe ?
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct r_bin_plugin_t r_bin_plugin_vsf = {
|
||||
.name = "vsf",
|
||||
.desc = "VICE Snapshot File",
|
||||
.license = "LGPL3",
|
||||
// .get_sdb = &get_sdb,
|
||||
.load_bytes = &load_bytes,
|
||||
.check = &check,
|
||||
.check_bytes = &check_bytes,
|
||||
.entries = &entries,
|
||||
.sections = sections,
|
||||
.symbols = &symbols,
|
||||
.info = &info,
|
||||
.destroy = &destroy,
|
||||
.mem = &mem,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_BIN,
|
||||
.data = &r_bin_plugin_vsf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
10
libr/bin/p/vsf.mk
Normal file
10
libr/bin/p/vsf.mk
Normal file
@ -0,0 +1,10 @@
|
||||
OBJ_VSF=bin_vsf.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_VSF}
|
||||
TARGET_VSF=bin_vsf.${EXT_SO}
|
||||
|
||||
ALL_TARGETS+=${TARGET_VSF}
|
||||
|
||||
${TARGET_VSF}: ${OBJ_VSF}
|
||||
${CC} $(call libname,bin_vsf) -shared ${CFLAGS} \
|
||||
-o ${TARGET_VSF} ${OBJ_VSF} $(LINK) $(LDFLAGS)
|
@ -561,6 +561,7 @@ extern RBinPlugin r_bin_plugin_smd;
|
||||
extern RBinPlugin r_bin_plugin_sms;
|
||||
extern RBinPlugin r_bin_plugin_psxexe;
|
||||
extern RBinPlugin r_bin_plugin_spc700;
|
||||
extern RBinPlugin r_bin_plugin_vsf;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ bin.smd
|
||||
bin.sms
|
||||
bin.spc700
|
||||
bin.te
|
||||
bin.vsf
|
||||
bin.xbe
|
||||
bin_xtr.dyldcache
|
||||
bin_xtr.fatmach0
|
||||
|
Loading…
Reference in New Issue
Block a user