#define VUEAPI #include /***************************************************************************** * Macros * *****************************************************************************/ /* Sign-extend a value */ #define SIGN_EXTEND(bits, value) \ ((value) & 1 << (bits - 1) ? (value) | (~(1 << bits) + 1) : (value)) /***************************************************************************** * Constants * *****************************************************************************/ /* Memory access type sizes */ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 }; /***************************************************************************** * Component Includes * *****************************************************************************/ #include "bus.c" #include "cpu.c" /***************************************************************************** * Library Functions * *****************************************************************************/ /* Retrieve the value of a register */ int32_t vueGetRegister(VUE *vue, int index, vbool system) { /* Error checking */ if (vue == NULL) return 0; /* Non-indexed registers */ if (system && index < 0) switch (index) { case VUE_JUMP_FROM: return vue->cpu.jumpFrom[vue->cpu.psw_np ? 2 : vue->cpu.psw_ep]; case VUE_JUMP_TO : return vue->cpu.jumpTo [vue->cpu.psw_np ? 2 : vue->cpu.psw_ep]; case VUE_PC : return vue->cpu.pc; } /* Indexed registers */ return index < 0 || index > 31 ? 0 : system ? cpuGetSystemRegister(vue, index) : vue->cpu.program[index] ; } /* Prepare an emulation state context for use */ void vueInitialize(VUE *vue) { if (vue == NULL) return; vue->bus.rom = NULL; vue->bus.sram = NULL; } /* Read bytes from the CPU bus */ vbool vueRead(VUE *vue, uint32_t address, uint8_t *dest, uint32_t length) { uint32_t count; /* Bytes to read in one iteration */ /* Error checking */ if (vue == NULL || dest == NULL) return VUE_FALSE; /* Perform the operation */ for (; length > 0; address += count, length -= count, dest += count) { /* Determine the maximum number of bytes to process at once */ count = 0x01000000 - (address & 0x00FFFFFF); if (count > length) count = length; /* Process by component */ switch (address >> 24 & 7) { case 1: /* Fallthrough */ /* VSU (write-only) */ case 3: /* Fallthrough */ /* Unmapped */ case 4: /* Cartridge expansion (not supported) */ busReadBytes(NULL, dest, address, 0, count); break; case 5: busReadBytes(vue->bus.wram, dest, /* System WRAM */ address, 0x10000 , count); break; case 6: busReadBytes(vue->bus.sram, dest, /* Cartridge RAM */ address, vue->bus.sramSize, count); break; case 7: busReadBytes(vue->bus.rom , dest, /* Cartridge ROM */ address, vue->bus.romSize , count); break; } }; return VUE_TRUE; } /* Initialize all system components */ void vueReset(VUE *vue) { if (vue == NULL) return; busReset(vue); cpuReset(vue); } /* Specify a value for a register */ int32_t vueSetRegister(VUE *vue, int index, vbool system, int32_t value) { return vue == NULL ? 0 : index == VUE_PC && system ? vue->cpu.pc = value & 0xFFFFFFFE : index < 0 || index > 31 ? 0 : system ? cpuSetSystemRegister(vue, index, value, VUE_TRUE) : index == 0 ? 0 : (vue->cpu.program[index] = value) ; } /* Specify a new ROM buffer */ vbool vueSetROM(VUE *vue, uint8_t *rom, uint32_t size) { /* Error checking */ if ( vue == NULL || rom == NULL || size < 1024 || size > 0x01000000 || (size & (size - 1)) != 0 ) return VUE_FALSE; /* Accept the new ROM buffer */ vue->bus.rom = rom; vue->bus.romSize = size; return VUE_TRUE; } /* Write bytes to the CPU bus */ vbool vueWrite(VUE *vue, uint32_t address, uint8_t *src, uint32_t length) { uint32_t count; /* Bytes to write in one iteration */ /* Error checking */ if (vue == NULL || src == NULL) return VUE_FALSE; /* Perform the operation */ for (; length > 0; address += count, length -= count, src += count) { /* Determine the maximum number of bytes to process at once */ count = 0x01000000 - (address & 0x00FFFFFF); if (count > length) count = length; /* Process by component */ switch (address >> 24 & 7) { case 5: /* System WRAM */ busWriteBytes(vue->bus.wram, src, address, 0x10000, count); break; case 6: busWriteBytes(vue->bus.sram, src, /* Cartridge RAM */ address, vue->bus.sramSize, count); break; case 7: busWriteBytes(vue->bus.rom , src, /* Cartridge ROM */ address, vue->bus.romSize , count); break; } }; return VUE_TRUE; }