pvbemu/src/core/bus.c

141 lines
4.2 KiB
C

/* This file is included through vue.c and cannot be built directly. */
#ifdef VUEAPI
/* Read bytes from host memory */
static void busReadBytes(uint8_t *src, uint8_t *dest, uint32_t address,
uint32_t size, uint32_t length) {
/* There is no source data */
if (src == NULL)
while (length-- > 0)
*dest++ = 0;
/* Copy bytes from the source as a circular buffer */
else for (size--; length-- > 0;)
*dest++ = src[address++ & size];
}
/* Read a value directly from host memory */
static int32_t busReadMemory(uint8_t *data, uint32_t offset, int type) {
int32_t value; /* Value read */
/* There is no source data */
if (data == NULL)
return 0;
/* Locate the value */
data = &data[offset];
/* Read the value */
switch (type) {
case VUE_S8 : value = *(int8_t *)data; break;
case VUE_U8 : value = *(uint8_t *)data; break;
case VUE_S16: value = *(int16_t *)data; break;
case VUE_U16: value = *(uint16_t *)data; break;
case VUE_S32: value = *(int32_t *)data; break;
}
/* Host memory is big-endian */
#ifdef VUE_BIGENDIAN
switch (type) {
case VUE_S32:
value = (value >> 16 & 0x0000FFFF) | value << 16;
/* Fallthrough */
case VUE_S16:
case VUE_U16:
value = (value >> 8 & 0x00FF00FF) | (value << 8 & 0xFF00FF00);
break;
}
#endif
return value;
}
/* Read a value from the CPU bus */
static int32_t busReadValue(VUE *vue, uint32_t address, int type) {
address &= -TYPE_SIZES[type];
switch (address >> 24 & 7) {
case 1: /* Fallthrough */ /* VSU (write-only) */
case 3: /* Fallthrough */ /* Unmapped */
case 4: /* Cartridge expansion (not supported) */
return 0;
case 5: /* System WRAM */
return busReadMemory(vue->bus.wram, address & 0xFFFF, type);
case 6: return busReadMemory(vue->bus.sram, /* Cartridge RAM */
address & (vue->bus.sramSize - 1), type);
case 7: return busReadMemory(vue->bus.rom , /* Cartridge ROM */
address & (vue->bus.romSize - 1), type);
}
return 0; /* Unreachable */
}
/* Perform a system reset */
static void busReset(VUE *vue) {
int x;
for (x = 0; x < 0x10000; x++)
vue->bus.wram[x] = 0;
}
/* Write bytes to host memory */
static void busWriteBytes(uint8_t *dest, uint8_t *src, uint32_t address,
uint32_t size, uint32_t length) {
if (dest != NULL)
for (size--; length-- > 0;)
dest[address++ & size] = *src++;
}
/* Write a value directly to host memory */
static void busWriteMemory(uint8_t *data, uint32_t offset, int type,
int32_t value) {
/* There is no destination data */
if (data == NULL)
return;
/* Locate the value */
data = &data[offset];
/* Host memory is big-endian */
#ifdef VUE_BIGENDIAN
switch (type) {
case VUE_S32:
value = (value >> 16 & 0x0000FFFF) | value << 16;
/* Fallthrough */
case VUE_S16:
case VUE_U16:
value = (value >> 8 & 0x00FF00FF) | (value << 8 & 0xFF00FF00);
break;
}
#endif
/* Write the value */
switch (type) {
case VUE_S8 : /* Fallthrough */
case VUE_U8 : *(uint8_t *)data = (uint8_t) value; break;
case VUE_S16: /* Fallthrough */
case VUE_U16: *(uint16_t *)data = (int16_t) value; break;
case VUE_S32: *(int32_t *)data = (int32_t) value; break;
}
}
/* Write a value to the CPU bus */
static void busWriteValue(VUE *vue, uint32_t address, int type, int32_t value){
address &= -TYPE_SIZES[type];
switch (address >> 24 & 7) {
case 5: /* System WRAM */
busWriteMemory(vue->bus.wram, address & 0xFFFF, type, value);
break;
case 6: /* Cartridge RAM */
busWriteMemory(vue->bus.sram,
address & (vue->bus.sramSize - 1), type, value);
break;
case 7: /* Cartridge ROM */
busWriteMemory(vue->bus.rom ,
address & (vue->bus.romSize - 1), type, value);
break;
}
}
#endif /* VUEAPI */