mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 15:15:43 +00:00
Clean up sandbox to prepare for adding ARMv5 tools to it
This commit is contained in:
@@ -49,6 +49,7 @@ This thing: case SEND_STATUS://HACK, need to add real write protection, this com
|
||||
|
||||
Debug tools:
|
||||
ADS7846 channels can't be read in single reference mode in hwTestSuite
|
||||
Mu sandbox dosent have memory and opcode hooks setup when in ARMv5 mode
|
||||
|
||||
MakePalmBitmap:
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
#include "sandbox.h"
|
||||
#include "trapNames.h"
|
||||
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
#include "../armv5te/cpu.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(EMU_SUPPORT_PALM_OS5)
|
||||
//fake functions for ARMv5 CPU accesses
|
||||
#define reg_pc(x) 0
|
||||
#endif
|
||||
|
||||
#define SANDBOX_MAX_UNLOGGED_JUMP_SIZE 0xFFFFFFFF
|
||||
#define SANDBOX_MAX_WATCH_REGIONS 1000
|
||||
@@ -39,7 +48,7 @@ typedef struct{
|
||||
uint16_t sr;
|
||||
uint32_t a0;
|
||||
uint32_t d0;
|
||||
}local_cpu_state_t;
|
||||
}m68k_local_cpu_state_t;
|
||||
|
||||
typedef struct{
|
||||
uint32_t address;
|
||||
@@ -48,16 +57,16 @@ typedef struct{
|
||||
}mem_region_t;
|
||||
|
||||
|
||||
static bool sandboxActive;//used to "log out" of the emulator once a test has finished
|
||||
static bool sandboxControlHandoff;//used for functions that depend on timing, hands full control to the m68k
|
||||
static uint8_t sandboxCurrentCpuArch;
|
||||
static local_cpu_state_t sandboxOldFunctionCpuState;
|
||||
static uint64_t sandboxFramesRan;
|
||||
static mem_region_t sandboxWatchRegions[SANDBOX_MAX_WATCH_REGIONS];//code locations in 68k address space to be sandboxed
|
||||
static uint16_t sandboxWatchRegionsActive;//number of used sandboxWatchRegions entrys
|
||||
static bool sandboxActive;//used to "log out" of the emulator once a test has finished
|
||||
static bool sandboxControlHandoff;//used for functions that depend on timing, hands full control to the m68k
|
||||
static uint8_t sandboxCurrentCpuArch;
|
||||
static m68k_local_cpu_state_t sandboxOldFunctionM68kCpuState;
|
||||
static uint64_t sandboxFramesRan;
|
||||
static mem_region_t sandboxWatchRegions[SANDBOX_MAX_WATCH_REGIONS];//code locations in 68k address space to be sandboxed
|
||||
static uint16_t sandboxWatchRegionsActive;//number of used sandboxWatchRegions entrys
|
||||
|
||||
|
||||
static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...);
|
||||
static uint32_t m515CallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...);
|
||||
|
||||
#include "sandboxTrapNumToName.c.h"
|
||||
|
||||
@@ -104,7 +113,7 @@ static void patchOsRom(uint32_t address, char* patch){
|
||||
swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
|
||||
}
|
||||
|
||||
static const char* getLowMemGlobalName(uint32_t address){
|
||||
static const char* m515GetLowMemGlobalName(uint32_t address){
|
||||
switch(address){
|
||||
case 0x00000100:
|
||||
return "MemTotalCards";
|
||||
@@ -147,7 +156,7 @@ static const char* getLowMemGlobalName(uint32_t address){
|
||||
}
|
||||
}
|
||||
|
||||
static bool ignoreTrap(uint16_t trap){
|
||||
static bool m515IgnoreTrap(uint16_t trap){
|
||||
switch(trap){
|
||||
case HwrDisableDataWrites:
|
||||
case HwrEnableDataWrites:
|
||||
@@ -160,11 +169,11 @@ static bool ignoreTrap(uint16_t trap){
|
||||
return false;
|
||||
}
|
||||
|
||||
static void printTrapInfo(uint16_t trap){
|
||||
static void m515PrintTrapInfo(uint16_t trap){
|
||||
debugLog("name:%s, API:0x%04X, location:0x%08X\n", lookupTrap(trap), trap, m68k_read_memory_32(0x000008CC + (trap & 0x0FFF) * 4));
|
||||
}
|
||||
|
||||
bool validExecutionAddress(uint32_t address){
|
||||
bool m515ValidExecutionAddress(uint32_t address){
|
||||
if(dbvzChipSelects[DBVZ_CHIP_A0_ROM].inBootMode || address >= dbvzChipSelects[DBVZ_CHIP_A0_ROM].start && address < dbvzChipSelects[DBVZ_CHIP_A0_ROM].start + dbvzChipSelects[DBVZ_CHIP_A0_ROM].lineSize)
|
||||
return true;
|
||||
if(address >= dbvzChipSelects[DBVZ_CHIP_DX_RAM].start && address < dbvzChipSelects[DBVZ_CHIP_DX_RAM].start + dbvzChipSelects[DBVZ_CHIP_DX_RAM].lineSize)
|
||||
@@ -174,26 +183,26 @@ bool validExecutionAddress(uint32_t address){
|
||||
return false;
|
||||
}
|
||||
|
||||
void log68kJumps(void){
|
||||
void logM68kJumps(void){
|
||||
uint32_t opcodeStartPc = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
uint32_t opcodeEndPc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
uint32_t difference = llabs((int64_t)opcodeStartPc - (int64_t)opcodeEndPc);
|
||||
|
||||
//if invalid always log, otherwise only log if big jump
|
||||
if(!validExecutionAddress(opcodeEndPc))
|
||||
if(!m515ValidExecutionAddress(opcodeEndPc))
|
||||
debugLog("m68k jumped 0x%08X bytes to invalid address, from 0x%08X to 0x%08X\n", difference, opcodeStartPc, opcodeEndPc);
|
||||
else if(difference > SANDBOX_MAX_UNLOGGED_JUMP_SIZE)
|
||||
debugLog("m68k jumped 0x%08X bytes, from 0x%08X to 0x%08X\n", difference, opcodeStartPc, opcodeEndPc);
|
||||
}
|
||||
|
||||
static void logApiCalls(void){
|
||||
static void m515LogApiCalls(void){
|
||||
uint32_t programCounter = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
uint16_t instruction = m68k_read_memory_16(programCounter);
|
||||
|
||||
if(instruction == 0x4E4F/*Trap F/API call opcode*/){
|
||||
uint16_t trap = m68k_read_memory_16(programCounter + 2);
|
||||
|
||||
if(!ignoreTrap(trap))
|
||||
if(!m515IgnoreTrap(trap))
|
||||
debugLog("Trap F API:%s, API number:0x%04X, PC:0x%08X\n", lookupTrap(trap), trap, programCounter);
|
||||
}
|
||||
}
|
||||
@@ -212,7 +221,7 @@ static bool readable6CharsBack(uint32_t address){
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t find68kString(const char* str, uint32_t rangeStart, uint32_t rangeEnd){
|
||||
static uint32_t findM68kString(const char* str, uint32_t rangeStart, uint32_t rangeEnd){
|
||||
uint32_t strLength = strlen(str) + 1;//include null terminator
|
||||
uint32_t scanAddress;
|
||||
|
||||
@@ -240,7 +249,7 @@ static uint32_t find68kString(const char* str, uint32_t rangeStart, uint32_t ran
|
||||
return rangeEnd;
|
||||
}
|
||||
|
||||
static uint32_t skip68kString(uint32_t address){
|
||||
static uint32_t skipM68kString(uint32_t address){
|
||||
while(m68k_read_memory_8(address) != '\0')
|
||||
address++;
|
||||
address++;//skip null terminator too
|
||||
@@ -248,18 +257,18 @@ static uint32_t skip68kString(uint32_t address){
|
||||
}
|
||||
|
||||
//THIS FUNCTION DOES NOT WORK IF A WORD ALIGNED 0x0000 IS FOUND IN THE FUNCTION BEING SEARCHED FOR, THIS IS A BUG
|
||||
static uint32_t scanForPrivateFunctionAddress(const char* name){
|
||||
static uint32_t m515ScanForPrivateFunctionAddress(const char* name){
|
||||
//function name format [0x**(unknown), string(with null terminator), 0x00, 0x00(if last 0x00 was on an even address, protects opcode alignemnt)]
|
||||
//this is not 100% accurate, it scans memory for a function address based on a string
|
||||
//if a duplicate set of stings is found but not encasing a function a fatal error will occur on execution
|
||||
uint32_t rangeEnd = dbvzChipSelects[DBVZ_CHIP_A0_ROM].start + dbvzChipSelects[DBVZ_CHIP_A0_ROM].lineSize - 1;
|
||||
uint32_t address = find68kString(name, dbvzChipSelects[DBVZ_CHIP_A0_ROM].start, rangeEnd);
|
||||
uint32_t address = findM68kString(name, dbvzChipSelects[DBVZ_CHIP_A0_ROM].start, rangeEnd);
|
||||
|
||||
while(address < rangeEnd){
|
||||
uint32_t signatureBegining = address - 3;//last opcode of function being looked for if the string is correct
|
||||
|
||||
//skip string to test the null terminators
|
||||
address = skip68kString(address);
|
||||
address = skipM68kString(address);
|
||||
|
||||
//after a function string there are 2 null terminators(the one all strings have and 1 extra) or 3(2 extra) if the previous one was on an even address
|
||||
if(m68k_read_memory_8(address) == '\0' && (address & 0x00000001 || m68k_read_memory_8(address + 1) == '\0')){
|
||||
@@ -284,14 +293,14 @@ static uint32_t scanForPrivateFunctionAddress(const char* name){
|
||||
}
|
||||
|
||||
//string matched but structure was invalid, get next string
|
||||
address = find68kString(name, address, rangeEnd);
|
||||
address = findM68kString(name, address, rangeEnd);
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
|
||||
//call anywhere in a function to get its name, used to determine the location of a crash, must free the pointer after reading the string
|
||||
static char* getFunctionName68k(uint32_t address){
|
||||
static char* getFunctionNameM68k(uint32_t address){
|
||||
char* data;
|
||||
uint32_t offset;
|
||||
|
||||
@@ -324,9 +333,9 @@ static char* getFunctionName68k(uint32_t address){
|
||||
return data;
|
||||
}
|
||||
|
||||
static uint32_t makePalmString(const char* str){
|
||||
static uint32_t m515MakePalmString(const char* str){
|
||||
uint32_t strLength = strlen(str) + 1;
|
||||
uint32_t strData = sandboxCallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength);
|
||||
uint32_t strData = m515CallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength);
|
||||
|
||||
if(strData){
|
||||
uint32_t count;
|
||||
@@ -338,9 +347,9 @@ static uint32_t makePalmString(const char* str){
|
||||
return strData;
|
||||
}
|
||||
|
||||
static char* makeNativeString(uint32_t address){
|
||||
static char* m515MakeNativeString(uint32_t address){
|
||||
if(address){
|
||||
int16_t strLength = sandboxCallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1;
|
||||
int16_t strLength = m515CallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1;
|
||||
char* nativeStr = malloc(strLength);
|
||||
int16_t count;
|
||||
|
||||
@@ -351,11 +360,11 @@ static char* makeNativeString(uint32_t address){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void freePalmString(uint32_t address){
|
||||
sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", address);
|
||||
static void m515FreePalmString(uint32_t address){
|
||||
m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", address);
|
||||
}
|
||||
|
||||
static bool installResourceToDevice(uint8_t* data, uint32_t size){
|
||||
static bool m515InstallResourceToDevice(uint8_t* data, uint32_t size){
|
||||
/*
|
||||
#define memNewChunkFlagNonMovable 0x0200
|
||||
#define memNewChunkFlagAllowLarge 0x1000 // this is not in the sdk *g*
|
||||
@@ -375,7 +384,7 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){
|
||||
}
|
||||
*/
|
||||
|
||||
uint32_t palmSideResourceData = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", 1/*heapID, storage RAM*/, size, 0x1200/*attr, seems to work without memOwnerID*/);
|
||||
uint32_t palmSideResourceData = m515CallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", 1/*heapID, storage RAM*/, size, 0x1200/*attr, seems to work without memOwnerID*/);
|
||||
bool storageRamReadOnly = dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory;
|
||||
uint16_t error;
|
||||
uint32_t count;
|
||||
@@ -388,8 +397,8 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){
|
||||
for(count = 0; count < size; count++)
|
||||
m68k_write_memory_8(palmSideResourceData + count, data[count]);
|
||||
dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory = storageRamReadOnly;//restore old protection state
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, DmCreateDatabaseFromImage, "w(p)", palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best
|
||||
sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", palmSideResourceData);
|
||||
error = m515CallGuestFunction(false, 0x00000000, DmCreateDatabaseFromImage, "w(p)", palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best
|
||||
m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", palmSideResourceData);
|
||||
|
||||
//didnt install
|
||||
if(error != 0)
|
||||
@@ -398,187 +407,7 @@ static bool installResourceToDevice(uint8_t* data, uint32_t size){
|
||||
return true;
|
||||
}
|
||||
|
||||
static void printChunkHeader(uint32_t pointer){
|
||||
uint32_t address = pointer - 8;
|
||||
uint32_t headerLong1 = m68k_read_memory_32(address);
|
||||
uint32_t totalSize = headerLong1 & 0x00FFFFFF;
|
||||
uint8_t extraBytes = headerLong1 >> 24 & 0x0F;
|
||||
uint32_t userRequestedSize = totalSize - 8 - extraBytes;
|
||||
|
||||
debugLog("Chunk header: address:0x%08X, totalSize:%d(0x%08X), userSize:%d(0x%08X), extraBytes:%d(0x%02X)\n", address, totalSize, totalSize, userRequestedSize, userRequestedSize, extraBytes, extraBytes);
|
||||
}
|
||||
|
||||
static void checkMemoryAlignmentPointer(uint16_t heap){
|
||||
uint32_t memPtrs[100];
|
||||
uint8_t index;
|
||||
uint16_t error;
|
||||
|
||||
memset(memPtrs, 0x00, sizeof(memPtrs));
|
||||
|
||||
//get randomly sized memory regions
|
||||
for(index = 0; index < 100; index++){
|
||||
memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", heap, getRandomRange(1, 100), 0x0200/*memNewChunkFlagNonMovable*/);
|
||||
if(!memPtrs[index]){
|
||||
debugLog("Memory test: Failed to allocate memory\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//check alignment
|
||||
for(index = 0; index < 100; index++){
|
||||
if(memPtrs[index] & 0x00000003){
|
||||
debugLog("Memory test: Memory allocations are not 32 bit aligned:0x%08X\n", memPtrs[index]);
|
||||
printChunkHeader(memPtrs[index]);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//non moveable memory wont resize
|
||||
|
||||
//shuffle memory
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHeapCompact, "w(w)", heap);
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Unable to scramble heap:0x%04X\n", error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
//check alignment again
|
||||
for(index = 0; index < 100; index++){
|
||||
if(memPtrs[index] & 0x00000003){
|
||||
debugLog("Memory test: Memory misaligned by defragment:0x%08X\n", memPtrs[index]);
|
||||
printChunkHeader(memPtrs[index]);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("Memory test: Memory aligned correctly\n");
|
||||
|
||||
failed:
|
||||
|
||||
//free pointers
|
||||
for(index = 0; index < 100; index++)
|
||||
if(memPtrs[index])
|
||||
sandboxCallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", memPtrs[index]);
|
||||
}
|
||||
|
||||
static void checkMemoryAlignmentHandle(uint16_t heap){
|
||||
uint32_t memHandles[100];
|
||||
uint32_t memPtrs[100];
|
||||
uint8_t index;
|
||||
uint16_t error;
|
||||
|
||||
//a handle is just a pointer with bit 31 set, when the pointer is moved a look up table entry is set to the new address and used for future operations
|
||||
|
||||
memset(memHandles, 0x00, sizeof(memHandles));
|
||||
memset(memPtrs, 0x00, sizeof(memPtrs));
|
||||
|
||||
//get randomly sized memory regions
|
||||
for(index = 0; index < 100; index++){
|
||||
memHandles[index] = sandboxCallGuestFunction(false, 0x00000000, MemChunkNew, "p(wlw)", heap, getRandomRange(1, 100), 0x0000);
|
||||
if(!memHandles[index]){
|
||||
debugLog("Memory test: Failed to allocate memory\n");
|
||||
goto failed;
|
||||
}
|
||||
memHandles[index] |= 0x80000000;//tell the OS this is a handle, this is all MemHandleNew does is allocate memory normally and set that bit
|
||||
}
|
||||
|
||||
//update pointer list
|
||||
for(index = 0; index < 100; index++){
|
||||
memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]);
|
||||
if(!memPtrs[index]){
|
||||
debugLog("Memory test: Failed to lock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]);
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Failed to unlock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//check alignment
|
||||
for(index = 0; index < 100; index++){
|
||||
if(memPtrs[index] & 0x00000003){
|
||||
debugLog("Memory test: Memory allocations are not 32 bit aligned:0x%08X\n", memPtrs[index]);
|
||||
printChunkHeader(memPtrs[index]);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//resize memory
|
||||
for(index = 0; index < 100; index++){
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHandleResize, "w(ll)", memHandles[index], getRandomRange(1, 100));
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Failed to resize memory:0x%04X\n", error);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//update pointer list
|
||||
for(index = 0; index < 100; index++){
|
||||
memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]);
|
||||
if(!memPtrs[index]){
|
||||
debugLog("Memory test: Failed to lock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]);
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Failed to unlock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//check alignment again
|
||||
for(index = 0; index < 100; index++){
|
||||
if(memPtrs[index] & 0x00000003){
|
||||
debugLog("Memory test: Memory misaligned by resize:0x%08X\n", memPtrs[index]);
|
||||
printChunkHeader(memPtrs[index]);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//shuffle memory
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHeapCompact, "w(w)", heap);
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Unable to scramble heap:0x%04X\n", error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
//update pointer list
|
||||
for(index = 0; index < 100; index++){
|
||||
memPtrs[index] = sandboxCallGuestFunction(false, 0x00000000, MemHandleLock, "p(l)", memHandles[index]);
|
||||
if(!memPtrs[index]){
|
||||
debugLog("Memory test: Failed to lock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
error = sandboxCallGuestFunction(false, 0x00000000, MemHandleUnlock, "w(l)", memHandles[index]);
|
||||
if(error != 0x0000/*errNone*/){
|
||||
debugLog("Memory test: Failed to unlock handle\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
//check alignment again
|
||||
for(index = 0; index < 100; index++){
|
||||
if(memPtrs[index] & 0x00000003){
|
||||
debugLog("Memory test: Memory misaligned by defragment:0x%08X\n", memPtrs[index]);
|
||||
printChunkHeader(memPtrs[index]);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
debugLog("Memory test: Memory aligned correctly\n");
|
||||
|
||||
failed:
|
||||
|
||||
//free handles
|
||||
for(index = 0; index < 100; index++)
|
||||
if(memHandles[index])
|
||||
sandboxCallGuestFunction(false, 0x00000000, MemHandleFree, "w(l)", memHandles[index]);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t sandboxGetStackFrameSize(const char* prototype){
|
||||
static uint32_t m515GetStackFrameSize(const char* prototype){
|
||||
const char* params = prototype + 2;
|
||||
uint32_t size = 0;
|
||||
|
||||
@@ -611,23 +440,23 @@ static uint32_t sandboxGetStackFrameSize(const char* prototype){
|
||||
return size;
|
||||
}
|
||||
|
||||
static void sandboxBackupCpuState(void){
|
||||
sandboxOldFunctionCpuState.sp = m68k_get_reg(NULL, M68K_REG_SP);
|
||||
sandboxOldFunctionCpuState.pc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
sandboxOldFunctionCpuState.sr = m68k_get_reg(NULL, M68K_REG_SR);
|
||||
sandboxOldFunctionCpuState.a0 = m68k_get_reg(NULL, M68K_REG_A0);
|
||||
sandboxOldFunctionCpuState.d0 = m68k_get_reg(NULL, M68K_REG_D0);
|
||||
static void m515BackupCpuState(void){
|
||||
sandboxOldFunctionM68kCpuState.sp = m68k_get_reg(NULL, M68K_REG_SP);
|
||||
sandboxOldFunctionM68kCpuState.pc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
sandboxOldFunctionM68kCpuState.sr = m68k_get_reg(NULL, M68K_REG_SR);
|
||||
sandboxOldFunctionM68kCpuState.a0 = m68k_get_reg(NULL, M68K_REG_A0);
|
||||
sandboxOldFunctionM68kCpuState.d0 = m68k_get_reg(NULL, M68K_REG_D0);
|
||||
}
|
||||
|
||||
static void sandboxRestoreCpuState(void){
|
||||
m68k_set_reg(M68K_REG_SP, sandboxOldFunctionCpuState.sp);
|
||||
m68k_set_reg(M68K_REG_PC, sandboxOldFunctionCpuState.pc);
|
||||
m68k_set_reg(M68K_REG_SR, sandboxOldFunctionCpuState.sr & 0xF0FF | m68k_get_reg(NULL, M68K_REG_SR) & 0x0700);//dont restore intMask
|
||||
m68k_set_reg(M68K_REG_A0, sandboxOldFunctionCpuState.a0);
|
||||
m68k_set_reg(M68K_REG_D0, sandboxOldFunctionCpuState.d0);
|
||||
static void m515RestoreCpuState(void){
|
||||
m68k_set_reg(M68K_REG_SP, sandboxOldFunctionM68kCpuState.sp);
|
||||
m68k_set_reg(M68K_REG_PC, sandboxOldFunctionM68kCpuState.pc);
|
||||
m68k_set_reg(M68K_REG_SR, sandboxOldFunctionM68kCpuState.sr & 0xF0FF | m68k_get_reg(NULL, M68K_REG_SR) & 0x0700);//dont restore intMask
|
||||
m68k_set_reg(M68K_REG_A0, sandboxOldFunctionM68kCpuState.a0);
|
||||
m68k_set_reg(M68K_REG_D0, sandboxOldFunctionM68kCpuState.d0);
|
||||
}
|
||||
|
||||
static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...){
|
||||
static uint32_t m515CallGuestFunction(bool fallthrough, uint32_t address, uint16_t trap, const char* prototype, ...){
|
||||
//prototype is a Java style function signature describing values passed and returned "v(wllp)"
|
||||
//is return void and pass a uint16_t(word), 2 uint32_t(long) and 1 pointer
|
||||
//valid types are b(yte), w(ord), l(ong), p(ointer) and v(oid), a capital letter means its a return pointer
|
||||
@@ -636,7 +465,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin
|
||||
va_list args;
|
||||
const char* params = prototype + 2;
|
||||
uint32_t stackFrameStart = m68k_get_reg(NULL, M68K_REG_SP);
|
||||
uint32_t newStackFrameSize = sandboxGetStackFrameSize(prototype);
|
||||
uint32_t newStackFrameSize = m515GetStackFrameSize(prototype);
|
||||
uint32_t stackWriteAddr = stackFrameStart - newStackFrameSize;
|
||||
uint32_t oldStopped = m68ki_cpu.stopped;
|
||||
uint32_t functionReturn = 0x00000000;
|
||||
@@ -646,7 +475,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin
|
||||
uint32_t callStart;
|
||||
uint8_t count;
|
||||
|
||||
sandboxBackupCpuState();
|
||||
m515BackupCpuState();
|
||||
|
||||
va_start(args, prototype);
|
||||
while(*params != ')'){
|
||||
@@ -751,7 +580,7 @@ static uint32_t sandboxCallGuestFunction(bool fallthrough, uint32_t address, uin
|
||||
else if(prototype[0] == 'b' || prototype[0] == 'w' || prototype[0] == 'l')
|
||||
functionReturn = m68k_get_reg(NULL, M68K_REG_D0);
|
||||
m68ki_cpu.stopped = oldStopped;
|
||||
sandboxRestoreCpuState();
|
||||
m515RestoreCpuState();
|
||||
|
||||
//remap all argument pointers
|
||||
for(count = 0; count < functionReturnPointerIndex; count++){
|
||||
@@ -783,6 +612,7 @@ void sandboxInit(void){
|
||||
void sandboxReset(void){
|
||||
sandboxActive = false;
|
||||
sandboxControlHandoff = false;
|
||||
sandboxCurrentCpuArch = SANDBOX_CPU_ARCH_M68K;
|
||||
sandboxFramesRan = 0;
|
||||
|
||||
memset(sandboxWatchRegions, 0x00, sizeof(sandboxWatchRegions));
|
||||
@@ -802,8 +632,8 @@ uint32_t sandboxStateSize(void){
|
||||
uint32_t size = 0;
|
||||
|
||||
size += sizeof(uint8_t) * 3;//sandboxActive / sandboxControlHandoff / sandboxCurrentCpuArch
|
||||
size += sizeof(uint32_t) * 4;//sandboxOldFunctionCpuState.(sp/pc/a0/d0)
|
||||
size += sizeof(uint16_t);//sandboxOldFunctionCpuState.sr
|
||||
size += sizeof(uint32_t) * 4;//sandboxOldFunctionM68kCpuState.(sp/pc/a0/d0)
|
||||
size += sizeof(uint16_t);//sandboxOldFunctionM68kCpuState.sr
|
||||
size += sizeof(uint64_t);//sandboxFramesRan
|
||||
size += sizeof(uint32_t) * 2 * SANDBOX_MAX_WATCH_REGIONS;//sandboxWatchRegions.(address/size)
|
||||
size += sizeof(uint8_t) * SANDBOX_MAX_WATCH_REGIONS;//sandboxWatchRegions.type
|
||||
@@ -822,15 +652,15 @@ void sandboxSaveState(uint8_t* data){
|
||||
offset += sizeof(uint8_t);
|
||||
writeStateValue8(data + offset, sandboxCurrentCpuArch);//currently cant be ARMv5 during a frame boundry but that may change
|
||||
offset += sizeof(uint8_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionCpuState.sp);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.sp);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionCpuState.pc);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.pc);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue16(data + offset, sandboxOldFunctionCpuState.sr);
|
||||
writeStateValue16(data + offset, sandboxOldFunctionM68kCpuState.sr);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionCpuState.a0);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.a0);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionCpuState.d0);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.d0);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue64(data + offset, sandboxFramesRan);
|
||||
offset += sizeof(uint64_t);
|
||||
@@ -856,15 +686,15 @@ void sandboxLoadState(uint8_t* data){
|
||||
offset += sizeof(uint8_t);
|
||||
sandboxCurrentCpuArch = readStateValue8(data + offset);//currently cant be ARMv5 during a frame boundry but that may change
|
||||
offset += sizeof(uint8_t);
|
||||
sandboxOldFunctionCpuState.sp = readStateValue32(data + offset);
|
||||
sandboxOldFunctionM68kCpuState.sp = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionCpuState.pc = readStateValue32(data + offset);
|
||||
sandboxOldFunctionM68kCpuState.pc = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionCpuState.sr = readStateValue16(data + offset);
|
||||
sandboxOldFunctionM68kCpuState.sr = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
sandboxOldFunctionCpuState.a0 = readStateValue32(data + offset);
|
||||
sandboxOldFunctionM68kCpuState.a0 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionCpuState.d0 = readStateValue32(data + offset);
|
||||
sandboxOldFunctionM68kCpuState.d0 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxFramesRan = readStateValue64(data + offset);
|
||||
offset += sizeof(uint64_t);
|
||||
@@ -898,173 +728,12 @@ uint32_t sandboxCommand(uint32_t command, void* data){
|
||||
//patchOsRom(0x83B0A, "203C000800004E75");//move.l 0x80000, d0; rts
|
||||
//patchOsRom(0x5CC6, "203C001000004E75");//move.l 0x100000, d0; rts
|
||||
//patchOsRom(0x83B0A, "203C001000004E75");//move.l 0x100000, d0; rts
|
||||
|
||||
//patch PrvChunkNew to only allocate in 4 byte intervals
|
||||
//PrvChunkNew_10020CBC:
|
||||
//TODO
|
||||
|
||||
//set RAM to 32MB
|
||||
//patchOsRom(0x2C5E, "203C020000004E75");//move.l 0x2000000, d0; rts
|
||||
//patchOsRom(0x8442E, "203C020000004E75");//move.l 0x2000000, d0; rts
|
||||
|
||||
//set RAM to 128MB
|
||||
//PrvGetRAMSize_10002C5E, small ROM
|
||||
//PrvGetRAMSize_1008442E, big ROM
|
||||
//patchOsRom(0x2C5E, "203C080000004E75");//move.l 0x8000000, d0; rts
|
||||
//patchOsRom(0x8442E, "203C080000004E75");//move.l 0x8000000, d0; rts
|
||||
//ROM:100219D0 move.l #unk_FFFFFF,d0
|
||||
//patchOsRom(0x219D0, "203C01FFFFFF4E75");//move.l 0x1FFFFFF, d0; rts
|
||||
//bus error at 0x1001DEDA when 128MB is present
|
||||
//0x55 memory filler, 32 bit, at PC:0x1001FFDC, and of course, its MemSet, need a stack trace now
|
||||
//PrvInitHeapPtr_10021908 sets up the 0x55 stuff in RAM
|
||||
/*
|
||||
ROM:100219C2 move.l d0,6(a4) ; Move Data from Source to Destination
|
||||
ROM:100219C6 tst.b arg_A(a6) ; Test an Operand
|
||||
ROM:100219CA beq.s loc_100219EA ; Branch if Equal
|
||||
ROM:100219CC move.b #$55,-(sp) ; 'U' ; Move Data from Source to Destination
|
||||
ROM:100219D0 move.l #unk_FFFFFF,d0 ; Move Data from Source to Destination
|
||||
ROM:100219D6 and.l (a3),d0 ; AND Logical
|
||||
ROM:100219D8 subq.l #8,d0 ; Subtract Quick
|
||||
ROM:100219DA move.l d0,-(sp) ; Move Data from Source to Destination
|
||||
ROM:100219DC movea.l a3,a0 ; Move Address
|
||||
ROM:100219DE pea 8(a0) ; Push Effective Address
|
||||
ROM:100219E2 trap #$F ; Trap sysTrapMemSet
|
||||
ROM:100219E2 dc.w $A027
|
||||
ROM:100219E6 lea $A(sp),sp ; Load Effective Address
|
||||
*/
|
||||
//D0 is 0x3E1CC(254412) at PC:0x10021988
|
||||
|
||||
// Add the heap, as long as it's not the dynamic heap. During
|
||||
// bootup, the memory initialization sequence goes like:
|
||||
//
|
||||
// if hard reset required:
|
||||
// MemCardFormat
|
||||
// lay out the card
|
||||
// MemStoreInit
|
||||
// for each heap
|
||||
// MemHeapInit
|
||||
// MemInit
|
||||
// for each card:
|
||||
// MemInitHeapTable
|
||||
// for each dynamic heap:
|
||||
// MemHeapInit
|
||||
// for each RAM heap:
|
||||
// Unlock all chunks
|
||||
// Compact
|
||||
//
|
||||
// Which means that if there's no hard reset, MemHeapInit
|
||||
// has not been called on the dynamic heap at the time
|
||||
// MemInitHeapTable is called. And since the dynamic heap
|
||||
// is currently in a corrupted state (because the boot stack
|
||||
// and initial LCD buffer have been whapped over it), we
|
||||
// can't perform the heap walk we'd normally do when adding
|
||||
// a heap object.
|
||||
|
||||
//need to investigate what these vars are
|
||||
/*
|
||||
ROM:100148EE move.l #$3BE,(dword_15C).w ; Move Data from Source to Destination
|
||||
ROM:100148F6 move.l #$422,(dword_112).w ; Move Data from Source to Destination
|
||||
ROM:100148FE move.l #$890,(dword_11A).w ; Move Data from Source to Destination
|
||||
ROM:10014906 move.l #$8CC,(TrapTablePointer).w ; Move Data from Source to Destination
|
||||
ROM:1001490E move.w #$45A,(word_13E).w ; Move Data from Source to Destination
|
||||
ROM:10014914 move.w #$1000,(word_28E).w ; Move Data from Source to Destination
|
||||
*/
|
||||
|
||||
//another road block surfaces
|
||||
/*
|
||||
When a Palm Powered handheld is presented with multiple dynamic heaps,
|
||||
the first heap (heap 0) on card 0 is the active dynamic heap.
|
||||
All other potential dynamic heaps are ignored. For example, it
|
||||
is possible that a future Palm Powered handheld supporting multiple
|
||||
cards might be presented with two cards, each having its own dynamic heap;
|
||||
if so, only the dynamic heap residing on card 0 would be active—the system
|
||||
would not treat any heaps on other cards as dynamic heaps, nor would heap
|
||||
IDs be assigned to these heaps. Subsequent storage heaps would be assigned
|
||||
IDs in sequential order, as always beginning with RAM heaps, followed by ROM heaps.
|
||||
*/
|
||||
|
||||
//PrvChunkNew alignment code
|
||||
/*
|
||||
ROM:10020D04 moveq #1,d0 ; Move Quick
|
||||
ROM:10020D06 and.l size(a6),d0 ; Check if size is a multiple of 2
|
||||
ROM:10020D0A addq.w #2,sp ; Add Quick
|
||||
ROM:10020D0C beq.s loc_10020D16 ; Skip adding extra byte if already aligned
|
||||
ROM:10020D0E moveq #9,d0 ; Size is not 16 bit aligned, align and add 8 bytes
|
||||
ROM:10020D10 add.l size(a6),d0 ; Add requested size
|
||||
ROM:10020D14 bra.s loc_10020D1C ; Branch Always
|
||||
ROM:10020D16 ; ---------------------------------------------------------------------------
|
||||
ROM:10020D16
|
||||
ROM:10020D16 loc_10020D16: ; CODE XREF: PrvChunkNew_10020CBC+50↑j
|
||||
ROM:10020D16 move.l size(a6),d0 ; Set requested size
|
||||
ROM:10020D1A addq.l #8,d0 ; Add 8 bytes(currently dont know what there for)
|
||||
ROM:10020D1C
|
||||
*/
|
||||
|
||||
//PrvPtrResize alignment code
|
||||
/*
|
||||
ROM:1002123C moveq #1,d0 ; Move Quick
|
||||
ROM:1002123E and.l arg_4(a6),d0 ; AND Logical
|
||||
ROM:10021242 addq.w #8,sp ; Add Quick
|
||||
ROM:10021244 beq.s loc_1002124E ; Branch if Equal
|
||||
ROM:10021246 moveq #9,d0 ; Move Quick
|
||||
ROM:10021248 add.l arg_4(a6),d0 ; Add
|
||||
ROM:1002124C bra.s loc_10021254 ; Branch Always
|
||||
ROM:1002124E ; ---------------------------------------------------------------------------
|
||||
ROM:1002124E
|
||||
ROM:1002124E loc_1002124E: ; CODE XREF: PrvPtrResize_100211F6+4E↑j
|
||||
ROM:1002124E move.l arg_4(a6),d0 ; Move Data from Source to Destination
|
||||
ROM:10021252 addq.l #8,d0 ; Add Quick
|
||||
ROM:10021254
|
||||
*/
|
||||
|
||||
//PrvMoveChunk alignment code???(not sure yet)
|
||||
/*
|
||||
ROM:10021C82 sub.l d0,d7 ; Subtract
|
||||
ROM:10021C84 move.l d7,d5 ; Move Data from Source to Destination
|
||||
ROM:10021C86 moveq #1,d0 ; Set bitmask
|
||||
ROM:10021C88 and.l d7,d0 ; Check if bit 0 of d7 is set
|
||||
ROM:10021C8A beq.s loc_10021C8E ; If bit 0 of d7 is set add 1 to d5
|
||||
ROM:10021C8C addq.l #1,d5 ; 16 bit align ???
|
||||
*/
|
||||
|
||||
//size extra bits are not being set when chunks are allocated
|
||||
|
||||
//PrvChunkNew derives size extra from total size - requested size, so its already safe, PrvPtrResize does the same
|
||||
/*
|
||||
ROM:10020FFA setSizeExtra: ; CODE XREF: PrvChunkNew_10020CBC+312↑j
|
||||
ROM:10020FFA move.l d3,d0 ; Move Data from Source to Destination
|
||||
ROM:10020FFC sub.l size(a6),d0 ; Subtract
|
||||
ROM:10021000 subq.l #8,d0 ; Subtract Quick
|
||||
ROM:10021002 andi.b #$F,d0 ; AND Immediate
|
||||
ROM:10021006 andi.b #$F0,(a2) ; AND Immediate
|
||||
ROM:1002100A or.b d0,(a2) ; Inclusive-OR Logical
|
||||
*/
|
||||
|
||||
//current suspect functions are PrvCreateFreeChunk and PrvUseFreeChunk
|
||||
//also merging chunks may cause some kind of issue
|
||||
|
||||
//PrvPtrResize is likely moving the chunk in front forwards if its small enough and leaving the data in place to save the opcodes needed to copy the data elsewhere
|
||||
//if this is true then a resize of existing size + 2 will push the next chunk forward by 2 misaligning it
|
||||
//could also be moving the header backwards by 2 if its willing to shift all the data manualy or corrupt the data
|
||||
|
||||
//patch PrvChunkNew to 32 bit alignment, this alone does not fix 32 bit alignment issues
|
||||
patchOsRom(0x20D04, "202E000AC0BCFFFFFFFCB0AE000A6700000458805080544F");//adds an extra 4 bytes if & 0x00000003 is true
|
||||
//when moving memory around some 16 bit aligned pointers still show up
|
||||
|
||||
//patch PrvPtrResize to 32 bit alignment, this alone does not fix 32 bit alignment issues
|
||||
patchOsRom(0x2123C, "202E000CC0BCFFFFFFFCB0AE000C6700000458805080504F");//adds an extra 4 bytes if & 0x00000003 is true
|
||||
|
||||
//may need to patch 0x7FFFFFFE's to 0x7FFFFFFC's
|
||||
|
||||
//other functions that may need to be patched are:
|
||||
//PrvCompactHeap_10021A12
|
||||
//PrvMoveChunk_10021C3E
|
||||
}
|
||||
break;
|
||||
|
||||
case SANDBOX_CMD_DEBUG_INSTALL_APP:{
|
||||
uintptr_t* values = data;
|
||||
bool success = installResourceToDevice(values[0], values[1]);
|
||||
bool success = m515InstallResourceToDevice(values[0], values[1]);
|
||||
|
||||
if(!success)
|
||||
result = EMU_ERROR_OUT_OF_MEMORY;
|
||||
@@ -1077,14 +746,6 @@ uint32_t sandboxCommand(uint32_t command, void* data){
|
||||
}
|
||||
break;
|
||||
|
||||
case SANDBOX_CMD_TEST_MEMORY_ALIGNMENT:{
|
||||
checkMemoryAlignmentPointer(0);//RAM heap
|
||||
checkMemoryAlignmentPointer(1);//storage heap
|
||||
checkMemoryAlignmentHandle(0);//RAM heap
|
||||
checkMemoryAlignmentHandle(1);//storage heap
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1098,11 +759,7 @@ void sandboxOnFrameRun(void){
|
||||
//run at the end of every frame
|
||||
sandboxFramesRan++;
|
||||
|
||||
/*
|
||||
if(sandboxFramesRan == SANDBOX_SECONDS_TO_FRAMES(10)){
|
||||
sandboxCommand(SANDBOX_CMD_TEST_MEMORY_ALIGNMENT, NULL);
|
||||
}
|
||||
*/
|
||||
//add tests here
|
||||
}
|
||||
|
||||
void sandboxOnOpcodeRun(void){
|
||||
@@ -1193,7 +850,7 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t
|
||||
|
||||
if(sandboxedMemory || sandboxRunning()){
|
||||
uint32_t pc = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
char* function = getFunctionName68k(pc);
|
||||
char* function = getFunctionNameM68k(pc);
|
||||
bool functionValid = !!function;
|
||||
|
||||
if(!functionValid)
|
||||
@@ -1204,9 +861,9 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t
|
||||
address &= 0xFFFF;
|
||||
|
||||
if(write)
|
||||
debugLog("Writing low mem global: name:%s/global:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", getLowMemGlobalName(address), address, size, value, function, pc);
|
||||
debugLog("Writing low mem global: name:%s/global:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", m515GetLowMemGlobalName(address), address, size, value, function, pc);
|
||||
else
|
||||
debugLog("Reading low mem global: name:%s/global:0x%08X, size:%d, function:%s/PC:0x%08X\n", getLowMemGlobalName(address), address, size, function, pc);
|
||||
debugLog("Reading low mem global: name:%s/global:0x%08X, size:%d, function:%s/PC:0x%08X\n", m515GetLowMemGlobalName(address), address, size, function, pc);
|
||||
}
|
||||
else if(address >= 0xFFFFF000){
|
||||
//hardware registers
|
||||
@@ -1268,7 +925,7 @@ void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t
|
||||
}
|
||||
|
||||
bool sandboxRunning(void){
|
||||
uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
uint32_t pc = sandboxCurrentCpuArch == SANDBOX_CPU_ARCH_M68K ? m68k_get_reg(NULL, M68K_REG_PC) : reg_pc(15);
|
||||
uint16_t memRegion;
|
||||
|
||||
//this is used to capture full logs when running from specific locations
|
||||
@@ -1285,7 +942,7 @@ void sandboxReturn(void){
|
||||
if(sandboxControlHandoff){
|
||||
//control was just handed back to the host
|
||||
sandboxControlHandoff = false;
|
||||
sandboxRestoreCpuState();
|
||||
m515RestoreCpuState();
|
||||
debugLog("Sandbox: Control returned to host\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
enum{
|
||||
SANDBOX_CMD_PATCH_OS = 0,
|
||||
SANDBOX_CMD_DEBUG_INSTALL_APP,
|
||||
SANDBOX_CMD_REGISTER_WATCH_ENABLE,
|
||||
SANDBOX_CMD_TEST_MEMORY_ALIGNMENT
|
||||
SANDBOX_CMD_REGISTER_WATCH_ENABLE
|
||||
};
|
||||
|
||||
enum{
|
||||
@@ -20,8 +19,7 @@ enum{
|
||||
|
||||
enum{
|
||||
SANDBOX_CPU_ARCH_M68K = 0,
|
||||
SANDBOX_CPU_ARCH_ARMV5,
|
||||
SANDBOX_CPU_ARCH_THUMB
|
||||
SANDBOX_CPU_ARCH_ARMV5
|
||||
};
|
||||
|
||||
void sandboxInit(void);
|
||||
|
||||
@@ -139,6 +139,7 @@ uint32_t emulatorInit(uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmB
|
||||
pxa260Framebuffer = palmFramebuffer;
|
||||
blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
|
||||
sandboxInit();
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_ARMV5);
|
||||
|
||||
//reset everything
|
||||
emulatorSoftReset();
|
||||
@@ -185,6 +186,7 @@ uint32_t emulatorInit(uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmB
|
||||
//initialize components
|
||||
blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
|
||||
sandboxInit();
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_M68K);
|
||||
|
||||
//reset everything
|
||||
emulatorSoftReset();
|
||||
|
||||
Reference in New Issue
Block a user