mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-08 23:07:17 +00:00
546 lines
15 KiB
C
546 lines
15 KiB
C
/* 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("Unsupported 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;
|
|
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 64 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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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;
|
|
ptr->add = true;
|
|
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->kv, "vsf.reg_a", vsf_obj->maincpu->ac, 0);
|
|
sdb_num_set (vsf_obj->kv, "vsf.reg_x", vsf_obj->maincpu->xr, 0);
|
|
sdb_num_set (vsf_obj->kv, "vsf.reg_y", vsf_obj->maincpu->yr, 0);
|
|
sdb_num_set (vsf_obj->kv, "vsf.reg_sp", vsf_obj->maincpu->sp, 0);
|
|
sdb_num_set (vsf_obj->kv, "vsf.reg_pc", vsf_obj->maincpu->pc, 0);
|
|
sdb_num_set (vsf_obj->kv, "vsf.reg_st", vsf_obj->maincpu->st, 0);
|
|
sdb_num_set (vsf_obj->kv, "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"},
|
|
|
|
// Defines taken from c64.inc from cc65
|
|
// I/O: VIC
|
|
{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"},
|
|
|
|
// I/O: SID
|
|
{0xD400, "SID_S1Lo"},
|
|
{0xD401, "SID_S1Hi"},
|
|
{0xD402, "SID_PB1Lo"},
|
|
{0xD403, "SID_PB1Hi"},
|
|
{0xD404, "SID_Ctl1"},
|
|
{0xD405, "SID_AD1"},
|
|
{0xD406, "SID_SUR1"},
|
|
|
|
{0xD407, "SID_S2Lo"},
|
|
{0xD408, "SID_S2Hi"},
|
|
{0xD409, "SID_PB2Lo"},
|
|
{0xD40A, "SID_PB2Hi"},
|
|
{0xD40B, "SID_Ctl2"},
|
|
{0xD40C, "SID_AD2"},
|
|
{0xD40D, "SID_SUR2"},
|
|
|
|
{0xD40E, "SID_S3Lo"},
|
|
{0xD40F, "SID_S3Hi"},
|
|
{0xD410, "SID_PB3Lo"},
|
|
{0xD411, "SID_PB3Hi"},
|
|
{0xD412, "SID_Ctl3"},
|
|
{0xD413, "SID_AD3"},
|
|
{0xD414, "SID_SUR3"},
|
|
|
|
{0xD415, "SID_FltLo"},
|
|
{0xD416, "SID_FltHi"},
|
|
{0xD417, "SID_FltCtl"},
|
|
{0xD418, "SID_Amp"},
|
|
{0xD419, "SID_ADConv1"},
|
|
{0xD41A, "SID_ADConv2"},
|
|
{0xD41B, "SID_Noise"},
|
|
{0xD41C, "SID_Read3"},
|
|
|
|
// I/O: VDC (128 only)
|
|
{0xd600, "VDC_INDEX"},
|
|
{0xd601, "VDC_DATA"},
|
|
|
|
// I/O: CIAs
|
|
{0xDC00, "CIA1_PRA"},
|
|
{0xDC01, "CIA1_PRB"},
|
|
{0xDC02, "CIA1_DDRA"},
|
|
{0xDC03, "CIA1_DDRB"},
|
|
{0xDC08, "CIA1_TOD10"},
|
|
{0xDC09, "CIA1_TODSEC"},
|
|
{0xDC0A, "CIA1_TODMIN"},
|
|
{0xDC0B, "CIA1_TODHR"},
|
|
{0xDC0D, "CIA1_ICR"},
|
|
{0xDC0E, "CIA1_CRA"},
|
|
{0xDC0F, "CIA1_CRB"},
|
|
|
|
{0xDD00, "CIA2_PRA"},
|
|
{0xDD01, "CIA2_PRB"},
|
|
{0xDD02, "CIA2_DDRA"},
|
|
{0xDD03, "CIA2_DDRB"},
|
|
{0xDD08, "CIA2_TOD10"},
|
|
{0xDD09, "CIA2_TODSEC"},
|
|
{0xDD0A, "CIA2_TODMIN"},
|
|
{0xDD0B, "CIA2_TODHR"},
|
|
{0xDD0D, "CIA2_ICR"},
|
|
{0xDD0E, "CIA2_CRA"},
|
|
{0xDD0F, "CIA2_CRB"},
|
|
};
|
|
|
|
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;
|
|
|
|
int i;
|
|
for (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
|