// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
+// JLH 11/26/2011 Added fixes for LOAD/STORE alignment issues
//
#include "dsp.h"
#include "m68k.h"
//#include "memory.h"
+
+// Seems alignment in loads & stores was off...
+#define DSP_CORRECT_ALIGNMENT
+
//#define DSP_DEBUG
//#define DSP_DEBUG_IRQ
//#define DSP_DEBUG_PL2
// Disassembly definitions
+#if 0
#define DSP_DIS_ABS
#define DSP_DIS_ADD
#define DSP_DIS_ADDC
//*/
bool doDSPDis = false;
//bool doDSPDis = true;
-
+#endif
/*
No dis yet:
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2));
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ DSPWriteLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
}
static void dsp_opcode_store_r15_indexed(void)
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2));
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ DSPWriteLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
}
static void dsp_opcode_load_r14_ri(void)
if (doDSPDis)
WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[14], IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[14] + RM) & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(dsp_reg[14] + RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD14R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[15], IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[15] + RM) & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(dsp_reg[15] + RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD15R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
if (doDSPDis)
WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ DSPWriteLong(RM & 0xFFFFFFFE, RN & 0xFFFF, DSP);
+ else
+ JaguarWriteWord(RM & 0xFFFFFFFE, RN, DSP);
+#else
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
DSPWriteLong(RM, RN & 0xFFFF, DSP);
else
JaguarWriteWord(RM, RN, DSP);
+#endif
}
static void dsp_opcode_store(void)
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ DSPWriteLong(RM & 0xFFFFFFFC, RN, DSP);
+#else
DSPWriteLong(RM, RN, DSP);
+#endif
}
static void dsp_opcode_loadb(void)
if (doDSPDis)
WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ RN = DSPReadLong(RM & 0xFFFFFFFE, DSP) & 0xFFFF;
+ else
+ RN = JaguarReadWord(RM & 0xFFFFFFFE, DSP);
+#else
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
RN = DSPReadLong(RM, DSP) & 0xFFFF;
else
RN = JaguarReadWord(RM, DSP);
+#endif
#ifdef DSP_DIS_LOADW
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
if (doDSPDis)
WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
if (doDSPDis)
WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD14I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD15I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
pcQueue1[pcQPtr1++] = dsp_pc;
pcQPtr1 &= 0x3FF;
+#ifdef DSP_DEBUG_PL2
if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
{
WriteLog("DSP: PC has stepped out of bounds...\n\nBacktrace:\n\n");
}
WriteLog("\n");
}//*/
+#endif
+
if (IMASKCleared) // If IMASK was cleared,
{
#ifdef DSP_DEBUG_IRQ
// Stage 2: Execute
if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
{
+#ifdef DSP_DEBUG_PL2
if (doDSPDis)
WriteLog("\t[inst=%02u][R28=%08X, alt R28=%08X, REGPAGE=%s]\n", pipeline[plPtrExec].opcode, dsp_reg[28], dsp_alternate_reg[28], (dsp_flags & REGPAGE ? "set" : "not set"));
-#ifdef DSP_DEBUG_PL2
+
if (doDSPDis)
{
WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
if (doDSPDis)
WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong(PRM & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ PRES = DSPReadLong(PRM & 0xFFFFFFFE, DSP) & 0xFFFF;
+ else
+ PRES = JaguarReadWord(PRM & 0xFFFFFFFE, DSP);
+#else
if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
else
PRES = JaguarReadWord(PRM, DSP);
+#endif
#ifdef DSP_DIS_LOADW
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD14I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRES);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[14] + PRM) & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD14R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[15] &0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD15I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[15] + PRM) & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD15R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
#endif
// DSPWriteLong(PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = PRM & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
// JaguarWriteWord(PRM, PRN, DSP);
//
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = PRM & 0xFFFFFFFE;
+#else
pipeline[plPtrExec].address = PRM;
+#endif
if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
{
#endif
// DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = (dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
{
// DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = (dsp_reg[14] + PRM) & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = dsp_reg[14] + PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
#endif
// DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = (dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
{
// DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT
+ pipeline[plPtrExec].address = (dsp_reg[15] + PRM) & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = dsp_reg[15] + PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
// Who When What
// --- ---------- -------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
+// JLH 11/26/2011 Added fixes for LOAD/STORE alignment issues
//
// Note: Endian wrongness probably stems from the MAME origins of this emu and
//#include "memory.h"
#include "tom.h"
+
+// Seems alignment in loads & stores was off...
+#define GPU_CORRECT_ALIGNMENT
//#define GPU_DEBUG
// For GPU dissasembly...
+#if 0
#define GPU_DIS_ABS
#define GPU_DIS_ADD
#define GPU_DIS_ADDC
bool doGPUDis = false;
//bool doGPUDis = true;
//*/
+#endif
+
/*
GPU opcodes use (BIOS flying ATARI logo):
+ add 357416
if (doGPUDis)
WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2));
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong((gpu_reg[14] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
+#else
GPUWriteLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
+#endif
}
static void gpu_opcode_store_r15_indexed(void)
if (doGPUDis)
WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", gpu_pc-2, IMM_2, gpu_convert_zero[IMM_1] << 2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2));
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong((gpu_reg[15] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
+#else
GPUWriteLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), RN, GPU);
+#endif
}
static void gpu_opcode_load_r14_ri(void)
if (doGPUDis)
WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM+gpu_reg[14], IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ RN = GPUReadLong((gpu_reg[14] + RM) & 0xFFFFFFFC, GPU);
+#else
RN = GPUReadLong(gpu_reg[14] + RM, GPU);
+#endif
#ifdef GPU_DIS_LOAD14R
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
if (doGPUDis)
WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM+gpu_reg[15], IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ RN = GPUReadLong((gpu_reg[15] + RM) & 0xFFFFFFFC, GPU);
+#else
RN = GPUReadLong(gpu_reg[15] + RM, GPU);
+#endif
#ifdef GPU_DIS_LOAD15R
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
if (doGPUDis)
WriteLog("%06X: STORE R%02u, (R14+R%02u) [NCZ:%u%u%u, R%02u=%08X, R14+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[14]);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong((gpu_reg[14] + RM) & 0xFFFFFFFC, RN, GPU);
+#else
GPUWriteLong(gpu_reg[14] + RM, RN, GPU);
+#endif
}
static void gpu_opcode_store_r15_ri(void)
if (doGPUDis)
WriteLog("%06X: STORE R%02u, (R15+R%02u) [NCZ:%u%u%u, R%02u=%08X, R15+R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM+gpu_reg[15]);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong((gpu_reg[15] + RM) & 0xFFFFFFFC, RN, GPU);
+#else
GPUWriteLong(gpu_reg[15] + RM, RN, GPU);
+#endif
}
static void gpu_opcode_nop(void)
if (doGPUDis)
WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
+ GPUWriteLong(RM & 0xFFFFFFFE, RN & 0xFFFF, GPU);
+ else
+ JaguarWriteWord(RM & 0xFFFFFFFE, RN, GPU);
+#else
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
GPUWriteLong(RM, RN & 0xFFFF, GPU);
else
JaguarWriteWord(RM, RN, GPU);
+#endif
}
static void gpu_opcode_store(void)
if (doGPUDis)
WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", gpu_pc-2, IMM_2, IMM_1, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong(RM & 0xFFFFFFFC, RN, GPU);
+#else
GPUWriteLong(RM, RN, GPU);
+#endif
}
static void gpu_opcode_storep(void)
{
+#ifdef GPU_CORRECT_ALIGNMENT
+ GPUWriteLong((RM & 0xFFFFFFF8) + 0, gpu_hidata, GPU);
+ GPUWriteLong((RM & 0xFFFFFFF8) + 4, RN, GPU);
+#else
GPUWriteLong(RM + 0, gpu_hidata, GPU);
GPUWriteLong(RM + 4, RN, GPU);
+#endif
}
static void gpu_opcode_loadb(void)
if (doGPUDis)
WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
+ RN = GPUReadLong(RM & 0xFFFFFFFE, GPU) & 0xFFFF;
+ else
+ RN = JaguarReadWord(RM & 0xFFFFFFFE, GPU);
+#else
if ((RM >= 0xF03000) && (RM <= 0xF03FFF))
RN = GPUReadLong(RM, GPU) & 0xFFFF;
else
RN = JaguarReadWord(RM, GPU);
+#endif
#ifdef GPU_DIS_LOADW
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
#endif
}
+// According to the docs, & "Do The Same", this address is long aligned...
+// So let's try it:
+// And it works!!! Need to fix all instances...
static void gpu_opcode_load(void)
{
#ifdef GPU_DIS_LOAD
if (doGPUDis)
WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", gpu_pc-2, IMM_1, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ RN = GPUReadLong(RM & 0xFFFFFFFC, GPU);
+#else
RN = GPUReadLong(RM, GPU);
+#endif
#ifdef GPU_DIS_LOAD
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
static void gpu_opcode_loadp(void)
{
+#ifdef GPU_CORRECT_ALIGNMENT
+ gpu_hidata = GPUReadLong((RM & 0xFFFFFFF8) + 0, GPU);
+ RN = GPUReadLong((RM & 0xFFFFFFF8) + 4, GPU);
+#else
gpu_hidata = GPUReadLong(RM + 0, GPU);
RN = GPUReadLong(RM + 4, GPU);
+#endif
}
static void gpu_opcode_load_r14_indexed(void)
if (doGPUDis)
WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[14]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ RN = GPUReadLong((gpu_reg[14] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), GPU);
+#else
RN = GPUReadLong(gpu_reg[14] + (gpu_convert_zero[IMM_1] << 2), GPU);
+#endif
#ifdef GPU_DIS_LOAD14I
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
if (doGPUDis)
WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", gpu_pc-2, gpu_convert_zero[IMM_1] << 2, IMM_2, gpu_flag_n, gpu_flag_c, gpu_flag_z, gpu_convert_zero[IMM_1] << 2, gpu_reg[15]+(gpu_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef GPU_CORRECT_ALIGNMENT
+ RN = GPUReadLong((gpu_reg[15] & 0xFFFFFFFC) + (gpu_convert_zero[IMM_1] << 2), GPU);
+#else
RN = GPUReadLong(gpu_reg[15] + (gpu_convert_zero[IMM_1] << 2), GPU);
+#endif
#ifdef GPU_DIS_LOAD15I
if (doGPUDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", gpu_flag_n, gpu_flag_c, gpu_flag_z, IMM_2, RN);
}
//New timer based code stuffola...
-void ScanlineCallback(void);
+void HalflineCallback(void);
void RenderCallback(void);
void JaguarReset(void)
{
// New timer base code stuffola...
InitializeEventList();
// SetCallbackTime(ScanlineCallback, 63.5555);
- SetCallbackTime(ScanlineCallback, 31.77775);
-// SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
-// SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time
+// SetCallbackTime(ScanlineCallback, 31.77775);
+ SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
}
void JaguarDone(void)
//if (start_logging)
// WriteLog("About to execute OP (%u)...\n", i);
- TOMExecScanline(i, render);
+ TOMExecHalfline(i, render);
}
}
while (!frameDone);
}
-/*
-BIG NOTE: NEED TO FIX THIS TO RUN ON ABSOLUTE TIMINGS BASED ON SCANLINES,
- *NOT* ON THE VERTICAL PERIOD!!!
-
-<Zerosquare> scanlines are 64 µs in PAL
-<Zerosquare> and 63.5555... µs in NTSC
-
-Also: 625 lines per frame in PAL, 525 in NTSC
-
-So... can use
-#define RISC_CYCLE_IN_USEC 0.03760684198
-#define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2)
-
-#define HORIZ_PERIOD_IN_USEC_NTSC 63.555555555
-#define HORIZ_PERIOD_IN_USEC_PAL 64.0
-
-#define USEC_TO_RISC_CYCLES(u) (uint32)(((u) / RISC_CYCLE_IN_USEC) + 0.5)
-#define USEC_TO_M68K_CYCLES(u) (uint32)(((u) / M68K_CYCLE_IN_USEC) + 0.5)
-
-to figure cycles per half-line...
-
-USEC_TO_RISC_CYCLES(HORIZ_PERIOD_IN_USEC_NTSC) / 2
-USEC_TO_M68K_CYCLES(HORIZ_PERIOD_IN_USEC_NTSC) / 2
-USEC_TO_RISC_CYCLES(HORIZ_PERIOD_IN_USEC_PAL) / 2
-USEC_TO_M68K_CYCLES(HORIZ_PERIOD_IN_USEC_PAL) / 2
-
-// Full lines here, divide by two for half-lines...
-which gives the following: 1690, 845 (NTSC), 1702, 851 (PAL)
-So, for a full frame, that would yield:
-887250 (NTSC), 1063750 (PAL)
-one second:
-26617500 (NTSC), 26593750 (PAL)
-
-Which is off a little bit for NTSC...
-#define M68K_CLOCK_RATE_PAL 13296950
-#define M68K_CLOCK_RATE_NTSC 13295453
-#define RISC_CLOCK_RATE_PAL 26593900
-#define RISC_CLOCK_RATE_NTSC 26590906
-
-*/
-
#define USE_CORRECT_PAL_TIMINGS
-void ScanlineCallback(void)
+// A lot of confusion comes from here...
+// The thing to keep in mind is that the VC is advanced every HALF line, regardless
+// of whether the display is interlaced or not. The only difference with an
+// interlaced display is that the high bit of VC will be set when the lower
+// field is being rendered.
+//
+// Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
+// rendering two fields that are slighty vertically offset from each other.
+// Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
+// is rendered in this mode so that each field, when overlaid on each other,
+// will yield the final picture at the full resolution for the full frame.
+//
+// We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
+// Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
+// it will be half this number for a half frame. BUT, since we're counting
+// HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
+//
+// Scanline times are 63.5555... µs in NTSC and 64 µs in PAL
+// Half line times are, naturally, half of this. :-P
+void HalflineCallback(void)
{
//OK, this is hardwired to run in NTSC, and for who knows how long.
//Need to fix this so that it does a half-line in the correct amount of time
m68k_set_irq(2);
}
- TOMExecScanline(vc, true);
+ TOMExecHalfline(vc, true);
//Change this to VBB???
//Doesn't seem to matter (at least for Flip Out & I-War)
}//*/
#ifdef USE_CORRECT_PAL_TIMINGS
- SetCallbackTime(ScanlineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
+ SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
#else
-// SetCallbackTime(ScanlineCallback, 63.5555);
- SetCallbackTime(ScanlineCallback, 31.77775);
+// SetCallbackTime(HalflineCallback, 63.5555);
+ SetCallbackTime(HalflineCallback, 31.77775);
#endif
}
void OPDone(void)
{
+#warning "!!! Fix OL dump so that it follows links !!!"
const char * opType[8] =
{ "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", "(STOP)", "???", "???", "???" };
const char * ccType[8] =
// Object Processor main routine
//
#warning "Need to fix this so that when an GPU object IRQ happens, we can pick up OP processing where we left off. !!! FIX !!!"
-void OPProcessList(int scanline, bool render)
+void OPProcessList(int halfline, bool render)
{
extern int op_start_log;
// char * condition_to_str[8] =
// objectp_stop_reading_list = false;
-//WriteLog("OP: Processing line #%u (OLP=%08X)...\n", scanline, op_pointer);
+//WriteLog("OP: Processing line #%u (OLP=%08X)...\n", halfline, op_pointer);
//op_done();
// *** BEGIN OP PROCESSOR TESTING ONLY ***
uint32 opCyclesToRun = 30000; // This is a pulled-out-of-the-air value (will need to be fixed, obviously!)
-// if (op_pointer) WriteLog(" new op list at 0x%.8x scanline %i\n",op_pointer,scanline);
+// if (op_pointer) WriteLog(" new op list at 0x%.8x halfline %i\n",op_pointer,halfline);
while (op_pointer)
{
// *** BEGIN OP PROCESSOR TESTING ONLY ***
// return;
uint64 p0 = OPLoadPhrase(op_pointer);
-//WriteLog("\t%08X type %i\n", op_pointer, (uint8)p0 & 0x07);
op_pointer += 8;
+//WriteLog("\t%08X type %i\n", op_pointer, (uint8)p0 & 0x07);
#if 1
-if (scanline == TOMGetVDB() && op_start_log)
-//if (scanline == 215 && op_start_log)
-//if (scanline == 28 && op_start_log)
-//if (scanline == 0)
+if (halfline == TOMGetVDB() && op_start_log)
+//if (halfline == 215 && op_start_log)
+//if (halfline == 28 && op_start_log)
+//if (halfline == 0)
{
WriteLog("%08X --> phrase %08X %08X", op_pointer - 8, (int)(p0>>32), (int)(p0&0xFFFFFFFF));
if ((p0 & 0x07) == OBJECT_TYPE_BITMAP)
bitmapCounter++;
if (!inhibit) // For OP testing only!
// *** END OP PROCESSOR TESTING ONLY ***
- if (scanline >= ypos && height > 0)
+ if (halfline >= ypos && height > 0)
{
uint64 p1 = OPLoadPhrase(op_pointer);
op_pointer += 8;
-//WriteLog("OP: Writing scanline %d with ypos == %d...\n", scanline, ypos);
+//WriteLog("OP: Writing halfline %d with ypos == %d...\n", halfline, ypos);
//WriteLog("--> Writing %u BPP bitmap...\n", op_bitmap_bit_depth[(p1 >> 12) & 0x07]);
-// OPProcessFixedBitmap(scanline, p0, p1, render);
+// OPProcessFixedBitmap(halfline, p0, p1, render);
OPProcessFixedBitmap(p0, p1, render);
// OP write-backs
// *** BEGIN OP PROCESSOR TESTING ONLY ***
if (inhibit && op_start_log)
{
- WriteLog("!!! ^^^ This object is INHIBITED! ^^^ !!! (scanline=%u, ypos=%u, height=%u)\n", scanline, ypos, height);
+ WriteLog("!!! ^^^ This object is INHIBITED! ^^^ !!! (halfline=%u, ypos=%u, height=%u)\n", halfline, ypos, height);
DumpScaledObject(p0, OPLoadPhrase(op_pointer), OPLoadPhrase(op_pointer+8));
}
bitmapCounter++;
if (!inhibit) // For OP testing only!
// *** END OP PROCESSOR TESTING ONLY ***
- if (scanline >= ypos && height > 0)
+ if (halfline >= ypos && height > 0)
{
uint64 p1 = OPLoadPhrase(op_pointer);
op_pointer += 8;
uint64 p2 = OPLoadPhrase(op_pointer);
op_pointer += 8;
-//WriteLog("OP: %08X (%d) %08X%08X %08X%08X %08X%08X\n", oldOPP, scanline, (uint32)(p0>>32), (uint32)(p0&0xFFFFFFFF), (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF), (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF));
+//WriteLog("OP: %08X (%d) %08X%08X %08X%08X %08X%08X\n", oldOPP, halfline, (uint32)(p0>>32), (uint32)(p0&0xFFFFFFFF), (uint32)(p1>>32), (uint32)(p1&0xFFFFFFFF), (uint32)(p2>>32), (uint32)(p2&0xFFFFFFFF));
OPProcessScaledBitmap(p0, p1, p2, render);
// OP write-backs
//Here's another problem:
// [hsc: 20, vsc: 20, rem: 00]
// Since we're not checking for $E0 (but that's what we get from the above), we end
-// up repeating this scanline unnecessarily... !!! FIX !!! [DONE, but... still not quite
+// up repeating this halfline unnecessarily... !!! FIX !!! [DONE, but... still not quite
// right. Either that, or the Accolade team that wrote Bubsy screwed up royal.]
//Also note: $E0 = 7.0 which IS a legal vscale value...
//Do something like:
//OPSuspendedByGPU = true;
//Dunno if the OP keeps processing from where it was interrupted, or if it just continues
-//on the next scanline...
+//on the next halfline...
// --> It continues from where it was interrupted! !!! FIX !!!
break;
}
uint32 link = (p0 >> 21) & 0x3FFFF8;
// if ((ypos!=507)&&(ypos!=25))
-// WriteLog("\t%i%s%i link=0x%.8x\n",scanline,condition_to_str[cc],ypos>>1,link);
+// WriteLog("\t%i%s%i link=0x%.8x\n",halfline,condition_to_str[cc],ypos>>1,link);
switch (cc)
{
case CONDITION_EQUAL:
exit(0);
break;
default:
+ // Basically, if you do this, the OP does nothing. :-)
WriteLog("OP: Unimplemented branch condition %i\n", cc);
}
break;
// and bail out/reenter to properly simulate an overloaded OP... !!! FIX !!!
#warning "Better would be to count how many actual cycles it used and bail out/reenter to properly simulate an overloaded OP... !!! FIX !!!"
opCyclesToRun--;
+
if (!opCyclesToRun)
return;
}
//
// Process a single scanline
+// (this is bad terminology; each tick of the VC is actually a half-line)
//
-void TOMExecScanline(uint16 scanline, bool render)
+void TOMExecHalfline(uint16 halfline, bool render)
{
bool inActiveDisplayArea = true;
//Interlacing is still not handled correctly here... !!! FIX !!!
- if (scanline & 0x01) // Execute OP only on even lines (non-interlaced only!)
+ if (halfline & 0x01) // Execute OP only on even lines (non-interlaced only!)
return;
//Hm, it seems that the OP needs to execute from zero, so let's try it:
*/
#if 1
// 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
-// if (scanline >= ((uint16)GET16(tomRam8, VDB) / 2) && scanline < ((uint16)GET16(tomRam8, VDE) / 2))
- if (scanline >= (uint16)GET16(tomRam8, VDB) && scanline < (uint16)GET16(tomRam8, VDE))
-// if (scanline >= ((uint16)GET16(tomRam8, VDB) - 16) && scanline < (uint16)GET16(tomRam8, VDE))
-// if (scanline >= 20 && scanline < (uint16)GET16(tomRam8, VDE))
+// if (halfline >= ((uint16)GET16(tomRam8, VDB) / 2) && halfline < ((uint16)GET16(tomRam8, VDE) / 2))
+ if (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE))
+// if (halfline >= ((uint16)GET16(tomRam8, VDB) - 16) && halfline < (uint16)GET16(tomRam8, VDE))
+// if (halfline >= 20 && halfline < (uint16)GET16(tomRam8, VDE))
{
if (render)
{
for(uint32 i=0; i<720; i++)
*current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
- OPProcessList(scanline, render);
+ OPProcessList(halfline, render);
}
}
else
inActiveDisplayArea = false;
#else
inActiveDisplayArea =
- (scanline >= (uint16)GET16(tomRam8, VDB) && scanline < (uint16)GET16(tomRam8, VDE)
+ (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE)
? true : false);
- if (scanline < (uint16)GET16(tomRam8, VDE))
+ if (halfline < (uint16)GET16(tomRam8, VDE))
{
if (render)//With JaguarExecuteNew() this is always true...
{
for(uint32 i=0; i<720; i++)
*current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
-// OPProcessList(scanline, render);
+// OPProcessList(halfline, render);
//This seems to take care of it...
- OPProcessList(scanline, inActiveDisplayArea);
+ OPProcessList(halfline, inActiveDisplayArea);
}
}
#endif
uint16 topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
- uint32 * TOMCurrentLine = &(screenBuffer[((scanline - topVisible) / 2) * screenPitch]);
+ uint32 * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
// Here's our virtualized scanline code...
- if (scanline >= topVisible && scanline < bottomVisible)
+ if (halfline >= topVisible && halfline < bottomVisible)
{
if (inActiveDisplayArea)
{
#ifndef __TOM_H__
#define __TOM_H__
-//#include "jaguar.h"
-//#include "types.h"
#include "memory.h"
#define VIDEO_MODE_16BPP_CRY 0
void TOMWriteByte(uint32 offset, uint8 data, uint32 who = UNKNOWN);
void TOMWriteWord(uint32 offset, uint16 data, uint32 who = UNKNOWN);
-void TOMExecScanline(uint16 scanline, bool render);
+void TOMExecHalfline(uint16 halfline, bool render);
uint32 TOMGetVideoModeWidth(void);
uint32 TOMGetVideoModeHeight(void);
uint8 TOMGetVideoMode(void);
uint8 * TOMGetRamPointer(void);
uint16 TOMGetHDB(void);
uint16 TOMGetVDB(void);
-//uint16 tom_get_scanline(void);
-//uint32 tom_getHBlankWidthInPixels(void);
int TOMIRQEnabled(int irq);
uint16 TOMIRQControlReg(void);