mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 07:05:37 +00:00
Remove sandbox, it was all unused 68k stuff anyway
This commit is contained in:
@@ -221,7 +221,6 @@ SOURCES += \
|
||||
../../src/ads7846.c \
|
||||
../../src/audio/blip_buf.c \
|
||||
../../src/dbvz.c \
|
||||
../../src/debug/sandbox.c \
|
||||
../../src/emulator.c \
|
||||
../../src/fileLauncher/launcher.c \
|
||||
../../src/flx68000.c \
|
||||
@@ -251,9 +250,6 @@ HEADERS += \
|
||||
../../src/dbvzRegisterAccessors.c.h \
|
||||
../../src/dbvzRegisterNames.c.h \
|
||||
../../src/dbvzTiming.c.h \
|
||||
../../src/debug/sandbox.h \
|
||||
../../src/debug/sandboxTrapNumToName.c.h \
|
||||
../../src/debug/trapNames.h \
|
||||
../../src/emulator.h \
|
||||
../../src/fileLauncher/launcher.h \
|
||||
../../src/flx68000.h \
|
||||
|
||||
@@ -25,7 +25,6 @@ extern "C"{
|
||||
#include "../../src/m68k/m68k.h"
|
||||
#include "../../src/pxa260/pxa260.h"
|
||||
#include "../../src/armv5te/disasm.h"
|
||||
#include "../../src/debug/sandbox.h"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "sdCard.h"
|
||||
#include "audio/blip_buf.h"
|
||||
#include "m68k/m68k.h"
|
||||
#include "debug/sandbox.h"
|
||||
|
||||
|
||||
#include "dbvzRegisterNames.c.h"
|
||||
|
||||
@@ -1,980 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX)
|
||||
//this wrappers 68K code and allows calling it for tests, this should be useful for determining if hardware accesses are correct
|
||||
//Note: when running a test the emulator runs at native speed and no clocks are emulated
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../m68k/m68k.h"
|
||||
#include "../m68k/m68kcpu.h"
|
||||
#include "../emulator.h"
|
||||
#include "../ads7846.h"
|
||||
#include "../dbvz.h"
|
||||
#include "../portability.h"
|
||||
#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
|
||||
|
||||
#define SANDBOX_SECONDS_TO_FRAMES(x) ((x) * EMU_FPS)
|
||||
|
||||
|
||||
typedef struct{
|
||||
void* hostPointer;
|
||||
uint32_t emuPointer;
|
||||
uint64_t bytes;//may be used for strings or structs in the future
|
||||
}return_pointer_t;
|
||||
|
||||
typedef struct{
|
||||
uint32_t sp;
|
||||
uint32_t pc;
|
||||
uint16_t sr;
|
||||
uint32_t a0;
|
||||
uint32_t d0;
|
||||
}m68k_local_cpu_state_t;
|
||||
|
||||
typedef struct{
|
||||
uint32_t address;
|
||||
uint32_t size;
|
||||
uint8_t type;
|
||||
}mem_region_t;
|
||||
|
||||
|
||||
static bool sandboxActive;//used to "log out" of the emulator once a test has finished
|
||||
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 m515CallGuestFunction(uint32_t address, uint16_t trap, const char* prototype, ...);
|
||||
|
||||
#include "sandboxTrapNumToName.c.h"
|
||||
|
||||
uint32_t getRandomRange(uint32_t start, uint32_t end){
|
||||
static bool seeded = false;
|
||||
|
||||
if(!seeded){
|
||||
srand(time(NULL));
|
||||
seeded = true;
|
||||
}
|
||||
|
||||
return (uint32_t)rand() % (end + 1 - start) + start;
|
||||
}
|
||||
|
||||
static char* takeStackDump(uint32_t bytes){
|
||||
char* textBytes = malloc(bytes * 2);
|
||||
uint32_t textBytesOffset = 0;
|
||||
uint32_t stackAddress = m68k_get_reg(NULL, M68K_REG_SP);
|
||||
uint32_t count;
|
||||
|
||||
textBytes[0] = '\0';
|
||||
|
||||
for(count = 0; count < bytes; count++){
|
||||
sprintf(textBytes + textBytesOffset, "%02X", m68k_read_memory_8(stackAddress + count));
|
||||
textBytesOffset = strlen(textBytes);
|
||||
}
|
||||
|
||||
return textBytes;
|
||||
}
|
||||
|
||||
static void patchOsRom(uint32_t address, char* patch){
|
||||
uint32_t offset;
|
||||
uint32_t patchBytes = strlen(patch) / 2;//1 char per nibble
|
||||
uint32_t swapBegin = address & 0xFFFFFFFE;
|
||||
uint32_t swapSize = patchBytes / sizeof(uint16_t) + 1;
|
||||
char conv[5] = "0xXX";
|
||||
|
||||
if(sandboxCurrentCpuArch == SANDBOX_CPU_ARCH_M68K)
|
||||
swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
|
||||
for(offset = 0; offset < patchBytes; offset++){
|
||||
conv[2] = patch[offset * 2];
|
||||
conv[3] = patch[offset * 2 + 1];
|
||||
palmRom[address + offset] = strtol(conv, NULL, 0);
|
||||
}
|
||||
if(sandboxCurrentCpuArch == SANDBOX_CPU_ARCH_M68K)
|
||||
swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
|
||||
}
|
||||
|
||||
static const char* m515GetLowMemGlobalName(uint32_t address){
|
||||
switch(address){
|
||||
case 0x00000100:
|
||||
return "MemTotalCards";
|
||||
|
||||
case 0x00000102:
|
||||
return "MemCard0Start";
|
||||
|
||||
case 0x0000010A:
|
||||
return "MemDebugFlags";
|
||||
|
||||
case 0x00000122:
|
||||
return "TrapTablePtr";
|
||||
|
||||
case 0x00000164:
|
||||
return "ScrStatePtr";
|
||||
|
||||
case 0x0000016C:
|
||||
return "PenStatePtr";
|
||||
|
||||
case 0x00000170:
|
||||
return "EvtStatePtr";
|
||||
|
||||
case 0x00000174:
|
||||
return "SndStatePtr";
|
||||
|
||||
case 0x00000178:
|
||||
return "TimStatePtr";
|
||||
|
||||
case 0x0000017C:
|
||||
return "AlmStatePtr";
|
||||
|
||||
case 0x00000180:
|
||||
return "FtrStatePtr";
|
||||
|
||||
case 0x00000184:
|
||||
return "GrfStatePtr";
|
||||
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static bool m515IgnoreTrap(uint16_t trap){
|
||||
switch(trap){
|
||||
case HwrDisableDataWrites:
|
||||
case HwrEnableDataWrites:
|
||||
case DmGetDatabase://this could be important later but is spammy on boot
|
||||
case MemStoreInfo://this could be important later but is spammy on boot
|
||||
case HwrDelay:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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 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)
|
||||
return true;
|
||||
if(sandboxActive && address >= 0xFFFFFE00)//used to run custom code when in sandbox mode
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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(!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 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(!m515IgnoreTrap(trap))
|
||||
debugLog("Trap F API:%s, API number:0x%04X, PC:0x%08X\n", lookupTrap(trap), trap, programCounter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isAlphanumeric(char chr){
|
||||
if((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool readable6CharsBack(uint32_t address){
|
||||
uint8_t count;
|
||||
for(count = 0; count < 6; count++)
|
||||
if(!isAlphanumeric(m68k_read_memory_8(address - count)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for(scanAddress = rangeStart; scanAddress <= rangeEnd - (strLength - 1); scanAddress++){
|
||||
//since only the first char is range checked remove the rest from the range to prevent reading off the end
|
||||
|
||||
//check every byte against the start character
|
||||
if(m68k_read_memory_8(scanAddress) == str[0]){
|
||||
bool wrongString = false;
|
||||
uint32_t strIndex;
|
||||
|
||||
//character match found, check for string
|
||||
for(strIndex = 1; strIndex < strLength; strIndex++){
|
||||
if(m68k_read_memory_8(scanAddress + strIndex) != str[strIndex]){
|
||||
wrongString = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(wrongString == false)
|
||||
return scanAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return rangeEnd;
|
||||
}
|
||||
|
||||
static uint32_t skipM68kString(uint32_t address){
|
||||
while(m68k_read_memory_8(address) != '\0')
|
||||
address++;
|
||||
address++;//skip null terminator too
|
||||
return 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 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 = 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 = 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')){
|
||||
//valid string match found, get prior functions signature(a function string has a minimum of 6 printable chars with 2 null terminators)
|
||||
uint32_t priorFunctionSignature = signatureBegining;//last opcode of the function thats being looked for
|
||||
bool extraNull = false;
|
||||
|
||||
while(m68k_read_memory_16(priorFunctionSignature) != '\0\0')
|
||||
priorFunctionSignature -= 2;
|
||||
|
||||
//remove extra null terminator if present
|
||||
if(m68k_read_memory_8(priorFunctionSignature - 1) == '\0'){
|
||||
priorFunctionSignature--;
|
||||
extraNull = true;
|
||||
}
|
||||
|
||||
//check that there are 6 valid alphanumeric characters before the nulls, this indicates that its a valid function signature
|
||||
if(readable6CharsBack(priorFunctionSignature - 1)){
|
||||
//valid, get first opcode after string and return its address
|
||||
return priorFunctionSignature + (extraNull ? 3 : 2);
|
||||
}
|
||||
}
|
||||
|
||||
//string matched but structure was invalid, get next string
|
||||
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* getFunctionNameM68k(uint32_t address){
|
||||
char* data;
|
||||
uint32_t offset;
|
||||
|
||||
address &= 0xFFFFFFFE;
|
||||
|
||||
for(offset = 0; offset < 0x10000; offset += 2){
|
||||
if(m68k_read_memory_16(address + offset) == 0x4E75/*RTS*/){
|
||||
offset += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(offset < 0x10000){
|
||||
uint16_t size = 0;
|
||||
uint16_t offset2;
|
||||
|
||||
for(offset2 = 0; offset2 < 0x100; offset2++)
|
||||
if(isAlphanumeric(m68k_read_memory_8(address + offset + offset2)))
|
||||
size++;
|
||||
|
||||
data = malloc(size + 1);
|
||||
for(offset2 = 0; offset2 < size; offset2++)
|
||||
data[offset2] = m68k_read_memory_8(address + offset + offset2);
|
||||
data[offset2] = '\0';
|
||||
}
|
||||
else{
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static uint32_t m515MakePalmString(const char* str){
|
||||
uint32_t strLength = strlen(str) + 1;
|
||||
uint32_t strData = m515CallGuestFunction(false, 0x00000000, MemPtrNew, "p(l)", strLength);
|
||||
|
||||
if(strData){
|
||||
uint32_t count;
|
||||
|
||||
for(count = 0; count < strLength; count++)
|
||||
m68k_write_memory_8(strData + count, str[count]);
|
||||
}
|
||||
|
||||
return strData;
|
||||
}
|
||||
|
||||
static char* m515MakeNativeString(uint32_t address){
|
||||
if(address){
|
||||
int16_t strLength = m515CallGuestFunction(false, 0x00000000, StrLen, "w(p)", address) + 1;
|
||||
char* nativeStr = malloc(strLength);
|
||||
int16_t count;
|
||||
|
||||
for(count = 0; count < strLength; count++)
|
||||
nativeStr[count] = m68k_read_memory_8(address + count);
|
||||
return nativeStr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void m515FreePalmString(uint32_t address){
|
||||
m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", address);
|
||||
}
|
||||
|
||||
static bool m515InstallResourceToDevice(uint8_t* data, uint32_t size){
|
||||
/*
|
||||
#define memNewChunkFlagNonMovable 0x0200
|
||||
#define memNewChunkFlagAllowLarge 0x1000 // this is not in the sdk *g*
|
||||
|
||||
void *MemPtrNewL ( UInt32 size ) {
|
||||
|
||||
SysAppInfoPtr appInfoP;
|
||||
UInt16 ownerID;
|
||||
|
||||
ownerID = ((SysAppInfoPtr)SysGetAppInfo(&appInfoP, &appInfoP))->memOwnerID;
|
||||
|
||||
return MemChunkNew (0, size, ownerID | memNewChunkFlagNonMovable | memNewChunkFlagAllowLarge);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
//buffer not allocated
|
||||
if(!palmSideResourceData)
|
||||
return false;
|
||||
|
||||
dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory = false;//need to unprotect storage RAM
|
||||
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 = m515CallGuestFunction(0x00000000, DmCreateDatabaseFromImage, "w(p)", palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best
|
||||
m515CallGuestFunction(false, 0x00000000, MemChunkFree, "w(p)", palmSideResourceData);
|
||||
|
||||
//didnt install
|
||||
if(error != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t m515GetStackFrameSize(const char* prototype){
|
||||
const char* params = prototype + 2;
|
||||
uint32_t size = 0;
|
||||
|
||||
while(*params != ')'){
|
||||
switch(*params){
|
||||
case 'v':
|
||||
case 'V':
|
||||
//do nothing
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
//bytes are 16 bits long on the stack due to memory alignment restrictions
|
||||
case 'w':
|
||||
size += 2;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'p':
|
||||
case 'B':
|
||||
case 'W':
|
||||
case 'L':
|
||||
case 'P':
|
||||
size += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
params++;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
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 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 m515CallGuestFunction(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
|
||||
//EvtGetPen v(WWB) returns nothing but writes back to the calling function with 3 pointers,
|
||||
//these are allocated in the bootloader area and interpreted to host pointers on return
|
||||
va_list args;
|
||||
const char* params = prototype + 2;
|
||||
uint32_t stackFrameStart = m68k_get_reg(NULL, M68K_REG_SP);
|
||||
uint32_t newStackFrameSize = m515GetStackFrameSize(prototype);
|
||||
uint32_t stackWriteAddr = stackFrameStart - newStackFrameSize;
|
||||
uint32_t oldStopped = m68ki_cpu.stopped;
|
||||
uint32_t functionReturn = 0x00000000;
|
||||
return_pointer_t functionReturnPointers[10];
|
||||
uint8_t functionReturnPointerIndex = 0;
|
||||
uint32_t callWriteOut = 0xFFFFFFE0;
|
||||
uint32_t callStart;
|
||||
uint8_t count;
|
||||
|
||||
m515BackupCpuState();
|
||||
|
||||
va_start(args, prototype);
|
||||
while(*params != ')'){
|
||||
switch(*params){
|
||||
case 'v':
|
||||
case 'V':
|
||||
//do nothing, this is wrong for "V"
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
//bytes are 16 bits long on the stack due to memory alignment restrictions
|
||||
//bytes are written to the top byte of there word
|
||||
m68k_write_memory_8(stackWriteAddr, va_arg(args, uint32_t));
|
||||
stackWriteAddr += 2;
|
||||
break;
|
||||
case 'w':
|
||||
m68k_write_memory_16(stackWriteAddr, va_arg(args, uint32_t));
|
||||
stackWriteAddr += 2;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'p':
|
||||
m68k_write_memory_32(stackWriteAddr, va_arg(args, uint32_t));
|
||||
stackWriteAddr += 4;
|
||||
break;
|
||||
|
||||
//return pointer values
|
||||
case 'B':
|
||||
functionReturnPointers[functionReturnPointerIndex].hostPointer = va_arg(args, void*);
|
||||
functionReturnPointers[functionReturnPointerIndex].emuPointer = callWriteOut;
|
||||
functionReturnPointers[functionReturnPointerIndex].bytes = 1;
|
||||
m68k_write_memory_32(stackWriteAddr, functionReturnPointers[functionReturnPointerIndex].emuPointer);
|
||||
stackWriteAddr += 4;
|
||||
callWriteOut += 4;
|
||||
functionReturnPointerIndex++;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
functionReturnPointers[functionReturnPointerIndex].hostPointer = va_arg(args, void*);
|
||||
functionReturnPointers[functionReturnPointerIndex].emuPointer = callWriteOut;
|
||||
functionReturnPointers[functionReturnPointerIndex].bytes = 2;
|
||||
m68k_write_memory_32(stackWriteAddr, functionReturnPointers[functionReturnPointerIndex].emuPointer);
|
||||
stackWriteAddr += 4;
|
||||
callWriteOut += 4;
|
||||
functionReturnPointerIndex++;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
case 'P':
|
||||
functionReturnPointers[functionReturnPointerIndex].hostPointer = va_arg(args, void*);
|
||||
functionReturnPointers[functionReturnPointerIndex].emuPointer = callWriteOut;
|
||||
functionReturnPointers[functionReturnPointerIndex].bytes = 4;
|
||||
m68k_write_memory_32(stackWriteAddr, functionReturnPointers[functionReturnPointerIndex].emuPointer);
|
||||
stackWriteAddr += 4;
|
||||
callWriteOut += 4;
|
||||
functionReturnPointerIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
params++;
|
||||
}
|
||||
|
||||
//write to the bootloader memory, its not important when debugging
|
||||
callStart = callWriteOut;
|
||||
|
||||
if(address){
|
||||
//direct jump handler, used for private APIs
|
||||
m68k_write_memory_16(callWriteOut, 0x4EB9);//jump to subroutine opcode
|
||||
callWriteOut += 2;
|
||||
m68k_write_memory_32(callWriteOut, address);
|
||||
callWriteOut += 4;
|
||||
}
|
||||
else{
|
||||
//OS function handler
|
||||
m68k_write_memory_16(callWriteOut, 0x4E4F);//trap f opcode
|
||||
callWriteOut += 2;
|
||||
m68k_write_memory_16(callWriteOut, trap);
|
||||
callWriteOut += 2;
|
||||
}
|
||||
|
||||
m68ki_cpu.stopped = 0;
|
||||
m68k_set_reg(M68K_REG_SP, stackFrameStart - newStackFrameSize);
|
||||
m68k_set_reg(M68K_REG_PC, callStart);
|
||||
|
||||
while(m68k_get_reg(NULL, M68K_REG_PC) != callWriteOut)
|
||||
m68k_execute(1);//m68k_execute() always runs requested cycles + extra cycles of the final opcode, this executes 1 opcode
|
||||
|
||||
if(prototype[0] == 'p')
|
||||
functionReturn = m68k_get_reg(NULL, M68K_REG_A0);
|
||||
else if(prototype[0] == 'b' || prototype[0] == 'w' || prototype[0] == 'l')
|
||||
functionReturn = m68k_get_reg(NULL, M68K_REG_D0);
|
||||
m68ki_cpu.stopped = oldStopped;
|
||||
m515RestoreCpuState();
|
||||
|
||||
//remap all argument pointers
|
||||
for(count = 0; count < functionReturnPointerIndex; count++){
|
||||
switch(functionReturnPointers[count].bytes){
|
||||
case 1:
|
||||
*(uint8_t*)functionReturnPointers[count].hostPointer = m68k_read_memory_8(functionReturnPointers[count].emuPointer);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(uint16_t*)functionReturnPointers[count].hostPointer = m68k_read_memory_16(functionReturnPointers[count].emuPointer);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(uint32_t*)functionReturnPointers[count].hostPointer = m68k_read_memory_32(functionReturnPointers[count].emuPointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return functionReturn;
|
||||
}
|
||||
|
||||
|
||||
void sandboxInit(void){
|
||||
//nothing to init yet
|
||||
sandboxCurrentCpuArch = SANDBOX_CPU_ARCH_M68K;
|
||||
}
|
||||
|
||||
void sandboxReset(void){
|
||||
sandboxActive = false;
|
||||
sandboxFramesRan = 0;
|
||||
|
||||
memset(sandboxWatchRegions, 0x00, sizeof(sandboxWatchRegions));
|
||||
sandboxWatchRegionsActive = 0;
|
||||
}
|
||||
|
||||
uint32_t sandboxStateSize(void){
|
||||
uint32_t size = 0;
|
||||
|
||||
size += sizeof(uint8_t) * 3;//sandboxActive / sandboxControlHandoff / sandboxCurrentCpuArch
|
||||
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
|
||||
size += sizeof(uint16_t);//sandboxWatchRegionsActive
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void sandboxSaveState(uint8_t* data){
|
||||
uint32_t offset = 0;
|
||||
uint16_t index;
|
||||
|
||||
writeStateValue8(data + offset, sandboxActive);
|
||||
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, sandboxOldFunctionM68kCpuState.sp);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.pc);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue16(data + offset, sandboxOldFunctionM68kCpuState.sr);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.a0);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, sandboxOldFunctionM68kCpuState.d0);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue64(data + offset, sandboxFramesRan);
|
||||
offset += sizeof(uint64_t);
|
||||
for(index = 0; index < SANDBOX_MAX_WATCH_REGIONS; index++){
|
||||
writeStateValue32(data + offset, sandboxWatchRegions[index].address);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, sandboxWatchRegions[index].size);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue8(data + offset, sandboxWatchRegions[index].type);
|
||||
offset += sizeof(uint8_t);
|
||||
}
|
||||
writeStateValue16(data + offset, sandboxWatchRegionsActive);
|
||||
offset += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
void sandboxLoadState(uint8_t* data){
|
||||
uint32_t offset = 0;
|
||||
uint16_t index;
|
||||
|
||||
sandboxActive = readStateValue8(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
sandboxCurrentCpuArch = readStateValue8(data + offset);//currently cant be ARMv5 during a frame boundry but that may change
|
||||
offset += sizeof(uint8_t);
|
||||
sandboxOldFunctionM68kCpuState.sp = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionM68kCpuState.pc = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionM68kCpuState.sr = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
sandboxOldFunctionM68kCpuState.a0 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxOldFunctionM68kCpuState.d0 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxFramesRan = readStateValue64(data + offset);
|
||||
offset += sizeof(uint64_t);
|
||||
for(index = 0; index < SANDBOX_MAX_WATCH_REGIONS; index++){
|
||||
sandboxWatchRegions[index].address = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxWatchRegions[index].size = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
sandboxWatchRegions[index].type = readStateValue8(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
}
|
||||
sandboxWatchRegionsActive = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
uint32_t sandboxCommand(uint32_t command, void* data){
|
||||
uint32_t result = EMU_ERROR_NONE;
|
||||
|
||||
debugLog("Sandbox: Command %d started\n", command);
|
||||
|
||||
switch(command){
|
||||
case SANDBOX_CMD_PATCH_OS:{
|
||||
if(sandboxCurrentCpuArch == SANDBOX_CPU_ARCH_M68K){
|
||||
//double dynamic heap size, verified working
|
||||
//HwrCalcDynamicRAMSize_10005CC6:
|
||||
//HwrCalcDynamicRAMSize_10083B0A:
|
||||
//patchOsRom(0x5CC6, "203C000800004E75");//move.l 0x80000, d0; rts
|
||||
//patchOsRom(0x83B0A, "203C000800004E75");//move.l 0x80000, d0; rts
|
||||
//patchOsRom(0x5CC6, "203C001000004E75");//move.l 0x100000, d0; rts
|
||||
//patchOsRom(0x83B0A, "203C001000004E75");//move.l 0x100000, d0; rts
|
||||
}
|
||||
else{
|
||||
//disable weird SD chip
|
||||
patchOsRom(0x333EC6, "0000");//blocks out the slot driver
|
||||
patchOsRom(0x205C, "0000A0E1");//blocks idle loop jump with NOP
|
||||
//patchOsRom(0x1FE8, "0000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E10000A0E1");//blocks idle loop with NOPs
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SANDBOX_CMD_DEBUG_INSTALL_APP:{
|
||||
uintptr_t* values = data;
|
||||
bool success = m515InstallResourceToDevice(values[0], values[1]);
|
||||
|
||||
if(!success)
|
||||
result = EMU_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SANDBOX_CMD_REGISTER_WATCH_ENABLE:{
|
||||
sandboxSetWatchRegion(0xFFFFF000, 0xFFF, SANDBOX_WATCH_DATA);//0x1000 will cause an overflow to 0x00000000 making it never trigger
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
debugLog("Sandbox: Command %d finished\n", command);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void sandboxOnFrameRun(void){
|
||||
//run at the end of every frame
|
||||
sandboxFramesRan++;
|
||||
|
||||
//add tests here
|
||||
}
|
||||
|
||||
void sandboxOnOpcodeRun(void){
|
||||
if(sandboxRunning()){
|
||||
#if defined(EMU_SANDBOX_LOG_JUMPS)
|
||||
log68kJumps();
|
||||
#endif
|
||||
|
||||
#if defined(EMU_SANDBOX_LOG_APIS)
|
||||
logApiCalls();
|
||||
#endif
|
||||
}
|
||||
switch(m68k_get_reg(NULL, M68K_REG_PC)){//switched this from PPC to PC
|
||||
//case 0x10083652://USB issue location //address based on PPC
|
||||
//case 0x100846C0://HwrDelay, before mysterious jump //address based on PPC
|
||||
//case 0x100846CC://HwrDelay, after mysterious jump //address based on PPC
|
||||
//case 0x100AD514://HwrSpiSdioInterrupts, SD card interrupt handler
|
||||
case 0x10021988://just before "andi.l #unk_FFFFFF, d0"
|
||||
//to add a emulator breakpoint add a new line above here|^^^
|
||||
{
|
||||
uint32_t m68kRegisters[M68K_REG_CPU_TYPE];
|
||||
uint8_t count;
|
||||
|
||||
for(count = 0; count < M68K_REG_CPU_TYPE; count++)
|
||||
m68kRegisters[count] = m68k_get_reg(NULL, count);
|
||||
|
||||
/*
|
||||
register order, read m68kRegisters with debugger
|
||||
M68K_REG_D0,
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0,
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC,
|
||||
M68K_REG_SR,
|
||||
M68K_REG_SP,
|
||||
M68K_REG_USP,
|
||||
M68K_REG_ISP,
|
||||
M68K_REG_MSP,
|
||||
M68K_REG_SFC,
|
||||
M68K_REG_DFC,
|
||||
M68K_REG_VBR,
|
||||
M68K_REG_CACR,
|
||||
M68K_REG_CAAR,
|
||||
M68K_REG_PREF_ADDR,
|
||||
M68K_REG_PREF_DATA,
|
||||
M68K_REG_PPC,
|
||||
M68K_REG_IR
|
||||
*/
|
||||
|
||||
//set host breakpoint here|vvv
|
||||
if(true){
|
||||
bool breakpoint = true;
|
||||
}
|
||||
//set host breakpoint here|^^^
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t value){
|
||||
static bool isRecursive = false;
|
||||
|
||||
//this function can read or write Palm memory, which calls this function, so dont run this function when calling from this function to prevent an infinte loop
|
||||
if(!isRecursive){
|
||||
isRecursive = true;
|
||||
{//actual code goes below:vvv
|
||||
bool sandboxedMemory = false;
|
||||
uint16_t memRegion;
|
||||
|
||||
for(memRegion = 0; memRegion < sandboxWatchRegionsActive; memRegion++){
|
||||
if(sandboxWatchRegions[memRegion].type == SANDBOX_WATCH_DATA && address >= sandboxWatchRegions[memRegion].address && address < sandboxWatchRegions[memRegion].address + sandboxWatchRegions[memRegion].size){
|
||||
sandboxedMemory = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(sandboxedMemory || sandboxRunning()){
|
||||
uint32_t pc = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
char* function = getFunctionNameM68k(pc);
|
||||
bool functionValid = !!function;
|
||||
|
||||
if(!functionValid)
|
||||
function = "NAME NOT FOUND";
|
||||
|
||||
if(address >= dbvzChipSelects[DBVZ_CHIP_DX_RAM].start && address < dbvzChipSelects[DBVZ_CHIP_DX_RAM].start + 0x10000){
|
||||
//low mem globals
|
||||
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", 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", m515GetLowMemGlobalName(address), address, size, function, pc);
|
||||
}
|
||||
else if(address >= 0xFFFFF000){
|
||||
//hardware registers
|
||||
if(address >= 0xFFFFFE00){
|
||||
//bootloader area
|
||||
if(write){
|
||||
if(address >= 0xFFFFFFC0)
|
||||
debugLog("Writing bootloader area(valid): address:0x%08X, size:%d, function:%s/PC:0x%08X\n", address, size, function, pc);
|
||||
else
|
||||
debugLog("Writing bootloader area(invalid): address:0x%08X, size:%d, function:%s/PC:0x%08X\n", address, size, function, pc);
|
||||
}
|
||||
else{
|
||||
debugLog("Reading bootloader area: address:0x%08X, size:%d, function:%s/PC:0x%08X\n", address, size, function, pc);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//normal regs
|
||||
const char* registerName = "UNKNOWN";
|
||||
|
||||
//TODO: get register name list
|
||||
|
||||
if(write)
|
||||
debugLog("Writing hardware register: name:%s/address:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", registerName, address, size, value, function, pc);
|
||||
else
|
||||
debugLog("Reading hardware register: name:%s/address:0x%08X, size:%d, function:%s/PC:0x%08X\n", registerName, address, size, function, pc);
|
||||
}
|
||||
}
|
||||
else if(address >= dbvzChipSelects[DBVZ_CHIP_B0_SED].start && address < dbvzChipSelects[DBVZ_CHIP_B0_SED].start + dbvzChipSelects[DBVZ_CHIP_B0_SED].lineSize){
|
||||
//SED1376
|
||||
if(address & SED1376_MR_BIT){
|
||||
//SED1376 data
|
||||
if(write)
|
||||
debugLog("Writing SED1376 buffer: address:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", address, size, value, function, pc);
|
||||
else
|
||||
debugLog("Reading SED1376 buffer: address:0x%08X, size:%d, function:%s/PC:0x%08X\n", address, size, function, pc);
|
||||
}
|
||||
else{
|
||||
//SED1376 register, these are 8 bit only
|
||||
if(write)
|
||||
debugLog("Writing SED1376 register: address:0x%08X, value:0x%02X, function:%s/PC:0x%08X\n", address, value & 0xFF, function, pc);
|
||||
else
|
||||
debugLog("Reading SED1376 register: address:0x%08X, function:%s/PC:0x%08X\n", address, function, pc);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//everywhere else
|
||||
if(write)
|
||||
debugLog("Writing: address:0x%08X, size:%d, value:0x%08X, function:%s/PC:0x%08X\n", address, size, value, function, pc);
|
||||
else
|
||||
debugLog("Reading: address:0x%08X, size:%d, function:%s/PC:0x%08X\n", address, size, function, pc);
|
||||
}
|
||||
|
||||
if(functionValid)
|
||||
free(function);
|
||||
}
|
||||
}//actual code goes above:^^^
|
||||
isRecursive = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool sandboxRunning(void){
|
||||
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
|
||||
for(memRegion = 0; memRegion < sandboxWatchRegionsActive; memRegion++){
|
||||
if(sandboxWatchRegions[memRegion].type == SANDBOX_WATCH_CODE && pc >= sandboxWatchRegions[memRegion].address && pc < sandboxWatchRegions[memRegion].address + sandboxWatchRegions[memRegion].size)
|
||||
return true;
|
||||
}
|
||||
|
||||
return sandboxActive;
|
||||
}
|
||||
|
||||
uint16_t sandboxSetWatchRegion(uint32_t address, uint32_t size, uint8_t type){
|
||||
uint16_t index;
|
||||
|
||||
//invalid type
|
||||
if(type == SANDBOX_WATCH_NONE || type >= SANDBOX_WATCH_TOTAL_TYPES)
|
||||
return 0xFFFF;
|
||||
|
||||
//cant watch 0 sized memory area
|
||||
if(size < 1)
|
||||
return 0xFFFF;
|
||||
|
||||
//try to use old watch region if available
|
||||
for(index = 0; index < sandboxWatchRegionsActive; index++){
|
||||
if(sandboxWatchRegions[index].type == SANDBOX_WATCH_NONE){
|
||||
//found reusable region
|
||||
sandboxWatchRegions[index].address = address;
|
||||
sandboxWatchRegions[index].size = size;
|
||||
sandboxWatchRegions[index].type = type;
|
||||
|
||||
//return watch region reference, this doesnt change until the region is deleted
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
//check if new region is available
|
||||
if(sandboxWatchRegionsActive < SANDBOX_MAX_WATCH_REGIONS){
|
||||
//use new region
|
||||
sandboxWatchRegions[sandboxWatchRegionsActive].address = address;
|
||||
sandboxWatchRegions[sandboxWatchRegionsActive].size = size;
|
||||
sandboxWatchRegions[sandboxWatchRegionsActive].type = type;
|
||||
sandboxWatchRegionsActive++;
|
||||
|
||||
//return watch region reference, this doesnt change until the region is deleted
|
||||
return sandboxWatchRegionsActive - 1;
|
||||
}
|
||||
|
||||
//no regions left, error
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
void sandboxClearWatchRegion(uint16_t index){
|
||||
if(index < sandboxWatchRegionsActive){
|
||||
if(index == sandboxWatchRegionsActive - 1)
|
||||
sandboxWatchRegionsActive--;//remove from end
|
||||
else
|
||||
sandboxWatchRegions[index].type = SANDBOX_WATCH_NONE;//mark as empty
|
||||
}
|
||||
}
|
||||
|
||||
void sandboxSetCpuArch(uint8_t arch){
|
||||
sandboxCurrentCpuArch = arch;
|
||||
}
|
||||
|
||||
#else
|
||||
void sandboxInit(void){}
|
||||
void sandboxReset(void){}
|
||||
uint32_t sandboxStateSize(void){return 0;}
|
||||
void sandboxSaveState(uint8_t* data){}
|
||||
void sandboxLoadState(uint8_t* data){}
|
||||
uint32_t sandboxCommand(uint32_t command, void* data){return 0;}
|
||||
void sandboxOnFrameRun(void){}
|
||||
void sandboxOnOpcodeRun(void){}
|
||||
void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t value){}
|
||||
bool sandboxRunning(void){return false;}
|
||||
uint16_t sandboxSetWatchRegion(uint32_t address, uint32_t size, uint8_t type){return 0;}
|
||||
void sandboxClearWatchRegion(uint16_t index){}
|
||||
void sandboxSetCpuArch(uint8_t arch){}
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef SANDBOX_H
|
||||
#define SANDBOX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum{
|
||||
SANDBOX_CMD_PATCH_OS = 0,
|
||||
SANDBOX_CMD_DEBUG_INSTALL_APP,
|
||||
SANDBOX_CMD_REGISTER_WATCH_ENABLE
|
||||
};
|
||||
|
||||
enum{
|
||||
SANDBOX_WATCH_NONE = 0,
|
||||
SANDBOX_WATCH_CODE,
|
||||
SANDBOX_WATCH_DATA,
|
||||
SANDBOX_WATCH_TOTAL_TYPES
|
||||
};
|
||||
|
||||
enum{
|
||||
SANDBOX_CPU_ARCH_M68K = 0,
|
||||
SANDBOX_CPU_ARCH_ARMV5
|
||||
};
|
||||
|
||||
void sandboxInit(void);
|
||||
void sandboxReset(void);
|
||||
uint32_t sandboxStateSize(void);
|
||||
void sandboxSaveState(uint8_t* data);
|
||||
void sandboxLoadState(uint8_t* data);
|
||||
uint32_t sandboxCommand(uint32_t command, void* data);
|
||||
void sandboxOnFrameRun(void);
|
||||
void sandboxOnOpcodeRun(void);
|
||||
void sandboxOnMemoryAccess(uint32_t address, uint8_t size, bool write, uint32_t value);
|
||||
bool sandboxRunning(void);
|
||||
uint16_t sandboxSetWatchRegion(uint32_t address, uint32_t size, uint8_t type);
|
||||
void sandboxClearWatchRegion(uint16_t index);
|
||||
void sandboxSetCpuArch(uint8_t arch);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,6 @@
|
||||
#include "sdCard.h"
|
||||
#include "silkscreen.h"
|
||||
#include "portability.h"
|
||||
#include "debug/sandbox.h"
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
#include "tungstenT3Bus.h"
|
||||
#include "pxa260/pxa260.h"
|
||||
@@ -78,6 +77,29 @@ void (*palmSerialDataFlush)(void);//called by the emulator to delete all da
|
||||
void (*palmGetRtcFromHost)(uint8_t* writeBack);//[0] = hours, [1] = minutes, [2] = seconds
|
||||
|
||||
|
||||
static void patchOsRom(uint32_t address, char* patch){
|
||||
uint32_t offset;
|
||||
uint32_t patchBytes = strlen(patch) / 2;//1 char per nibble
|
||||
uint32_t swapBegin = address & 0xFFFFFFFE;
|
||||
uint32_t swapSize = patchBytes / sizeof(uint16_t) + 1;
|
||||
char conv[5] = "0xXX";
|
||||
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(!palmEmulatingTungstenT3)
|
||||
#endif
|
||||
swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
|
||||
for(offset = 0; offset < patchBytes; offset++){
|
||||
conv[2] = patch[offset * 2];
|
||||
conv[3] = patch[offset * 2 + 1];
|
||||
palmRom[address + offset] = strtol(conv, NULL, 0);
|
||||
}
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(!palmEmulatingTungstenT3)
|
||||
#endif
|
||||
swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
|
||||
}
|
||||
|
||||
|
||||
uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmBootloaderData, uint32_t palmBootloaderSize, bool syncRtc, bool allowInvalidBehavior){
|
||||
if(emulatorInitialized)
|
||||
return EMU_ERROR_RESOURCE_LOCKED;
|
||||
@@ -136,11 +158,9 @@ uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t pal
|
||||
//initialize components, I dont think theres much in a Tungsten T3
|
||||
pxa260Framebuffer = palmFramebuffer;
|
||||
blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
|
||||
sandboxInit();
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_ARMV5);
|
||||
|
||||
//TODO:remove this
|
||||
sandboxCommand(SANDBOX_CMD_PATCH_OS, NULL);
|
||||
patchOsRom(0x333EC6, "0000");//blocks out the slot driver
|
||||
patchOsRom(0x205C, "0000A0E1");//blocks idle loop jump with NOP
|
||||
|
||||
//reset everything
|
||||
emulatorSoftReset();
|
||||
@@ -196,8 +216,6 @@ uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t pal
|
||||
|
||||
//initialize components
|
||||
blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
|
||||
sandboxInit();
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_M68K);
|
||||
|
||||
//reset everything
|
||||
emulatorSoftReset();
|
||||
@@ -261,7 +279,6 @@ void emulatorSoftReset(void){
|
||||
tps65010Reset();
|
||||
tsc2101Reset(true);
|
||||
w86l488Reset();
|
||||
sandboxReset();
|
||||
}
|
||||
else{
|
||||
#endif
|
||||
@@ -270,7 +287,6 @@ void emulatorSoftReset(void){
|
||||
ads7846Reset();
|
||||
pdiUsbD12Reset();
|
||||
dbvzReset();
|
||||
sandboxReset();
|
||||
//sdCardReset() should not be called here, the SD card does not have a reset line and should only be reset by a power cycle
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
@@ -318,7 +334,6 @@ uint32_t emulatorGetStateSize(void){
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
#endif
|
||||
size += sandboxStateSize();
|
||||
size += sizeof(uint8_t) * 7;//palmMisc
|
||||
size += sizeof(uint32_t) * 4;//palmEmuFeatures.(src/dst/size/value)
|
||||
size += sizeof(uint64_t);//palmSdCard.command
|
||||
@@ -394,10 +409,6 @@ bool emulatorSaveState(uint8_t* data, uint32_t size){
|
||||
}
|
||||
#endif
|
||||
|
||||
//sandbox, does nothing when disabled
|
||||
sandboxSaveState(data + offset);
|
||||
offset += sandboxStateSize();
|
||||
|
||||
//misc
|
||||
writeStateValue8(data + offset, palmMisc.greenLed);
|
||||
offset += sizeof(uint8_t);
|
||||
@@ -522,10 +533,6 @@ bool emulatorLoadState(uint8_t* data, uint32_t size){
|
||||
}
|
||||
#endif
|
||||
|
||||
//sandbox, does nothing when disabled
|
||||
sandboxLoadState(data + offset);
|
||||
offset += sandboxStateSize();
|
||||
|
||||
//misc
|
||||
palmMisc.greenLed = readStateValue8(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
@@ -614,7 +621,7 @@ bool emulatorSaveRam(uint8_t* data, uint32_t size){
|
||||
}
|
||||
else{
|
||||
#endif
|
||||
if(size < palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE)
|
||||
if(size < (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE))
|
||||
return false;
|
||||
|
||||
memcpy(data, palmRam, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
|
||||
@@ -636,7 +643,7 @@ bool emulatorLoadRam(uint8_t* data, uint32_t size){
|
||||
}
|
||||
else{
|
||||
#endif
|
||||
if(size < palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE)
|
||||
if(size < (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE))
|
||||
return false;
|
||||
|
||||
memcpy(palmRam, data, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
|
||||
@@ -799,10 +806,6 @@ void emulatorRunFrame(void){
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(EMU_SANDBOX)
|
||||
sandboxOnFrameRun();
|
||||
#endif
|
||||
}
|
||||
|
||||
void emulatorSkipFrame(void){
|
||||
@@ -820,8 +823,4 @@ void emulatorSkipFrame(void){
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(EMU_SANDBOX)
|
||||
sandboxOnFrameRun();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ extern "C" {
|
||||
//define EMU_BIG_ENDIAN on big endian systems
|
||||
//define EMU_HAVE_FILE_LAUNCHER to enable launching files from the host system
|
||||
//to enable degguging define EMU_DEBUG, all options below do nothing unless EMU_DEBUG is defined
|
||||
//to enable sandbox debugging define EMU_SANDBOX
|
||||
//to enable memory access logging define EMU_SANDBOX_LOG_MEMORY_ACCESSES
|
||||
//to enable opcode level debugging define EMU_SANDBOX_OPCODE_LEVEL_DEBUG
|
||||
//to enable flow control logging define EMU_SANDBOX_LOG_JUMPS, EMU_SANDBOX_OPCODE_LEVEL_DEBUG must also be defined for this to work
|
||||
|
||||
@@ -32,7 +32,7 @@ void flx68000PcLongJump(uint32_t newPc){
|
||||
break;
|
||||
|
||||
case DBVZ_CHIP_REGISTERS:
|
||||
//needed for when EMU_NO_SAFETY is set and a function is run in the sandbox
|
||||
//needed for when EMU_NO_SAFETY is set and a function is run in the launcher
|
||||
dataBufferHost = (uintptr_t)dbvzReg;
|
||||
dataBufferGuest = DBVZ_BANK_ADDRESS(DBVZ_START_BANK(newPc));
|
||||
windowSize = DBVZ_REG_SIZE;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "flx68000.h"
|
||||
#include "sed1376.h"
|
||||
#include "pdiUsbD12.h"
|
||||
#include "debug/sandbox.h"
|
||||
|
||||
|
||||
uint8_t dbvzBankType[DBVZ_TOTAL_MEMORY_BANKS];
|
||||
@@ -117,10 +116,6 @@ uint8_t m68k_read_memory_8(uint32_t address){
|
||||
return 0x00;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 8, false, 0);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return romRead8(address);
|
||||
@@ -157,10 +152,6 @@ uint16_t m68k_read_memory_16(uint32_t address){
|
||||
return 0x0000;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 16, false, 0);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return romRead16(address);
|
||||
@@ -197,10 +188,6 @@ uint32_t m68k_read_memory_32(uint32_t address){
|
||||
return 0x00000000;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 32, false, 0);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return romRead32(address);
|
||||
@@ -237,10 +224,6 @@ void m68k_write_memory_8(uint32_t address, uint8_t value){
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 8, true, value);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return;
|
||||
@@ -281,10 +264,6 @@ void m68k_write_memory_16(uint32_t address, uint16_t value){
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 16, true, value);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return;
|
||||
@@ -325,10 +304,6 @@ void m68k_write_memory_32(uint32_t address, uint32_t value){
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_LOG_MEMORY_ACCESSES)
|
||||
sandboxOnMemoryAccess(address, 32, true, value);
|
||||
#endif
|
||||
|
||||
switch(addressType){
|
||||
case DBVZ_CHIP_A0_ROM:
|
||||
return;
|
||||
|
||||
@@ -133,12 +133,8 @@
|
||||
/* If ON, CPU will call the instruction hook callback before every
|
||||
* instruction.
|
||||
*/
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX) && defined(EMU_SANDBOX_OPCODE_LEVEL_DEBUG)
|
||||
#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
|
||||
#else
|
||||
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||
#endif
|
||||
#define M68K_INSTRUCTION_CALLBACK() sandboxOnOpcodeRun()
|
||||
#define M68K_INSTRUCTION_CALLBACK() on_opcode_run()
|
||||
|
||||
|
||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000.
|
||||
|
||||
@@ -6,6 +6,5 @@
|
||||
int32_t interruptAcknowledge(int32_t intLevel);
|
||||
void emulatorSoftReset(void);
|
||||
void flx68000PcLongJump(uint32_t newPc);
|
||||
void sandboxOnOpcodeRun(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,6 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.c \
|
||||
$(EMU_PATH)/pdiUsbD12.c \
|
||||
$(EMU_PATH)/sdCard.c \
|
||||
$(EMU_PATH)/silkscreen.c \
|
||||
$(EMU_PATH)/debug/sandbox.c \
|
||||
$(EMU_PATH)/audio/blip_buf.c \
|
||||
$(EMU_PATH)/m68k/m68kops.c \
|
||||
$(EMU_PATH)/m68k/m68kopnz.c \
|
||||
|
||||
Reference in New Issue
Block a user