shrooms-vb-core/core/bus.c

236 lines
7.3 KiB
C

/* This file is included into vb.c and cannot be compiled on its own. */
#ifdef VBAPI
/******************************** Lookup Data ********************************/
/* Memory access address masks by data type */
static const uint32_t TYPE_MASKS[] = {
0x07FFFFFF, /* S8 */
0x07FFFFFF, /* U8 */
0x07FFFFFE, /* S16 */
0x07FFFFFE, /* U16 */
0x07FFFFFC /* S32 */
};
/**************************** Forward references *****************************/
static void vipRead (VB *, uint32_t, int, int32_t *);
static void vipWrite(VB *, uint32_t, int, int32_t, int);
static void vsuWrite(VB *, uint32_t, int, int32_t, int);
/*************************** Sub-Module Functions ****************************/
/* Read a typed value from a buffer in host memory */
static int32_t busReadBuffer(uint8_t *data, int type) {
/* Processing by data type */
switch (type) {
/* Generic implementation */
#ifndef VB_LITTLE_ENDIAN
case VB_S8 : return ((int8_t *)data)[0];
case VB_U8 : return data [0];
case VB_S16: return (int32_t) ((int8_t *)data)[1] << 8 | data[0];
case VB_U16: return (int32_t) data [1] << 8 | data[0];
case VB_S32: return
(int32_t) data[3] << 24 | (int32_t) data[2] << 16 |
(int32_t) data[1] << 8 | data[0];
/* Little-endian host */
#else
case VB_S8 : return *(int8_t *) data;
case VB_U8 : return * data;
case VB_S16: return *(int16_t *) data;
case VB_U16: return *(uint16_t *) data;
case VB_S32: return *(int32_t *) data;
#endif
}
return 0; /* Unreachable */
}
/* Write a typed value to a buffer in host memory */
static void busWriteBuffer(uint8_t *data, int type, int32_t value) {
/* Processing by data type */
switch (type) {
/* Generic implementation */
#ifndef VB_LITTLE_ENDIAN
case VB_S32: data[3] = value >> 24;
data[2] = value >> 16; /* Fallthrough */
case VB_S16: /* Fallthrough */
case VB_U16: data[1] = value >> 8; /* Fallthrough */
case VB_S8 : /* Fallthrough */
case VB_U8 : data[0] = value;
/* Little-endian host */
#else
case VB_S8 : /* Fallthrough */
case VB_U8 : * data = value; return;
case VB_S16: /* Fallthrough */
case VB_U16: *(uint16_t *) data = value; return;
case VB_S32: *(int32_t *) data = value; return;
#endif
}
}
/* Read a value from miscellaneous hardware I/O */
static int32_t busReadMisc(VB *sim, uint8_t address, int type) {
/* Unmapped */
switch (type) {
case VB_S8 : case VB_U8 : if (address & 3) return 0; break;
case VB_S16: case VB_U16: if (address & 2) return 0;
}
/* Access by register */
switch (address >> 2 & 15) {
case 0x00>>2: return extReadCCR(sim); /* CCR */
case 0x04>>2: return extReadCCSR(sim); /* CCSR */
case 0x08>>2: return sim->ext.cdtr; /* CDTR */
case 0x0C>>2: return sim->ext.cdrr; /* CDRR */
case 0x10>>2: return sim->pad.sdlr; /* SDLR */
case 0x14>>2: return sim->pad.sdhr; /* SDHR */
case 0x18>>2: return sim->tmr.counter & 0xFF; /* TLR */
case 0x1C>>2: return sim->tmr.counter >> 8 & 0xFF; /* THR */
case 0x20>>2: return tmrReadControl(sim); /* TCR */
case 0x28>>2: return padReadControl(sim); /* SCR */
case 0x24>>2: return sim->wcr.exp1w << 1 | sim->wcr.rom1w; /* WCR */
}
/* Unmapped */
return 0;
}
/* Write a value to miscellaneous hardware I/O */
static void busWriteMisc(VB *sim, uint8_t address, int type, int32_t value) {
/* Unmapped */
switch (type) {
case VB_S8 : case VB_U8 : if (address & 3) return; break;
case VB_S16: case VB_U16: if (address & 2) return;
}
/* Access by register */
switch (address >> 2 & 15) {
case 0x00>>2: extWriteCCR (sim, value); break; /* CCR */
case 0x04>>2: extWriteCCSR(sim, value); break; /* CCSR */
case 0x08>>2: sim->ext.cdtr = value; break; /* CDTR */
case 0x18>>2: tmrWriteLow (sim, value); break; /* TLR */
case 0x1C>>2: tmrWriteHigh (sim, value); break; /* THR */
case 0x20>>2: tmrWriteControl(sim, value); break; /* TCR */
case 0x28>>2: padWriteControl(sim, value); break; /* SCR */
case 0x24>>2: /* WCR */
sim->wcr.exp1w = value >> 1 & 1;
sim->wcr.rom1w = value & 1;
}
}
/***************************** Library Functions *****************************/
/* Read a typed value from the simulation bus */
static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
/* Working variables */
address &= TYPE_MASKS[type];
*value = 0;
/* Process by address range */
switch (address >> 24) {
case 0: /* VIP */
vipRead(sim, address, type, value);
break;
case 1: break; /* VSU */
case 2: /* Misc. I/O */
*value = busReadMisc(sim, address, type);
break;
case 3: break; /* Unmapped */
case 4: break; /* Game Pak expansion */
case 5: /* WRAM */
*value = busReadBuffer(&sim->wram[address & 0x0000FFFF], type);
break;
case 6: /* Game Pak RAM */
if (sim->cart.ram != NULL) {
*value = busReadBuffer(
&sim->cart.ram[address & sim->cart.ramMask], type);
}
break;
case 7: /* Game Pak ROM */
if (sim->cart.rom != NULL) {
*value = busReadBuffer(
&sim->cart.rom[address & sim->cart.romMask], type);
}
break;
}
}
/* Write a typed value to the simulation bus */
static void busWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
/* Working variables */
address &= TYPE_MASKS[type];
/* Process by address range */
switch (address >> 24) {
case 0: /* VIP */
vipWrite(sim, address, type, value, debug);
break;
case 1: /* VSU */
vsuWrite(sim, address, type, value, debug);
break;
case 2: /* Misc. I/O */
busWriteMisc(sim, address, type, value);
break;
case 3: break; /* Unmapped */
case 4: break; /* Game Pak expansion */
case 5: /* WRAM */
busWriteBuffer(&sim->wram[address & 0x0000FFFF], type, value);
break;
case 6: /* Game Pak RAM */
if (sim->cart.ram != NULL) {
busWriteBuffer(
&sim->cart.ram[address & sim->cart.ramMask], type, value);
}
break;
case 7: /* Game Pak ROM */
if (debug && sim->cart.rom != NULL) {
busWriteBuffer(
&sim->cart.rom[address & sim->cart.romMask], type, value);
}
break;
}
}
#endif /* VBAPI */