prepare: obj
@echo -e "\033[01;33m***\033[00;32m Preparing to compile Virtual Jaguar...\033[00m"
- @echo "#define VJ_RELEASE_VERSION \"v2.1.0\"" > src/version.h
- @echo "#define VJ_RELEASE_SUBVERSION \"Final\"" >> src/version.h
-# @echo "#define VJ_RELEASE_VERSION \"GIT `git log -1 --pretty=format:%ci | cut -d ' ' -f 1 | tr -d -`\"" > src/version.h
-# @echo "#define VJ_RELEASE_SUBVERSION \"2.1.0 Prerelease\"" >> src/version.h
+# @echo "#define VJ_RELEASE_VERSION \"v2.1.1\"" > src/version.h
+# @echo "#define VJ_RELEASE_SUBVERSION \"Final\"" >> src/version.h
+ @echo "#define VJ_RELEASE_VERSION \"GIT `git log -1 --pretty=format:%ci | cut -d ' ' -f 1 | tr -d -`\"" > src/version.h
+ @echo "#define VJ_RELEASE_SUBVERSION \"2.1.1 Prerelease\"" >> src/version.h
virtualjaguar: sources libs makefile-qt
@echo -e "\033[01;33m***\033[00;32m Making Virtual Jaguar GUI...\033[00m"
bool doDSPDis = false;
//bool doDSPDis = true;
#endif
+bool doDSPDis = false;
+//#define DSP_DIS_JR
+//#define DSP_DIS_JUMP
/*
No dis yet:
static void dsp_opcode_subq(void);
static void dsp_opcode_subqmod(void);
static void dsp_opcode_subqt(void);
+static void dsp_opcode_illegal(void);
uint8 dsp_opcode_cycles[64] =
{
dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
- dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
+ dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_illegal, dsp_opcode_addqmod,
};
uint32 dsp_opcode_use[65];
static uint32 dsp_div_control;
static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
static uint32 * dsp_reg = NULL, * dsp_alternate_reg = NULL;
-static uint32 dsp_reg_bank_0[32], dsp_reg_bank_1[32];
+uint32 dsp_reg_bank_0[32], dsp_reg_bank_1[32];
static uint32 dsp_opcode_first_parameter;
static uint32 dsp_opcode_second_parameter;
32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
+
uint8 dsp_branch_condition_table[32 * 8];
static uint16 mirror_table[65536];
static uint8 dsp_ram_8[0x2000];
WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
//???
offset &= 0xFFFFFFFE;
- // jaguar cd bios
-/* if (jaguar_mainRom_crc32==0xa74a97cd)
- {
- if (offset==0xF1A114) return(0x0000);
- if (offset==0xF1A116) return(0x0000);
- if (offset==0xF1B000) return(0x1234);
- if (offset==0xF1B002) return(0x5678);
- }*/
-/*
- if (jaguar_mainRom_crc32==0x7ae20823)
- {
- if (offset==0xF1B9D8) return(0x0000);
- if (offset==0xF1B9Da) return(0x0000);
- if (offset==0xF1B2C0) return(0x0000);
- if (offset==0xF1B2C2) return(0x0000);
- }
-*/
- // pour permettre � wolfenstein 3d de tourner sans le dsp
-/* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
- return(0);
-*/
-
- // pour permettre � nba jam de tourner sans le dsp
-/* if (jaguar_mainRom_crc32==0x4faddb18)
- {
- if (offset==0xf1b2c0) return(0);
- if (offset==0xf1b2c2) return(0);
- if (offset==0xf1b240) return(0);
- if (offset==0xf1b242) return(0);
- if (offset==0xF1B340) return(0);
- if (offset==0xF1B342) return(0);
- if (offset==0xF1BAD8) return(0);
- if (offset==0xF1BADA) return(0);
- if (offset==0xF1B040) return(0);
- if (offset==0xF1B042) return(0);
- if (offset==0xF1B0C0) return(0);
- if (offset==0xF1B0C2) return(0);
- if (offset==0xF1B140) return(0);
- if (offset==0xF1B142) return(0);
- if (offset==0xF1B1C0) return(0);
- if (offset==0xF1B1C2) return(0);
- }*/
if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
{
break;
}
case 0x18:
+WriteLog("DSP: Modulo data %08X written by %s.\n", data, whoName[who]);
dsp_modulo = data;
break;
case 0x1C:
dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
else
dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
+
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Register bank #%s active.\n", (bank ? "1" : "0"));
+#endif
}
//
return;
int which = 0; // Determine which interrupt
+
if (bits & 0x01)
which = 0;
if (bits & 0x02)
if (bits & 0x20)
which = 5;
-#ifdef DSP_DEBUG_IRQ
- WriteLog("DSP: Generating interrupt #%i...", which);
-#endif
-
- dsp_flags |= IMASK;
+ dsp_flags |= IMASK; // Force Bank #0
//CC only!
#ifdef DSP_DEBUG_CC
ctrl1[4] = dsp_flags;
#endif
//!!!!!!!!
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Bank 0: R30=%08X, R31=%08X\n", dsp_reg_bank_0[30], dsp_reg_bank_0[31]);
+ WriteLog("DSP: Bank 1: R30=%08X, R31=%08X\n", dsp_reg_bank_1[30], dsp_reg_bank_1[31]);
+#endif
DSPUpdateRegisterBanks();
#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Bank 0: R30=%08X, R31=%08X\n", dsp_reg_bank_0[30], dsp_reg_bank_0[31]);
+ WriteLog("DSP: Bank 1: R30=%08X, R31=%08X\n", dsp_reg_bank_1[30], dsp_reg_bank_1[31]);
+#endif
+
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Generating interrupt #%i...", which);
WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
#endif
// move pc,r30 ; address of interrupted code
// store r30,(r31) ; store return address
dsp_reg[31] -= 4;
+ dsp_reg[30] = dsp_pc - 2; // -2 because we've executed the instruction already
+
//CC only!
#ifdef DSP_DEBUG_CC
regs1[31] -= 4;
#endif
//!!!!!!!!
- DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
+// DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
+ DSPWriteLong(dsp_reg[31], dsp_reg[30], DSP);
//CC only!
#ifdef DSP_DEBUG_CC
SET32(ram1, regs1[31] - 0xF1B000, dsp_pc - 2);
if (state)
{
dsp_control |= mask; // Set the latch bit
- DSPHandleIRQs();
+#warning !!! No checking done to see if we're using pipelined DSP or not !!!
+// DSPHandleIRQs();
+ DSPHandleIRQsNP();
//CC only!
#ifdef DSP_DEBUG_CC
ctrl1[8] = ctrl2[8] = dsp_control;
for(int j=0; j<8; j++)
{
WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
- (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
+ (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
+ (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
+ (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
+ (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
}
WriteLog("Registers bank 1\n");
for(int j=0; j<8; j++)
{
WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
- (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
+ (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
+ (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
+ (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
+ (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
}
}
if (dsp_opcode_use[i])
WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
}//*/
-
-// memory_free(dsp_ram_8);
-// memory_free(dsp_reg_bank_0);
-// memory_free(dsp_reg_bank_1);
-// if (dsp_branch_condition_table)
-// free(dsp_branch_condition_table);
-
-// if (mirror_table)
-// free(mirror_table);
}
//static uint32 pcQueue[32], ptrPCQ = 0;
void DSPExec(int32 cycles)
{
-/*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
- dsp_check_if_i2s_interrupt_needed();*/
-
#ifdef DSP_SINGLE_STEPPING
if (dsp_control & 0x18)
{
if (IMASKCleared) // If IMASK was cleared,
{
#ifdef DSP_DEBUG_IRQ
- WriteLog("DSP: Finished interrupt.\n");
+ WriteLog("DSP: Finished interrupt. PC=$%06X\n", dsp_pc);
#endif
DSPHandleIRQsNP(); // See if any other interrupts are pending!
IMASKCleared = false;
if (doDSPDis)
WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
+ // NB: This instruction is the *only* one that does (32 - immediate data).
int32 r1 = 32 - IMM_1;
uint32 res = RN << r1;
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
SET_ZN(res);
}
+void dsp_opcode_illegal(void)
+{
+ // Don't know what it does, but it does *something*...
+ WriteLog("%06X: illegal %u, %u [NCZ:%u%u%u]\n", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
+}
+
//
// New pipelined DSP core
//
// Exported vars
extern bool doDSPDis;
+extern uint32 dsp_reg_bank_0[], dsp_reg_bank_1[];
// DSP interrupt numbers (in $F1A100, bits 4-8 & 16)
memcpy(jagMemSpace + loadAddress, buffer + 0x2E, jaguarROMSize - 0x2E);
delete[] buffer;
jaguarRunAddress = runAddress;
+
+// Hmm. Is this kludge necessary?
+SET32(jaguarMainRAM, 0x10, 0x00001000); // Set Exception #4 (Illegal Instruction)
+SET16(jaguarMainRAM, 0x1000, 0x60FE); // Here: bra Here
+
return true;
// }
// else // Special WTFOMGBBQ type here...
// a bit before writing a result. I.e., if the result of an operation leaves a zero in
// the carry flag, you don't have to zero gpu_flag_c before you can write that zero!
static uint8 gpu_flag_z, gpu_flag_n, gpu_flag_c;
-static uint32 gpu_reg_bank_0[32];
-static uint32 gpu_reg_bank_1[32];
+uint32 gpu_reg_bank_0[32];
+uint32 gpu_reg_bank_1[32];
static uint32 * gpu_reg;
static uint32 * gpu_alternate_reg;
enum { GPUIRQ_CPU = 0, GPUIRQ_DSP, GPUIRQ_TIMER, GPUIRQ_OBJECT, GPUIRQ_BLITTER };
+// Exported vars
+
+extern uint32 gpu_reg_bank_0[], gpu_reg_bank_1[];
+
#endif // __GPU_H__
void CPUBrowserWindow::RefreshContents(void)
{
- char string[1024], buf[64];
+ char string[2048];
QString s;
// 68K
sprintf(string, "GPU PC: %06X FLAGS: %08X<br><br>", GPUReadLong(0xF02010), GPUReadLong(0xF02000));
s += QString(string);
+ sprintf(string, "Bank 0:<br>"
+ "R00: %08X R01: %08X R02: %08X R03: %08X<br>"
+ "R04: %08X R05: %08X R06: %08X R07: %08X<br>"
+ "R08: %08X R09: %08X R10: %08X R11: %08X<br>"
+ "R12: %08X R13: %08X R14: %08X R15: %08X<br>"
+ "R16: %08X R17: %08X R18: %08X R19: %08X<br>"
+ "R20: %08X R21: %08X R22: %08X R23: %08X<br>"
+ "R24: %08X R25: %08X R26: %08X R27: %08X<br>"
+ "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>",
+ gpu_reg_bank_0[0], gpu_reg_bank_0[1], gpu_reg_bank_0[2], gpu_reg_bank_0[3],
+ gpu_reg_bank_0[4], gpu_reg_bank_0[5], gpu_reg_bank_0[6], gpu_reg_bank_0[7],
+ gpu_reg_bank_0[8], gpu_reg_bank_0[9], gpu_reg_bank_0[10], gpu_reg_bank_0[11],
+ gpu_reg_bank_0[12], gpu_reg_bank_0[13], gpu_reg_bank_0[14], gpu_reg_bank_0[15],
+ gpu_reg_bank_0[16], gpu_reg_bank_0[17], gpu_reg_bank_0[18], gpu_reg_bank_0[19],
+ gpu_reg_bank_0[20], gpu_reg_bank_0[21], gpu_reg_bank_0[22], gpu_reg_bank_0[23],
+ gpu_reg_bank_0[24], gpu_reg_bank_0[25], gpu_reg_bank_0[26], gpu_reg_bank_0[27],
+ gpu_reg_bank_0[28], gpu_reg_bank_0[29], gpu_reg_bank_0[30], gpu_reg_bank_0[31]);
+ s += QString(string);
+
+ sprintf(string, "Bank 1:<br>"
+ "R00: %08X R01: %08X R02: %08X R03: %08X<br>"
+ "R04: %08X R05: %08X R06: %08X R07: %08X<br>"
+ "R08: %08X R09: %08X R10: %08X R11: %08X<br>"
+ "R12: %08X R13: %08X R14: %08X R15: %08X<br>"
+ "R16: %08X R17: %08X R18: %08X R19: %08X<br>"
+ "R20: %08X R21: %08X R22: %08X R23: %08X<br>"
+ "R24: %08X R25: %08X R26: %08X R27: %08X<br>"
+ "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>",
+ gpu_reg_bank_1[0], gpu_reg_bank_1[1], gpu_reg_bank_1[2], gpu_reg_bank_1[3],
+ gpu_reg_bank_1[4], gpu_reg_bank_1[5], gpu_reg_bank_1[6], gpu_reg_bank_1[7],
+ gpu_reg_bank_1[8], gpu_reg_bank_1[9], gpu_reg_bank_1[10], gpu_reg_bank_1[11],
+ gpu_reg_bank_1[12], gpu_reg_bank_1[13], gpu_reg_bank_1[14], gpu_reg_bank_1[15],
+ gpu_reg_bank_1[16], gpu_reg_bank_1[17], gpu_reg_bank_1[18], gpu_reg_bank_1[19],
+ gpu_reg_bank_1[20], gpu_reg_bank_1[21], gpu_reg_bank_1[22], gpu_reg_bank_1[23],
+ gpu_reg_bank_1[24], gpu_reg_bank_1[25], gpu_reg_bank_1[26], gpu_reg_bank_1[27],
+ gpu_reg_bank_1[28], gpu_reg_bank_1[29], gpu_reg_bank_1[30], gpu_reg_bank_1[31]);
+ s += QString(string);
+
// DSP
sprintf(string, "DSP PC: %06X FLAGS: %08X<br><br>", DSPReadLong(0xF1A110), DSPReadLong(0xF1A100));
s += QString(string);
+ sprintf(string, "Bank 0:<br>"
+ "R00: %08X R01: %08X R02: %08X R03: %08X<br>"
+ "R04: %08X R05: %08X R06: %08X R07: %08X<br>"
+ "R08: %08X R09: %08X R10: %08X R11: %08X<br>"
+ "R12: %08X R13: %08X R14: %08X R15: %08X<br>"
+ "R16: %08X R17: %08X R18: %08X R19: %08X<br>"
+ "R20: %08X R21: %08X R22: %08X R23: %08X<br>"
+ "R24: %08X R25: %08X R26: %08X R27: %08X<br>"
+ "R28: %08X R29: %08X R30: %08X R31: %08X<br><br>",
+ dsp_reg_bank_0[0], dsp_reg_bank_0[1], dsp_reg_bank_0[2], dsp_reg_bank_0[3],
+ dsp_reg_bank_0[4], dsp_reg_bank_0[5], dsp_reg_bank_0[6], dsp_reg_bank_0[7],
+ dsp_reg_bank_0[8], dsp_reg_bank_0[9], dsp_reg_bank_0[10], dsp_reg_bank_0[11],
+ dsp_reg_bank_0[12], dsp_reg_bank_0[13], dsp_reg_bank_0[14], dsp_reg_bank_0[15],
+ dsp_reg_bank_0[16], dsp_reg_bank_0[17], dsp_reg_bank_0[18], dsp_reg_bank_0[19],
+ dsp_reg_bank_0[20], dsp_reg_bank_0[21], dsp_reg_bank_0[22], dsp_reg_bank_0[23],
+ dsp_reg_bank_0[24], dsp_reg_bank_0[25], dsp_reg_bank_0[26], dsp_reg_bank_0[27],
+ dsp_reg_bank_0[28], dsp_reg_bank_0[29], dsp_reg_bank_0[30], dsp_reg_bank_0[31]);
+ s += QString(string);
+
+ sprintf(string, "Bank 1:<br>"
+ "R00: %08X R01: %08X R02: %08X R03: %08X<br>"
+ "R04: %08X R05: %08X R06: %08X R07: %08X<br>"
+ "R08: %08X R09: %08X R10: %08X R11: %08X<br>"
+ "R12: %08X R13: %08X R14: %08X R15: %08X<br>"
+ "R16: %08X R17: %08X R18: %08X R19: %08X<br>"
+ "R20: %08X R21: %08X R22: %08X R23: %08X<br>"
+ "R24: %08X R25: %08X R26: %08X R27: %08X<br>"
+ "R28: %08X R29: %08X R30: %08X R31: %08X<br>",
+ dsp_reg_bank_1[0], dsp_reg_bank_1[1], dsp_reg_bank_1[2], dsp_reg_bank_1[3],
+ dsp_reg_bank_1[4], dsp_reg_bank_1[5], dsp_reg_bank_1[6], dsp_reg_bank_1[7],
+ dsp_reg_bank_1[8], dsp_reg_bank_1[9], dsp_reg_bank_1[10], dsp_reg_bank_1[11],
+ dsp_reg_bank_1[12], dsp_reg_bank_1[13], dsp_reg_bank_1[14], dsp_reg_bank_1[15],
+ dsp_reg_bank_1[16], dsp_reg_bank_1[17], dsp_reg_bank_1[18], dsp_reg_bank_1[19],
+ dsp_reg_bank_1[20], dsp_reg_bank_1[21], dsp_reg_bank_1[22], dsp_reg_bank_1[23],
+ dsp_reg_bank_1[24], dsp_reg_bank_1[25], dsp_reg_bank_1[26], dsp_reg_bank_1[27],
+ dsp_reg_bank_1[28], dsp_reg_bank_1[29], dsp_reg_bank_1[30], dsp_reg_bank_1[31]);
+ s += QString(string);
+
text->clear();
text->setText(s);
}
void MainWin::keyPressEvent(QKeyEvent * e)
{
+ // From jaguar.cpp
+ extern bool startM68KTracing;
+
// We ignore the Alt key for now, since it causes problems with the GUI
if (e->key() == Qt::Key_Alt)
{
e->accept();
return;
}
+ else if (e->key() == Qt::Key_F11)
+ {
+ startM68KTracing = true;
+ e->accept();
+ return;
+ }
+
/*
if (e->key() == Qt::Key_F9)
{
case 21: sprintf(buffer, "DIV R%02d,R%02d", reg1, reg2); break;
case 22: sprintf(buffer, "ABS R%02d", reg2); break;
case 23: sprintf(buffer, "SH R%02d,R%02d", reg1, reg2); break;
- case 24: sprintf(buffer, "SHLQ $%X,R%02d", 32 - convert_zero[reg1], reg2); break;
+ case 24: sprintf(buffer, "SHLQ $%X,R%02d", 32 - reg1, reg2); break;
case 25: sprintf(buffer, "SHRQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 26: sprintf(buffer, "SHA R%02d,R%02d", reg1, reg2); break;
case 27: sprintf(buffer, "SHARQ $%X,R%02d", convert_zero[reg1], reg2); break;
case 62: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, "SAT24 R%02d", reg2);
else
- sprintf(buffer, "illegal");
+ sprintf(buffer, "illegal [%d,%d]", reg1, reg2);
break;
case 63: if (dsp_type == JAGUAR_GPU)
sprintf(buffer, (reg1 ? "UNPACK R%02d" : "PACK R%02d"), reg2);
//Do this in makefile??? Yes! Could, but it's easier to define here...
//#define LOG_UNMAPPED_MEMORY_ACCESSES
//#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
-#define ABORT_ON_ILLEGAL_INSTRUCTIONS
+//#define ABORT_ON_ILLEGAL_INSTRUCTIONS
//#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
#define CPU_DEBUG_MEMORY
//#define LOG_CD_BIOS_CALLS
+#define CPU_DEBUG_TRACING
// Private function prototypes
uint32 pcQueue[0x400];
uint32 pcQPtr = 0;
+bool startM68KTracing = false;
//
// Callback function to detect illegal instructions
instSeen++;
#endif
+// For code tracing...
+#ifdef CPU_DEBUG_TRACING
+ if (startM68KTracing)
+ {
+ static char buffer[2048];
+
+ m68k_disassemble(buffer, m68kPC, 0);
+ WriteLog("%06X: %s\n", m68kPC, buffer);
+ }
+#endif
+
// For tracebacks...
// Ideally, we'd save all the registers as well...
pcQueue[pcQPtr++] = m68kPC;
m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
}//*/
- if (m68kPC == 0x82E1A)
+/* if (m68kPC == 0x82E1A)
{
static char buffer[2048];
m68k_disassemble(buffer, m68kPC, 0);//M68K_CPU_TYPE_68000);
m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
}//*/
- if (m68kPC == 0x82E58)
+/* if (m68kPC == 0x82E58)
WriteLog("--> [Routine end]\n");
if (m68kPC == 0x80004)
{
#endif
int irq_ack_handler(int level)
{
+#ifdef CPU_DEBUG_TRACING
+ if (startM68KTracing)
+ {
+ WriteLog("irq_ack_handler: M68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
+ }
+#endif
+
// Tracing the IPL lines on the Jaguar schematic yields the following:
// IPL1 is connected to INTL on TOM (OUT to 68K)
// IPL0-2 are also tied to Vcc via 4.7K resistors!
joypad_0_buttons[BUTTON_D] = 0;
#endif
+// This is handled by the GUI layer, as it should
+#if 0
// Joystick support [nwagenaar]
if (vjs.useJoystick)
// Needed to ensure that the events queue is empty [nwagenaar]
SDL_PumpEvents();
+#endif
}
void JoystickReset(void)
#include <stdarg.h>
#include "types.h"
-#define MAX_LOG_SIZE 10000000 // Maximum size of log file (10 MB)
+//#define MAX_LOG_SIZE 10000000 // Maximum size of log file (10 MB)
+#define MAX_LOG_SIZE 100000000 // Maximum size of log file (100 MB)
static FILE * log_stream = NULL;
static uint32 logSize = 0;
//
#include "m68kinterface.h"
+//#include <pthread.h>
#include "cpudefs.h"
#include "inlines.h"
#include "cpuextra.h"
#include "readcpu.h"
-
// Exception Vectors handled by emulation
#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */
#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */
STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr);
unsigned long IllegalOpcode(uint32_t opcode);
void BuildCPUFunctionTable(void);
+void m68k_set_irq2(unsigned int intLevel);
// Local "Global" vars
static int32_t initialCycles;
cpuop_func * cpuFunctionTable[65536];
+// By virtue of the fact that m68k_set_irq() can be called asychronously by
+// another thread, we need something along the lines of this:
+static int checkForIRQToHandle = 0;
+//static pthread_mutex_t executionLock = PTHREAD_MUTEX_INITIALIZER;
+static int IRQLevelToHandle = 0;
#if 0
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
//94C0: 6A02 BPL.B $94C4
//94C2: 2452 MOVEA.L (A2), A2 ; <--- HERE
//94C4: 4283 CLR.L D3
+#endif
+// pthread_mutex_lock(&executionLock);
+ if (checkForIRQToHandle)
+ {
+ checkForIRQToHandle = 0;
+ m68k_set_irq2(IRQLevelToHandle);
+ }
+
+#ifdef M68K_HOOK_FUNCTION
+ M68KInstructionHook();
#endif
uint32_t opcode = get_iword(0);
//if ((opcode & 0xFFF8) == 0x31C0)
//}
int32_t cycles = (int32_t)(*cpuFunctionTable[opcode])(opcode);
regs.remainingCycles -= cycles;
+// pthread_mutex_unlock(&executionLock);
+
//printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles);
#endif
}
-#if 0
- while (GET_CYCLES() > 0);
-#else
while (regs.remainingCycles > 0);
-#endif
#if 0
/* set previous PC to current PC for the next entry into the loop */
}
-/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
void m68k_set_irq(unsigned int intLevel)
{
-#if 0
- uint old_level = CPU_INT_LEVEL;
- CPU_INT_LEVEL = int_level << 8;
+ // Since this can be called asynchronously, we need to fix it so that it
+ // doesn't fuck up the main execution loop.
+ IRQLevelToHandle = intLevel;
+ checkForIRQToHandle = 1;
+}
+
+
+/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
+void m68k_set_irq2(unsigned int intLevel)
+{
+// pthread_mutex_lock(&executionLock);
+// printf("m68k_set_irq: Could not get the lock!!!\n");
- /* A transition from < 7 to 7 always interrupts (NMI) */
- /* Note: Level 7 can also level trigger like a normal IRQ */
- if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
- m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
- else
- m68ki_check_interrupts(); /* Level triggered (IRQ) */
-#else
int oldLevel = regs.intLevel;
regs.intLevel = intLevel;
m68ki_exception_interrupt(7); // Edge triggered level 7 (NMI)
else
m68ki_check_interrupts(); // Level triggered (IRQ)
-#endif
+
+// pthread_mutex_unlock(&executionLock);
}
// Set the interrupt mask to the level of the one being serviced
regs.intmask = intLevel;
+#if 0
+extern int startM68KTracing;
+if (startM68KTracing)
+{
+ printf("IRQ: old PC=%06X, ", regs.pc);
+}
+#endif
+
// Get the new PC
uint32_t newPC = m68k_read_memory_32(vector << 2);
+#if 0
+if (startM68KTracing)
+{
+ printf("new PC=%06X, vector=%u, ", newPC, vector);
+}
+#endif
+
// If vector is uninitialized, call the uninitialized interrupt vector
if (newPC == 0)
newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2);
m68ki_stack_frame_3word(regs.pc, sr);
m68k_setpc(newPC);
+#if 0
+if (startM68KTracing)
+{
+ printf("(PC=%06X)\n", regs.pc);
+}
+#endif
// Defer cycle counting until later
regs.interruptCycles += 56; // NOT ACCURATE-- !!! FIX !!!
int m68k_cycles_run(void) {} /* Number of cycles run so far */
int m68k_cycles_remaining(void) {} /* Number of cycles left */
-void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
+//void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
//void m68k_end_timeslice(void) {} /* End timeslice now */
+void m68k_modify_timeslice(int cycles)
+{
+ regs.remainingCycles = cycles;
+}
+
+
void m68k_end_timeslice(void)
{
#if 0
// Convenience functions
+// Uncomment this to have the emulated CPU call a hook function after every instruction
+// NB: This must be implemented by the user!
+#define M68K_HOOK_FUNCTION
+#ifdef M68K_HOOK_FUNCTION
+void M68KInstructionHook(void);
+#endif
+
/* Peek at the internals of a CPU context. This can either be a context
* retrieved using m68k_get_context() or the currently running context.
* If context is NULL, the currently running CPU context will be used.