4 // Originally by David Raingeard (Cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Carwin Jones (BeOS)
6 // Cleanups and endian wrongness amelioration by James L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 // the braindead way in which MAME handles memory. :-)
10 // JLH = James L. Hammons
13 // --- ---------- -----------------------------------------------------------
14 // JLH 11/25/2009 Major rewrite of memory subsystem and handlers
20 #include "SDL_opengl.h"
40 //Do this in makefile??? Yes! Could, but it's easier to define here...
41 //#define LOG_UNMAPPED_MEMORY_ACCESSES
42 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
43 #define ABORT_ON_ILLEGAL_INSTRUCTIONS
44 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
45 #define CPU_DEBUG_MEMORY
47 // Private function prototypes
49 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
50 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
51 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
52 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
53 void M68K_show_context(void);
57 #ifdef CPU_DEBUG_MEMORY
58 extern bool startMemLog; // Set by "e" key
59 extern int effect_start;
60 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
63 // Memory debugging identifiers
65 const char * whoName[9] =
66 { "Unknown", "Jaguar", "DSP", "GPU", "TOM", "JERRY", "M68K", "Blitter", "OP" };
68 uint32 jaguar_active_memory_dumps = 0;
70 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
72 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
73 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
74 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
75 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
76 bool BIOSLoaded = false;
77 bool CDBIOSLoaded = false;
80 uint8 * cdRAM = &jaguarMainROM[0x5FFF00];
82 uint8 jerryRAM[0x10000];
84 #ifdef CPU_DEBUG_MEMORY
85 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
86 uint8 readMem[0x400000];
87 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
90 uint32 pcQueue[0x400];
94 // Callback function to detect illegal instructions
96 void GPUDumpDisassembly(void);
97 void GPUDumpRegisters(void);
98 static bool start = false;
100 void M68KInstructionHook(void)
102 uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
105 // Ideally, we'd save all the registers as well...
106 pcQueue[pcQPtr++] = m68kPC;
109 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
111 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
113 static char buffer[2048];
114 for(int i=0; i<0x400; i++)
116 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
117 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
121 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
122 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
123 for(int i=0; i<10; i++)
124 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
125 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
131 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
133 static char buffer[2048];
134 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
135 WriteLog("%08X: %s", m68kPC, buffer);
136 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
137 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
138 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
140 /* if (m68kPC == 0x8D0E48 && effect_start5)
142 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
144 GPUDumpDisassembly();
148 /* uint16 opcode = JaguarReadWord(m68kPC);
149 if (opcode == 0x4E75) // RTS
152 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
154 uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
156 if (raPtr != 0xFFFFFFFF)
158 for(uint32 i=0; i<=raPtr; i++)
160 if (returnAddr[i] == addr)
169 returnAddr[++raPtr] = addr;
173 //Flip Out! debugging...
176 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
177 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
178 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
179 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
181 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
183 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
184 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
185 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
186 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
187 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
188 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
189 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
191 /* static char buffer[2048];
192 //if (m68kPC > 0x805F48) start = true;
193 //if (m68kPC > 0x806486) start = true;
194 //if (m68kPC == 0x805FEE) start = true;
195 //if (m68kPC == 0x80600C)// start = true;
196 if (m68kPC == 0x802058) start = true;
198 // GPUDumpRegisters();
199 // GPUDumpDisassembly();
201 // M68K_show_context();
207 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
208 WriteLog("%08X: %s \t\tD0=%08X, A0=%08X, D1=%08X, A1=%08X\n", m68kPC, buffer, m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_A1));
211 /* if (m68kPC == 0x803F16)
213 WriteLog("M68K: Registers found at $803F16:\n");
214 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
215 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
216 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
218 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
219 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
221 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
222 // !!! Investigate !!!
223 /*extern bool doDSPDis;
224 static bool disgo = false;
225 if (m68kPC == 0x50222)
228 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
229 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
232 if (m68kPC == 0x5000)
237 static char buffer[2048];
238 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
239 WriteLog("%08X: %s", m68kPC, buffer);
240 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
241 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
242 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
244 if (m68kPC == 0x82E1A)
246 static char buffer[2048];
247 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
248 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
249 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
250 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
251 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
253 if (m68kPC == 0x82E58)
254 WriteLog("--> [Routine end]\n");
255 if (m68kPC == 0x80004)
257 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
258 // m68k_set_reg(M68K_REG_D2, 0x12345678);
282 if (m68kPC == 0x3000)
283 WriteLog("M68K: CD_init\n");
284 else if (m68kPC == 0x3006 + (6 * 0))
285 WriteLog("M68K: CD_mode\n");
286 else if (m68kPC == 0x3006 + (6 * 1))
287 WriteLog("M68K: CD_ack\n");
288 else if (m68kPC == 0x3006 + (6 * 2))
289 WriteLog("M68K: CD_jeri\n");
290 else if (m68kPC == 0x3006 + (6 * 3))
291 WriteLog("M68K: CD_spin\n");
292 else if (m68kPC == 0x3006 + (6 * 4))
293 WriteLog("M68K: CD_stop\n");
294 else if (m68kPC == 0x3006 + (6 * 5))
295 WriteLog("M68K: CD_mute\n");
296 else if (m68kPC == 0x3006 + (6 * 6))
297 WriteLog("M68K: CD_umute\n");
298 else if (m68kPC == 0x3006 + (6 * 7))
299 WriteLog("M68K: CD_paus\n");
300 else if (m68kPC == 0x3006 + (6 * 8))
301 WriteLog("M68K: CD_upaus\n");
302 else if (m68kPC == 0x3006 + (6 * 9))
303 WriteLog("M68K: CD_read\n");
304 else if (m68kPC == 0x3006 + (6 * 10))
305 WriteLog("M68K: CD_uread\n");
306 else if (m68kPC == 0x3006 + (6 * 11))
307 WriteLog("M68K: CD_setup\n");
308 else if (m68kPC == 0x3006 + (6 * 12))
309 WriteLog("M68K: CD_ptr\n");
310 else if (m68kPC == 0x3006 + (6 * 13))
311 WriteLog("M68K: CD_osamp\n");
312 else if (m68kPC == 0x3006 + (6 * 14))
313 WriteLog("M68K: CD_getoc\n");
314 else if (m68kPC == 0x3006 + (6 * 15))
315 WriteLog("M68K: CD_initm\n");
316 else if (m68kPC == 0x3006 + (6 * 16))
317 WriteLog("M68K: CD_initf\n");
318 else if (m68kPC == 0x3006 + (6 * 17))
319 WriteLog("M68K: CD_switch\n");
321 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
322 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
323 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
324 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
326 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
327 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
329 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
330 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
332 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
333 // keep going even when the 68K dumped back to the debugger or what have you).
335 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
336 // Try setting the vector to the illegal instruction...
337 //This doesn't work right either! Do something else! Quick!
338 // SET32(jaguar_mainRam, 0x10, m68kPC);
344 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
345 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
346 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
347 for(int i=0; i<10; i++)
348 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
349 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
353 // WriteLog("\n\n68K disasm\n\n");
354 // jaguar_dasm(0x802000, 0x50C);
365 Now here be dragons...
366 Here is how memory ranges are defined in the CoJag driver.
367 Note that we only have to be concerned with 3 entities read/writing anything:
368 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
369 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
370 things that are entirely internal to those modules. This way we should be able to get a handle on all
371 this crap which is currently scattered over Hell's Half Acre(tm).
373 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
374 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
376 /*************************************
378 * Main CPU memory handlers
380 *************************************/
382 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
383 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
384 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
385 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
386 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
387 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
388 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
389 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
390 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
391 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
392 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
393 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
394 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
395 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
396 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
397 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
398 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
399 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
400 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
401 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
402 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
403 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
404 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
407 /*************************************
409 * GPU memory handlers
411 *************************************/
413 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
414 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
415 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
416 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
417 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
418 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
419 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
420 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
421 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
422 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
423 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
426 /*************************************
428 * DSP memory handlers
430 *************************************/
432 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
433 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
434 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
435 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
436 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
437 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
438 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
439 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
440 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
445 //#define EXPERIMENTAL_MEMORY_HANDLING
446 // Experimental memory mappage...
447 // Dunno if this is a good approach or not, but it seems to make better
448 // sense to have all this crap in one spot intstead of scattered all over
449 // the place the way it is now.
450 #ifdef EXPERIMENTAL_MEMORY_HANDLING
452 #define NEW_TIMER_SYSTEM
455 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
456 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
457 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
458 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
459 bool BIOSLoaded = false;
460 bool CDBIOSLoaded = false;
463 uint8 tomRAM[0x4000];
464 uint8 jerryRAM[0x10000];
465 static uint16 eeprom_ram[64];
467 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
470 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
472 // M68K Memory map/handlers
474 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
475 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
476 // Note that this is really memory mapped I/O region...
477 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
478 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
479 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
480 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
481 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
482 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
483 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
484 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
485 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
486 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
487 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
488 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
490 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
492 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
493 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
494 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
495 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
496 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
497 //What about LBUF writes???
498 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
499 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
500 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
502 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
506 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
507 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
508 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
511 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
512 0 = pad0/1 button values (4 bits each), RO(?)
513 1 = pad0/1 index value (4 bits each), WO
515 3 = NTSC/PAL, certain button states, RO
517 JOYSTICK $F14000 Read/Write
519 Read fedcba98 7654321q f-1 Signals J15 to J1
520 q Cartridge EEPROM output data
521 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
522 0 = disable J7-J0 outputs
525 0 = Audio muted (reset state)
527 7-4 J7-J4 outputs (port 2)
528 3-0 J3-J0 outputs (port 1)
529 JOYBUTS $F14002 Read Only
531 Read xxxxxxxx rrdv3210 x don't care
534 v 1 = NTSC Video hardware
535 0 = PAL Video hardware
536 3-2 Button inputs B3 & B2 (port 2)
537 1-0 Button inputs B1 & B0 (port 1)
539 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
540 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
548 0 1 1 1 Row 3 C3 Option # 9 6 3
552 1 0 1 1 Row 2 C2 C 0 8 5 2
554 1 1 0 1 Row 1 C1 B * 7 4 1
555 1 1 1 0 Row 0 Pause A Up Down Left Right
558 0 bit read in any position means that button is pressed.
559 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
563 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
565 // Not sure, but I think the system only has 24 address bits...
566 address &= 0x00FFFFFF;
568 // RAM ($000000 - $3FFFFF) 4M
569 if (address <= 0x3FFFFF)
570 jaguarMainRAM[address] = byte;
571 // hole ($400000 - $7FFFFF) 4M
572 else if (address <= 0x7FFFFF)
574 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
575 else if (address <= 0xDFFEFF)
577 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
578 else if (address <= 0xDFFFFF)
580 cdRAM[address & 0xFF] = byte;
582 if ((address & 0xFF) < 12 * 4)
583 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
584 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
587 // BIOS ROM ($E00000 - $E3FFFF) 256K
588 else if (address <= 0xE3FFFF)
590 // hole ($E40000 - $EFFFFF) 768K
591 else if (address <= 0xEFFFFF)
593 // TOM ($F00000 - $F0FFFF) 64K
594 else if (address <= 0xF0FFFF)
597 if (address == 0xF00050)
599 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
603 else if (address == 0xF00051)
605 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
609 else if (address == 0xF00052)
611 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
615 else if (address == 0xF00053)
617 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
621 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
623 // Writing to one CLUT writes to the other
624 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
625 tomRAM[address] = tomRAM[address + 0x200] = byte;
628 //What about LBUF writes???
629 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
631 GPUWriteByte(address, byte, who);
634 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
636 BlitterWriteByte(address, byte, who);
639 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
641 GPUWriteByte(address, byte, who);
645 tomRAM[address & 0x3FFF] = byte;
647 // JERRY ($F10000 - $F1FFFF) 64K
648 else if (address <= 0xF1FFFF)
652 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
654 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
656 DSPWriteByte(address, byte, who);
659 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
661 DSPWriteByte(address, byte, who);
664 // SCLK ($F1A150--8 bits wide)
665 //NOTE: This should be taken care of in DAC...
666 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
668 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
669 if ((address & 0x03) == 2)
670 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
672 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
674 JERRYI2SInterruptTimer = -1;
675 #ifndef NEW_TIMER_SYSTEM
678 RemoveCallback(JERRYI2SCallback);
683 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
684 else if (address >= 0xF1A148 && address <= 0xF1A157)
686 DACWriteByte(address, byte, who);
689 else if (address >= 0xF10000 && address <= 0xF10007)
691 #ifndef NEW_TIMER_SYSTEM
692 switch (address & 0x07)
695 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
699 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
703 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
707 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
711 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
715 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
719 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
723 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
727 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
731 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
733 clock_byte_write(offset, byte);
736 // JERRY -> 68K interrupt enables/latches (need to be handled!)
737 else if (address >= 0xF10020 && address <= 0xF10023)
739 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
741 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
743 anajoy_byte_write(offset, byte);
746 else if ((address >= 0xF14000) && (address <= 0xF14003))
748 JoystickWriteByte(address, byte);
749 EepromWriteByte(address, byte);
752 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
754 EepromWriteByte(address, byte);
757 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
758 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
761 jerryRAM[address & 0xFFFF] = byte;
763 // hole ($F20000 - $FFFFFF) 1M - 128K
768 void WriteWord(uint32 adddress, uint16 word)
772 void WriteDWord(uint32 adddress, uint32 dword)
776 uint8 ReadByte(uint32 adddress)
780 uint16 ReadWord(uint32 adddress)
784 uint32 ReadDWord(uint32 adddress)
790 // Musashi 68000 read/write/IRQ functions
793 int irq_ack_handler(int level)
795 int vector = M68K_INT_ACK_AUTOVECTOR;
797 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
801 m68k_set_irq(0); // Clear the IRQ...
802 vector = 64; // Set user interrupt #0
810 unsigned int m68k_read_memory_8(unsigned int address)
812 #ifdef CPU_DEBUG_MEMORY
813 if ((address >= 0x000000) && (address <= 0x3FFFFF))
816 readMem[address] = 1;
819 //WriteLog("[RM8] Addr: %08X\n", address);
820 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
821 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
822 || address == 0x1AF05E)
823 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
825 unsigned int retVal = 0;
827 if ((address >= 0x000000) && (address <= 0x3FFFFF))
828 retVal = jaguarMainRAM[address];
829 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
830 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
831 retVal = jaguarMainROM[address - 0x800000];
832 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
833 retVal = jaguarBootROM[address - 0xE00000];
834 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
835 retVal = CDROMReadByte(address);
836 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
837 retVal = TOMReadByte(address, M68K);
838 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
839 retVal = JERRYReadByte(address, M68K);
841 retVal = jaguar_unknown_readbyte(address, M68K);
843 //if (address >= 0x2800 && address <= 0x281F)
844 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
845 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
846 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
849 return MMURead8(address, M68K);
853 void gpu_dump_disassembly(void);
854 void gpu_dump_registers(void);
856 unsigned int m68k_read_memory_16(unsigned int address)
858 #ifdef CPU_DEBUG_MEMORY
859 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
862 readMem[address] = 1, readMem[address + 1] = 1;
864 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
866 return 0x4E71; // NOP
868 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
870 return 0x4E71; // NOP
872 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
874 return 0x4E71; // NOP
876 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
878 return 0x4E71; // NOP
880 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
882 return 0x4E71; // NOP
884 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
886 return 0x4E71; // NOP
889 //WriteLog("[RM16] Addr: %08X\n", address);
890 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
891 // for(int i=0; i<10000; i++)
892 WriteLog("[M68K] In routine #6!\n");//*/
893 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
894 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
895 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
897 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
898 gpu_dump_registers();
899 gpu_dump_disassembly();
900 // for(int i=0; i<10000; i++)
901 // WriteLog("[M68K] About to run GPU!\n");
903 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
904 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
906 if (address == 0x000066A0)
908 gpu_dump_registers();
909 gpu_dump_disassembly();
911 for(int i=0; i<10000; i++)
912 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
914 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
915 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
916 || address == 0x1AF05E)
917 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
919 unsigned int retVal = 0;
921 if ((address >= 0x000000) && (address <= 0x3FFFFE))
922 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
923 retVal = GET16(jaguarMainRAM, address);
924 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
925 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
926 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
927 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
928 retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
929 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
930 retVal = CDROMReadWord(address, M68K);
931 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
932 retVal = TOMReadWord(address, M68K);
933 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
934 retVal = JERRYReadWord(address, M68K);
936 retVal = jaguar_unknown_readword(address, M68K);
938 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
939 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
940 //if (address >= 0x2800 && address <= 0x281F)
941 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
942 //$8B3AE -> Transferred from $F1C010
943 //$8B5E4 -> Only +1 read at $808AA
944 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
945 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
948 return MMURead16(address, M68K);
952 unsigned int m68k_read_memory_32(unsigned int address)
954 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
955 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
956 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));//*/
958 //WriteLog("--> [RM32]\n");
960 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
962 return MMURead32(address, M68K);
966 void m68k_write_memory_8(unsigned int address, unsigned int value)
968 #ifdef CPU_DEBUG_MEMORY
969 if ((address >= 0x000000) && (address <= 0x3FFFFF))
973 if (value > writeMemMax[address])
974 writeMemMax[address] = value;
975 if (value < writeMemMin[address])
976 writeMemMin[address] = value;
980 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
981 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
982 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
984 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
985 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
988 if ((address >= 0x000000) && (address <= 0x3FFFFF))
989 jaguarMainRAM[address] = value;
990 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
991 CDROMWriteByte(address, value, M68K);
992 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
993 TOMWriteByte(address, value, M68K);
994 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
995 JERRYWriteByte(address, value, M68K);
997 jaguar_unknown_writebyte(address, value, M68K);
999 MMUWrite8(address, value, M68K);
1003 void m68k_write_memory_16(unsigned int address, unsigned int value)
1005 #ifdef CPU_DEBUG_MEMORY
1006 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1010 uint8 hi = value >> 8, lo = value & 0xFF;
1012 if (hi > writeMemMax[address])
1013 writeMemMax[address] = hi;
1014 if (hi < writeMemMin[address])
1015 writeMemMin[address] = hi;
1017 if (lo > writeMemMax[address+1])
1018 writeMemMax[address+1] = lo;
1019 if (lo < writeMemMin[address+1])
1020 writeMemMin[address+1] = lo;
1024 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1025 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1026 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1027 //if (address >= 0xF02200 && address <= 0xF0229F)
1028 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1029 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1030 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1031 /*extern uint32 totalFrames;
1032 if (address == 0xF02114)
1033 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1034 if (address == 0xF02110)
1035 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1036 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1037 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1039 /*if (address == 0x0100)//64*4)
1040 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1042 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1043 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1044 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1045 || address == 0x1AF05E)
1046 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1049 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1051 /* jaguar_mainRam[address] = value >> 8;
1052 jaguar_mainRam[address + 1] = value & 0xFF;*/
1053 SET16(jaguarMainRAM, address, value);
1055 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1056 CDROMWriteWord(address, value, M68K);
1057 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1058 TOMWriteWord(address, value, M68K);
1059 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1060 JERRYWriteWord(address, value, M68K);
1063 jaguar_unknown_writeword(address, value, M68K);
1064 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1065 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1066 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1067 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1071 MMUWrite16(address, value, M68K);
1075 void m68k_write_memory_32(unsigned int address, unsigned int value)
1077 //WriteLog("--> [WM32]\n");
1078 /*if (address == 0x0100)//64*4)
1079 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1080 /*if (address >= 0xF03214 && address < 0xF0321F)
1081 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1082 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1083 /*extern bool doGPUDis;
1084 if (address == 0xF03214 && value == 0x88E30047)
1086 doGPUDis = true;//*/
1087 /* if (address == 0x51136 || address == 0xFB074)
1088 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1091 m68k_write_memory_16(address, value >> 16);
1092 m68k_write_memory_16(address + 2, value & 0xFFFF);
1094 MMUWrite32(address, value, M68K);
1099 uint32 JaguarGetHandler(uint32 i)
1101 return JaguarReadLong(i * 4);
1104 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1106 uint32 handler = JaguarGetHandler(i);
1107 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1110 void M68K_show_context(void)
1112 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1113 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1114 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1116 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1117 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1119 WriteLog("68K disasm\n");
1120 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1121 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1122 // jaguar_dasm(0x5000, 0x14414);
1124 // WriteLog("\n.......[Cart start]...........\n\n");
1125 // jaguar_dasm(0x192000, 0x1000);//0x200);
1127 WriteLog("..................\n");
1129 if (TOMIRQEnabled(IRQ_VBLANK))
1131 WriteLog("vblank int: enabled\n");
1132 JaguarDasm(JaguarGetHandler(64), 0x200);
1135 WriteLog("vblank int: disabled\n");
1137 WriteLog("..................\n");
1139 for(int i=0; i<256; i++)
1140 WriteLog("handler %03i at $%08X\n", i, (unsigned int)JaguarGetHandler(i));
1144 // Unknown read/write byte/word routines
1147 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1148 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1150 // 807EC4: movea.l #$f1b000, A1
1151 // 807ECA: movea.l #$8129e0, A0
1152 // 807ED0: move.l A0, D0
1153 // 807ED2: move.l #$f1bb94, D1
1154 // 807ED8: sub.l D0, D1
1155 // 807EDA: lsr.l #2, D1
1156 // 807EDC: move.l (A0)+, (A1)+
1157 // 807EDE: dbra D1, 807edc
1159 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1160 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1161 // space! (That is, unless the 68K causes a bus error...)
1163 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1165 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1166 WriteLog("Jaguar: Unknown byte %02X written at %08X by %s (M68K PC=%06X)\n", data, address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1168 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1169 // extern bool finished;
1171 // extern bool doDSPDis;
1177 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1179 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1180 WriteLog("Jaguar: Unknown word %04X written at %08X by %s (M68K PC=%06X)\n", data, address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1182 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1183 // extern bool finished;
1185 // extern bool doDSPDis;
1191 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1193 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1194 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1196 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1197 // extern bool finished;
1199 // extern bool doDSPDis;
1206 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1208 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1209 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1211 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1212 // extern bool finished;
1214 // extern bool doDSPDis;
1222 // Disassemble M68K instructions at the given offset
1225 unsigned int m68k_read_disassembler_8(unsigned int address)
1227 return m68k_read_memory_8(address);
1230 unsigned int m68k_read_disassembler_16(unsigned int address)
1232 return m68k_read_memory_16(address);
1235 unsigned int m68k_read_disassembler_32(unsigned int address)
1237 return m68k_read_memory_32(address);
1240 void JaguarDasm(uint32 offset, uint32 qt)
1243 static char buffer[2048];//, mem[64];
1244 int pc = offset, oldpc;
1246 for(uint32 i=0; i<qt; i++)
1249 for(int j=0; j<64; j++)
1250 mem[j^0x01] = jaguar_byte_read(pc + j);
1252 pc += Dasm68000((char *)mem, buffer, 0);
1253 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1255 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
1256 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1261 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1266 if (offset < 0x400000)
1267 data = jaguarMainRAM[offset & 0x3FFFFF];
1268 else if ((offset >= 0x800000) && (offset < 0xC00000))
1269 data = jaguarMainROM[offset - 0x800000];
1270 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1271 data = CDROMReadByte(offset, who);
1272 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1273 data = jaguarBootROM[offset & 0x3FFFF];
1274 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1275 data = TOMReadByte(offset, who);
1276 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1277 data = JERRYReadByte(offset, who);
1279 data = jaguar_unknown_readbyte(offset, who);
1284 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1287 if (offset <= 0x3FFFFE)
1289 return (jaguarMainRAM[(offset+0) & 0x3FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x3FFFFF];
1291 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1294 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1296 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1297 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1298 return CDROMReadWord(offset, who);
1299 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1300 return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1301 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1302 return TOMReadWord(offset, who);
1303 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1304 return JERRYReadWord(offset, who);
1306 return jaguar_unknown_readword(offset, who);
1309 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1311 //Need to check for writes in the range of $18FA70 + 8000...
1313 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1314 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1317 if (offset < 0x400000)
1319 jaguarMainRAM[offset & 0x3FFFFF] = data;
1322 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1324 CDROMWriteByte(offset, data, who);
1327 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1329 TOMWriteByte(offset, data, who);
1332 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1334 JERRYWriteByte(offset, data, who);
1338 jaguar_unknown_writebyte(offset, data, who);
1342 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1344 /*if (offset == 0x0100)//64*4)
1345 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1346 if (offset == 0x0102)//64*4)
1347 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1348 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1349 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1350 //Need to check for writes in the range of $18FA70 + 8000...
1352 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1353 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1354 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1355 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1359 if (offset <= 0x3FFFFE)
1364 1A 69 F0 ($0000) -> Starfield
1365 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1368 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1377 //This MUST be done by the 68K!
1378 /*if (offset == 0x670C)
1379 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1381 /*extern bool doGPUDis;
1382 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1383 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1384 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1385 doGPUDis = true;//*/
1386 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1387 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1388 if ((data & 0xFF00) != 0x7700)
1389 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1390 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1392 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1393 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1394 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1396 /*extern bool doGPUDis;
1397 if (offset == 0x120216 && who == GPU)
1398 doGPUDis = true;//*/
1399 /*extern uint32 gpu_pc;
1400 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1402 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1403 uint32 y = base / 0x300;
1404 uint32 x = (base - (y * 0x300)) / 2;
1405 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1408 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1410 //if (offset == (0x001E17F8 + 0x34))
1411 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1413 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1414 /*extern uint32 gpu_pc;
1415 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1417 extern int objectPtr;
1418 // if (offset > 0x148000)
1421 if (starCount > objectPtr)
1424 // if (starCount == 1)
1425 // WriteLog("--> Drawing 1st star...\n");
1427 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1428 // uint32 y = base / 0x300;
1429 // uint32 x = (base - (y * 0x300)) / 2;
1430 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1432 //A star of interest...
1433 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1434 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1435 //JWW: Blitter writing echo 77B3 at 0011D022...
1437 //extern bool doGPUDis;
1438 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1441 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1444 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1445 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1447 jaguarMainRAM[(offset+0) & 0x3FFFFF] = data >> 8;
1448 jaguarMainRAM[(offset+1) & 0x3FFFFF] = data & 0xFF;
1451 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1453 CDROMWriteWord(offset, data, who);
1456 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1458 TOMWriteWord(offset, data, who);
1461 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1463 JERRYWriteWord(offset, data, who);
1466 // Don't bomb on attempts to write to ROM
1467 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1470 jaguar_unknown_writeword(offset, data, who);
1473 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1474 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1476 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1479 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1480 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1482 /* extern bool doDSPDis;
1483 if (offset < 0x400 && !doDSPDis)
1485 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1488 /*if (offset == 0x0100)//64*4)
1489 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1491 JaguarWriteWord(offset, data >> 16, who);
1492 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1496 // Jaguar console initialization
1498 void JaguarInit(void)
1500 #ifdef CPU_DEBUG_MEMORY
1501 memset(readMem, 0x00, 0x400000);
1502 memset(writeMemMin, 0xFF, 0x400000);
1503 memset(writeMemMax, 0x00, 0x400000);
1505 memset(jaguarMainRAM, 0x00, 0x400000);
1506 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1507 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1508 //NOTE: This *doesn't* fix FlipOut...
1509 //Or does it? Hmm...
1510 //Seems to want $01010101... Dunno why. Investigate!
1511 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1512 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1514 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1522 //New timer based code stuffola...
1523 void ScanlineCallback(void);
1524 void RenderCallback(void);
1525 //extern uint32 * backbuffer;
1526 void JaguarReset(void)
1528 //NOTE: This causes a (virtual) crash if this is set in the config but not found... !!! FIX !!!
1529 if (vjs.useJaguarBIOS)
1530 memcpy(jaguarMainRAM, jaguarBootROM, 8);
1532 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1534 // WriteLog("jaguar_reset():\n");
1540 m68k_pulse_reset(); // Reset the 68000
1541 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1543 // New timer base code stuffola...
1544 InitializeEventList();
1545 TOMResetBackbuffer(backbuffer);
1546 // SetCallbackTime(ScanlineCallback, 63.5555);
1547 SetCallbackTime(ScanlineCallback, 31.77775);
1548 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1549 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time
1552 void JaguarDone(void)
1554 #ifdef CPU_DEBUG_MEMORY
1555 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1557 for(uint32 i=0; i<=raPtr; i++)
1559 WriteLog("\t%08X\n", returnAddr[i]);
1560 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1561 jaguar_dasm(returnAddr[i] - 16, 16);
1566 /* int start = 0, end = 0;
1567 bool endTriggered = false, startTriggered = false;
1568 for(int i=0; i<0x400000; i++)
1570 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1572 if (!startTriggered)
1573 startTriggered = true, endTriggered = false, start = i;
1575 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1581 end = i - 1, endTriggered = true, startTriggered = false;
1582 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1589 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1590 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1591 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1592 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1593 for(int i=-2; i<9; i++)
1594 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1596 /* WriteLog("\nM68000 disassembly at $802288...\n");
1597 jaguar_dasm(0x802288, 3);
1598 WriteLog("\nM68000 disassembly at $802200...\n");
1599 jaguar_dasm(0x802200, 500);
1600 WriteLog("\nM68000 disassembly at $802518...\n");
1601 jaguar_dasm(0x802518, 100);//*/
1603 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1604 jaguar_dasm(0x803F00, 500);
1607 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1608 jaguar_dasm(0x802B00, 500);
1611 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1612 jaguar_dasm(0x809900, 500);
1615 /* WriteLog("\n\nDump of $8093C8:\n\n");
1616 for(int i=0x8093C8; i<0x809900; i+=4)
1617 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1618 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1619 jaguar_dasm(0x90006C, 500);
1621 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1622 jaguar_dasm(0x1AC000, 6000);
1625 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1626 WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
1627 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
1628 M68K_show_context();
1639 // Main Jaguar execution loop (1 frame)
1641 void JaguarExecute(uint32 * backbuffer, bool render)
1643 uint16 vp = TOMReadWord(0xF0003E) + 1;
1644 uint16 vi = TOMReadWord(0xF0004E);
1645 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1646 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1648 // uint16 vdb = TOMReadWord(0xF00046);
1649 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1650 // uint16 vbb = TOMReadWord(0xF00040);
1651 //It seems that they mean it when they say that VDE is the end of object processing.
1652 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1653 //buffer and not to write any more pixels... !!! FIX !!!
1654 // uint16 vde = TOMReadWord(0xF00048);
1656 uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1657 uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1658 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1659 //seem to indicate the refresh rate is *half* the above...
1660 // uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1661 // Should these be hardwired or read from VP? Yes, from VP!
1662 uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1663 uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1665 TOMResetBackbuffer(backbuffer);
1666 /*extern int effect_start;
1668 WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1670 //extern int start_logging;
1671 for(uint16 i=0; i<vp; i++)
1673 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1674 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004) + 1) & 0x7FF);
1676 TOMWriteWord(0xF00006, i); // Write the VC
1678 // if (i == vi) // Time for Vertical Interrupt?
1679 //Not sure if this is correct...
1680 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1681 //Which means that it normally wouldn't go when it's zero.
1682 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1684 // We don't have to worry about autovectors & whatnot because the Jaguar
1685 // tells you through its HW registers who sent the interrupt...
1686 TOMSetPendingVideoInt();
1690 //if (start_logging)
1691 // WriteLog("About to execute M68K (%u)...\n", i);
1692 m68k_execute(M68KCyclesPerScanline);
1693 //if (start_logging)
1694 // WriteLog("About to execute TOM's PIT (%u)...\n", i);
1695 TOMExecPIT(RISCCyclesPerScanline);
1696 //if (start_logging)
1697 // WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1698 JERRYExecPIT(RISCCyclesPerScanline);
1699 //if (start_logging)
1700 // WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1701 JERRYI2SExec(RISCCyclesPerScanline);
1702 BUTCHExec(RISCCyclesPerScanline);
1703 //if (start_logging)
1704 // WriteLog("About to execute GPU (%u)...\n", i);
1705 GPUExec(RISCCyclesPerScanline);
1709 if (vjs.usePipelinedDSP)
1710 DSPExecP2(RISCCyclesPerScanline); // Pipelined DSP execution (3 stage)...
1712 DSPExec(RISCCyclesPerScanline); // Ordinary non-pipelined DSP
1713 // DSPExecComp(RISCCyclesPerScanline); // Comparison core
1716 //if (start_logging)
1717 // WriteLog("About to execute OP (%u)...\n", i);
1718 TOMExecScanline(i, render);
1722 // Temp debugging stuff
1724 void DumpMainMemory(void)
1726 FILE * fp = fopen("./memdump.bin", "wb");
1731 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1735 uint8 * GetRamPtr(void)
1737 return jaguarMainRAM;
1741 // New Jaguar execution stack
1746 void JaguarExecuteNew(void)
1748 extern bool finished, showGUI;
1749 extern bool debounceRunKey;
1750 // Pass a message to the "joystick" code to debounce the ESC key...
1751 debounceRunKey = true;
1753 /* InitializeEventList();
1754 TOMResetBackbuffer(backbuffer);
1755 // SetCallbackTime(ScanlineCallback, 63.5555);
1756 SetCallbackTime(ScanlineCallback, 31.77775);
1757 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1758 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1759 // uint8 * keystate = SDL_GetKeyState(NULL);
1763 double timeToNextEvent = GetTimeToNextEvent();
1764 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1766 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1767 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1771 if (vjs.usePipelinedDSP)
1772 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1774 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1779 // if (keystate[SDLK_ESCAPE])
1782 // SDL_PumpEvents(); // Needed to keep the keystate current...
1787 void ScanlineCallback(void)
1789 uint16 vc = TOMReadWord(0xF00006);
1790 uint16 vp = TOMReadWord(0xF0003E) + 1;
1791 uint16 vi = TOMReadWord(0xF0004E);
1792 // uint16 vbb = TOMReadWord(0xF00040);
1798 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1799 TOMWriteWord(0xF00006, vc);
1801 //This is a crappy kludge, but maybe it'll work for now...
1802 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1803 if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1805 // We don't have to worry about autovectors & whatnot because the Jaguar
1806 // tells you through its HW registers who sent the interrupt...
1807 tom_set_pending_video_int();
1811 TOMExecScanline(vc, true);
1813 //Change this to VBB???
1814 //Doesn't seem to matter (at least for Flip Out & I-War)
1821 TOMResetBackbuffer(backbuffer);
1825 // TOMResetBackbuffer(backbuffer);
1827 // SetCallbackTime(ScanlineCallback, 63.5555);
1828 SetCallbackTime(ScanlineCallback, 31.77775);
1834 void JaguarExecuteNew(void)
1836 // extern bool finished, showGUI;
1837 // extern bool debounceRunKey;
1838 // Pass a message to the "joystick" code to debounce the ESC key...
1839 // debounceRunKey = true;
1840 // finished = false;
1841 /* InitializeEventList();
1842 TOMResetBackbuffer(backbuffer);
1843 // SetCallbackTime(ScanlineCallback, 63.5555);
1844 SetCallbackTime(ScanlineCallback, 31.77775);
1845 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1846 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1847 // uint8 * keystate = SDL_GetKeyState(NULL);
1852 double timeToNextEvent = GetTimeToNextEvent();
1853 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1855 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1856 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1860 if (vjs.usePipelinedDSP)
1861 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1863 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1868 // if (keystate[SDLK_ESCAPE])
1871 // SDL_PumpEvents(); // Needed to keep the keystate current...
1876 void ScanlineCallback(void)
1878 uint16 vc = TOMReadWord(0xF00006);
1879 uint16 vp = TOMReadWord(0xF0003E) + 1;
1880 uint16 vi = TOMReadWord(0xF0004E);
1881 // uint16 vbb = TOMReadWord(0xF00040);
1887 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1888 TOMWriteWord(0xF00006, vc);
1890 //This is a crappy kludge, but maybe it'll work for now...
1891 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1892 if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1894 // We don't have to worry about autovectors & whatnot because the Jaguar
1895 // tells you through its HW registers who sent the interrupt...
1896 TOMSetPendingVideoInt();
1900 TOMExecScanline(vc, true);
1902 //Change this to VBB???
1903 //Doesn't seem to matter (at least for Flip Out & I-War)
1909 TOMResetBackbuffer(backbuffer);
1914 // TOMResetBackbuffer(backbuffer);
1916 // SetCallbackTime(ScanlineCallback, 63.5555);
1917 SetCallbackTime(ScanlineCallback, 31.77775);
1922 // This isn't currently used, but maybe it should be...
1923 void RenderCallback(void)
1926 TOMResetBackbuffer(backbuffer);
1927 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1928 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time