127 lines
3.2 KiB
C
127 lines
3.2 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <emscripten/emscripten.h>
|
|
#include <vb.h>
|
|
|
|
|
|
|
|
/////////////////////////////// Module Commands ///////////////////////////////
|
|
|
|
// Allocate and initialize multiple simulations
|
|
EMSCRIPTEN_KEEPALIVE VB** Create(int count) {
|
|
VB **sims = malloc(count * sizeof (void *));
|
|
for (int x = 0; x < count; x++)
|
|
vbReset(sims[x] = malloc(sizeof (VB)));
|
|
return sims;
|
|
}
|
|
|
|
// Delete a simulation
|
|
EMSCRIPTEN_KEEPALIVE void Destroy(VB *sim) {
|
|
free(&sim->cart.rom);
|
|
free(&sim->cart.sram);
|
|
free(sim);
|
|
}
|
|
|
|
// Proxy for free()
|
|
EMSCRIPTEN_KEEPALIVE void Free(void *ptr) {
|
|
free(ptr);
|
|
}
|
|
|
|
// Proxy for malloc()
|
|
EMSCRIPTEN_KEEPALIVE void* Malloc(int size) {
|
|
return malloc(size);
|
|
}
|
|
|
|
// Determine the size in bytes of a pointer
|
|
EMSCRIPTEN_KEEPALIVE int PointerSize() {
|
|
return sizeof (void *);
|
|
}
|
|
|
|
// Read multiple bytes from the bus
|
|
EMSCRIPTEN_KEEPALIVE void ReadBuffer(
|
|
VB* sim, uint8_t *dest, uint32_t address, uint32_t size) {
|
|
for (; size > 0; address++, size--, dest++)
|
|
*dest = vbRead(sim, address, VB_U8, 1);
|
|
}
|
|
|
|
// Supply a ROM buffer
|
|
EMSCRIPTEN_KEEPALIVE int SetROM(VB *sim, uint8_t *rom, uint32_t size) {
|
|
uint8_t *prev = vbGetROM(sim, NULL);
|
|
int ret = vbSetROM(sim, rom, size);
|
|
if (ret) {
|
|
free(prev);
|
|
vbReset(sim);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Write multiple bytes to the bus
|
|
EMSCRIPTEN_KEEPALIVE void WriteBuffer(
|
|
VB* sim, uint8_t *src, uint32_t address, uint32_t size) {
|
|
for (; size > 0; address++, size--, src++)
|
|
vbWrite(sim, address, VB_U8, *src, 1);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////// Debugger Commands //////////////////////////////
|
|
|
|
// Attempt to execute until the following instruction
|
|
static uint32_t RunNextPC;
|
|
static int RunNextProcB(VB *sim, int fetch, VB_ACCESS *acc) {
|
|
if (fetch == 0 && vbGetProgramCounter(sim) == RunNextPC)
|
|
return 1;
|
|
acc->value = vbRead(sim, acc->address, acc->type, 0);
|
|
return 0;
|
|
}
|
|
static int RunNextProcA(VB *sim, VB_INSTRUCTION *inst) {
|
|
RunNextPC = vbGetProgramCounter(sim) + inst->size;
|
|
vbSetCallback(sim, VB_ONEXECUTE, NULL);
|
|
vbSetCallback(sim, VB_ONFETCH, &RunNextProcB);
|
|
return 0;
|
|
}
|
|
EMSCRIPTEN_KEEPALIVE void RunNext(VB *sim0, VB *sim1) {
|
|
uint32_t clocks = 400000; // 1/50s
|
|
VB *sims[2];
|
|
|
|
vbSetCallback(sim0, VB_ONEXECUTE, &RunNextProcA);
|
|
|
|
if (sim1 != NULL) {
|
|
sims[0] = sim0;
|
|
sims[1] = sim1;
|
|
vbEmulateMulti(sims, 2, &clocks);
|
|
}
|
|
|
|
else vbEmulate(sim0, &clocks);
|
|
|
|
vbSetCallback(sim0, VB_ONFETCH, NULL);
|
|
}
|
|
|
|
// Execute one instruction
|
|
static uint32_t SingleStepPC;
|
|
static int SingleStepProc(VB *sim, int fetch, VB_ACCESS *acc) {
|
|
if (fetch == 0 && vbGetProgramCounter(sim) != SingleStepPC)
|
|
return 1;
|
|
acc->value = vbRead(sim, acc->address, acc->type, 0);
|
|
return 0;
|
|
}
|
|
EMSCRIPTEN_KEEPALIVE void SingleStep(VB *sim0, VB *sim1) {
|
|
uint32_t clocks = 400000; // 1/50s
|
|
VB *sims[2];
|
|
|
|
SingleStepPC = vbGetProgramCounter(sim0);
|
|
vbSetCallback(sim0, VB_ONFETCH, &SingleStepProc);
|
|
|
|
if (sim1 != NULL) {
|
|
sims[0] = sim0;
|
|
sims[1] = sim1;
|
|
vbEmulateMulti(sims, 2, &clocks);
|
|
}
|
|
|
|
else vbEmulate(sim0, &clocks);
|
|
|
|
vbSetCallback(sim0, VB_ONFETCH, NULL);
|
|
}
|