Adding Memory window
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
/* This file is included into vb.c and cannot be compiled on its own. */
|
||||
#ifdef VBAPI
|
||||
|
||||
|
||||
|
||||
/**************************** Component Functions ****************************/
|
||||
|
||||
/* Read a value from a memory buffer */
|
||||
static int32_t busReadMemory(uint8_t *mem, int type) {
|
||||
|
||||
/* Generic implementation */
|
||||
#ifdef VB_BIGENDIAN
|
||||
switch (type) {
|
||||
case VB_S8 : return (int8_t) *mem;
|
||||
case VB_U8 : return *mem;
|
||||
case VB_S16: return (int16_t ) (int8_t) mem[1] << 8 | mem[0];
|
||||
case VB_U16: return (uint16_t) mem[1] << 8 | mem[0];
|
||||
}
|
||||
return (int32_t ) mem[3] << 24 | (uint32_t) mem[2] << 16 |
|
||||
(uint32_t) mem[1] << 8 | mem[0];
|
||||
|
||||
/* Little-endian implementation */
|
||||
#else
|
||||
switch (type) {
|
||||
case VB_S8 : return *(int8_t *)mem;
|
||||
case VB_U8 : return * mem;
|
||||
case VB_S16: return *(int16_t *)mem;
|
||||
case VB_U16: return *(uint16_t *)mem;
|
||||
}
|
||||
return *(int32_t *)mem;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Read a data unit from the bus */
|
||||
static int32_t busRead(VB *emu, uint32_t address, int type, int debug) {
|
||||
|
||||
/* Force address alignment */
|
||||
address &= ~((uint32_t) TYPE_SIZES[type] - 1);
|
||||
|
||||
/* Process by address range */
|
||||
switch (address >> 24 ^ 7) {
|
||||
case 0 : return 0; /* VIP */
|
||||
case 1 : debug = debug; return 0; /* VSU */
|
||||
case 2 : return 0; /* Miscellaneous hardware */
|
||||
case 3 : return 0; /* Unmapped */
|
||||
case 4 : return 0; /* Game pak expansion */
|
||||
case 5 : return /* WRAM */
|
||||
busReadMemory(&emu->wram[address & 0xFFFF], type);
|
||||
case 6 : return emu->cart.sram == NULL ? 0 : /* Game pak RAM */
|
||||
busReadMemory(&emu->cart.sram
|
||||
[address & (emu->cart.sramSize - 1)], type);
|
||||
default: return emu->cart.rom == NULL ? 0 : /* Game pak ROM */
|
||||
busReadMemory(&emu->cart.rom
|
||||
[address & (emu->cart.romSize - 1)], type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Write a data unit to a memory buffer */
|
||||
static void busWriteMemory(uint8_t *mem, int type, int32_t value) {
|
||||
|
||||
/* Generic implementation */
|
||||
#ifdef VB_BIGENDIAN
|
||||
switch (type) {
|
||||
case VB_S32:
|
||||
mem[3] = value >> 24;
|
||||
mem[2] = value >> 16;
|
||||
/* Fallthrough */
|
||||
case VB_S16:
|
||||
case VB_U16:
|
||||
mem[1] = value >> 8;
|
||||
}
|
||||
mem[0] = value;
|
||||
|
||||
/* Little-endian implementation */
|
||||
#else
|
||||
switch (type) {
|
||||
case VB_S16: case VB_U16: *(uint16_t *)mem = value; return;
|
||||
case VB_S8 : case VB_U8 : * mem = value; return;
|
||||
}
|
||||
*(int32_t *)mem = value;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Read a value from the bus */
|
||||
static void busWrite(
|
||||
VB *emu, uint32_t address, int type, uint32_t value, int debug) {
|
||||
|
||||
/* Force address alignment */
|
||||
address &= ~((uint32_t) TYPE_SIZES[type] - 1);
|
||||
|
||||
/* Process by address range */
|
||||
switch (address >> 24 ^ 7) {
|
||||
case 0 : return; /* VIP */
|
||||
case 1 : return; /* VSU */
|
||||
case 2 : return; /* Miscellaneous hardware */
|
||||
case 3 : return; /* Unmapped */
|
||||
case 4 : return; /* Game pak expansion */
|
||||
case 5 : /* WRAM */
|
||||
busWriteMemory(&emu->wram[address & 0xFFFF], type, value);
|
||||
return;
|
||||
case 6 : /* Cartridge RAM */
|
||||
if (emu->cart.sram != NULL)
|
||||
busWriteMemory(&emu->cart.sram
|
||||
[address & (emu->cart.sramSize - 1)], type, value);
|
||||
return;
|
||||
default: /* Cartridge ROM */
|
||||
if (debug && emu->cart.rom != NULL)
|
||||
busWriteMemory(&emu->cart.rom
|
||||
[address & (emu->cart.romSize - 1)], type, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* VBAPI */
|
||||
@@ -0,0 +1,196 @@
|
||||
#define VBAPI
|
||||
|
||||
/* Header includes */
|
||||
#include <vb.h>
|
||||
|
||||
|
||||
|
||||
/********************************* Constants *********************************/
|
||||
|
||||
/* Type sizes */
|
||||
static const uint8_t TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
||||
|
||||
|
||||
|
||||
/********************************** Macros ***********************************/
|
||||
|
||||
/* Sign-extend a value of some number of bits to 32 bits */
|
||||
#define SignExtend(v,b) ( (v) | (((v) & 1 << b - 1) ? ~(int32_t)0 << b : 0) )
|
||||
|
||||
|
||||
|
||||
/*************************** Subsystem Components ****************************/
|
||||
|
||||
/* Component includes */
|
||||
#include "bus.c"
|
||||
|
||||
|
||||
|
||||
/******************************* API Functions *******************************/
|
||||
|
||||
/* Retrieve the value of PC */
|
||||
uint32_t vbGetProgramCounter(VB *emu) {
|
||||
return emu->cpu.pc;
|
||||
}
|
||||
|
||||
/* Retrieve the value of a program register */
|
||||
int32_t vbGetProgramRegister(VB *emu, int id) {
|
||||
return id < 1 || id > 31 ? 0 : emu->cpu.program[id];
|
||||
}
|
||||
|
||||
/* Retrieve the value of a system register */
|
||||
uint32_t vbGetSystemRegister(VB *emu, int id) {
|
||||
switch (id) {
|
||||
case VB_ADTRE: return emu->cpu.adtre;
|
||||
case VB_CHCW : return emu->cpu.chcw.ice << 1;
|
||||
case VB_EIPC : return emu->cpu.eipc;
|
||||
case VB_EIPSW: return emu->cpu.eipsw;
|
||||
case VB_FEPC : return emu->cpu.fepc;
|
||||
case VB_FEPSW: return emu->cpu.fepsw;
|
||||
case VB_PIR : return 0x00005346;
|
||||
case VB_TKCW : return 0x000000E0;
|
||||
case 29 : return emu->cpu.sr29;
|
||||
case 31 : return emu->cpu.sr31;
|
||||
case VB_ECR : return
|
||||
(uint32_t) emu->cpu.ecr.fecc << 16 | emu->cpu.ecr.eicc;
|
||||
case VB_PSW : return
|
||||
(uint32_t) emu->cpu.psw.i << 16 |
|
||||
(uint32_t) emu->cpu.psw.np << 15 |
|
||||
(uint32_t) emu->cpu.psw.ep << 14 |
|
||||
(uint32_t) emu->cpu.psw.ae << 13 |
|
||||
(uint32_t) emu->cpu.psw.id << 12 |
|
||||
(uint32_t) emu->cpu.psw.fro << 9 |
|
||||
(uint32_t) emu->cpu.psw.fiv << 8 |
|
||||
(uint32_t) emu->cpu.psw.fzd << 7 |
|
||||
(uint32_t) emu->cpu.psw.fov << 6 |
|
||||
(uint32_t) emu->cpu.psw.fud << 5 |
|
||||
(uint32_t) emu->cpu.psw.fpr << 4 |
|
||||
(uint32_t) emu->cpu.psw.cy << 3 |
|
||||
(uint32_t) emu->cpu.psw.ov << 2 |
|
||||
(uint32_t) emu->cpu.psw.s << 1 |
|
||||
(uint32_t) emu->cpu.psw.z
|
||||
;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare a simulation state instance for use */
|
||||
void vbInit(VB *emu) {
|
||||
emu->cart.rom = NULL;
|
||||
emu->cart.sram = NULL;
|
||||
}
|
||||
|
||||
/* Read a data unit from the bus */
|
||||
int32_t vbRead(VB *emu, uint32_t address, int type, int debug) {
|
||||
return type < 0 || type >= (int) sizeof TYPE_SIZES ? 0 :
|
||||
busRead(emu, address, type, debug);
|
||||
}
|
||||
|
||||
/* Simulate a hardware reset */
|
||||
void vbReset(VB *emu) {
|
||||
uint32_t x;
|
||||
|
||||
/* Initialize CPU registers */
|
||||
emu->cpu.pc = 0xFFFFFFF0;
|
||||
vbSetSystemRegister(emu, VB_ECR, 0x0000FFF0);
|
||||
vbSetSystemRegister(emu, VB_PSW, 0x00008000);
|
||||
|
||||
/* Initialize extra CPU registers (the hardware does not do this) */
|
||||
emu->cpu.adtre = 0;
|
||||
emu->cpu.eipc = 0;
|
||||
emu->cpu.eipsw = 0;
|
||||
emu->cpu.fepc = 0;
|
||||
emu->cpu.fepsw = 0;
|
||||
emu->cpu.sr29 = 0;
|
||||
emu->cpu.sr31 = 0;
|
||||
|
||||
/* Erase WRAM (the hardware does not do this) */
|
||||
for (x = 0; x < 0x10000; x++)
|
||||
emu->wram[x] = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Specify a new value for PC */
|
||||
uint32_t vbSetProgramCounter(VB *emu, uint32_t value) {
|
||||
value &= 0xFFFFFFFE;
|
||||
emu->cpu.pc = value;
|
||||
/* Set stage to fecth=0 */
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Specify a new value for a program register */
|
||||
int32_t vbSetProgramRegister(VB *emu, int id, int32_t value) {
|
||||
return id < 1 || id > 31 ? 0 : (emu->cpu.program[id] = value);
|
||||
}
|
||||
|
||||
/* Supply a ROM buffer */
|
||||
int vbSetROM(VB *emu, void *rom, uint32_t size) {
|
||||
|
||||
/* Check the buffer size */
|
||||
if (size < 1024 || size > 0x1000000 || ((size - 1) & size) != 0)
|
||||
return 0;
|
||||
|
||||
/* Configure the ROM buffer */
|
||||
emu->cart.rom = (uint8_t *) rom;
|
||||
emu->cart.romSize = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Supply an SRAM buffer */
|
||||
int vbSetSRAM(VB *emu, void *sram, uint32_t size) {
|
||||
|
||||
/* Check the buffer size */
|
||||
if (size == 0 || ((size - 1) & size) != 0)
|
||||
return 0;
|
||||
|
||||
/* Configure the SRAM buffer */
|
||||
emu->cart.sram = (uint8_t *) sram;
|
||||
emu->cart.sramSize = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Specify a new value for a system register */
|
||||
uint32_t vbSetSystemRegister(VB *emu, int id, uint32_t value) {
|
||||
switch (id) {
|
||||
case VB_ADTRE: return emu->cpu.adtre = value & 0xFFFFFFFE;
|
||||
case VB_EIPC : return emu->cpu.eipc = value & 0xFFFFFFFE;
|
||||
case VB_EIPSW: return emu->cpu.eipsw = value & 0x000FF3FF;
|
||||
case VB_FEPC : return emu->cpu.fepc = value & 0xFFFFFFFE;
|
||||
case VB_FEPSW: return emu->cpu.fepsw = value & 0x000FF3FF;
|
||||
case VB_PIR : return 0x00005346;
|
||||
case VB_TKCW : return 0x000000E0;
|
||||
case 29 : return emu->cpu.sr29 = value & 0x00000001;
|
||||
case 31 : return emu->cpu.sr31 = value;
|
||||
case VB_CHCW :
|
||||
emu->cpu.chcw.ice = value >> 1 & 1;
|
||||
return value & 0x00000002;
|
||||
case VB_ECR :
|
||||
emu->cpu.ecr.fecc = value >> 16;
|
||||
emu->cpu.ecr.eicc = value;
|
||||
return value;
|
||||
case VB_PSW :
|
||||
emu->cpu.psw.i = value >> 16 & 15;
|
||||
emu->cpu.psw.np = value >> 15 & 1;
|
||||
emu->cpu.psw.ep = value >> 14 & 1;
|
||||
emu->cpu.psw.ae = value >> 13 & 1;
|
||||
emu->cpu.psw.id = value >> 12 & 1;
|
||||
emu->cpu.psw.fro = value >> 9 & 1;
|
||||
emu->cpu.psw.fiv = value >> 8 & 1;
|
||||
emu->cpu.psw.fzd = value >> 7 & 1;
|
||||
emu->cpu.psw.fov = value >> 6 & 1;
|
||||
emu->cpu.psw.fud = value >> 5 & 1;
|
||||
emu->cpu.psw.fpr = value >> 4 & 1;
|
||||
emu->cpu.psw.cy = value >> 3 & 1;
|
||||
emu->cpu.psw.ov = value >> 2 & 1;
|
||||
emu->cpu.psw.s = value >> 1 & 1;
|
||||
emu->cpu.psw.z = value & 1;
|
||||
return value & 0x000FF3FF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write a data unit to the bus */
|
||||
void vbWrite(VB *emu, uint32_t address, int type, int32_t value, int debug) {
|
||||
if (type < 0 || type >= (int32_t) sizeof TYPE_SIZES)
|
||||
busWrite(emu, address, type, value, debug);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifndef __VB_H__
|
||||
#define __VB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VBAPI
|
||||
#define VBAPI extern
|
||||
#endif
|
||||
|
||||
/* Header includes */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
/********************************* Constants *********************************/
|
||||
|
||||
/* Value types */
|
||||
#define VB_S8 0
|
||||
#define VB_U8 1
|
||||
#define VB_S16 2
|
||||
#define VB_U16 3
|
||||
#define VB_S32 4
|
||||
|
||||
/* System register IDs */
|
||||
#define VB_ADTRE 25
|
||||
#define VB_CHCW 24
|
||||
#define VB_ECR 4
|
||||
#define VB_EIPC 0
|
||||
#define VB_EIPSW 1
|
||||
#define VB_FEPC 2
|
||||
#define VB_FEPSW 3
|
||||
#define VB_PIR 6
|
||||
#define VB_PSW 5
|
||||
#define VB_TKCW 7
|
||||
|
||||
|
||||
|
||||
/*********************************** Types ***********************************/
|
||||
|
||||
/* Simulation state */
|
||||
typedef struct VB VB;
|
||||
struct VB {
|
||||
|
||||
/* Game pak */
|
||||
struct {
|
||||
uint8_t *rom; /* Active ROM buffer */
|
||||
uint32_t romSize; /* Size of ROM data */
|
||||
uint8_t *sram; /* Active SRAM buffer */
|
||||
uint32_t sramSize; /* Size of SRAM data */
|
||||
} cart;
|
||||
|
||||
/* CPU */
|
||||
struct {
|
||||
|
||||
/* System registers */
|
||||
uint32_t adtre; /* Address trap register for execution */
|
||||
uint32_t eipc; /* Exception/Interrupt PC */
|
||||
uint32_t eipsw; /* Exception/Interrupt PSW */
|
||||
uint32_t fepc; /* Fatal error PC */
|
||||
uint32_t fepsw; /* Fatal error PSW */
|
||||
uint32_t sr29; /* Unknown system register */
|
||||
uint32_t sr31; /* Unknown system register */
|
||||
|
||||
/* Cache control word */
|
||||
struct {
|
||||
int8_t ice; /* Instruction cache enable */
|
||||
} chcw;
|
||||
|
||||
/* Exception cause register */
|
||||
struct {
|
||||
uint16_t eicc; /* Exception/interrupt cause code */
|
||||
uint16_t fecc; /* Fatal error cause code */
|
||||
} ecr;
|
||||
|
||||
/* Program status word */
|
||||
struct {
|
||||
int8_t ae; /* Address trap enable */
|
||||
int8_t cy; /* Carry */
|
||||
int8_t ep; /* Exception pending */
|
||||
int8_t fiv; /* Floating invalid */
|
||||
int8_t fov; /* Floating overflow */
|
||||
int8_t fpr; /* Floating precision */
|
||||
int8_t fro; /* Floating reserved operand */
|
||||
int8_t fud; /* Floating underflow */
|
||||
int8_t fzd; /* Floating zero divide */
|
||||
int8_t i; /* Interrupt level */
|
||||
int8_t id; /* Interrupt disable */
|
||||
int8_t np; /* NMI pending */
|
||||
int8_t ov; /* Overflow */
|
||||
int8_t s; /* Sign */
|
||||
int8_t z; /* Zero */
|
||||
} psw;
|
||||
|
||||
/* Other registers */
|
||||
uint32_t pc; /* Program counter */
|
||||
int32_t program[32]; /* program registers */
|
||||
|
||||
/* Other fields */
|
||||
uint32_t clocks; /* Clocks until next action */
|
||||
uint8_t fatch; /* Index of fetch unit */
|
||||
uint8_t state; /* Operations state */
|
||||
} cpu;
|
||||
|
||||
/* Other fields */
|
||||
uint8_t wram[0x10000]; /* Main memory */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**************************** Function Prototypes ****************************/
|
||||
|
||||
VBAPI uint32_t vbGetProgramCounter (VB *emu);
|
||||
VBAPI int32_t vbGetProgramRegister (VB *emu, int id);
|
||||
VBAPI uint32_t vbGetSystemRegister (VB *emu, int id);
|
||||
VBAPI void vbInit (VB *emu);
|
||||
VBAPI int32_t vbRead (VB *emu, uint32_t address, int type, int debug);
|
||||
VBAPI void vbReset (VB *emu);
|
||||
VBAPI uint32_t vbSetProgramCounter (VB *emu, uint32_t value);
|
||||
VBAPI int32_t vbSetProgramRegister (VB *emu, int id, int32_t value);
|
||||
VBAPI int vbSetROM (VB *emu, void *rom, uint32_t size);
|
||||
VBAPI int vbSetSRAM (VB *emu, void *sram, uint32_t size);
|
||||
VBAPI uint32_t vbSetSystemRegister (VB *emu, int id, uint32_t value);
|
||||
VBAPI void vbWrite (VB *emu, uint32_t address, int type, int32_t value, int debug);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __VB_H__ */
|
||||
Reference in New Issue
Block a user