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 handled memory when this was written. :-)
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 uint32 jaguar_active_memory_dumps = 0;
65 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
67 bool BIOSLoaded = false;
68 bool CDBIOSLoaded = false;
70 #ifdef CPU_DEBUG_MEMORY
71 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
72 uint8 readMem[0x400000];
73 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
76 uint32 pcQueue[0x400];
80 // Callback function to detect illegal instructions
82 void GPUDumpDisassembly(void);
83 void GPUDumpRegisters(void);
84 static bool start = false;
86 void M68KInstructionHook(void)
88 uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
91 // Ideally, we'd save all the registers as well...
92 pcQueue[pcQPtr++] = m68kPC;
95 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
97 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
99 static char buffer[2048];
100 for(int i=0; i<0x400; i++)
102 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
103 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
107 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
108 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
109 for(int i=0; i<10; i++)
110 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
111 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
117 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
119 static char buffer[2048];
120 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
121 WriteLog("%08X: %s", m68kPC, buffer);
122 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
123 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
124 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
126 /* if (m68kPC == 0x8D0E48 && effect_start5)
128 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
130 GPUDumpDisassembly();
134 /* uint16 opcode = JaguarReadWord(m68kPC);
135 if (opcode == 0x4E75) // RTS
138 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
140 uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
142 if (raPtr != 0xFFFFFFFF)
144 for(uint32 i=0; i<=raPtr; i++)
146 if (returnAddr[i] == addr)
155 returnAddr[++raPtr] = addr;
159 //Flip Out! debugging...
162 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
163 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
164 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
165 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
167 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
169 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
170 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
171 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
172 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
173 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
174 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
175 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
177 /* static char buffer[2048];
178 //if (m68kPC > 0x805F48) start = true;
179 //if (m68kPC > 0x806486) start = true;
180 //if (m68kPC == 0x805FEE) start = true;
181 //if (m68kPC == 0x80600C)// start = true;
182 if (m68kPC == 0x802058) start = true;
184 // GPUDumpRegisters();
185 // GPUDumpDisassembly();
187 // M68K_show_context();
193 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
194 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));
197 /* if (m68kPC == 0x803F16)
199 WriteLog("M68K: Registers found at $803F16:\n");
200 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
201 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
202 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
204 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
205 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
207 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
208 // !!! Investigate !!!
209 /*extern bool doDSPDis;
210 static bool disgo = false;
211 if (m68kPC == 0x50222)
214 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
215 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
218 if (m68kPC == 0x5000)
223 static char buffer[2048];
224 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
225 WriteLog("%08X: %s", m68kPC, buffer);
226 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
227 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
228 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
230 if (m68kPC == 0x82E1A)
232 static char buffer[2048];
233 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
234 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
235 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
236 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
237 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
239 if (m68kPC == 0x82E58)
240 WriteLog("--> [Routine end]\n");
241 if (m68kPC == 0x80004)
243 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
244 // m68k_set_reg(M68K_REG_D2, 0x12345678);
268 if (m68kPC == 0x3000)
269 WriteLog("M68K: CD_init\n");
270 else if (m68kPC == 0x3006 + (6 * 0))
271 WriteLog("M68K: CD_mode\n");
272 else if (m68kPC == 0x3006 + (6 * 1))
273 WriteLog("M68K: CD_ack\n");
274 else if (m68kPC == 0x3006 + (6 * 2))
275 WriteLog("M68K: CD_jeri\n");
276 else if (m68kPC == 0x3006 + (6 * 3))
277 WriteLog("M68K: CD_spin\n");
278 else if (m68kPC == 0x3006 + (6 * 4))
279 WriteLog("M68K: CD_stop\n");
280 else if (m68kPC == 0x3006 + (6 * 5))
281 WriteLog("M68K: CD_mute\n");
282 else if (m68kPC == 0x3006 + (6 * 6))
283 WriteLog("M68K: CD_umute\n");
284 else if (m68kPC == 0x3006 + (6 * 7))
285 WriteLog("M68K: CD_paus\n");
286 else if (m68kPC == 0x3006 + (6 * 8))
287 WriteLog("M68K: CD_upaus\n");
288 else if (m68kPC == 0x3006 + (6 * 9))
289 WriteLog("M68K: CD_read\n");
290 else if (m68kPC == 0x3006 + (6 * 10))
291 WriteLog("M68K: CD_uread\n");
292 else if (m68kPC == 0x3006 + (6 * 11))
293 WriteLog("M68K: CD_setup\n");
294 else if (m68kPC == 0x3006 + (6 * 12))
295 WriteLog("M68K: CD_ptr\n");
296 else if (m68kPC == 0x3006 + (6 * 13))
297 WriteLog("M68K: CD_osamp\n");
298 else if (m68kPC == 0x3006 + (6 * 14))
299 WriteLog("M68K: CD_getoc\n");
300 else if (m68kPC == 0x3006 + (6 * 15))
301 WriteLog("M68K: CD_initm\n");
302 else if (m68kPC == 0x3006 + (6 * 16))
303 WriteLog("M68K: CD_initf\n");
304 else if (m68kPC == 0x3006 + (6 * 17))
305 WriteLog("M68K: CD_switch\n");
307 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
308 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
309 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
310 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
312 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
313 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
315 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
316 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
318 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
319 // keep going even when the 68K dumped back to the debugger or what have you).
321 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
322 // Try setting the vector to the illegal instruction...
323 //This doesn't work right either! Do something else! Quick!
324 // SET32(jaguar_mainRam, 0x10, m68kPC);
330 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
331 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
332 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
333 for(int i=0; i<10; i++)
334 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
335 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
339 // WriteLog("\n\n68K disasm\n\n");
340 // jaguar_dasm(0x802000, 0x50C);
351 Now here be dragons...
352 Here is how memory ranges are defined in the CoJag driver.
353 Note that we only have to be concerned with 3 entities read/writing anything:
354 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
355 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
356 things that are entirely internal to those modules. This way we should be able to get a handle on all
357 this crap which is currently scattered over Hell's Half Acre(tm).
359 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
360 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
362 /*************************************
364 * Main CPU memory handlers
366 *************************************/
368 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
369 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
370 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
371 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
372 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
373 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
374 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
375 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
376 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
377 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
378 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
379 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
380 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
381 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
382 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
383 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
384 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
385 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
386 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
387 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
388 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
389 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
390 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
393 /*************************************
395 * GPU memory handlers
397 *************************************/
399 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
400 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
401 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
402 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
403 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
404 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
405 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
406 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
407 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
408 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
409 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
412 /*************************************
414 * DSP memory handlers
416 *************************************/
418 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
419 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
420 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
421 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
422 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
423 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
424 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
425 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
426 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
431 //#define EXPERIMENTAL_MEMORY_HANDLING
432 // Experimental memory mappage...
433 // Dunno if this is a good approach or not, but it seems to make better
434 // sense to have all this crap in one spot intstead of scattered all over
435 // the place the way it is now.
436 #ifdef EXPERIMENTAL_MEMORY_HANDLING
438 #define NEW_TIMER_SYSTEM
441 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
442 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
443 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
444 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
445 bool BIOSLoaded = false;
446 bool CDBIOSLoaded = false;
449 uint8 tomRAM[0x4000];
450 uint8 jerryRAM[0x10000];
451 static uint16 eeprom_ram[64];
453 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
456 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
458 // M68K Memory map/handlers
460 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
461 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
462 // Note that this is really memory mapped I/O region...
463 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
464 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
465 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
466 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
467 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
468 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
469 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
470 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
471 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
472 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
473 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
474 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
476 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
478 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
479 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
480 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
481 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
482 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
483 //What about LBUF writes???
484 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
485 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
486 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
488 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
492 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
493 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
494 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
497 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
498 0 = pad0/1 button values (4 bits each), RO(?)
499 1 = pad0/1 index value (4 bits each), WO
501 3 = NTSC/PAL, certain button states, RO
503 JOYSTICK $F14000 Read/Write
505 Read fedcba98 7654321q f-1 Signals J15 to J1
506 q Cartridge EEPROM output data
507 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
508 0 = disable J7-J0 outputs
511 0 = Audio muted (reset state)
513 7-4 J7-J4 outputs (port 2)
514 3-0 J3-J0 outputs (port 1)
515 JOYBUTS $F14002 Read Only
517 Read xxxxxxxx rrdv3210 x don't care
520 v 1 = NTSC Video hardware
521 0 = PAL Video hardware
522 3-2 Button inputs B3 & B2 (port 2)
523 1-0 Button inputs B1 & B0 (port 1)
525 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
526 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
534 0 1 1 1 Row 3 C3 Option # 9 6 3
538 1 0 1 1 Row 2 C2 C 0 8 5 2
540 1 1 0 1 Row 1 C1 B * 7 4 1
541 1 1 1 0 Row 0 Pause A Up Down Left Right
544 0 bit read in any position means that button is pressed.
545 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
549 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
551 // Not sure, but I think the system only has 24 address bits...
552 address &= 0x00FFFFFF;
554 // RAM ($000000 - $3FFFFF) 4M
555 if (address <= 0x3FFFFF)
556 jaguarMainRAM[address] = byte;
557 // hole ($400000 - $7FFFFF) 4M
558 else if (address <= 0x7FFFFF)
560 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
561 else if (address <= 0xDFFEFF)
563 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
564 else if (address <= 0xDFFFFF)
566 cdRAM[address & 0xFF] = byte;
568 if ((address & 0xFF) < 12 * 4)
569 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
570 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
573 // BIOS ROM ($E00000 - $E3FFFF) 256K
574 else if (address <= 0xE3FFFF)
576 // hole ($E40000 - $EFFFFF) 768K
577 else if (address <= 0xEFFFFF)
579 // TOM ($F00000 - $F0FFFF) 64K
580 else if (address <= 0xF0FFFF)
583 if (address == 0xF00050)
585 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
589 else if (address == 0xF00051)
591 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
595 else if (address == 0xF00052)
597 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
601 else if (address == 0xF00053)
603 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
607 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
609 // Writing to one CLUT writes to the other
610 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
611 tomRAM[address] = tomRAM[address + 0x200] = byte;
614 //What about LBUF writes???
615 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
617 GPUWriteByte(address, byte, who);
620 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
622 BlitterWriteByte(address, byte, who);
625 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
627 GPUWriteByte(address, byte, who);
631 tomRAM[address & 0x3FFF] = byte;
633 // JERRY ($F10000 - $F1FFFF) 64K
634 else if (address <= 0xF1FFFF)
638 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
640 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
642 DSPWriteByte(address, byte, who);
645 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
647 DSPWriteByte(address, byte, who);
650 // SCLK ($F1A150--8 bits wide)
651 //NOTE: This should be taken care of in DAC...
652 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
654 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
655 if ((address & 0x03) == 2)
656 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
658 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
660 JERRYI2SInterruptTimer = -1;
661 #ifndef NEW_TIMER_SYSTEM
664 RemoveCallback(JERRYI2SCallback);
669 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
670 else if (address >= 0xF1A148 && address <= 0xF1A157)
672 DACWriteByte(address, byte, who);
675 else if (address >= 0xF10000 && address <= 0xF10007)
677 #ifndef NEW_TIMER_SYSTEM
678 switch (address & 0x07)
681 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
685 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
689 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
693 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
697 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
701 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
705 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
709 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
713 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
717 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
719 clock_byte_write(offset, byte);
722 // JERRY -> 68K interrupt enables/latches (need to be handled!)
723 else if (address >= 0xF10020 && address <= 0xF10023)
725 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
727 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
729 anajoy_byte_write(offset, byte);
732 else if ((address >= 0xF14000) && (address <= 0xF14003))
734 JoystickWriteByte(address, byte);
735 EepromWriteByte(address, byte);
738 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
740 EepromWriteByte(address, byte);
743 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
744 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
747 jerryRAM[address & 0xFFFF] = byte;
749 // hole ($F20000 - $FFFFFF) 1M - 128K
754 void WriteWord(uint32 adddress, uint16 word)
758 void WriteDWord(uint32 adddress, uint32 dword)
762 uint8 ReadByte(uint32 adddress)
766 uint16 ReadWord(uint32 adddress)
770 uint32 ReadDWord(uint32 adddress)
776 // Musashi 68000 read/write/IRQ functions
779 int irq_ack_handler(int level)
781 int vector = M68K_INT_ACK_AUTOVECTOR;
783 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
787 m68k_set_irq(0); // Clear the IRQ...
788 vector = 64; // Set user interrupt #0
794 //#define USE_NEW_MMU
796 unsigned int m68k_read_memory_8(unsigned int address)
798 #ifdef CPU_DEBUG_MEMORY
799 if ((address >= 0x000000) && (address <= 0x3FFFFF))
802 readMem[address] = 1;
805 //WriteLog("[RM8] Addr: %08X\n", address);
806 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
807 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
808 || address == 0x1AF05E)
809 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
811 unsigned int retVal = 0;
813 if ((address >= 0x000000) && (address <= 0x3FFFFF))
814 retVal = jaguarMainRAM[address];
815 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
816 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
817 retVal = jaguarMainROM[address - 0x800000];
818 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
819 retVal = jaguarBootROM[address - 0xE00000];
820 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
821 retVal = CDROMReadByte(address);
822 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
823 retVal = TOMReadByte(address, M68K);
824 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
825 retVal = JERRYReadByte(address, M68K);
827 retVal = jaguar_unknown_readbyte(address, M68K);
829 //if (address >= 0x2800 && address <= 0x281F)
830 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
831 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
832 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
835 return MMURead8(address, M68K);
839 void gpu_dump_disassembly(void);
840 void gpu_dump_registers(void);
842 unsigned int m68k_read_memory_16(unsigned int address)
844 #ifdef CPU_DEBUG_MEMORY
845 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
848 readMem[address] = 1, readMem[address + 1] = 1;
850 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
852 return 0x4E71; // NOP
854 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
856 return 0x4E71; // NOP
858 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
860 return 0x4E71; // NOP
862 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
864 return 0x4E71; // NOP
866 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
868 return 0x4E71; // NOP
870 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
872 return 0x4E71; // NOP
875 //WriteLog("[RM16] Addr: %08X\n", address);
876 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
877 // for(int i=0; i<10000; i++)
878 WriteLog("[M68K] In routine #6!\n");//*/
879 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
880 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
881 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
883 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
884 gpu_dump_registers();
885 gpu_dump_disassembly();
886 // for(int i=0; i<10000; i++)
887 // WriteLog("[M68K] About to run GPU!\n");
889 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
890 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
892 if (address == 0x000066A0)
894 gpu_dump_registers();
895 gpu_dump_disassembly();
897 for(int i=0; i<10000; i++)
898 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
900 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
901 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
902 || address == 0x1AF05E)
903 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
905 unsigned int retVal = 0;
907 if ((address >= 0x000000) && (address <= 0x3FFFFE))
908 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
909 retVal = GET16(jaguarMainRAM, address);
910 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
911 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
912 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
913 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
914 retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
915 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
916 retVal = CDROMReadWord(address, M68K);
917 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
918 retVal = TOMReadWord(address, M68K);
919 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
920 retVal = JERRYReadWord(address, M68K);
922 retVal = jaguar_unknown_readword(address, M68K);
924 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
925 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
926 //if (address >= 0x2800 && address <= 0x281F)
927 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
928 //$8B3AE -> Transferred from $F1C010
929 //$8B5E4 -> Only +1 read at $808AA
930 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
931 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
934 return MMURead16(address, M68K);
938 unsigned int m68k_read_memory_32(unsigned int address)
940 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
941 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
942 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));//*/
944 //WriteLog("--> [RM32]\n");
946 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
948 return MMURead32(address, M68K);
952 void m68k_write_memory_8(unsigned int address, unsigned int value)
954 #ifdef CPU_DEBUG_MEMORY
955 if ((address >= 0x000000) && (address <= 0x3FFFFF))
959 if (value > writeMemMax[address])
960 writeMemMax[address] = value;
961 if (value < writeMemMin[address])
962 writeMemMin[address] = value;
966 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
967 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
968 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
970 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
971 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
974 if ((address >= 0x000000) && (address <= 0x3FFFFF))
975 jaguarMainRAM[address] = value;
976 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
977 CDROMWriteByte(address, value, M68K);
978 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
979 TOMWriteByte(address, value, M68K);
980 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
981 JERRYWriteByte(address, value, M68K);
983 jaguar_unknown_writebyte(address, value, M68K);
985 MMUWrite8(address, value, M68K);
989 void m68k_write_memory_16(unsigned int address, unsigned int value)
991 #ifdef CPU_DEBUG_MEMORY
992 if ((address >= 0x000000) && (address <= 0x3FFFFE))
996 uint8 hi = value >> 8, lo = value & 0xFF;
998 if (hi > writeMemMax[address])
999 writeMemMax[address] = hi;
1000 if (hi < writeMemMin[address])
1001 writeMemMin[address] = hi;
1003 if (lo > writeMemMax[address+1])
1004 writeMemMax[address+1] = lo;
1005 if (lo < writeMemMin[address+1])
1006 writeMemMin[address+1] = lo;
1010 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1011 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1012 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1013 //if (address >= 0xF02200 && address <= 0xF0229F)
1014 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1015 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1016 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1017 /*extern uint32 totalFrames;
1018 if (address == 0xF02114)
1019 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1020 if (address == 0xF02110)
1021 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1022 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1023 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1025 /*if (address == 0x0100)//64*4)
1026 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1028 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1029 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1030 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1031 || address == 0x1AF05E)
1032 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1035 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1037 /* jaguar_mainRam[address] = value >> 8;
1038 jaguar_mainRam[address + 1] = value & 0xFF;*/
1039 SET16(jaguarMainRAM, address, value);
1041 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1042 CDROMWriteWord(address, value, M68K);
1043 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1044 TOMWriteWord(address, value, M68K);
1045 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1046 JERRYWriteWord(address, value, M68K);
1049 jaguar_unknown_writeword(address, value, M68K);
1050 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1051 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1052 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1053 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1057 MMUWrite16(address, value, M68K);
1061 void m68k_write_memory_32(unsigned int address, unsigned int value)
1063 //WriteLog("--> [WM32]\n");
1064 /*if (address == 0x0100)//64*4)
1065 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1066 /*if (address >= 0xF03214 && address < 0xF0321F)
1067 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1068 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1069 /*extern bool doGPUDis;
1070 if (address == 0xF03214 && value == 0x88E30047)
1072 doGPUDis = true;//*/
1073 /* if (address == 0x51136 || address == 0xFB074)
1074 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1077 m68k_write_memory_16(address, value >> 16);
1078 m68k_write_memory_16(address + 2, value & 0xFFFF);
1080 MMUWrite32(address, value, M68K);
1085 uint32 JaguarGetHandler(uint32 i)
1087 return JaguarReadLong(i * 4);
1090 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1092 uint32 handler = JaguarGetHandler(i);
1093 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1096 void M68K_show_context(void)
1098 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1099 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1100 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1102 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1103 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1105 WriteLog("68K disasm\n");
1106 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1107 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1108 // jaguar_dasm(0x5000, 0x14414);
1110 // WriteLog("\n.......[Cart start]...........\n\n");
1111 // jaguar_dasm(0x192000, 0x1000);//0x200);
1113 WriteLog("..................\n");
1115 if (TOMIRQEnabled(IRQ_VBLANK))
1117 WriteLog("vblank int: enabled\n");
1118 JaguarDasm(JaguarGetHandler(64), 0x200);
1121 WriteLog("vblank int: disabled\n");
1123 WriteLog("..................\n");
1125 for(int i=0; i<256; i++)
1126 WriteLog("handler %03i at $%08X\n", i, (unsigned int)JaguarGetHandler(i));
1130 // Unknown read/write byte/word routines
1133 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1134 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1136 // 807EC4: movea.l #$f1b000, A1
1137 // 807ECA: movea.l #$8129e0, A0
1138 // 807ED0: move.l A0, D0
1139 // 807ED2: move.l #$f1bb94, D1
1140 // 807ED8: sub.l D0, D1
1141 // 807EDA: lsr.l #2, D1
1142 // 807EDC: move.l (A0)+, (A1)+
1143 // 807EDE: dbra D1, 807edc
1145 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1146 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1147 // space! (That is, unless the 68K causes a bus error...)
1149 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1151 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1152 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));
1154 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1155 // extern bool finished;
1157 // extern bool doDSPDis;
1163 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1165 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1166 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));
1168 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1169 // extern bool finished;
1171 // extern bool doDSPDis;
1177 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1179 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1180 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", 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;
1192 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1194 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1195 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1197 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1198 // extern bool finished;
1200 // extern bool doDSPDis;
1208 // Disassemble M68K instructions at the given offset
1211 unsigned int m68k_read_disassembler_8(unsigned int address)
1213 return m68k_read_memory_8(address);
1216 unsigned int m68k_read_disassembler_16(unsigned int address)
1218 return m68k_read_memory_16(address);
1221 unsigned int m68k_read_disassembler_32(unsigned int address)
1223 return m68k_read_memory_32(address);
1226 void JaguarDasm(uint32 offset, uint32 qt)
1229 static char buffer[2048];//, mem[64];
1230 int pc = offset, oldpc;
1232 for(uint32 i=0; i<qt; i++)
1235 for(int j=0; j<64; j++)
1236 mem[j^0x01] = jaguar_byte_read(pc + j);
1238 pc += Dasm68000((char *)mem, buffer, 0);
1239 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1241 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
1242 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1247 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1252 if (offset < 0x400000)
1253 data = jaguarMainRAM[offset & 0x3FFFFF];
1254 else if ((offset >= 0x800000) && (offset < 0xC00000))
1255 data = jaguarMainROM[offset - 0x800000];
1256 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1257 data = CDROMReadByte(offset, who);
1258 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1259 data = jaguarBootROM[offset & 0x3FFFF];
1260 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1261 data = TOMReadByte(offset, who);
1262 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1263 data = JERRYReadByte(offset, who);
1265 data = jaguar_unknown_readbyte(offset, who);
1270 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1273 if (offset <= 0x3FFFFE)
1275 return (jaguarMainRAM[(offset+0) & 0x3FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x3FFFFF];
1277 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1280 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1282 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1283 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1284 return CDROMReadWord(offset, who);
1285 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1286 return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1287 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1288 return TOMReadWord(offset, who);
1289 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1290 return JERRYReadWord(offset, who);
1292 return jaguar_unknown_readword(offset, who);
1295 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1297 //Need to check for writes in the range of $18FA70 + 8000...
1299 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1300 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1303 if (offset < 0x400000)
1305 jaguarMainRAM[offset & 0x3FFFFF] = data;
1308 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1310 CDROMWriteByte(offset, data, who);
1313 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1315 TOMWriteByte(offset, data, who);
1318 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1320 JERRYWriteByte(offset, data, who);
1324 jaguar_unknown_writebyte(offset, data, who);
1328 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1330 /*if (offset == 0x0100)//64*4)
1331 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1332 if (offset == 0x0102)//64*4)
1333 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1334 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1335 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1336 //Need to check for writes in the range of $18FA70 + 8000...
1338 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1339 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1340 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1341 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1345 if (offset <= 0x3FFFFE)
1350 1A 69 F0 ($0000) -> Starfield
1351 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1354 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1363 //This MUST be done by the 68K!
1364 /*if (offset == 0x670C)
1365 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1367 /*extern bool doGPUDis;
1368 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1369 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1370 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1371 doGPUDis = true;//*/
1372 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1373 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1374 if ((data & 0xFF00) != 0x7700)
1375 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1376 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1378 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1379 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1380 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1382 /*extern bool doGPUDis;
1383 if (offset == 0x120216 && who == GPU)
1384 doGPUDis = true;//*/
1385 /*extern uint32 gpu_pc;
1386 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1388 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1389 uint32 y = base / 0x300;
1390 uint32 x = (base - (y * 0x300)) / 2;
1391 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1394 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1396 //if (offset == (0x001E17F8 + 0x34))
1397 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1399 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1400 /*extern uint32 gpu_pc;
1401 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1403 extern int objectPtr;
1404 // if (offset > 0x148000)
1407 if (starCount > objectPtr)
1410 // if (starCount == 1)
1411 // WriteLog("--> Drawing 1st star...\n");
1413 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1414 // uint32 y = base / 0x300;
1415 // uint32 x = (base - (y * 0x300)) / 2;
1416 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1418 //A star of interest...
1419 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1420 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1421 //JWW: Blitter writing echo 77B3 at 0011D022...
1423 //extern bool doGPUDis;
1424 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1427 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1430 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1431 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1433 jaguarMainRAM[(offset+0) & 0x3FFFFF] = data >> 8;
1434 jaguarMainRAM[(offset+1) & 0x3FFFFF] = data & 0xFF;
1437 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1439 CDROMWriteWord(offset, data, who);
1442 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1444 TOMWriteWord(offset, data, who);
1447 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1449 JERRYWriteWord(offset, data, who);
1452 // Don't bomb on attempts to write to ROM
1453 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1456 jaguar_unknown_writeword(offset, data, who);
1459 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1460 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1462 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1465 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1466 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1468 /* extern bool doDSPDis;
1469 if (offset < 0x400 && !doDSPDis)
1471 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1474 /*if (offset == 0x0100)//64*4)
1475 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1477 JaguarWriteWord(offset, data >> 16, who);
1478 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1482 // Jaguar console initialization
1484 void JaguarInit(void)
1486 #ifdef CPU_DEBUG_MEMORY
1487 memset(readMem, 0x00, 0x400000);
1488 memset(writeMemMin, 0xFF, 0x400000);
1489 memset(writeMemMax, 0x00, 0x400000);
1491 memset(jaguarMainRAM, 0x00, 0x400000);
1492 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1493 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1494 //NOTE: This *doesn't* fix FlipOut...
1495 //Or does it? Hmm...
1496 //Seems to want $01010101... Dunno why. Investigate!
1497 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1498 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1500 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1508 //New timer based code stuffola...
1509 void ScanlineCallback(void);
1510 void RenderCallback(void);
1511 //extern uint32 * backbuffer;
1512 void JaguarReset(void)
1514 //NOTE: This causes a (virtual) crash if this is set in the config but not found... !!! FIX !!!
1515 if (vjs.useJaguarBIOS)
1516 memcpy(jaguarMainRAM, jaguarBootROM, 8);
1518 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1520 // WriteLog("jaguar_reset():\n");
1526 m68k_pulse_reset(); // Reset the 68000
1527 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1529 // New timer base code stuffola...
1530 InitializeEventList();
1531 TOMResetBackbuffer(backbuffer);
1532 // SetCallbackTime(ScanlineCallback, 63.5555);
1533 SetCallbackTime(ScanlineCallback, 31.77775);
1534 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1535 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time
1538 void JaguarDone(void)
1540 #ifdef CPU_DEBUG_MEMORY
1541 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1543 for(uint32 i=0; i<=raPtr; i++)
1545 WriteLog("\t%08X\n", returnAddr[i]);
1546 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1547 jaguar_dasm(returnAddr[i] - 16, 16);
1552 /* int start = 0, end = 0;
1553 bool endTriggered = false, startTriggered = false;
1554 for(int i=0; i<0x400000; i++)
1556 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1558 if (!startTriggered)
1559 startTriggered = true, endTriggered = false, start = i;
1561 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1567 end = i - 1, endTriggered = true, startTriggered = false;
1568 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1575 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1576 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1577 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1578 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1579 for(int i=-2; i<9; i++)
1580 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1582 /* WriteLog("\nM68000 disassembly at $802288...\n");
1583 jaguar_dasm(0x802288, 3);
1584 WriteLog("\nM68000 disassembly at $802200...\n");
1585 jaguar_dasm(0x802200, 500);
1586 WriteLog("\nM68000 disassembly at $802518...\n");
1587 jaguar_dasm(0x802518, 100);//*/
1589 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1590 jaguar_dasm(0x803F00, 500);
1593 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1594 jaguar_dasm(0x802B00, 500);
1597 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1598 jaguar_dasm(0x809900, 500);
1601 /* WriteLog("\n\nDump of $8093C8:\n\n");
1602 for(int i=0x8093C8; i<0x809900; i+=4)
1603 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1604 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1605 jaguar_dasm(0x90006C, 500);
1607 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1608 jaguar_dasm(0x1AC000, 6000);
1611 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1612 WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
1613 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
1614 M68K_show_context();
1625 // Main Jaguar execution loop (1 frame)
1627 void JaguarExecute(uint32 * backbuffer, bool render)
1629 uint16 vp = TOMReadWord(0xF0003E) + 1;
1630 uint16 vi = TOMReadWord(0xF0004E);
1631 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1632 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1634 // uint16 vdb = TOMReadWord(0xF00046);
1635 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1636 // uint16 vbb = TOMReadWord(0xF00040);
1637 //It seems that they mean it when they say that VDE is the end of object processing.
1638 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1639 //buffer and not to write any more pixels... !!! FIX !!!
1640 // uint16 vde = TOMReadWord(0xF00048);
1642 uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1643 uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1644 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1645 //seem to indicate the refresh rate is *half* the above...
1646 // uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1647 // Should these be hardwired or read from VP? Yes, from VP!
1648 uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1649 uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1651 TOMResetBackbuffer(backbuffer);
1652 /*extern int effect_start;
1654 WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1656 //extern int start_logging;
1657 for(uint16 i=0; i<vp; i++)
1659 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1660 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004) + 1) & 0x7FF);
1662 TOMWriteWord(0xF00006, i); // Write the VC
1664 // if (i == vi) // Time for Vertical Interrupt?
1665 //Not sure if this is correct...
1666 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1667 //Which means that it normally wouldn't go when it's zero.
1668 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1670 // We don't have to worry about autovectors & whatnot because the Jaguar
1671 // tells you through its HW registers who sent the interrupt...
1672 TOMSetPendingVideoInt();
1676 //if (start_logging)
1677 // WriteLog("About to execute M68K (%u)...\n", i);
1678 m68k_execute(M68KCyclesPerScanline);
1679 //if (start_logging)
1680 // WriteLog("About to execute TOM's PIT (%u)...\n", i);
1681 TOMExecPIT(RISCCyclesPerScanline);
1682 //if (start_logging)
1683 // WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1684 JERRYExecPIT(RISCCyclesPerScanline);
1685 //if (start_logging)
1686 // WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1687 JERRYI2SExec(RISCCyclesPerScanline);
1688 BUTCHExec(RISCCyclesPerScanline);
1689 //if (start_logging)
1690 // WriteLog("About to execute GPU (%u)...\n", i);
1691 GPUExec(RISCCyclesPerScanline);
1695 if (vjs.usePipelinedDSP)
1696 DSPExecP2(RISCCyclesPerScanline); // Pipelined DSP execution (3 stage)...
1698 DSPExec(RISCCyclesPerScanline); // Ordinary non-pipelined DSP
1699 // DSPExecComp(RISCCyclesPerScanline); // Comparison core
1702 //if (start_logging)
1703 // WriteLog("About to execute OP (%u)...\n", i);
1704 TOMExecScanline(i, render);
1708 // Temp debugging stuff
1710 void DumpMainMemory(void)
1712 FILE * fp = fopen("./memdump.bin", "wb");
1717 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1721 uint8 * GetRamPtr(void)
1723 return jaguarMainRAM;
1727 // New Jaguar execution stack
1732 void JaguarExecuteNew(void)
1734 extern bool finished, showGUI;
1735 extern bool debounceRunKey;
1736 // Pass a message to the "joystick" code to debounce the ESC key...
1737 debounceRunKey = true;
1739 /* InitializeEventList();
1740 TOMResetBackbuffer(backbuffer);
1741 // SetCallbackTime(ScanlineCallback, 63.5555);
1742 SetCallbackTime(ScanlineCallback, 31.77775);
1743 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1744 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1745 // uint8 * keystate = SDL_GetKeyState(NULL);
1749 double timeToNextEvent = GetTimeToNextEvent();
1750 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1752 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1753 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1757 if (vjs.usePipelinedDSP)
1758 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1760 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1765 // if (keystate[SDLK_ESCAPE])
1768 // SDL_PumpEvents(); // Needed to keep the keystate current...
1773 void ScanlineCallback(void)
1775 uint16 vc = TOMReadWord(0xF00006);
1776 uint16 vp = TOMReadWord(0xF0003E) + 1;
1777 uint16 vi = TOMReadWord(0xF0004E);
1778 // uint16 vbb = TOMReadWord(0xF00040);
1784 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1785 TOMWriteWord(0xF00006, vc);
1787 //This is a crappy kludge, but maybe it'll work for now...
1788 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1789 if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1791 // We don't have to worry about autovectors & whatnot because the Jaguar
1792 // tells you through its HW registers who sent the interrupt...
1793 tom_set_pending_video_int();
1797 TOMExecScanline(vc, true);
1799 //Change this to VBB???
1800 //Doesn't seem to matter (at least for Flip Out & I-War)
1807 TOMResetBackbuffer(backbuffer);
1811 // TOMResetBackbuffer(backbuffer);
1813 // SetCallbackTime(ScanlineCallback, 63.5555);
1814 SetCallbackTime(ScanlineCallback, 31.77775);
1820 void JaguarExecuteNew(void)
1822 // extern bool finished, showGUI;
1823 // extern bool debounceRunKey;
1824 // Pass a message to the "joystick" code to debounce the ESC key...
1825 // debounceRunKey = true;
1826 // finished = false;
1827 /* InitializeEventList();
1828 TOMResetBackbuffer(backbuffer);
1829 // SetCallbackTime(ScanlineCallback, 63.5555);
1830 SetCallbackTime(ScanlineCallback, 31.77775);
1831 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1832 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1833 // uint8 * keystate = SDL_GetKeyState(NULL);
1838 double timeToNextEvent = GetTimeToNextEvent();
1839 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1841 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1842 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1846 if (vjs.usePipelinedDSP)
1847 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1849 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1854 // if (keystate[SDLK_ESCAPE])
1857 // SDL_PumpEvents(); // Needed to keep the keystate current...
1862 void ScanlineCallback(void)
1864 uint16 vc = TOMReadWord(0xF00006);
1865 uint16 vp = TOMReadWord(0xF0003E) + 1;
1866 uint16 vi = TOMReadWord(0xF0004E);
1867 // uint16 vbb = TOMReadWord(0xF00040);
1873 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1874 TOMWriteWord(0xF00006, vc);
1876 //This is a crappy kludge, but maybe it'll work for now...
1877 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1878 if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1880 // We don't have to worry about autovectors & whatnot because the Jaguar
1881 // tells you through its HW registers who sent the interrupt...
1882 TOMSetPendingVideoInt();
1886 TOMExecScanline(vc, true);
1888 //Change this to VBB???
1889 //Doesn't seem to matter (at least for Flip Out & I-War)
1894 //We comment this out so that the GUI can manage this instead. Which is how it should be anyway.
1895 // RenderBackbuffer();
1896 TOMResetBackbuffer(backbuffer);
1901 // TOMResetBackbuffer(backbuffer);
1903 // SetCallbackTime(ScanlineCallback, 63.5555);
1904 SetCallbackTime(ScanlineCallback, 31.77775);
1909 // This isn't currently used, but maybe it should be...
1910 void RenderCallback(void)
1913 TOMResetBackbuffer(backbuffer);
1914 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1915 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time