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. :-)
14 #include "SDL_opengl.h"
34 //Do this in makefile??? Yes! Could, but it's easier to define here...
35 //#define LOG_UNMAPPED_MEMORY_ACCESSES
36 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
37 #define ABORT_ON_ILLEGAL_INSTRUCTIONS
38 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
39 #define CPU_DEBUG_MEMORY
41 // Private function prototypes
43 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
44 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
45 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
46 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
47 void M68K_show_context(void);
51 #ifdef CPU_DEBUG_MEMORY
52 extern bool startMemLog; // Set by "e" key
53 extern int effect_start;
54 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
57 // Memory debugging identifiers
59 const char * whoName[9] =
60 { "Unknown", "Jaguar", "DSP", "GPU", "TOM", "JERRY", "M68K", "Blitter", "OP" };
62 uint32 jaguar_active_memory_dumps = 0;
64 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
66 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
67 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
68 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
69 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
70 bool BIOSLoaded = false;
71 bool CDBIOSLoaded = false;
74 uint8 * cdRAM = &jaguarMainROM[0x5FFF00];
76 uint8 jerryRAM[0x10000];
78 #ifdef CPU_DEBUG_MEMORY
79 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
80 uint8 readMem[0x400000];
81 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
84 uint32 pcQueue[0x400];
88 // Callback function to detect illegal instructions
90 void GPUDumpDisassembly(void);
91 void GPUDumpRegisters(void);
92 static bool start = false;
94 void M68KInstructionHook(void)
96 uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
99 // Ideally, we'd save all the registers as well...
100 pcQueue[pcQPtr++] = m68kPC;
103 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
105 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
107 static char buffer[2048];
108 for(int i=0; i<0x400; i++)
110 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
111 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
115 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
116 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
117 for(int i=0; i<10; i++)
118 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
119 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
125 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
127 static char buffer[2048];
128 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
129 WriteLog("%08X: %s", m68kPC, buffer);
130 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
131 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
132 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
134 /* if (m68kPC == 0x8D0E48 && effect_start5)
136 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
138 GPUDumpDisassembly();
142 /* uint16 opcode = JaguarReadWord(m68kPC);
143 if (opcode == 0x4E75) // RTS
146 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
148 uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
150 if (raPtr != 0xFFFFFFFF)
152 for(uint32 i=0; i<=raPtr; i++)
154 if (returnAddr[i] == addr)
163 returnAddr[++raPtr] = addr;
167 //Flip Out! debugging...
170 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
171 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
172 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
173 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
175 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
177 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
178 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
179 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
180 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
181 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
182 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
183 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
185 /* static char buffer[2048];
186 //if (m68kPC > 0x805F48) start = true;
187 //if (m68kPC > 0x806486) start = true;
188 //if (m68kPC == 0x805FEE) start = true;
189 //if (m68kPC == 0x80600C)// start = true;
190 if (m68kPC == 0x802058) start = true;
192 // GPUDumpRegisters();
193 // GPUDumpDisassembly();
195 // M68K_show_context();
201 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
202 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));
205 /* if (m68kPC == 0x803F16)
207 WriteLog("M68K: Registers found at $803F16:\n");
208 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
209 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
210 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
212 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
213 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
215 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
216 // !!! Investigate !!!
217 /*extern bool doDSPDis;
218 static bool disgo = false;
219 if (m68kPC == 0x50222)
222 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
223 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
226 if (m68kPC == 0x5000)
231 static char buffer[2048];
232 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
233 WriteLog("%08X: %s", m68kPC, buffer);
234 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
235 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
236 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
238 if (m68kPC == 0x82E1A)
240 static char buffer[2048];
241 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
242 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
243 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
244 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
245 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
247 if (m68kPC == 0x82E58)
248 WriteLog("--> [Routine end]\n");
249 if (m68kPC == 0x80004)
251 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
252 // m68k_set_reg(M68K_REG_D2, 0x12345678);
276 if (m68kPC == 0x3000)
277 WriteLog("M68K: CD_init\n");
278 else if (m68kPC == 0x3006 + (6 * 0))
279 WriteLog("M68K: CD_mode\n");
280 else if (m68kPC == 0x3006 + (6 * 1))
281 WriteLog("M68K: CD_ack\n");
282 else if (m68kPC == 0x3006 + (6 * 2))
283 WriteLog("M68K: CD_jeri\n");
284 else if (m68kPC == 0x3006 + (6 * 3))
285 WriteLog("M68K: CD_spin\n");
286 else if (m68kPC == 0x3006 + (6 * 4))
287 WriteLog("M68K: CD_stop\n");
288 else if (m68kPC == 0x3006 + (6 * 5))
289 WriteLog("M68K: CD_mute\n");
290 else if (m68kPC == 0x3006 + (6 * 6))
291 WriteLog("M68K: CD_umute\n");
292 else if (m68kPC == 0x3006 + (6 * 7))
293 WriteLog("M68K: CD_paus\n");
294 else if (m68kPC == 0x3006 + (6 * 8))
295 WriteLog("M68K: CD_upaus\n");
296 else if (m68kPC == 0x3006 + (6 * 9))
297 WriteLog("M68K: CD_read\n");
298 else if (m68kPC == 0x3006 + (6 * 10))
299 WriteLog("M68K: CD_uread\n");
300 else if (m68kPC == 0x3006 + (6 * 11))
301 WriteLog("M68K: CD_setup\n");
302 else if (m68kPC == 0x3006 + (6 * 12))
303 WriteLog("M68K: CD_ptr\n");
304 else if (m68kPC == 0x3006 + (6 * 13))
305 WriteLog("M68K: CD_osamp\n");
306 else if (m68kPC == 0x3006 + (6 * 14))
307 WriteLog("M68K: CD_getoc\n");
308 else if (m68kPC == 0x3006 + (6 * 15))
309 WriteLog("M68K: CD_initm\n");
310 else if (m68kPC == 0x3006 + (6 * 16))
311 WriteLog("M68K: CD_initf\n");
312 else if (m68kPC == 0x3006 + (6 * 17))
313 WriteLog("M68K: CD_switch\n");
315 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
316 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
317 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
318 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
320 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
321 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
323 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
324 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
326 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
327 // keep going even when the 68K dumped back to the debugger or what have you).
329 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
330 // Try setting the vector to the illegal instruction...
331 //This doesn't work right either! Do something else! Quick!
332 // SET32(jaguar_mainRam, 0x10, m68kPC);
338 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
339 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
340 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
341 for(int i=0; i<10; i++)
342 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
343 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
347 // WriteLog("\n\n68K disasm\n\n");
348 // jaguar_dasm(0x802000, 0x50C);
359 Now here be dragons...
360 Here is how memory ranges are defined in the CoJag driver.
361 Note that we only have to be concerned with 3 entities read/writing anything:
362 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
363 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
364 things that are entirely internal to those modules. This way we should be able to get a handle on all
365 this crap which is currently scattered over Hell's Half Acre(tm).
367 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
368 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
370 /*************************************
372 * Main CPU memory handlers
374 *************************************/
376 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
377 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
378 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
379 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
380 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
381 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
382 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
383 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
384 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
385 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
386 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
387 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
388 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
389 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
390 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
391 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
392 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
393 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
394 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
395 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
396 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
397 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
398 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
401 /*************************************
403 * GPU memory handlers
405 *************************************/
407 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
408 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
409 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
410 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
411 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
412 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
413 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
414 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
415 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
416 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
417 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
420 /*************************************
422 * DSP memory handlers
424 *************************************/
426 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
427 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
428 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
429 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
430 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
431 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
432 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
433 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
434 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
439 #define EXPERIMENTAL_MEMORY_HANDLING
440 // Experimental memory mappage...
441 // Dunno if this is a good approach or not, but it seems to make better
442 // sense to have all this crap in one spot intstead of scattered all over
443 // the place the way it is now.
444 #ifdef EXPERIMENTAL_MEMORY_HANDLING
446 #define NEW_TIMER_SYSTEM
449 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
450 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
451 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
452 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
453 bool BIOSLoaded = false;
454 bool CDBIOSLoaded = false;
457 uint8 tomRAM[0x4000];
458 uint8 jerryRAM[0x10000];
459 static uint16 eeprom_ram[64];
461 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
464 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
466 // M68K Memory map/handlers
468 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
469 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
470 // Note that this is really memory mapped I/O region...
471 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
472 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
473 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
474 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
475 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
476 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
477 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
478 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
479 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
480 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
481 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
482 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
484 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
486 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
487 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
488 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
489 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
490 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
491 //What about LBUF writes???
492 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
493 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
494 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
496 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
500 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
501 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
502 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
505 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
506 0 = pad0/1 button values (4 bits each), RO(?)
507 1 = pad0/1 index value (4 bits each), WO
509 3 = NTSC/PAL, certain button states, RO
511 JOYSTICK $F14000 Read/Write
513 Read fedcba98 7654321q f-1 Signals J15 to J1
514 q Cartridge EEPROM output data
515 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
516 0 = disable J7-J0 outputs
519 0 = Audio muted (reset state)
521 7-4 J7-J4 outputs (port 2)
522 3-0 J3-J0 outputs (port 1)
523 JOYBUTS $F14002 Read Only
525 Read xxxxxxxx rrdv3210 x don't care
528 v 1 = NTSC Video hardware
529 0 = PAL Video hardware
530 3-2 Button inputs B3 & B2 (port 2)
531 1-0 Button inputs B1 & B0 (port 1)
533 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
534 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
542 0 1 1 1 Row 3 C3 Option # 9 6 3
546 1 0 1 1 Row 2 C2 C 0 8 5 2
548 1 1 0 1 Row 1 C1 B * 7 4 1
549 1 1 1 0 Row 0 Pause A Up Down Left Right
552 0 bit read in any position means that button is pressed.
553 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
557 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
559 // Not sure, but I think the system only has 24 address bits...
560 address &= 0x00FFFFFF;
562 // RAM ($000000 - $3FFFFF) 4M
563 if (address <= 0x3FFFFF)
564 jaguarMainRAM[address] = byte;
565 // hole ($400000 - $7FFFFF) 4M
566 else if (address <= 0x7FFFFF)
568 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
569 else if (address <= 0xDFFEFF)
571 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
572 else if (address <= 0xDFFFFF)
574 cdRAM[address & 0xFF] = byte;
576 if ((address & 0xFF) < 12 * 4)
577 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
578 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
581 // BIOS ROM ($E00000 - $E3FFFF) 256K
582 else if (address <= 0xE3FFFF)
584 // hole ($E40000 - $EFFFFF) 768K
585 else if (address <= 0xEFFFFF)
587 // TOM ($F00000 - $F0FFFF) 64K
588 else if (address <= 0xF0FFFF)
591 if (address == 0xF00050)
593 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
597 else if (address == 0xF00051)
599 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
603 else if (address == 0xF00052)
605 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
609 else if (address == 0xF00053)
611 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
615 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
617 // Writing to one CLUT writes to the other
618 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
619 tomRAM[address] = tomRAM[address + 0x200] = byte;
622 //What about LBUF writes???
623 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
625 GPUWriteByte(address, byte, who);
628 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
630 BlitterWriteByte(address, byte, who);
633 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
635 GPUWriteByte(address, byte, who);
639 tomRAM[address & 0x3FFF] = byte;
641 // JERRY ($F10000 - $F1FFFF) 64K
642 else if (address <= 0xF1FFFF)
646 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
648 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
650 DSPWriteByte(address, byte, who);
653 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
655 DSPWriteByte(address, byte, who);
658 // SCLK ($F1A150--8 bits wide)
659 //NOTE: This should be taken care of in DAC...
660 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
662 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
663 if ((address & 0x03) == 2)
664 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
666 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
668 JERRYI2SInterruptTimer = -1;
669 #ifndef NEW_TIMER_SYSTEM
672 RemoveCallback(JERRYI2SCallback);
677 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
678 else if (address >= 0xF1A148 && address <= 0xF1A157)
680 DACWriteByte(address, byte, who);
683 else if (address >= 0xF10000 && address <= 0xF10007)
685 #ifndef NEW_TIMER_SYSTEM
686 switch (address & 0x07)
689 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
693 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
697 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
701 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
705 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
709 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
713 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
717 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
721 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
725 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
727 clock_byte_write(offset, byte);
730 // JERRY -> 68K interrupt enables/latches (need to be handled!)
731 else if (address >= 0xF10020 && address <= 0xF10023)
733 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
735 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
737 anajoy_byte_write(offset, byte);
740 else if ((address >= 0xF14000) && (address <= 0xF14003))
742 JoystickWriteByte(address, byte);
743 EepromWriteByte(address, byte);
746 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
748 EepromWriteByte(address, byte);
751 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
752 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
755 jerryRAM[address & 0xFFFF] = byte;
757 // hole ($F20000 - $FFFFFF) 1M - 128K
762 void WriteWord(uint32 adddress, uint16 word)
766 void WriteDWord(uint32 adddress, uint32 dword)
770 uint8 ReadByte(uint32 adddress)
774 uint16 ReadWord(uint32 adddress)
778 uint32 ReadDWord(uint32 adddress)
784 // Musashi 68000 read/write/IRQ functions
787 int irq_ack_handler(int level)
789 int vector = M68K_INT_ACK_AUTOVECTOR;
791 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
795 m68k_set_irq(0); // Clear the IRQ...
796 vector = 64; // Set user interrupt #0
802 unsigned int m68k_read_memory_8(unsigned int address)
804 #ifdef CPU_DEBUG_MEMORY
805 if ((address >= 0x000000) && (address <= 0x3FFFFF))
808 readMem[address] = 1;
811 //WriteLog("[RM8] Addr: %08X\n", address);
812 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
813 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
814 || address == 0x1AF05E)
815 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
816 unsigned int retVal = 0;
818 if ((address >= 0x000000) && (address <= 0x3FFFFF))
819 retVal = jaguarMainRam[address];
820 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
821 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
822 retVal = jaguarMainRom[address - 0x800000];
823 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
824 retVal = jaguarBootRom[address - 0xE00000];
825 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
826 retVal = CDROMReadByte(address);
827 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
828 retVal = TOMReadByte(address, M68K);
829 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
830 retVal = JERRYReadByte(address, M68K);
832 retVal = jaguar_unknown_readbyte(address, M68K);
834 //if (address >= 0x2800 && address <= 0x281F)
835 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
836 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
837 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
841 void gpu_dump_disassembly(void);
842 void gpu_dump_registers(void);
844 unsigned int m68k_read_memory_16(unsigned int address)
846 #ifdef CPU_DEBUG_MEMORY
847 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
850 readMem[address] = 1, readMem[address + 1] = 1;
852 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
854 return 0x4E71; // NOP
856 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
858 return 0x4E71; // NOP
860 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
862 return 0x4E71; // NOP
864 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
866 return 0x4E71; // NOP
868 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
870 return 0x4E71; // NOP
872 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
874 return 0x4E71; // NOP
877 //WriteLog("[RM16] Addr: %08X\n", address);
878 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
879 // for(int i=0; i<10000; i++)
880 WriteLog("[M68K] In routine #6!\n");//*/
881 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
882 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
883 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
885 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
886 gpu_dump_registers();
887 gpu_dump_disassembly();
888 // for(int i=0; i<10000; i++)
889 // WriteLog("[M68K] About to run GPU!\n");
891 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
892 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
894 if (address == 0x000066A0)
896 gpu_dump_registers();
897 gpu_dump_disassembly();
899 for(int i=0; i<10000; i++)
900 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
902 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
903 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
904 || address == 0x1AF05E)
905 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
906 unsigned int retVal = 0;
908 if ((address >= 0x000000) && (address <= 0x3FFFFE))
909 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
910 retVal = GET16(jaguarMainRam, address);
911 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
912 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
913 retVal = (jaguarMainRom[address - 0x800000] << 8) | jaguarMainRom[address - 0x800000 + 1];
914 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
915 retVal = (jaguarBootRom[address - 0xE00000] << 8) | jaguarBootRom[address - 0xE00000 + 1];
916 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
917 retVal = CDROMReadWord(address, M68K);
918 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
919 retVal = TOMReadWord(address, M68K);
920 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
921 retVal = JERRYReadWord(address, M68K);
923 retVal = jaguar_unknown_readword(address, M68K);
925 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
926 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
927 //if (address >= 0x2800 && address <= 0x281F)
928 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
929 //$8B3AE -> Transferred from $F1C010
930 //$8B5E4 -> Only +1 read at $808AA
931 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
932 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
936 unsigned int m68k_read_memory_32(unsigned int address)
938 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
939 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
940 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));//*/
942 //WriteLog("--> [RM32]\n");
943 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
946 void m68k_write_memory_8(unsigned int address, unsigned int value)
948 #ifdef CPU_DEBUG_MEMORY
949 if ((address >= 0x000000) && (address <= 0x3FFFFF))
953 if (value > writeMemMax[address])
954 writeMemMax[address] = value;
955 if (value < writeMemMin[address])
956 writeMemMin[address] = value;
960 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
961 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
962 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
964 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
965 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
967 if ((address >= 0x000000) && (address <= 0x3FFFFF))
968 jaguarMainRam[address] = value;
969 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
970 CDROMWriteByte(address, value, M68K);
971 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
972 TOMWriteByte(address, value, M68K);
973 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
974 JERRYWriteByte(address, value, M68K);
976 jaguar_unknown_writebyte(address, value, M68K);
979 void m68k_write_memory_16(unsigned int address, unsigned int value)
981 #ifdef CPU_DEBUG_MEMORY
982 if ((address >= 0x000000) && (address <= 0x3FFFFE))
986 uint8 hi = value >> 8, lo = value & 0xFF;
988 if (hi > writeMemMax[address])
989 writeMemMax[address] = hi;
990 if (hi < writeMemMin[address])
991 writeMemMin[address] = hi;
993 if (lo > writeMemMax[address+1])
994 writeMemMax[address+1] = lo;
995 if (lo < writeMemMin[address+1])
996 writeMemMin[address+1] = lo;
1000 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1001 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1002 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1003 //if (address >= 0xF02200 && address <= 0xF0229F)
1004 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1005 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1006 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1007 /*extern uint32 totalFrames;
1008 if (address == 0xF02114)
1009 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1010 if (address == 0xF02110)
1011 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1012 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1013 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1015 /*if (address == 0x0100)//64*4)
1016 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1018 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1019 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1020 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1021 || address == 0x1AF05E)
1022 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1024 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1026 /* jaguar_mainRam[address] = value >> 8;
1027 jaguar_mainRam[address + 1] = value & 0xFF;*/
1028 SET16(jaguarMainRam, address, value);
1030 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1031 CDROMWriteWord(address, value, M68K);
1032 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1033 TOMWriteWord(address, value, M68K);
1034 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1035 JERRYWriteWord(address, value, M68K);
1038 jaguar_unknown_writeword(address, value, M68K);
1039 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1040 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1041 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1042 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1047 void m68k_write_memory_32(unsigned int address, unsigned int value)
1049 //WriteLog("--> [WM32]\n");
1050 /*if (address == 0x0100)//64*4)
1051 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1052 /*if (address >= 0xF03214 && address < 0xF0321F)
1053 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1054 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1055 /*extern bool doGPUDis;
1056 if (address == 0xF03214 && value == 0x88E30047)
1058 doGPUDis = true;//*/
1059 /* if (address == 0x51136 || address == 0xFB074)
1060 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1062 m68k_write_memory_16(address, value >> 16);
1063 m68k_write_memory_16(address + 2, value & 0xFFFF);
1067 uint32 JaguarGetHandler(uint32 i)
1069 return JaguarReadLong(i * 4);
1072 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1074 uint32 handler = JaguarGetHandler(i);
1075 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1078 void M68K_show_context(void)
1080 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1081 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1082 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1084 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1085 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1087 WriteLog("68K disasm\n");
1088 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1089 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1090 // jaguar_dasm(0x5000, 0x14414);
1092 // WriteLog("\n.......[Cart start]...........\n\n");
1093 // jaguar_dasm(0x192000, 0x1000);//0x200);
1095 WriteLog("..................\n");
1097 if (TOMIRQEnabled(IRQ_VBLANK))
1099 WriteLog("vblank int: enabled\n");
1100 JaguarDasm(JaguarGetHandler(64), 0x200);
1103 WriteLog("vblank int: disabled\n");
1105 WriteLog("..................\n");
1107 for(int i=0; i<256; i++)
1108 WriteLog("handler %03i at $%08X\n", i, (unsigned int)JaguarGetHandler(i));
1112 // Unknown read/write byte/word routines
1115 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1116 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1118 // 807EC4: movea.l #$f1b000, A1
1119 // 807ECA: movea.l #$8129e0, A0
1120 // 807ED0: move.l A0, D0
1121 // 807ED2: move.l #$f1bb94, D1
1122 // 807ED8: sub.l D0, D1
1123 // 807EDA: lsr.l #2, D1
1124 // 807EDC: move.l (A0)+, (A1)+
1125 // 807EDE: dbra D1, 807edc
1127 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1128 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1129 // space! (That is, unless the 68K causes a bus error...)
1131 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1133 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1134 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));
1136 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1137 // extern bool finished;
1139 // extern bool doDSPDis;
1145 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1147 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1148 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));
1150 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1151 // extern bool finished;
1153 // extern bool doDSPDis;
1159 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1161 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1162 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1164 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1165 // extern bool finished;
1167 // extern bool doDSPDis;
1174 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1176 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1177 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1179 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1180 // extern bool finished;
1182 // extern bool doDSPDis;
1190 // Disassemble M68K instructions at the given offset
1193 unsigned int m68k_read_disassembler_8(unsigned int address)
1195 return m68k_read_memory_8(address);
1198 unsigned int m68k_read_disassembler_16(unsigned int address)
1200 return m68k_read_memory_16(address);
1203 unsigned int m68k_read_disassembler_32(unsigned int address)
1205 return m68k_read_memory_32(address);
1208 void JaguarDasm(uint32 offset, uint32 qt)
1211 static char buffer[2048];//, mem[64];
1212 int pc = offset, oldpc;
1214 for(uint32 i=0; i<qt; i++)
1217 for(int j=0; j<64; j++)
1218 mem[j^0x01] = jaguar_byte_read(pc + j);
1220 pc += Dasm68000((char *)mem, buffer, 0);
1221 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1223 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
1224 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1229 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1234 if (offset < 0x400000)
1235 data = jaguarMainRam[offset & 0x3FFFFF];
1236 else if ((offset >= 0x800000) && (offset < 0xC00000))
1237 data = jaguarMainRom[offset - 0x800000];
1238 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1239 data = CDROMReadByte(offset, who);
1240 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1241 data = jaguarBootRom[offset & 0x3FFFF];
1242 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1243 data = TOMReadByte(offset, who);
1244 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1245 data = JERRYReadByte(offset, who);
1247 data = jaguar_unknown_readbyte(offset, who);
1252 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1255 if (offset <= 0x3FFFFE)
1257 return (jaguarMainRam[(offset+0) & 0x3FFFFF] << 8) | jaguarMainRam[(offset+1) & 0x3FFFFF];
1259 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1262 return (jaguarMainRom[offset+0] << 8) | jaguarMainRom[offset+1];
1264 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1265 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1266 return CDROMReadWord(offset, who);
1267 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1268 return (jaguarBootRom[(offset+0) & 0x3FFFF] << 8) | jaguarBootRom[(offset+1) & 0x3FFFF];
1269 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1270 return TOMReadWord(offset, who);
1271 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1272 return JERRYReadWord(offset, who);
1274 return jaguar_unknown_readword(offset, who);
1277 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1279 //Need to check for writes in the range of $18FA70 + 8000...
1281 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1282 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1285 if (offset < 0x400000)
1287 jaguarMainRam[offset & 0x3FFFFF] = data;
1290 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1292 CDROMWriteByte(offset, data, who);
1295 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1297 TOMWriteByte(offset, data, who);
1300 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1302 JERRYWriteByte(offset, data, who);
1306 jaguar_unknown_writebyte(offset, data, who);
1310 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1312 /*if (offset == 0x0100)//64*4)
1313 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1314 if (offset == 0x0102)//64*4)
1315 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1316 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1317 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1318 //Need to check for writes in the range of $18FA70 + 8000...
1320 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1321 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1322 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1323 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1327 if (offset <= 0x3FFFFE)
1332 1A 69 F0 ($0000) -> Starfield
1333 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1336 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1345 //This MUST be done by the 68K!
1346 /*if (offset == 0x670C)
1347 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1349 /*extern bool doGPUDis;
1350 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1351 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1352 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1353 doGPUDis = true;//*/
1354 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1355 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1356 if ((data & 0xFF00) != 0x7700)
1357 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1358 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1360 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1361 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1362 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1364 /*extern bool doGPUDis;
1365 if (offset == 0x120216 && who == GPU)
1366 doGPUDis = true;//*/
1367 /*extern uint32 gpu_pc;
1368 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1370 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1371 uint32 y = base / 0x300;
1372 uint32 x = (base - (y * 0x300)) / 2;
1373 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1376 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1378 //if (offset == (0x001E17F8 + 0x34))
1379 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1381 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1382 /*extern uint32 gpu_pc;
1383 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1385 extern int objectPtr;
1386 // if (offset > 0x148000)
1389 if (starCount > objectPtr)
1392 // if (starCount == 1)
1393 // WriteLog("--> Drawing 1st star...\n");
1395 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1396 // uint32 y = base / 0x300;
1397 // uint32 x = (base - (y * 0x300)) / 2;
1398 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1400 //A star of interest...
1401 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1402 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1403 //JWW: Blitter writing echo 77B3 at 0011D022...
1405 //extern bool doGPUDis;
1406 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1409 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1412 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1413 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1415 jaguarMainRam[(offset+0) & 0x3FFFFF] = data >> 8;
1416 jaguarMainRam[(offset+1) & 0x3FFFFF] = data & 0xFF;
1419 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1421 CDROMWriteWord(offset, data, who);
1424 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1426 TOMWriteWord(offset, data, who);
1429 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1431 JERRYWriteWord(offset, data, who);
1434 // Don't bomb on attempts to write to ROM
1435 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1438 jaguar_unknown_writeword(offset, data, who);
1441 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1442 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1444 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1447 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1448 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1450 /* extern bool doDSPDis;
1451 if (offset < 0x400 && !doDSPDis)
1453 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1456 /*if (offset == 0x0100)//64*4)
1457 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1459 JaguarWriteWord(offset, data >> 16, who);
1460 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1464 // Jaguar console initialization
1466 void JaguarInit(void)
1468 #ifdef CPU_DEBUG_MEMORY
1469 memset(readMem, 0x00, 0x400000);
1470 memset(writeMemMin, 0xFF, 0x400000);
1471 memset(writeMemMax, 0x00, 0x400000);
1473 memset(jaguarMainRam, 0x00, 0x400000);
1474 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1475 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1476 //NOTE: This *doesn't* fix FlipOut...
1477 //Or does it? Hmm...
1478 //Seems to want $01010101... Dunno why. Investigate!
1479 memset(jaguarMainRom, 0x01, 0x600000); // & set it to all 01s...
1480 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1482 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1490 //New timer based code stuffola...
1491 void ScanlineCallback(void);
1492 void RenderCallback(void);
1493 //extern uint32 * backbuffer;
1494 void JaguarReset(void)
1496 //NOTE: This causes a (virtual) crash if this is set in the config but not found... !!! FIX !!!
1497 if (vjs.useJaguarBIOS)
1498 memcpy(jaguarMainRam, jaguarBootRom, 8);
1500 SET32(jaguarMainRam, 4, jaguarRunAddress);
1502 // WriteLog("jaguar_reset():\n");
1508 m68k_pulse_reset(); // Reset the 68000
1509 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1511 // New timer base code stuffola...
1512 InitializeEventList();
1513 TOMResetBackbuffer(backbuffer);
1514 // SetCallbackTime(ScanlineCallback, 63.5555);
1515 SetCallbackTime(ScanlineCallback, 31.77775);
1516 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1517 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time
1520 void JaguarDone(void)
1522 #ifdef CPU_DEBUG_MEMORY
1523 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1525 for(uint32 i=0; i<=raPtr; i++)
1527 WriteLog("\t%08X\n", returnAddr[i]);
1528 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1529 jaguar_dasm(returnAddr[i] - 16, 16);
1534 /* int start = 0, end = 0;
1535 bool endTriggered = false, startTriggered = false;
1536 for(int i=0; i<0x400000; i++)
1538 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1540 if (!startTriggered)
1541 startTriggered = true, endTriggered = false, start = i;
1543 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1549 end = i - 1, endTriggered = true, startTriggered = false;
1550 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1557 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1558 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1559 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1560 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1561 for(int i=-2; i<9; i++)
1562 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1564 /* WriteLog("\nM68000 disassembly at $802288...\n");
1565 jaguar_dasm(0x802288, 3);
1566 WriteLog("\nM68000 disassembly at $802200...\n");
1567 jaguar_dasm(0x802200, 500);
1568 WriteLog("\nM68000 disassembly at $802518...\n");
1569 jaguar_dasm(0x802518, 100);//*/
1571 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1572 jaguar_dasm(0x803F00, 500);
1575 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1576 jaguar_dasm(0x802B00, 500);
1579 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1580 jaguar_dasm(0x809900, 500);
1583 /* WriteLog("\n\nDump of $8093C8:\n\n");
1584 for(int i=0x8093C8; i<0x809900; i+=4)
1585 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1586 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1587 jaguar_dasm(0x90006C, 500);
1589 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1590 jaguar_dasm(0x1AC000, 6000);
1593 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1594 WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
1595 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
1596 M68K_show_context();
1607 // Main Jaguar execution loop (1 frame)
1609 void JaguarExecute(uint32 * backbuffer, bool render)
1611 uint16 vp = TOMReadWord(0xF0003E) + 1;
1612 uint16 vi = TOMReadWord(0xF0004E);
1613 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1614 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1616 // uint16 vdb = TOMReadWord(0xF00046);
1617 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1618 // uint16 vbb = TOMReadWord(0xF00040);
1619 //It seems that they mean it when they say that VDE is the end of object processing.
1620 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1621 //buffer and not to write any more pixels... !!! FIX !!!
1622 // uint16 vde = TOMReadWord(0xF00048);
1624 uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1625 uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1626 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1627 //seem to indicate the refresh rate is *half* the above...
1628 // uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1629 // Should these be hardwired or read from VP? Yes, from VP!
1630 uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1631 uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1633 TOMResetBackbuffer(backbuffer);
1634 /*extern int effect_start;
1636 WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1638 //extern int start_logging;
1639 for(uint16 i=0; i<vp; i++)
1641 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1642 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004) + 1) & 0x7FF);
1644 TOMWriteWord(0xF00006, i); // Write the VC
1646 // if (i == vi) // Time for Vertical Interrupt?
1647 //Not sure if this is correct...
1648 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1649 //Which means that it normally wouldn't go when it's zero.
1650 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1652 // We don't have to worry about autovectors & whatnot because the Jaguar
1653 // tells you through its HW registers who sent the interrupt...
1654 TOMSetPendingVideoInt();
1658 //if (start_logging)
1659 // WriteLog("About to execute M68K (%u)...\n", i);
1660 m68k_execute(M68KCyclesPerScanline);
1661 //if (start_logging)
1662 // WriteLog("About to execute TOM's PIT (%u)...\n", i);
1663 TOMExecPIT(RISCCyclesPerScanline);
1664 //if (start_logging)
1665 // WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1666 JERRYExecPIT(RISCCyclesPerScanline);
1667 //if (start_logging)
1668 // WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1669 JERRYI2SExec(RISCCyclesPerScanline);
1670 BUTCHExec(RISCCyclesPerScanline);
1671 //if (start_logging)
1672 // WriteLog("About to execute GPU (%u)...\n", i);
1673 GPUExec(RISCCyclesPerScanline);
1677 if (vjs.usePipelinedDSP)
1678 DSPExecP2(RISCCyclesPerScanline); // Pipelined DSP execution (3 stage)...
1680 DSPExec(RISCCyclesPerScanline); // Ordinary non-pipelined DSP
1681 // DSPExecComp(RISCCyclesPerScanline); // Comparison core
1684 //if (start_logging)
1685 // WriteLog("About to execute OP (%u)...\n", i);
1686 TOMExecScanline(i, render);
1690 // Temp debugging stuff
1692 void DumpMainMemory(void)
1694 FILE * fp = fopen("./memdump.bin", "wb");
1699 fwrite(jaguarMainRam, 1, 0x400000, fp);
1703 uint8 * GetRamPtr(void)
1705 return jaguarMainRam;
1709 // New Jaguar execution stack
1714 void JaguarExecuteNew(void)
1716 extern bool finished, showGUI;
1717 extern bool debounceRunKey;
1718 // Pass a message to the "joystick" code to debounce the ESC key...
1719 debounceRunKey = true;
1721 /* InitializeEventList();
1722 TOMResetBackbuffer(backbuffer);
1723 // SetCallbackTime(ScanlineCallback, 63.5555);
1724 SetCallbackTime(ScanlineCallback, 31.77775);
1725 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1726 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1727 // uint8 * keystate = SDL_GetKeyState(NULL);
1731 double timeToNextEvent = GetTimeToNextEvent();
1732 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1734 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1735 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1739 if (vjs.usePipelinedDSP)
1740 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1742 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1747 // if (keystate[SDLK_ESCAPE])
1750 // SDL_PumpEvents(); // Needed to keep the keystate current...
1755 void ScanlineCallback(void)
1757 uint16 vc = TOMReadWord(0xF00006);
1758 uint16 vp = TOMReadWord(0xF0003E) + 1;
1759 uint16 vi = TOMReadWord(0xF0004E);
1760 // uint16 vbb = TOMReadWord(0xF00040);
1766 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1767 TOMWriteWord(0xF00006, vc);
1769 //This is a crappy kludge, but maybe it'll work for now...
1770 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1771 if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1773 // We don't have to worry about autovectors & whatnot because the Jaguar
1774 // tells you through its HW registers who sent the interrupt...
1775 tom_set_pending_video_int();
1779 TOMExecScanline(vc, true);
1781 //Change this to VBB???
1782 //Doesn't seem to matter (at least for Flip Out & I-War)
1789 TOMResetBackbuffer(backbuffer);
1793 // TOMResetBackbuffer(backbuffer);
1795 // SetCallbackTime(ScanlineCallback, 63.5555);
1796 SetCallbackTime(ScanlineCallback, 31.77775);
1802 void JaguarExecuteNew(void)
1804 // extern bool finished, showGUI;
1805 // extern bool debounceRunKey;
1806 // Pass a message to the "joystick" code to debounce the ESC key...
1807 // debounceRunKey = true;
1808 // finished = false;
1809 /* InitializeEventList();
1810 TOMResetBackbuffer(backbuffer);
1811 // SetCallbackTime(ScanlineCallback, 63.5555);
1812 SetCallbackTime(ScanlineCallback, 31.77775);
1813 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1814 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1815 // uint8 * keystate = SDL_GetKeyState(NULL);
1820 double timeToNextEvent = GetTimeToNextEvent();
1821 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1823 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1824 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1828 if (vjs.usePipelinedDSP)
1829 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1831 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1836 // if (keystate[SDLK_ESCAPE])
1839 // SDL_PumpEvents(); // Needed to keep the keystate current...
1844 void ScanlineCallback(void)
1846 uint16 vc = TOMReadWord(0xF00006);
1847 uint16 vp = TOMReadWord(0xF0003E) + 1;
1848 uint16 vi = TOMReadWord(0xF0004E);
1849 // uint16 vbb = TOMReadWord(0xF00040);
1855 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1856 TOMWriteWord(0xF00006, vc);
1858 //This is a crappy kludge, but maybe it'll work for now...
1859 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1860 if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1862 // We don't have to worry about autovectors & whatnot because the Jaguar
1863 // tells you through its HW registers who sent the interrupt...
1864 TOMSetPendingVideoInt();
1868 TOMExecScanline(vc, true);
1870 //Change this to VBB???
1871 //Doesn't seem to matter (at least for Flip Out & I-War)
1877 TOMResetBackbuffer(backbuffer);
1882 // TOMResetBackbuffer(backbuffer);
1884 // SetCallbackTime(ScanlineCallback, 63.5555);
1885 SetCallbackTime(ScanlineCallback, 31.77775);
1890 // This isn't currently used, but maybe it should be...
1891 void RenderCallback(void)
1894 TOMResetBackbuffer(backbuffer);
1895 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1896 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time