mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 23:25:04 +00:00
The dragonball uses a 68000 not 68020, more boot chip fixes
This commit is contained in:
@@ -40,13 +40,13 @@ SOURCES += \
|
||||
src/m68k/m68kopdm.c \
|
||||
src/m68k/m68kopnz.c \
|
||||
src/m68k/m68kops.c \
|
||||
src/cpu32Opcodes.c \
|
||||
src/emulator.c \
|
||||
src/hardwareRegisters.c \
|
||||
src/memoryAccess.c \
|
||||
src/sdcard.c \
|
||||
src/sed1376.c \
|
||||
src/silkscreen.c
|
||||
src/silkscreen.c \
|
||||
src/68328Functions.c
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -61,7 +61,6 @@ HEADERS += \
|
||||
src/m68k/m68kconf.h \
|
||||
src/m68k/m68kcpu.h \
|
||||
src/m68k/m68kops.h \
|
||||
src/cpu32Opcodes.h \
|
||||
src/emuFeatureRegistersSpec.h \
|
||||
src/emulator.h \
|
||||
src/hardwareRegisterNames.h \
|
||||
@@ -70,7 +69,8 @@ HEADERS += \
|
||||
src/portability.h \
|
||||
src/sdcard.h \
|
||||
src/sed1376.h \
|
||||
src/silkscreen.h
|
||||
src/silkscreen.h \
|
||||
src/68328Functions.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui
|
||||
|
||||
@@ -17,7 +17,9 @@ bool lowPowerStopActive;
|
||||
|
||||
static inline void patchOpcode(uint16_t opcode, void (*handler)(void), unsigned char cycles){
|
||||
m68ki_instruction_jump_table[opcode] = handler;
|
||||
m68ki_cycles[2][opcode] = cycles;//set how many cycles for 68020
|
||||
m68ki_cycles[0][opcode] = cycles;
|
||||
m68ki_cycles[1][opcode] = cycles;
|
||||
m68ki_cycles[2][opcode] = cycles;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,28 +34,28 @@ void cpu32OpLpstop(void){
|
||||
//program lacks authority
|
||||
m68ki_exception_privilege_violation();
|
||||
}
|
||||
debugLog("LowPowerStop set, CPU is off, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("LowPowerStop set, CPU is off, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void cpu32OpTbls(void){
|
||||
debugLog("TBLS opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("TBLS opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void cpu32OpTblsn(void){
|
||||
debugLog("TBLSN opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("TBLSN opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void cpu32OpTblu(void){
|
||||
debugLog("TBLU opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("TBLU opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void cpu32OpTblun(void){
|
||||
debugLog("TBLUN opcode not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("TBLUN opcode not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
|
||||
void m68k_op_bgnd(void){
|
||||
debugLog("Opcode BGND not implemented, PC 0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
debugLog("Opcode BGND not implemented, PC:0x%08X!\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void m68k_op_cpu32_dispatch(void){
|
||||
@@ -89,9 +91,13 @@ void m68k_op_cpu32_dispatch(void){
|
||||
}
|
||||
|
||||
|
||||
void patchMusashiOpcodeHandlerCpu32(){
|
||||
void patchTo68328(){
|
||||
CPU_ADDRESS_MASK = 0xFFFFFFFF;
|
||||
|
||||
patchOpcode(OPCODE_BGND, m68k_op_bgnd, 16/*dont know how many cycles, average opcode*/);
|
||||
|
||||
for(uint32_t currentOpcode = OPCODE_CPU32_START; currentOpcode <= OPCODE_CPU32_END; currentOpcode++)
|
||||
patchOpcode(currentOpcode, m68k_op_cpu32_dispatch, 91/*dont know how many cycles, most expensive opcode*/);
|
||||
|
||||
//68328 may actually use some 68020 opcodes, those will be patched in if and when Palm OS attempts to call one
|
||||
}
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
extern bool lowPowerStopActive;
|
||||
|
||||
void patchMusashiOpcodeHandlerCpu32();
|
||||
void patchTo68328();
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <boolean.h>
|
||||
|
||||
#include "m68k/m68k.h"
|
||||
#include "cpu32Opcodes.h"
|
||||
#include "68328Functions.h"
|
||||
#include "emulator.h"
|
||||
#include "hardwareRegisters.h"
|
||||
#include "memoryAccess.h"
|
||||
@@ -54,20 +54,42 @@ static inline bool allSdCardCallbacksPresent(){
|
||||
|
||||
//debug
|
||||
#ifdef EMU_OPCODE_LEVEL_DEBUG
|
||||
#define LOGGED_OPCODES 10
|
||||
#define LOGGED_OPCODES 100
|
||||
static bool invalidBehaviorAbort;
|
||||
static char disassemblyBuffer[LOGGED_OPCODES][100];//store the opcode and program counter for the last 10 opcodes
|
||||
|
||||
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);
|
||||
|
||||
textBytes[0] = '\0';
|
||||
|
||||
for(uint32_t count = 0; count < bytes; count++){
|
||||
sprintf(textBytes + textBytesOffset, "%02X", m68k_read_memory_8(stackAddress + count));
|
||||
textBytesOffset = strlen(textBytes);
|
||||
}
|
||||
|
||||
return textBytes;
|
||||
}
|
||||
|
||||
static void invalidBehaviorCheck(){
|
||||
char opcodeName[100];
|
||||
uint32_t lastProgramCounter = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
uint32_t programCounter = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
uint16_t instruction = m68k_get_reg(NULL, M68K_REG_IR);
|
||||
bool invalidInstruction = !m68k_is_valid_instruction(instruction, M68K_CPU_TYPE_68020);
|
||||
bool invalidInstruction = !m68k_is_valid_instruction(instruction, M68K_CPU_TYPE_68000);
|
||||
bool invalidBank = (bankType[START_BANK(programCounter)] == CHIP_NONE);
|
||||
|
||||
//get current opcode
|
||||
m68k_disassemble(opcodeName, programCounter, M68K_CPU_TYPE_68020);
|
||||
if(!invalidBank){
|
||||
//must dissasemble as 68020 to prevent address masking, is also more descriptive for invalid opcodes
|
||||
m68k_disassemble(opcodeName, programCounter, M68K_CPU_TYPE_68020);
|
||||
}
|
||||
else{
|
||||
strcpy(opcodeName, "Invalid bank, cant read");
|
||||
}
|
||||
sprintf(opcodeName + strlen(opcodeName), " at PC:0x%08X", programCounter);
|
||||
|
||||
//shift opcode buffer
|
||||
for(uint32_t i = 0; i < LOGGED_OPCODES - 1; i++)
|
||||
@@ -85,7 +107,25 @@ static void invalidBehaviorCheck(){
|
||||
for(uint32_t i = 0; i < LOGGED_OPCODES; i++)
|
||||
debugLog("%s\n", disassemblyBuffer[i]);
|
||||
//currently CPU32 opcodes will be listed as "unknown", I cant change that properly unless I directly edit musashi source, something I want to avoid doing
|
||||
debugLog("Instruction:\"%s\", instruction value:0x%04X, bank type:%d, program counter:0x%08X\n", invalidInstruction ? "unknown" : opcodeName, instruction, START_BANK(programCounter), programCounter);
|
||||
debugLog("Instruction:\"%s\", instruction value:0x%04X, bank type:%d\n", invalidInstruction ? "unknown" : opcodeName, instruction, bankType[START_BANK(programCounter)]);
|
||||
}
|
||||
|
||||
//custom debug operations
|
||||
switch(programCounter){
|
||||
/*
|
||||
//case 0x10000566:
|
||||
case 0x100003F8:
|
||||
{
|
||||
//failing on executing first trap "HwrPreDebugInit"
|
||||
char* data = takeStackDump(32);
|
||||
debugLog("Stack dump:%s\n", data);
|
||||
free(data);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -94,7 +134,8 @@ static void invalidBehaviorCheck(){
|
||||
void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialFeatures){
|
||||
//CPU
|
||||
m68k_init();
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68020);
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
patchTo68328();
|
||||
m68k_set_reset_instr_callback(emulatorReset);
|
||||
m68k_set_int_ack_callback(interruptAcknowledge);
|
||||
#ifdef EMU_OPCODE_LEVEL_DEBUG
|
||||
@@ -102,7 +143,6 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF
|
||||
strcpy(disassemblyBuffer[i], "Not an opcode.\n");
|
||||
m68k_set_instr_hook_callback(invalidBehaviorCheck);
|
||||
#endif
|
||||
patchMusashiOpcodeHandlerCpu32();
|
||||
resetHwRegisters();
|
||||
lowPowerStopActive = false;
|
||||
palmCrystalCycles = 2.0 * (14.0 * (71.0/*p*/ + 1.0) + 3.0/*q*/ + 1.0) / 2.0/*prescaler1*/;
|
||||
@@ -166,8 +206,6 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF
|
||||
debugLog("Fixed 32.32:0x%08lX\n", fixed3232);
|
||||
debugLog("Rebuilt double:%f\n", rebuilt);
|
||||
*/
|
||||
|
||||
//debugLog("0x01000014 bank type:%d\n", bankType[0x0100]);
|
||||
}
|
||||
|
||||
void emulatorExit(){
|
||||
@@ -176,6 +214,7 @@ void emulatorExit(){
|
||||
|
||||
void emulatorReset(){
|
||||
//reset doesnt clear RAM or sdcard, all programs are stored in RAM or on sdcard
|
||||
debugLog("Reset triggered, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
resetHwRegisters();
|
||||
resetAddressSpace();//address space must be reset after hardware registers because it is dependant on them
|
||||
sed1376Reset();
|
||||
@@ -208,7 +247,7 @@ uint32_t emulatorGetStateSize(){
|
||||
size += REG_SIZE;//hardware registers
|
||||
size += TOTAL_MEMORY_BANKS;//bank handlers
|
||||
size += sizeof(uint32_t) * 4 * CHIP_END;//chip select states
|
||||
size += sizeof(uint8_t) * 4 * CHIP_END;//chip select states
|
||||
size += sizeof(uint8_t) * 5 * CHIP_END;//chip select states
|
||||
size += sizeof(uint64_t) * 3;//palmSdCard
|
||||
size += sizeof(uint8_t) * 2;//palmSdCard
|
||||
size += sizeof(uint64_t) * 4;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers
|
||||
@@ -254,6 +293,8 @@ void emulatorSaveState(uint8_t* data){
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValueUint32(data + offset, chips[chip].mask);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValueBool(data + offset, chips[chip].inBootMode);
|
||||
offset += sizeof(uint8_t);
|
||||
writeStateValueBool(data + offset, chips[chip].readOnly);
|
||||
offset += sizeof(uint8_t);
|
||||
writeStateValueBool(data + offset, chips[chip].readOnlyForProtectedMemory);
|
||||
@@ -338,6 +379,8 @@ void emulatorLoadState(uint8_t* data){
|
||||
offset += sizeof(uint32_t);
|
||||
chips[chip].mask = readStateValueUint32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
chips[chip].inBootMode = readStateValueBool(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
chips[chip].readOnly = readStateValueBool(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
chips[chip].readOnlyForProtectedMemory = readStateValueBool(data + offset);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "hardwareRegisterNames.h"
|
||||
#include "hardwareRegisters.h"
|
||||
#include "memoryAccess.h"
|
||||
#include "cpu32Opcodes.h"
|
||||
#include "68328Functions.h"
|
||||
#include "portability.h"
|
||||
#include "m68k/m68k.h"
|
||||
|
||||
@@ -70,6 +70,10 @@ static inline void setCsa(uint16_t value){
|
||||
chips[CHIP_A_ROM].readOnly = CAST_TO_BOOL(value & 0x8000);
|
||||
chips[CHIP_A_ROM].size = 0x20000/*128kb*/ << ((value >> 1) & 0x0007);
|
||||
|
||||
//CSA is now just a normal chipselect
|
||||
if(chips[CHIP_A_ROM].enable && chips[CHIP_A_ROM].inBootMode)
|
||||
chips[CHIP_A_ROM].inBootMode = false;
|
||||
|
||||
registerArrayWrite16(CSA, value & 0x81FF);
|
||||
}
|
||||
|
||||
@@ -818,6 +822,7 @@ void refreshButtonState(){
|
||||
|
||||
void setBusErrorTimeOut(){
|
||||
uint8_t scr = registerArrayRead8(SCR);
|
||||
debugLog("Bus error timeout, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
if(scr & 0x10){
|
||||
//trigger bus error interrupt
|
||||
}
|
||||
@@ -826,6 +831,7 @@ void setBusErrorTimeOut(){
|
||||
|
||||
void setWriteProtectViolation(){
|
||||
uint8_t scr = registerArrayRead8(SCR);
|
||||
debugLog("Write protect violation, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
if(scr & 0x10){
|
||||
//trigger bus error interrupt
|
||||
}
|
||||
@@ -834,6 +840,7 @@ void setWriteProtectViolation(){
|
||||
|
||||
void setPrivilegeViolation(){
|
||||
uint8_t scr = registerArrayRead8(SCR);
|
||||
debugLog("Privilege violation, PC:0x%08X\n", m68k_get_reg(NULL, M68K_REG_PC));
|
||||
if(scr & 0x10){
|
||||
//trigger bus error interrupt
|
||||
}
|
||||
@@ -920,7 +927,7 @@ unsigned int getHwRegister16(unsigned int address){
|
||||
}
|
||||
|
||||
address &= 0x00000FFF;
|
||||
printUnknownHwAccess(address, 0, 16, false);
|
||||
//printUnknownHwAccess(address, 0, 16, false);
|
||||
switch(address){
|
||||
|
||||
//32 bit registers accessed as 16 bit
|
||||
@@ -940,7 +947,7 @@ unsigned int getHwRegister16(unsigned int address){
|
||||
return registerArrayRead16(address);
|
||||
|
||||
default:
|
||||
//printUnknownHwAccess(address, 0, 16, false);
|
||||
printUnknownHwAccess(address, 0, 16, false);
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
@@ -1305,15 +1312,14 @@ void resetHwRegisters(){
|
||||
chips[chip].size = 0x00000000;
|
||||
chips[chip].mask = 0x00000000;
|
||||
|
||||
chips[chip].inBootMode = false;
|
||||
chips[chip].readOnly = false;
|
||||
chips[chip].readOnlyForProtectedMemory = false;
|
||||
chips[chip].supervisorOnlyProtectedMemory = false;
|
||||
chips[chip].unprotectedSize = 0x00000000;
|
||||
}
|
||||
//all chipselects are disabled at boot and CSA is mapped to 0x00000000 and covers the entire address range until CSGBA set otherwise
|
||||
chips[CHIP_A_ROM].enable = true;
|
||||
chips[CHIP_A_ROM].start = 0x00000000;
|
||||
chips[CHIP_A_ROM].size = 0xFFFF0000;//0xFFFFFFFF will block hw registers and emu registers
|
||||
chips[CHIP_A_ROM].inBootMode = true;
|
||||
|
||||
//masks for reading and writing
|
||||
chips[CHIP_A_ROM].mask = 0x003FFFFF;
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef struct{
|
||||
uint32_t mask;//the address lines the chip responds to, so 0x10000 on an chip with 16 address lines will return the value at 0x0000
|
||||
|
||||
//attributes
|
||||
bool inBootMode;
|
||||
bool readOnly;
|
||||
bool readOnlyForProtectedMemory;
|
||||
bool supervisorOnlyProtectedMemory;
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
/* Turn ON if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_010 OPT_OFF
|
||||
#define M68K_EMULATE_EC020 OPT_OFF
|
||||
#define M68K_EMULATE_020 OPT_ON
|
||||
#define M68K_EMULATE_020 OPT_OFF
|
||||
|
||||
|
||||
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
|
||||
@@ -4,7 +4,7 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.c \
|
||||
$(EMU_PATH)/sed1376.c \
|
||||
$(EMU_PATH)/sdcard.c \
|
||||
$(EMU_PATH)/silkscreen.c \
|
||||
$(EMU_PATH)/cpu32Opcodes.c \
|
||||
$(EMU_PATH)/68328Functions.c \
|
||||
$(EMU_PATH)/m68k/m68kops.c \
|
||||
$(EMU_PATH)/m68k/m68kopnz.c \
|
||||
$(EMU_PATH)/m68k/m68kopdm.c \
|
||||
|
||||
@@ -335,10 +335,10 @@ static uint8_t getProperBankType(uint32_t bank){
|
||||
|
||||
//normal banks
|
||||
if(BANK_IN_RANGE(bank, REG_START_ADDRESS, REG_SIZE)){
|
||||
//registers have first priority, they cover 0xFFFFF000 even if a chipselect overlaps this area
|
||||
//registers have first priority, they cover 0xFFFFF000 even if a chipselect overlaps this area or CHIP_A_ROM is in boot mode
|
||||
return CHIP_REGISTERS;
|
||||
}
|
||||
else if(chips[CHIP_A_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].size)){
|
||||
else if(chips[CHIP_A_ROM].inBootMode || (chips[CHIP_A_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].size))){
|
||||
return CHIP_A_ROM;
|
||||
}
|
||||
else if(chips[CHIP_B_SED].enable && BANK_IN_RANGE(bank, chips[CHIP_B_SED].start, chips[CHIP_B_SED].size) && sed1376ClockConnected()){
|
||||
|
||||
@@ -17,6 +17,7 @@ interrupt control register (ICR), POL5 and edge trigger selects
|
||||
storage RAM protect(likely already done from fixing chip select bits)
|
||||
|
||||
Fixed:
|
||||
Palm OS usage of the "rte" instruction is incompatible with the 68020, switch to 68000 core
|
||||
System Control Register, 0xXXFFF000 all upper banks are registers mode
|
||||
Port D keyboard enable register
|
||||
(HW verified)PDPOL inverts interrupts by inverting PDDATA bits, the data register is affected by PDPOL
|
||||
|
||||
Reference in New Issue
Block a user