uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
bool jaguarCartInserted = false;
+bool lowerField = false;
#ifdef CPU_DEBUG_MEMORY
uint8 writeMemMax[0x400000], writeMemMin[0x400000];
}
#endif
+void ShowM68KContext(void)
+{
+ printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
+
+ for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
+ {
+ printf("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
+
+ if (i == M68K_REG_D3 || i == M68K_REG_D7)
+ printf("\n");
+ }
+
+ for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
+ {
+ printf("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
+
+ if (i == M68K_REG_A3 || i == M68K_REG_A7)
+ printf("\n");
+ }
+
+ uint32_t currpc = m68k_get_reg(NULL, M68K_REG_PC);
+ uint32_t disPC = currpc - 30;
+ char buffer[128];
+
+ do
+ {
+ uint32_t oldpc = disPC;
+ disPC += m68k_disassemble(buffer, disPC, 0);
+ printf("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
+ }
+ while (disPC < (currpc + 10));
+}
+
//
// Musashi 68000 read/write/IRQ functions
//
unsigned int m68k_read_memory_8(unsigned int address)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
#ifdef CPU_DEBUG_MEMORY
if ((address >= 0x000000) && (address <= 0x3FFFFF))
{
unsigned int m68k_read_memory_16(unsigned int address)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
#ifdef CPU_DEBUG_MEMORY
/* if ((address >= 0x000000) && (address <= 0x3FFFFE))
{
unsigned int m68k_read_memory_32(unsigned int address)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
//; So, it seems that it stores the returned DWORD at $51136 and $FB074.
/* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
WriteLog("[RM32 PC=%08X] Addr: %08X, val: %08X\n", m68k_get_reg(NULL, M68K_REG_PC), address, (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2));//*/
void m68k_write_memory_8(unsigned int address, unsigned int value)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
#ifdef CPU_DEBUG_MEMORY
if ((address >= 0x000000) && (address <= 0x3FFFFF))
{
//$53D0
/*if (address >= 0x53D0 && address <= 0x53FF)
printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
+//Testing AvP on UAE core...
+//000075A0: FFFFF80E B6320220 (BITMAP)
+/*if (address == 0x75A0 && value == 0xFF)
+ printf("M68K: (8) Tripwire hit...\n");//*/
#ifndef USE_NEW_MMU
if ((address >= 0x000000) && (address <= 0x3FFFFF))
void m68k_write_memory_16(unsigned int address, unsigned int value)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
#ifdef CPU_DEBUG_MEMORY
if ((address >= 0x000000) && (address <= 0x3FFFFE))
{
//$53D0
/*if (address >= 0x53D0 && address <= 0x53FF)
printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
+//Testing AvP on UAE core...
+//000075A0: FFFFF80E B6320220 (BITMAP)
+/*if (address == 0x75A0 && value == 0xFFFF)
+{
+ printf("\nM68K: (16) Tripwire hit...\n");
+ ShowM68KContext();
+}//*/
#ifndef USE_NEW_MMU
if ((address >= 0x000000) && (address <= 0x3FFFFE))
void m68k_write_memory_32(unsigned int address, unsigned int value)
{
+ // Musashi does this automagically for you, UAE core does not :-P
+ address &= 0x00FFFFFF;
/*if (address == 0x4E00)
WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
//WriteLog("--> [WM32]\n");
doGPUDis = true;//*/
/* if (address == 0x51136 || address == 0xFB074)
WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
+//Testing AvP on UAE core...
+//000075A0: FFFFF80E B6320220 (BITMAP)
+/*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
+{
+ printf("\nM68K: (32) Tripwire hit...\n");
+ ShowM68KContext();
+}//*/
#ifndef USE_NEW_MMU
m68k_write_memory_16(address, value >> 16);
void M68K_show_context(void)
{
- WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
+ WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
+
for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
- WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
- WriteLog("\n");
+ {
+ WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
+
+ if (i == M68K_REG_D3 || i == M68K_REG_D7)
+ WriteLog("\n");
+ }
+
for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
- WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
+ {
+ WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
+
+ if (i == M68K_REG_A3 || i == M68K_REG_A7)
+ WriteLog("\n");
+ }
WriteLog("68K disasm\n");
// jaguar_dasm(s68000readPC()-0x1000,0x20000);
//Seems to want $01010101... Dunno why. Investigate!
memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
// memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
+ lowerField = false; // Reset the lower field flag
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
+ m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
GPUInit();
DSPInit();
TOMInit();
}
//New timer based code stuffola...
-void ScanlineCallback(void);
+void HalflineCallback(void);
void RenderCallback(void);
void JaguarReset(void)
{
m68k_pulse_reset(); // Reset the 68000
WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
+ lowerField = false; // Reset the lower field flag
// 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)
/* WriteLog("\n\nM68000 disassembly at $4000...\n");
JaguarDasm(0x4000, 10000);
WriteLog("\n");//*/
+// WriteLog("\n\nM68000 disassembly at $802000...\n");
+// JaguarDasm(0x800830, 0x1000);
}
//
//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. (NB: The high bit of VC is ALWAYS set on the lower field,
+// regardless of whether it's in interlace mode or not.
+// NB2: Seems it doens't always, not sure what the constraint is...)
+//
+// 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
// So we cut the number of half-lines in a frame in half. :-P
uint16 numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
- if (vc >= numHalfLines)
+ if ((vc & 0x7FF) >= numHalfLines)
#else
- if (vc >= vp)
+ if ((vc & 0x7FF) >= vp)
#endif
+ {
vc = 0;
+// lowerField = !lowerField;
+
+ // If we're rendering the lower field, set the high bit (#12, counting
+ // from 1) of VC
+ if (lowerField)
+ vc = 0x0800;
+ }
//WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
TOMWriteWord(0xF00006, vc, JAGUAR);
//This is a crappy kludge, but maybe it'll work for now...
//Maybe it's not so bad, since the IRQ happens on a scanline boundary...
- if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
+ if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
{
// We don't have to worry about autovectors & whatnot because the Jaguar
// tells you through its HW registers who sent the interrupt...
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)
- if (vc == 0)
+ if ((vc & 0x7FF) == 0)
// if (vc == vbb)
{
JoystickExec();
}//*/
#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
}