Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37b9a94338 | ||
|
|
3c2c9bb938 | ||
|
|
7a8cf8952a | ||
|
|
eecc55bbd7 | ||
|
|
448658430c | ||
|
|
c91eb0785f |
+14
-2
@@ -80,6 +80,10 @@ static void busWriteBuffer(uint8_t *data, int type, int32_t value) {
|
|||||||
|
|
||||||
/***************************** Library Functions *****************************/
|
/***************************** Library Functions *****************************/
|
||||||
|
|
||||||
|
/* Forward references */
|
||||||
|
static void vipRead (VB *, uint32_t, int, int32_t *);
|
||||||
|
static void vipWrite(VB *, uint32_t, int, int32_t, int);
|
||||||
|
|
||||||
/* Read a typed value from the simulation bus */
|
/* Read a typed value from the simulation bus */
|
||||||
static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
||||||
|
|
||||||
@@ -89,7 +93,11 @@ static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
|||||||
|
|
||||||
/* Process by address range */
|
/* Process by address range */
|
||||||
switch (address >> 24) {
|
switch (address >> 24) {
|
||||||
case 0: break; /* VIP */
|
|
||||||
|
case 0: /* VIP */
|
||||||
|
vipRead(sim, address, type, value);
|
||||||
|
break;
|
||||||
|
|
||||||
case 1: break; /* VSU */
|
case 1: break; /* VSU */
|
||||||
case 2: break; /* Misc. I/O */
|
case 2: break; /* Misc. I/O */
|
||||||
case 3: break; /* Unmapped */
|
case 3: break; /* Unmapped */
|
||||||
@@ -125,7 +133,11 @@ static void busWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
|
|||||||
|
|
||||||
/* Process by address range */
|
/* Process by address range */
|
||||||
switch (address >> 24) {
|
switch (address >> 24) {
|
||||||
case 0: break; /* VIP */
|
|
||||||
|
case 0: /* VIP */
|
||||||
|
vipWrite(sim, address, type, value, debug);
|
||||||
|
break;
|
||||||
|
|
||||||
case 1: break; /* VSU */
|
case 1: break; /* VSU */
|
||||||
case 2: break; /* Misc. I/O */
|
case 2: break; /* Misc. I/O */
|
||||||
case 3: break; /* Unmapped */
|
case 3: break; /* Unmapped */
|
||||||
|
|||||||
+48
-17
@@ -212,8 +212,8 @@ static const uint8_t OPDEFS_FLOATENDO[] = {
|
|||||||
#ifndef VB_DIRECT_EXCEPTION
|
#ifndef VB_DIRECT_EXCEPTION
|
||||||
#define VB_ON_EXCEPTION sim->onException
|
#define VB_ON_EXCEPTION sim->onException
|
||||||
#else
|
#else
|
||||||
extern int vbxOnException(VB *, uint16_t *);
|
extern int VB_DIRECT_EXCEPTION(VB *, uint16_t *);
|
||||||
#define VB_ON_EXCEPTION sim->onException
|
#define VB_ON_EXCEPTION VB_DIRECT_EXCEPTION
|
||||||
#endif
|
#endif
|
||||||
static int cpuOnException(VB *sim, uint16_t *cause) {
|
static int cpuOnException(VB *sim, uint16_t *cause) {
|
||||||
return sim->onException != NULL && VB_ON_EXCEPTION(sim, cause);
|
return sim->onException != NULL && VB_ON_EXCEPTION(sim, cause);
|
||||||
@@ -224,8 +224,8 @@ static int cpuOnException(VB *sim, uint16_t *cause) {
|
|||||||
#ifndef VB_DIRECT_EXECUTE
|
#ifndef VB_DIRECT_EXECUTE
|
||||||
#define VB_ON_EXECUTE sim->onExecute
|
#define VB_ON_EXECUTE sim->onExecute
|
||||||
#else
|
#else
|
||||||
extern int vbxOnExecute(VB *, uint32_t, const uint16_t *, int);
|
extern int VB_DIRECT_EXECUTE(VB *, uint32_t, const uint16_t *, int);
|
||||||
#define VB_ON_EXECUTE vbxOnExecute
|
#define VB_ON_EXECUTE VB_DIRECT_EXECUTE
|
||||||
#endif
|
#endif
|
||||||
static int cpuOnExecute(VB *sim) {
|
static int cpuOnExecute(VB *sim) {
|
||||||
return
|
return
|
||||||
@@ -239,8 +239,8 @@ static int cpuOnExecute(VB *sim) {
|
|||||||
#ifndef VB_DIRECT_READ
|
#ifndef VB_DIRECT_READ
|
||||||
#define VB_ON_READ sim->onRead
|
#define VB_ON_READ sim->onRead
|
||||||
#else
|
#else
|
||||||
extern int vbxOnRead(VB *, uint32_t, int, int32_t *, uint32_t *);
|
extern int VB_DIRECT_READ(VB *, uint32_t, int, int32_t *, uint32_t *);
|
||||||
#define VB_ON_READ vbxOnRead
|
#define VB_ON_READ VB_DIRECT_READ
|
||||||
#endif
|
#endif
|
||||||
static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
||||||
uint32_t cycles = 4; /* TODO: Research this */
|
uint32_t cycles = 4; /* TODO: Research this */
|
||||||
@@ -264,8 +264,8 @@ static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
|
|||||||
#ifndef VB_DIRECT_FETCH
|
#ifndef VB_DIRECT_FETCH
|
||||||
#define VB_ON_FETCH sim->onFetch
|
#define VB_ON_FETCH sim->onFetch
|
||||||
#else
|
#else
|
||||||
extern int vbxOnFetch(VB *, int, uint32_t, int32_t *, uint32_t *);
|
extern int VB_DIRECT_FETCH(VB *, int, uint32_t, int32_t *, uint32_t *);
|
||||||
#define VB_ON_FETCH vbxOnFetch
|
#define VB_ON_FETCH VB_DIRECT_FETCH
|
||||||
#endif
|
#endif
|
||||||
static int cpuReadFetch(VB *sim, int fetch, uint32_t address, int32_t *value) {
|
static int cpuReadFetch(VB *sim, int fetch, uint32_t address, int32_t *value) {
|
||||||
uint32_t cycles = 0;
|
uint32_t cycles = 0;
|
||||||
@@ -289,8 +289,8 @@ static int cpuReadFetch(VB *sim, int fetch, uint32_t address, int32_t *value) {
|
|||||||
#ifndef VB_DIRECT_WRITE
|
#ifndef VB_DIRECT_WRITE
|
||||||
#define VB_ON_WRITE sim->onWrite
|
#define VB_ON_WRITE sim->onWrite
|
||||||
#else
|
#else
|
||||||
extern int vbxOnWrite(VB *, uint32_t, int, int32_t *, uint32_t *, int *);
|
extern int VB_DIRECT_WRITE(VB *,uint32_t,int,int32_t *,uint32_t *,int *);
|
||||||
#define VB_ON_WRITE vbxOnWrite
|
#define VB_ON_WRITE VB_DIRECT_WRITE
|
||||||
#endif
|
#endif
|
||||||
static int cpuWrite(VB *sim, uint32_t address, int type, int32_t value) {
|
static int cpuWrite(VB *sim, uint32_t address, int type, int32_t value) {
|
||||||
int cancel = 0;
|
int cancel = 0;
|
||||||
@@ -376,7 +376,7 @@ static uint32_t cpuSetSystemRegister(VB*sim,
|
|||||||
case VB_FEPSW: return sim->cpu.fepsw = value & 0x000FF3FF;
|
case VB_FEPSW: return sim->cpu.fepsw = value & 0x000FF3FF;
|
||||||
case VB_PIR : return 0x00005346;
|
case VB_PIR : return 0x00005346;
|
||||||
case VB_PSW :
|
case VB_PSW :
|
||||||
sim->cpu.psw.i = value >> 16 & 0xF;
|
sim->cpu.psw.i = value >> 16 & 15;
|
||||||
sim->cpu.psw.np = value >> 15 & 1;
|
sim->cpu.psw.np = value >> 15 & 1;
|
||||||
sim->cpu.psw.ep = value >> 14 & 1;
|
sim->cpu.psw.ep = value >> 14 & 1;
|
||||||
sim->cpu.psw.ae = value >> 13 & 1;
|
sim->cpu.psw.ae = value >> 13 & 1;
|
||||||
@@ -414,7 +414,7 @@ static int cpuIRQ(VB *sim) {
|
|||||||
if (sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np)
|
if (sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np)
|
||||||
return 0;
|
return 0;
|
||||||
level = IRQ_LEVELS[sim->cpu.irq];
|
level = IRQ_LEVELS[sim->cpu.irq];
|
||||||
if (level == -1 || level > sim->cpu.psw.i)
|
if (level < sim->cpu.psw.i)
|
||||||
return 0;
|
return 0;
|
||||||
cpuThrow(sim, 0xFE00 | level << 4);
|
cpuThrow(sim, 0xFE00 | level << 4);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -476,6 +476,9 @@ static int cpuException(VB *sim) {
|
|||||||
/* Regular exception */
|
/* Regular exception */
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
/* All exceptions */
|
||||||
|
sim->cpu.eipsw = cpuGetSystemRegister(sim, VB_PSW);
|
||||||
|
|
||||||
/* Interrupts only */
|
/* Interrupts only */
|
||||||
if ((cause & 0xFF00) == 0xFE00) {
|
if ((cause & 0xFF00) == 0xFE00) {
|
||||||
sim->cpu.psw.i = (cause >> 4 & 7) + 1;
|
sim->cpu.psw.i = (cause >> 4 & 7) + 1;
|
||||||
@@ -487,7 +490,6 @@ static int cpuException(VB *sim) {
|
|||||||
|
|
||||||
/* All exceptions */
|
/* All exceptions */
|
||||||
sim->cpu.ecr.eicc = cause;
|
sim->cpu.ecr.eicc = cause;
|
||||||
sim->cpu.eipsw = cpuGetSystemRegister(sim, VB_PSW);
|
|
||||||
sim->cpu.eipc = sim->cpu.pc;
|
sim->cpu.eipc = sim->cpu.pc;
|
||||||
sim->cpu.psw.ep = 1;
|
sim->cpu.psw.ep = 1;
|
||||||
sim->cpu.nextPC = 0xFFFF0000 |
|
sim->cpu.nextPC = 0xFFFF0000 |
|
||||||
@@ -1692,10 +1694,8 @@ static int cpuEmulate(VB *sim, uint32_t clocks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Advance forward the CPU's number of clocks */
|
/* Advance forward the CPU's number of clocks */
|
||||||
if (sim->cpu.clocks != 0) {
|
clocks -= sim->cpu.clocks;
|
||||||
clocks -= sim->cpu.clocks;
|
sim->cpu.clocks = 0;
|
||||||
sim->cpu.clocks = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Processing by operation ID */
|
/* Processing by operation ID */
|
||||||
switch (sim->cpu.operation) {
|
switch (sim->cpu.operation) {
|
||||||
@@ -1792,6 +1792,37 @@ static int cpuEmulate(VB *sim, uint32_t clocks) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Simulate a hardware reset */
|
||||||
|
static void cpuReset(VB *sim) {
|
||||||
|
uint32_t x; /* Iterator */
|
||||||
|
|
||||||
|
/* Normal */
|
||||||
|
sim->cpu.exception = 0;
|
||||||
|
sim->cpu.halt = 0;
|
||||||
|
sim->cpu.irq = 0;
|
||||||
|
sim->cpu.pc = 0xFFFFFFF0;
|
||||||
|
cpuSetSystemRegister(sim, VB_ECR, 0x0000FFF0, 1);
|
||||||
|
cpuSetSystemRegister(sim, VB_PSW, 0x00008000, 1);
|
||||||
|
|
||||||
|
/* Extra (the hardware does not do this) */
|
||||||
|
sim->cpu.adtre = 0x00000000;
|
||||||
|
sim->cpu.eipc = 0x00000000;
|
||||||
|
sim->cpu.eipsw = 0x00000000;
|
||||||
|
sim->cpu.fepc = 0x00000000;
|
||||||
|
sim->cpu.fepsw = 0x00000000;
|
||||||
|
sim->cpu.sr29 = 0x00000000;
|
||||||
|
sim->cpu.sr31 = 0x00000000;
|
||||||
|
cpuSetSystemRegister(sim, VB_CHCW, 0x00000000, 1);
|
||||||
|
for (x = 0; x < 32; x++)
|
||||||
|
sim->cpu.program[x] = 0x00000000;
|
||||||
|
|
||||||
|
/* Other */
|
||||||
|
sim->cpu.clocks = 0;
|
||||||
|
sim->cpu.nextPC = 0xFFFFFFF0;
|
||||||
|
sim->cpu.operation = CPU_FETCH;
|
||||||
|
sim->cpu.step = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine how many clocks are guaranteed to process */
|
/* Determine how many clocks are guaranteed to process */
|
||||||
static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
|
static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
|
||||||
return sim->cpu.halt || sim->cpu.clocks > clocks ?
|
return sim->cpu.halt || sim->cpu.clocks > clocks ?
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
/*********************************** Types ***********************************/
|
/*********************************** Types ***********************************/
|
||||||
|
|
||||||
|
/* Output image */
|
||||||
|
typedef uint8_t Pixels[2][384*224];
|
||||||
|
|
||||||
/* Simulation state */
|
/* Simulation state */
|
||||||
struct VB {
|
struct VB {
|
||||||
|
|
||||||
@@ -87,13 +90,91 @@ struct VB {
|
|||||||
int step; /* Operation sub-task ID */
|
int step; /* Operation sub-task ID */
|
||||||
} cpu;
|
} cpu;
|
||||||
|
|
||||||
/* Other system state */
|
/* VIP */
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/* CTA */
|
||||||
|
struct {
|
||||||
|
uint8_t cta_l; /* Left column table index */
|
||||||
|
uint8_t cta_r; /* Right column table index */
|
||||||
|
} cta;
|
||||||
|
|
||||||
|
/* Display processor */
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/* Hardware state */
|
||||||
|
uint8_t disp; /* Display enabled */
|
||||||
|
uint8_t fclk; /* Frame clock signal high */
|
||||||
|
uint8_t l0bsy; /* Displaying left frame buffer 0 */
|
||||||
|
uint8_t l1bsy; /* Displaying left frame buffer 1 */
|
||||||
|
uint8_t lock; /* Lock CTA */
|
||||||
|
uint8_t r0bsy; /* Displaying right frame buffer 0 */
|
||||||
|
uint8_t r1bsy; /* Displaying right frame buffer 1*/
|
||||||
|
uint8_t re; /* Memory refresh enabled */
|
||||||
|
uint8_t scanrdy; /* Mirrors are stable */
|
||||||
|
uint8_t synce; /* Servo enabled */
|
||||||
|
|
||||||
|
/* Simulation state */
|
||||||
|
uint8_t brt[4]; /* Precomputed brightness */
|
||||||
|
int buffer; /* Index of frame buffer to display */
|
||||||
|
uint32_t clocks; /* Master clocks to wait */
|
||||||
|
int column; /* Index of column to display */
|
||||||
|
uint32_t cta; /* Column table pointer in memory */
|
||||||
|
uint32_t fbDest; /* Output frame pixel address */
|
||||||
|
uint32_t fbSrc; /* Source frame buffer address */
|
||||||
|
int32_t repeat; /* Current column table repeat value */
|
||||||
|
int step; /* Processing phase */
|
||||||
|
uint32_t until; /* Clocks until interrupt condition */
|
||||||
|
} dp;
|
||||||
|
|
||||||
|
/* Pixel processor */
|
||||||
|
struct {
|
||||||
|
|
||||||
|
/* Hardware state */
|
||||||
|
uint8_t f0bsy; /* Drawing into frame buffer 0 */
|
||||||
|
uint8_t f1bsy; /* Drawing into frame buffer 1 */
|
||||||
|
uint8_t overtime; /* Drawing extends into display interval */
|
||||||
|
uint8_t sbcmp; /* Vertical output position compare */
|
||||||
|
uint8_t sbcount; /* Current vertical output position */
|
||||||
|
uint32_t sbout; /* Drawing specified vertical output position */
|
||||||
|
uint8_t xpen; /* Drawing enabled */
|
||||||
|
|
||||||
|
/* Simulation state */
|
||||||
|
uint32_t clocks; /* Master clocks to wait */
|
||||||
|
int column; /* Current horizontal output position */
|
||||||
|
int frame; /* FRMCYC counter */
|
||||||
|
int32_t halfword; /* Current output halfword offset */
|
||||||
|
int step; /* Processing phase */
|
||||||
|
uint32_t until; /* Clocks until interrupt condition */
|
||||||
|
} xp;
|
||||||
|
|
||||||
|
/* Control state */
|
||||||
|
uint8_t bkcol; /* Backdrop color */
|
||||||
|
uint8_t brtRest[4]; /* Brightness and REST */
|
||||||
|
uint8_t frmcyc; /* Game frame control */
|
||||||
|
uint8_t gplt[4][4]; /* Background palettes */
|
||||||
|
uint16_t intenb; /* Interrupts enabled */
|
||||||
|
uint16_t intpnd; /* Interrupts pending */
|
||||||
|
uint8_t jplt[4][4]; /* Object palettes */
|
||||||
|
uint16_t spt[4]; /* Object control */
|
||||||
|
|
||||||
|
/* Rendering shadow memory */
|
||||||
|
uint16_t halfwords[384*28]; /* Output timing by 1x8 halfword */
|
||||||
|
Pixels output[2]; /* Output images, row-major */
|
||||||
|
Pixels shadow; /* Drawing shadow image, column-major */
|
||||||
|
|
||||||
|
/* Other state */
|
||||||
|
uint8_t ram[0x40000]; /* Video memory */
|
||||||
|
} vip;
|
||||||
|
|
||||||
|
/* Other state */
|
||||||
uint8_t wram[0x10000]; /* System RAM */
|
uint8_t wram[0x10000]; /* System RAM */
|
||||||
|
|
||||||
/* Application data */
|
/* Application data */
|
||||||
vbOnException onException; /* CPU exception */
|
vbOnException onException; /* CPU exception */
|
||||||
vbOnExecute onExecute; /* CPU instruction execute */
|
vbOnExecute onExecute; /* CPU instruction execute */
|
||||||
vbOnFetch onFetch; /* CPU instruction fetch */
|
vbOnFetch onFetch; /* CPU instruction fetch */
|
||||||
|
vbOnFrame onFrame; /* VIP frame ready */
|
||||||
vbOnRead onRead; /* CPU instruction read */
|
vbOnRead onRead; /* CPU instruction read */
|
||||||
vbOnWrite onWrite; /* CPU instruction write */
|
vbOnWrite onWrite; /* CPU instruction write */
|
||||||
void *tag; /* User data */
|
void *tag; /* User data */
|
||||||
@@ -120,6 +201,7 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
|
|||||||
|
|
||||||
#include "bus.c"
|
#include "bus.c"
|
||||||
#include "cpu.c"
|
#include "cpu.c"
|
||||||
|
#include "vip.c"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -128,13 +210,15 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
|
|||||||
/* Process a simulation for a given number of clocks */
|
/* Process a simulation for a given number of clocks */
|
||||||
static int sysEmulate(VB *sim, uint32_t clocks) {
|
static int sysEmulate(VB *sim, uint32_t clocks) {
|
||||||
return
|
return
|
||||||
cpuEmulate(sim, clocks)
|
cpuEmulate(sim, clocks) |
|
||||||
|
vipEmulate(sim, clocks)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine how many clocks are guaranteed to process */
|
/* Determine how many clocks are guaranteed to process */
|
||||||
static uint32_t sysUntil(VB *sim, uint32_t clocks) {
|
static uint32_t sysUntil(VB *sim, uint32_t clocks) {
|
||||||
clocks = cpuUntil(sim, clocks);
|
clocks = cpuUntil(sim, clocks);
|
||||||
|
clocks = vipUntil(sim, clocks);
|
||||||
return clocks;
|
return clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,21 +275,66 @@ VBAPI void* vbGetCartROM(VB *sim, uint32_t *size) {
|
|||||||
return sim->cart.rom;
|
return sim->cart.rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the exception callback handle */
|
/* Retrieve the exception callback handler */
|
||||||
VBAPI vbOnException vbGetExceptionCallback(VB *sim) {
|
VBAPI vbOnException vbGetExceptionCallback(VB *sim) {
|
||||||
return sim->onException;
|
return sim->onException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the execute callback handle */
|
/* Retrieve the execute callback handler */
|
||||||
VBAPI vbOnExecute vbGetExecuteCallback(VB *sim) {
|
VBAPI vbOnExecute vbGetExecuteCallback(VB *sim) {
|
||||||
return sim->onExecute;
|
return sim->onExecute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the fetch callback handle */
|
/* Retrieve the fetch callback handler */
|
||||||
VBAPI vbOnFetch vbGetFetchCallback(VB *sim) {
|
VBAPI vbOnFetch vbGetFetchCallback(VB *sim) {
|
||||||
return sim->onFetch;
|
return sim->onFetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve the frame callback handler */
|
||||||
|
VBAPI vbOnFrame vbGetFrameCallback(VB *sim) {
|
||||||
|
return sim->onFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the most recent frame image pixels */
|
||||||
|
VBAPI void vbGetPixels(VB *sim, void *left, int leftStrideX, int leftStrideY,
|
||||||
|
void *right, int rightStrideX, int rightStrideY) {
|
||||||
|
uint8_t *dest; /* Output data */
|
||||||
|
int offset; /* Horizontal offset of output pixel */
|
||||||
|
uint8_t *src; /* Source data */
|
||||||
|
int xStride; /* Bytes between output pixels */
|
||||||
|
int yStride; /* Bytes between output lines */
|
||||||
|
int i, x, y; /* Iterators */
|
||||||
|
|
||||||
|
/* Process both eyes */
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
|
||||||
|
/* Working variables for left image */
|
||||||
|
if (i == 0) {
|
||||||
|
dest = left;
|
||||||
|
xStride = leftStrideX;
|
||||||
|
yStride = leftStrideY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Working variables for right image */
|
||||||
|
else {
|
||||||
|
dest = right;
|
||||||
|
xStride = rightStrideX;
|
||||||
|
yStride = rightStrideY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing to do */
|
||||||
|
if (dest == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Transfer pixels to the destination */
|
||||||
|
src = sim->vip.output[sim->vip.dp.buffer ^ 1][i];
|
||||||
|
for (y = 0; y < 224; y++, dest += yStride)
|
||||||
|
for (x = offset = 0; x < 384; x++, offset += xStride)
|
||||||
|
dest[offset] = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Retrieve the value of the program counter */
|
/* Retrieve the value of the program counter */
|
||||||
VBAPI uint32_t vbGetProgramCounter(VB *sim) {
|
VBAPI uint32_t vbGetProgramCounter(VB *sim) {
|
||||||
return sim->cpu.pc;
|
return sim->cpu.pc;
|
||||||
@@ -216,7 +345,7 @@ VBAPI int32_t vbGetProgramRegister(VB *sim, int index) {
|
|||||||
return index < 1 || index > 31 ? 0 : sim->cpu.program[index];
|
return index < 1 || index > 31 ? 0 : sim->cpu.program[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the read callback handle */
|
/* Retrieve the read callback handler */
|
||||||
VBAPI vbOnRead vbGetReadCallback(VB *sim) {
|
VBAPI vbOnRead vbGetReadCallback(VB *sim) {
|
||||||
return sim->onRead;
|
return sim->onRead;
|
||||||
}
|
}
|
||||||
@@ -231,19 +360,20 @@ VBAPI void* vbGetUserData(VB *sim) {
|
|||||||
return sim->tag;
|
return sim->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the write callback handle */
|
/* Retrieve the write callback handler */
|
||||||
VBAPI vbOnWrite vbGetWriteCallback(VB *sim) {
|
VBAPI vbOnWrite vbGetWriteCallback(VB *sim) {
|
||||||
return sim->onWrite;
|
return sim->onWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a simulation instance */
|
/* Initialize a simulation instance */
|
||||||
VBAPI VB* vbInit(VB *sim) {
|
VBAPI VB* vbInit(VB *sim) {
|
||||||
sim->cart.ram = NULL;
|
sim->cart.ram = NULL;
|
||||||
sim->cart.rom = NULL;
|
sim->cart.rom = NULL;
|
||||||
sim->onExecute = NULL;
|
sim->onExecute = NULL;
|
||||||
sim->onFetch = NULL;
|
sim->onFetch = NULL;
|
||||||
sim->onRead = NULL;
|
sim->onFrame = NULL;
|
||||||
sim->onWrite = NULL;
|
sim->onRead = NULL;
|
||||||
|
sim->onWrite = NULL;
|
||||||
vbReset(sim);
|
vbReset(sim);
|
||||||
return sim;
|
return sim;
|
||||||
}
|
}
|
||||||
@@ -259,38 +389,15 @@ VBAPI int32_t vbRead(VB *sim, uint32_t address, int type) {
|
|||||||
|
|
||||||
/* Simulate a hardware reset */
|
/* Simulate a hardware reset */
|
||||||
VBAPI VB* vbReset(VB *sim) {
|
VBAPI VB* vbReset(VB *sim) {
|
||||||
uint32_t x; /* Iterator */
|
int x; /* Iterator */
|
||||||
|
|
||||||
/* WRAM (the hardware does not do this) */
|
/* WRAM (the hardware does not do this) */
|
||||||
for (x = 0; x < 0x10000; x++)
|
for (x = 0; x < 0x10000; x++)
|
||||||
sim->wram[x] = 0x00;
|
sim->wram[x] = 0x00;
|
||||||
|
|
||||||
/* CPU (normal) */
|
/* Components */
|
||||||
sim->cpu.exception = 0;
|
cpuReset(sim);
|
||||||
sim->cpu.halt = 0;
|
vipReset(sim);
|
||||||
sim->cpu.irq = 0;
|
|
||||||
sim->cpu.pc = 0xFFFFFFF0;
|
|
||||||
cpuSetSystemRegister(sim, VB_ECR, 0x0000FFF0, 1);
|
|
||||||
cpuSetSystemRegister(sim, VB_PSW, 0x00008000, 1);
|
|
||||||
|
|
||||||
/* CPU (extra, hardware does not do this) */
|
|
||||||
sim->cpu.adtre = 0x00000000;
|
|
||||||
sim->cpu.eipc = 0x00000000;
|
|
||||||
sim->cpu.eipsw = 0x00000000;
|
|
||||||
sim->cpu.fepc = 0x00000000;
|
|
||||||
sim->cpu.fepsw = 0x00000000;
|
|
||||||
sim->cpu.sr29 = 0x00000000;
|
|
||||||
sim->cpu.sr31 = 0x00000000;
|
|
||||||
cpuSetSystemRegister(sim, VB_CHCW, 0x00000000, 1);
|
|
||||||
for (x = 0; x < 32; x++)
|
|
||||||
sim->cpu.program[x] = 0x00000000;
|
|
||||||
|
|
||||||
/* CPU (other) */
|
|
||||||
sim->cpu.clocks = 0;
|
|
||||||
sim->cpu.nextPC = 0xFFFFFFF0;
|
|
||||||
sim->cpu.operation = CPU_FETCH;
|
|
||||||
sim->cpu.step = 0;
|
|
||||||
|
|
||||||
return sim;
|
return sim;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,27 +423,34 @@ VBAPI int vbSetCartROM(VB *sim, void *rom, uint32_t size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new exception callback handle */
|
/* Specify a new exception callback handler */
|
||||||
VBAPI vbOnException vbSetExceptionCallback(VB *sim, vbOnException callback) {
|
VBAPI vbOnException vbSetExceptionCallback(VB *sim, vbOnException callback) {
|
||||||
vbOnException prev = sim->onException;
|
vbOnException prev = sim->onException;
|
||||||
sim->onException = callback;
|
sim->onException = callback;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new execute callback handle */
|
/* Specify a new execute callback handler */
|
||||||
VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback) {
|
VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback) {
|
||||||
vbOnExecute prev = sim->onExecute;
|
vbOnExecute prev = sim->onExecute;
|
||||||
sim->onExecute = callback;
|
sim->onExecute = callback;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new fetch callback handle */
|
/* Specify a new fetch callback handler */
|
||||||
VBAPI vbOnFetch vbSetFetchCallback(VB *sim, vbOnFetch callback) {
|
VBAPI vbOnFetch vbSetFetchCallback(VB *sim, vbOnFetch callback) {
|
||||||
vbOnFetch prev = sim->onFetch;
|
vbOnFetch prev = sim->onFetch;
|
||||||
sim->onFetch = callback;
|
sim->onFetch = callback;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a new frame callback handler */
|
||||||
|
VBAPI vbOnFrame vbSetFrameCallback(VB *sim, vbOnFrame callback) {
|
||||||
|
vbOnFrame prev = sim->onFrame;
|
||||||
|
sim->onFrame = callback;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Specify a new value for the program counter */
|
/* Specify a new value for the program counter */
|
||||||
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
|
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
|
||||||
sim->cpu.operation = CPU_FETCH;
|
sim->cpu.operation = CPU_FETCH;
|
||||||
@@ -350,7 +464,7 @@ VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value) {
|
|||||||
return index < 1 || index > 31 ? 0 : (sim->cpu.program[index] = value);
|
return index < 1 || index > 31 ? 0 : (sim->cpu.program[index] = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new read callback handle */
|
/* Specify a new read callback handler */
|
||||||
VBAPI vbOnRead vbSetReadCallback(VB *sim, vbOnRead callback) {
|
VBAPI vbOnRead vbSetReadCallback(VB *sim, vbOnRead callback) {
|
||||||
vbOnRead prev = sim->onRead;
|
vbOnRead prev = sim->onRead;
|
||||||
sim->onRead = callback;
|
sim->onRead = callback;
|
||||||
@@ -363,7 +477,7 @@ VBAPI uint32_t vbSetSystemRegister(VB *sim, int index, uint32_t value) {
|
|||||||
cpuSetSystemRegister(sim, index, value, 1);
|
cpuSetSystemRegister(sim, index, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new write callback handle */
|
/* Specify a new write callback handler */
|
||||||
VBAPI vbOnWrite vbSetWriteCallback(VB *sim, vbOnWrite callback) {
|
VBAPI vbOnWrite vbSetWriteCallback(VB *sim, vbOnWrite callback) {
|
||||||
vbOnWrite prev = sim->onWrite;
|
vbOnWrite prev = sim->onWrite;
|
||||||
sim->onWrite = callback;
|
sim->onWrite = callback;
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ extern "C" {
|
|||||||
VB_DIRECT_EXCEPTION
|
VB_DIRECT_EXCEPTION
|
||||||
VB_DIRECT_EXECUTE
|
VB_DIRECT_EXECUTE
|
||||||
VB_DIRECT_FETCH
|
VB_DIRECT_FETCH
|
||||||
|
VB_DIRECT_FRAME
|
||||||
VB_DIRECT_READ
|
VB_DIRECT_READ
|
||||||
VB_DIRECT_WRITE
|
VB_DIRECT_WRITE
|
||||||
|
|
||||||
Implements callbacks as direct function calls with names in the form of
|
Implements callbacks as direct function calls with names given by the above
|
||||||
vbxOn<callback>() with the same prototypes as the regular function pointer
|
symbols in their respective situations. If left undefined, the function
|
||||||
callbacks. If left undefined, the function pointers are used.
|
pointer in the simulation state is used. Whether or not to call the callback
|
||||||
|
is still determined by whether the function pointer is NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -57,14 +59,6 @@ extern "C" {
|
|||||||
|
|
||||||
/********************************* Constants *********************************/
|
/********************************* Constants *********************************/
|
||||||
|
|
||||||
/* Callback IDs */
|
|
||||||
#define VB_EXCEPTION 0
|
|
||||||
#define VB_EXECUTE 1
|
|
||||||
#define VB_FETCH 2
|
|
||||||
#define VB_FRAME 3
|
|
||||||
#define VB_READ 4
|
|
||||||
#define VB_WRITE 5
|
|
||||||
|
|
||||||
/* System registers */
|
/* System registers */
|
||||||
#define VB_ADTRE 25
|
#define VB_ADTRE 25
|
||||||
#define VB_CHCW 24
|
#define VB_CHCW 24
|
||||||
@@ -95,6 +89,7 @@ typedef struct VB VB;
|
|||||||
typedef int (*vbOnException)(VB *sim, uint16_t *cause);
|
typedef int (*vbOnException)(VB *sim, uint16_t *cause);
|
||||||
typedef int (*vbOnExecute )(VB *sim, uint32_t address, const uint16_t *code, int length);
|
typedef int (*vbOnExecute )(VB *sim, uint32_t address, const uint16_t *code, int length);
|
||||||
typedef int (*vbOnFetch )(VB *sim, int fetch, uint32_t address, int32_t *value, uint32_t *cycles);
|
typedef int (*vbOnFetch )(VB *sim, int fetch, uint32_t address, int32_t *value, uint32_t *cycles);
|
||||||
|
typedef int (*vbOnFrame )(VB *sim);
|
||||||
typedef int (*vbOnRead )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles);
|
typedef int (*vbOnRead )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles);
|
||||||
typedef int (*vbOnWrite )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles, int *cancel);
|
typedef int (*vbOnWrite )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles, int *cancel);
|
||||||
|
|
||||||
@@ -111,6 +106,8 @@ VBAPI void* vbGetCartROM (VB *sim, uint32_t *size);
|
|||||||
VBAPI vbOnException vbGetExceptionCallback(VB *sim);
|
VBAPI vbOnException vbGetExceptionCallback(VB *sim);
|
||||||
VBAPI vbOnExecute vbGetExecuteCallback (VB *sim);
|
VBAPI vbOnExecute vbGetExecuteCallback (VB *sim);
|
||||||
VBAPI vbOnFetch vbGetFetchCallback (VB *sim);
|
VBAPI vbOnFetch vbGetFetchCallback (VB *sim);
|
||||||
|
VBAPI vbOnFrame vbGetFrameCallback (VB *sim);
|
||||||
|
VBAPI void vbGetPixels (VB *sim, void *left, int leftStrideX, int leftStrideY, void *right, int rightStrideX, int rightStrideY);
|
||||||
VBAPI uint32_t vbGetProgramCounter (VB *sim);
|
VBAPI uint32_t vbGetProgramCounter (VB *sim);
|
||||||
VBAPI int32_t vbGetProgramRegister (VB *sim, int index);
|
VBAPI int32_t vbGetProgramRegister (VB *sim, int index);
|
||||||
VBAPI vbOnRead vbGetReadCallback (VB *sim);
|
VBAPI vbOnRead vbGetReadCallback (VB *sim);
|
||||||
@@ -125,6 +122,7 @@ VBAPI int vbSetCartROM (VB *sim, void *rom, uint32_t size);
|
|||||||
VBAPI vbOnException vbSetExceptionCallback(VB *sim, vbOnException callback);
|
VBAPI vbOnException vbSetExceptionCallback(VB *sim, vbOnException callback);
|
||||||
VBAPI vbOnExecute vbSetExecuteCallback (VB *sim, vbOnExecute callback);
|
VBAPI vbOnExecute vbSetExecuteCallback (VB *sim, vbOnExecute callback);
|
||||||
VBAPI vbOnFetch vbSetFetchCallback (VB *sim, vbOnFetch callback);
|
VBAPI vbOnFetch vbSetFetchCallback (VB *sim, vbOnFetch callback);
|
||||||
|
VBAPI vbOnFrame vbSetFrameCallback (VB *sim, vbOnFrame callback);
|
||||||
VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value);
|
VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value);
|
||||||
VBAPI int32_t vbSetProgramRegister (VB *sim, int index, int32_t value);
|
VBAPI int32_t vbSetProgramRegister (VB *sim, int index, int32_t value);
|
||||||
VBAPI vbOnRead vbSetReadCallback (VB *sim, vbOnRead callback);
|
VBAPI vbOnRead vbSetReadCallback (VB *sim, vbOnRead callback);
|
||||||
|
|||||||
+1167
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
.PHONY: help
|
.PHONY: help
|
||||||
help:
|
help:
|
||||||
@echo
|
@echo
|
||||||
@echo "Shrooms Virtual Boy core module - October 14, 2024"
|
@echo "Shrooms Virtual Boy core module - October 15, 2024"
|
||||||
@echo
|
@echo
|
||||||
@echo "Target build environment is any Debian with the following packages:"
|
@echo "Target build environment is any Debian with the following packages:"
|
||||||
@echo " emscripten"
|
@echo " emscripten"
|
||||||
@@ -20,23 +20,25 @@ clean:
|
|||||||
.PHONY: core
|
.PHONY: core
|
||||||
core:
|
core:
|
||||||
# GCC generic
|
# GCC generic
|
||||||
@gcc core/vb.c -I core -c -o /dev/null \
|
@gcc core/vb.c -I core -c -o /dev/null -O3 \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
-Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing
|
||||||
# GCC compilation control
|
# GCC compilation control
|
||||||
@gcc core/vb.c -I core -c -o /dev/null \
|
@gcc core/vb.c -I core -c -o /dev/null -O3 \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
-Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing \
|
||||||
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
|
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
|
||||||
-D VB_DIRECT_EXCEPTION -D VB_DIRECT_EXECUTE -D VB_DIRECT_FETCH \
|
-D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
|
||||||
-D VB_DIRECT_READ -D VB_DIRECT_WRITE -D VB_DIV_GENERIC
|
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
|
||||||
|
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
|
||||||
# Clang generic
|
# Clang generic
|
||||||
@emcc core/vb.c -I core -c -o /dev/null \
|
@emcc core/vb.c -I core -c -o /dev/null -O3 \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
-Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing
|
||||||
# Clang compilation control
|
# Clang compilation control
|
||||||
@emcc core/vb.c -I core -c -o /dev/null \
|
@emcc core/vb.c -I core -c -o /dev/null -O3 \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
-Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing \
|
||||||
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
|
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
|
||||||
-D VB_DIRECT_EXCEPTION -D VB_DIRECT_EXECUTE -D VB_DIRECT_FETCH \
|
-D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
|
||||||
-D VB_DIRECT_READ -D VB_DIRECT_WRITE -D VB_DIV_GENERIC
|
-D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
|
||||||
|
-D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
|
||||||
|
|
||||||
.PHONY: wasm
|
.PHONY: wasm
|
||||||
wasm:
|
wasm:
|
||||||
|
|||||||
Reference in New Issue
Block a user