Clean up sandbox to prepare for adding ARMv5 tools to it

This commit is contained in:
meepingsnesroms
2019-07-22 15:00:20 -07:00
parent 81bbcd20f0
commit 07b4aa53a8
4 changed files with 85 additions and 427 deletions

View File

@@ -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:

View File

@@ -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");
}
}

View File

@@ -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);

View File

@@ -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();