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"
38 //Do this in makefile??? Yes! Could, but it's easier to define here...
39 //#define LOG_UNMAPPED_MEMORY_ACCESSES
40 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
41 #define ABORT_ON_ILLEGAL_INSTRUCTIONS
42 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
43 #define CPU_DEBUG_MEMORY
44 //#define LOG_CD_BIOS_CALLS
46 // Private function prototypes
48 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
49 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
50 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
51 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
52 void M68K_show_context(void);
56 #ifdef CPU_DEBUG_MEMORY
57 extern bool startMemLog; // Set by "e" key
58 extern int effect_start;
59 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
62 // Really, need to include memory.h for this, but it might interfere with some stuff...
63 extern uint8 jagMemSpace[];
67 uint32 jaguar_active_memory_dumps = 0;
69 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
71 bool BIOSLoaded = false;
72 bool CDBIOSLoaded = false;
76 #ifdef CPU_DEBUG_MEMORY
77 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
78 uint8 readMem[0x400000];
79 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
82 uint32 pcQueue[0x400];
86 // Callback function to detect illegal instructions
88 void GPUDumpDisassembly(void);
89 void GPUDumpRegisters(void);
90 static bool start = false;
92 void M68KInstructionHook(void)
94 uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
97 // Ideally, we'd save all the registers as well...
98 pcQueue[pcQPtr++] = m68kPC;
101 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
103 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
105 static char buffer[2048];
106 for(int i=0; i<0x400; i++)
108 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
109 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
113 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
114 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
115 for(int i=0; i<10; i++)
116 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
117 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
123 // Disassemble everything
125 static char buffer[2048];
126 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
127 WriteLog("%08X: %s", m68kPC, buffer);
128 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
129 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
130 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
132 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
134 static char buffer[2048];
135 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
136 WriteLog("%08X: %s", m68kPC, buffer);
137 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
138 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
139 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
141 /* if (m68kPC == 0x8D0E48 && effect_start5)
143 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
145 GPUDumpDisassembly();
149 /* uint16 opcode = JaguarReadWord(m68kPC);
150 if (opcode == 0x4E75) // RTS
153 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
155 uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
157 if (raPtr != 0xFFFFFFFF)
159 for(uint32 i=0; i<=raPtr; i++)
161 if (returnAddr[i] == addr)
170 returnAddr[++raPtr] = addr;
174 //Flip Out! debugging...
177 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
178 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
179 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
180 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
182 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
184 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
185 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
186 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
187 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
188 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
189 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
190 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
192 /* static char buffer[2048];
193 //if (m68kPC > 0x805F48) start = true;
194 //if (m68kPC > 0x806486) start = true;
195 //if (m68kPC == 0x805FEE) start = true;
196 //if (m68kPC == 0x80600C)// start = true;
197 if (m68kPC == 0x802058) start = true;
199 // GPUDumpRegisters();
200 // GPUDumpDisassembly();
202 // M68K_show_context();
208 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
209 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));
212 /* if (m68kPC == 0x803F16)
214 WriteLog("M68K: Registers found at $803F16:\n");
215 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
216 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
217 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
219 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
220 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
222 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
223 // !!! Investigate !!!
224 /*extern bool doDSPDis;
225 static bool disgo = false;
226 if (m68kPC == 0x50222)
229 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
230 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
233 if (m68kPC == 0x5000)
238 static char buffer[2048];
239 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
240 WriteLog("%08X: %s", m68kPC, buffer);
241 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
242 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
243 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
245 if (m68kPC == 0x82E1A)
247 static char buffer[2048];
248 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
249 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
250 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
251 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
252 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
254 if (m68kPC == 0x82E58)
255 WriteLog("--> [Routine end]\n");
256 if (m68kPC == 0x80004)
258 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
259 // m68k_set_reg(M68K_REG_D2, 0x12345678);
262 #ifdef LOG_CD_BIOS_CALLS
285 if (m68kPC == 0x3000)
286 WriteLog("M68K: CD_init\n");
287 else if (m68kPC == 0x3006 + (6 * 0))
288 WriteLog("M68K: CD_mode\n");
289 else if (m68kPC == 0x3006 + (6 * 1))
290 WriteLog("M68K: CD_ack\n");
291 else if (m68kPC == 0x3006 + (6 * 2))
292 WriteLog("M68K: CD_jeri\n");
293 else if (m68kPC == 0x3006 + (6 * 3))
294 WriteLog("M68K: CD_spin\n");
295 else if (m68kPC == 0x3006 + (6 * 4))
296 WriteLog("M68K: CD_stop\n");
297 else if (m68kPC == 0x3006 + (6 * 5))
298 WriteLog("M68K: CD_mute\n");
299 else if (m68kPC == 0x3006 + (6 * 6))
300 WriteLog("M68K: CD_umute\n");
301 else if (m68kPC == 0x3006 + (6 * 7))
302 WriteLog("M68K: CD_paus\n");
303 else if (m68kPC == 0x3006 + (6 * 8))
304 WriteLog("M68K: CD_upaus\n");
305 else if (m68kPC == 0x3006 + (6 * 9))
306 WriteLog("M68K: CD_read\n");
307 else if (m68kPC == 0x3006 + (6 * 10))
308 WriteLog("M68K: CD_uread\n");
309 else if (m68kPC == 0x3006 + (6 * 11))
310 WriteLog("M68K: CD_setup\n");
311 else if (m68kPC == 0x3006 + (6 * 12))
312 WriteLog("M68K: CD_ptr\n");
313 else if (m68kPC == 0x3006 + (6 * 13))
314 WriteLog("M68K: CD_osamp\n");
315 else if (m68kPC == 0x3006 + (6 * 14))
316 WriteLog("M68K: CD_getoc\n");
317 else if (m68kPC == 0x3006 + (6 * 15))
318 WriteLog("M68K: CD_initm\n");
319 else if (m68kPC == 0x3006 + (6 * 16))
320 WriteLog("M68K: CD_initf\n");
321 else if (m68kPC == 0x3006 + (6 * 17))
322 WriteLog("M68K: CD_switch\n");
324 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
325 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
326 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
327 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
330 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
331 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
333 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
334 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
336 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
337 // keep going even when the 68K dumped back to the debugger or what have you).
339 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
340 // Try setting the vector to the illegal instruction...
341 //This doesn't work right either! Do something else! Quick!
342 // SET32(jaguar_mainRam, 0x10, m68kPC);
348 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
349 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
350 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
351 for(int i=0; i<10; i++)
352 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
353 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
357 // WriteLog("\n\n68K disasm\n\n");
358 // jaguar_dasm(0x802000, 0x50C);
369 Now here be dragons...
370 Here is how memory ranges are defined in the CoJag driver.
371 Note that we only have to be concerned with 3 entities read/writing anything:
372 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
373 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
374 things that are entirely internal to those modules. This way we should be able to get a handle on all
375 this crap which is currently scattered over Hell's Half Acre(tm).
377 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
378 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
380 /*************************************
382 * Main CPU memory handlers
384 *************************************/
386 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
387 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
388 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
389 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
390 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
391 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
392 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
393 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
394 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
395 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
396 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
397 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
398 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
399 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
400 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
401 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
402 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
403 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
404 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
405 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
406 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
407 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
408 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
411 /*************************************
413 * GPU memory handlers
415 *************************************/
417 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
418 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
419 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
420 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
421 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
422 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
423 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
424 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
425 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
426 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
427 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
430 /*************************************
432 * DSP memory handlers
434 *************************************/
436 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
437 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
438 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
439 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
440 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
441 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
442 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
443 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
444 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
449 //#define EXPERIMENTAL_MEMORY_HANDLING
450 // Experimental memory mappage...
451 // Dunno if this is a good approach or not, but it seems to make better
452 // sense to have all this crap in one spot intstead of scattered all over
453 // the place the way it is now.
454 #ifdef EXPERIMENTAL_MEMORY_HANDLING
456 #define NEW_TIMER_SYSTEM
459 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
460 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
461 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
462 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
463 bool BIOSLoaded = false;
464 bool CDBIOSLoaded = false;
467 uint8 tomRAM[0x4000];
468 uint8 jerryRAM[0x10000];
469 static uint16 eeprom_ram[64];
471 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
474 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
476 // M68K Memory map/handlers
478 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
479 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
480 // Note that this is really memory mapped I/O region...
481 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
482 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
483 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
484 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
485 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
486 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
487 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
488 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
489 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
490 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
491 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
492 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
494 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
496 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
497 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
498 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
499 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
500 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
501 //What about LBUF writes???
502 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
503 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
504 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
506 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
510 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
511 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
512 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
515 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
516 0 = pad0/1 button values (4 bits each), RO(?)
517 1 = pad0/1 index value (4 bits each), WO
519 3 = NTSC/PAL, certain button states, RO
521 JOYSTICK $F14000 Read/Write
523 Read fedcba98 7654321q f-1 Signals J15 to J1
524 q Cartridge EEPROM output data
525 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
526 0 = disable J7-J0 outputs
529 0 = Audio muted (reset state)
531 7-4 J7-J4 outputs (port 2)
532 3-0 J3-J0 outputs (port 1)
533 JOYBUTS $F14002 Read Only
535 Read xxxxxxxx rrdv3210 x don't care
538 v 1 = NTSC Video hardware
539 0 = PAL Video hardware
540 3-2 Button inputs B3 & B2 (port 2)
541 1-0 Button inputs B1 & B0 (port 1)
543 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
544 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
552 0 1 1 1 Row 3 C3 Option # 9 6 3
556 1 0 1 1 Row 2 C2 C 0 8 5 2
558 1 1 0 1 Row 1 C1 B * 7 4 1
559 1 1 1 0 Row 0 Pause A Up Down Left Right
562 0 bit read in any position means that button is pressed.
563 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
567 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
569 // Not sure, but I think the system only has 24 address bits...
570 address &= 0x00FFFFFF;
572 // RAM ($000000 - $3FFFFF) 4M
573 if (address <= 0x3FFFFF)
574 jaguarMainRAM[address] = byte;
575 // hole ($400000 - $7FFFFF) 4M
576 else if (address <= 0x7FFFFF)
578 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
579 else if (address <= 0xDFFEFF)
581 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
582 else if (address <= 0xDFFFFF)
584 cdRAM[address & 0xFF] = byte;
586 if ((address & 0xFF) < 12 * 4)
587 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
588 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
591 // BIOS ROM ($E00000 - $E3FFFF) 256K
592 else if (address <= 0xE3FFFF)
594 // hole ($E40000 - $EFFFFF) 768K
595 else if (address <= 0xEFFFFF)
597 // TOM ($F00000 - $F0FFFF) 64K
598 else if (address <= 0xF0FFFF)
601 if (address == 0xF00050)
603 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
607 else if (address == 0xF00051)
609 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
613 else if (address == 0xF00052)
615 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
619 else if (address == 0xF00053)
621 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
625 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
627 // Writing to one CLUT writes to the other
628 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
629 tomRAM[address] = tomRAM[address + 0x200] = byte;
632 //What about LBUF writes???
633 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
635 GPUWriteByte(address, byte, who);
638 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
640 BlitterWriteByte(address, byte, who);
643 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
645 GPUWriteByte(address, byte, who);
649 tomRAM[address & 0x3FFF] = byte;
651 // JERRY ($F10000 - $F1FFFF) 64K
652 else if (address <= 0xF1FFFF)
656 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
658 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
660 DSPWriteByte(address, byte, who);
663 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
665 DSPWriteByte(address, byte, who);
668 // SCLK ($F1A150--8 bits wide)
669 //NOTE: This should be taken care of in DAC...
670 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
672 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
673 if ((address & 0x03) == 2)
674 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
676 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
678 JERRYI2SInterruptTimer = -1;
679 #ifndef NEW_TIMER_SYSTEM
682 RemoveCallback(JERRYI2SCallback);
687 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
688 else if (address >= 0xF1A148 && address <= 0xF1A157)
690 DACWriteByte(address, byte, who);
693 else if (address >= 0xF10000 && address <= 0xF10007)
695 #ifndef NEW_TIMER_SYSTEM
696 switch (address & 0x07)
699 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
703 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
707 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
711 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
715 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
719 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
723 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
727 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
731 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
735 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
737 clock_byte_write(offset, byte);
740 // JERRY -> 68K interrupt enables/latches (need to be handled!)
741 else if (address >= 0xF10020 && address <= 0xF10023)
743 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
745 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
747 anajoy_byte_write(offset, byte);
750 else if ((address >= 0xF14000) && (address <= 0xF14003))
752 JoystickWriteByte(address, byte);
753 EepromWriteByte(address, byte);
756 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
758 EepromWriteByte(address, byte);
761 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
762 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
765 jerryRAM[address & 0xFFFF] = byte;
767 // hole ($F20000 - $FFFFFF) 1M - 128K
772 void WriteWord(uint32 adddress, uint16 word)
776 void WriteDWord(uint32 adddress, uint32 dword)
780 uint8 ReadByte(uint32 adddress)
784 uint16 ReadWord(uint32 adddress)
788 uint32 ReadDWord(uint32 adddress)
794 // Musashi 68000 read/write/IRQ functions
801 IPL Name Vector Control
802 ---------+---------------+---------------+---------------
803 2 VBLANK IRQ $100 INT1 bit #0
804 2 GPU IRQ $100 INT1 bit #1
805 2 HBLANK IRQ $100 INT1 bit #2
806 2 Timer IRQ $100 INT1 bit #3
808 Note: Both timer interrupts (JPIT && PIT) are on the same INT1 bit.
809 and are therefore indistinguishable.
811 A typical way to install a LEVEL2 handler for the 68000 would be
812 something like this, you gotta supply "last_line" and "handler".
813 Note that the interrupt is auto vectored thru $100 (not $68)
821 IRQS_HANDLED=$909 ;; VBLANK and TIMER
823 move.w #$2700,sr ;; no IRQs please
824 move.l #handler,V_AUTO ;; install our routine
826 move.w #last_line,VI ;; scanline where IRQ should occur
827 ;; should be 'odd' BTW
828 move.w #IRQS_HANDLE&$FF,INT1 ;; enable VBLANK + TIMER
829 move.w #$2100,sr ;; enable IRQs on the 68K
847 move.w #IRQS_HANDLED,INT1 ; clear latch, keep IRQ alive
848 move.w #0,INT2 ; let GPU run again
852 As you can see, if you have multiple INT1 interrupts coming in,
853 you need to check the lower byte of INT1, to see which interrupt
856 int irq_ack_handler(int level)
858 // Tracing the IPL lines on the Jaguar schematic yields the following:
859 // IPL1 is connected to INTL on TOM (OUT to 68K)
860 // IPL0-2 are also tied to Vcc via 4.7K resistors!
861 // (DINT on TOM goes into DINT on JERRY (IN from Jerry))
862 // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
863 // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
865 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
866 // They aren't, and this causes problems with a, err, specific ROM. :-D
870 m68k_set_irq(0); // Clear the IRQ (NOTE: Without this, the BIOS fails)...
871 return 64; // Set user interrupt #0
874 return M68K_INT_ACK_AUTOVECTOR;
877 //#define USE_NEW_MMU
879 unsigned int m68k_read_memory_8(unsigned int address)
881 #ifdef CPU_DEBUG_MEMORY
882 if ((address >= 0x000000) && (address <= 0x3FFFFF))
885 readMem[address] = 1;
888 //WriteLog("[RM8] Addr: %08X\n", address);
889 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
890 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
891 || address == 0x1AF05E)
892 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
894 unsigned int retVal = 0;
896 if ((address >= 0x000000) && (address <= 0x3FFFFF))
897 retVal = jaguarMainRAM[address];
898 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
899 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
900 retVal = jaguarMainROM[address - 0x800000];
901 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
902 // retVal = jaguarBootROM[address - 0xE00000];
903 // retVal = jaguarDevBootROM1[address - 0xE00000];
904 retVal = jagMemSpace[address];
905 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
906 retVal = CDROMReadByte(address);
907 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
908 retVal = TOMReadByte(address, M68K);
909 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
910 retVal = JERRYReadByte(address, M68K);
912 retVal = jaguar_unknown_readbyte(address, M68K);
914 //if (address >= 0x2800 && address <= 0x281F)
915 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
916 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
917 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
920 return MMURead8(address, M68K);
924 void gpu_dump_disassembly(void);
925 void gpu_dump_registers(void);
927 unsigned int m68k_read_memory_16(unsigned int address)
929 #ifdef CPU_DEBUG_MEMORY
930 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
933 readMem[address] = 1, readMem[address + 1] = 1;
935 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
937 return 0x4E71; // NOP
939 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
941 return 0x4E71; // NOP
943 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
945 return 0x4E71; // NOP
947 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
949 return 0x4E71; // NOP
951 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
953 return 0x4E71; // NOP
955 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
957 return 0x4E71; // NOP
960 //WriteLog("[RM16] Addr: %08X\n", address);
961 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
962 // for(int i=0; i<10000; i++)
963 WriteLog("[M68K] In routine #6!\n");//*/
964 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
965 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
966 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
968 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
969 gpu_dump_registers();
970 gpu_dump_disassembly();
971 // for(int i=0; i<10000; i++)
972 // WriteLog("[M68K] About to run GPU!\n");
974 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
975 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
977 if (address == 0x000066A0)
979 gpu_dump_registers();
980 gpu_dump_disassembly();
982 for(int i=0; i<10000; i++)
983 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
985 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
986 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
987 || address == 0x1AF05E)
988 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
990 unsigned int retVal = 0;
992 if ((address >= 0x000000) && (address <= 0x3FFFFE))
993 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
994 retVal = GET16(jaguarMainRAM, address);
995 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
996 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
997 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
998 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
999 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1000 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1001 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1002 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1003 retVal = CDROMReadWord(address, M68K);
1004 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1005 retVal = TOMReadWord(address, M68K);
1006 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1007 retVal = JERRYReadWord(address, M68K);
1009 retVal = jaguar_unknown_readword(address, M68K);
1011 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
1012 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1013 //if (address >= 0x2800 && address <= 0x281F)
1014 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1015 //$8B3AE -> Transferred from $F1C010
1016 //$8B5E4 -> Only +1 read at $808AA
1017 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1018 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1021 return MMURead16(address, M68K);
1025 unsigned int m68k_read_memory_32(unsigned int address)
1027 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1028 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1029 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));//*/
1031 //WriteLog("--> [RM32]\n");
1033 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1035 return MMURead32(address, M68K);
1039 void m68k_write_memory_8(unsigned int address, unsigned int value)
1041 #ifdef CPU_DEBUG_MEMORY
1042 if ((address >= 0x000000) && (address <= 0x3FFFFF))
1046 if (value > writeMemMax[address])
1047 writeMemMax[address] = value;
1048 if (value < writeMemMin[address])
1049 writeMemMin[address] = value;
1053 /*if (address == 0x4E00)
1054 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1055 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1056 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
1057 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1059 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1060 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1063 if ((address >= 0x000000) && (address <= 0x3FFFFF))
1064 jaguarMainRAM[address] = value;
1065 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1066 CDROMWriteByte(address, value, M68K);
1067 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1068 TOMWriteByte(address, value, M68K);
1069 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1070 JERRYWriteByte(address, value, M68K);
1072 jaguar_unknown_writebyte(address, value, M68K);
1074 MMUWrite8(address, value, M68K);
1078 void m68k_write_memory_16(unsigned int address, unsigned int value)
1080 #ifdef CPU_DEBUG_MEMORY
1081 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1085 uint8 hi = value >> 8, lo = value & 0xFF;
1087 if (hi > writeMemMax[address])
1088 writeMemMax[address] = hi;
1089 if (hi < writeMemMin[address])
1090 writeMemMin[address] = hi;
1092 if (lo > writeMemMax[address+1])
1093 writeMemMax[address+1] = lo;
1094 if (lo < writeMemMin[address+1])
1095 writeMemMin[address+1] = lo;
1099 /*if (address == 0x4E00)
1100 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1101 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1102 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1103 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1104 //if (address >= 0xF02200 && address <= 0xF0229F)
1105 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1106 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1107 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1108 /*extern uint32 totalFrames;
1109 if (address == 0xF02114)
1110 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1111 if (address == 0xF02110)
1112 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1113 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1114 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1116 /*if (address == 0x0100)//64*4)
1117 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1119 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1120 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1121 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1122 || address == 0x1AF05E)
1123 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1126 if ((address >= 0x000000) && (address <= 0x3FFFFE))
1128 /* jaguar_mainRam[address] = value >> 8;
1129 jaguar_mainRam[address + 1] = value & 0xFF;*/
1130 SET16(jaguarMainRAM, address, value);
1132 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1133 CDROMWriteWord(address, value, M68K);
1134 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1135 TOMWriteWord(address, value, M68K);
1136 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1137 JERRYWriteWord(address, value, M68K);
1140 jaguar_unknown_writeword(address, value, M68K);
1141 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1142 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1143 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1144 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1148 MMUWrite16(address, value, M68K);
1152 void m68k_write_memory_32(unsigned int address, unsigned int value)
1154 /*if (address == 0x4E00)
1155 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1156 //WriteLog("--> [WM32]\n");
1157 /*if (address == 0x0100)//64*4)
1158 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1159 /*if (address >= 0xF03214 && address < 0xF0321F)
1160 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1161 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1162 /*extern bool doGPUDis;
1163 if (address == 0xF03214 && value == 0x88E30047)
1165 doGPUDis = true;//*/
1166 /* if (address == 0x51136 || address == 0xFB074)
1167 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1170 m68k_write_memory_16(address, value >> 16);
1171 m68k_write_memory_16(address + 2, value & 0xFFFF);
1173 MMUWrite32(address, value, M68K);
1178 uint32 JaguarGetHandler(uint32 i)
1180 return JaguarReadLong(i * 4);
1183 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1185 uint32 handler = JaguarGetHandler(i);
1186 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1189 void M68K_show_context(void)
1191 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1192 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1193 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1195 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1196 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1198 WriteLog("68K disasm\n");
1199 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1200 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1201 // jaguar_dasm(0x5000, 0x14414);
1203 // WriteLog("\n.......[Cart start]...........\n\n");
1204 // jaguar_dasm(0x192000, 0x1000);//0x200);
1206 WriteLog("..................\n");
1208 if (TOMIRQEnabled(IRQ_VBLANK))
1210 WriteLog("video int: enabled\n");
1211 JaguarDasm(JaguarGetHandler(64), 0x200);
1214 WriteLog("video int: disabled\n");
1216 WriteLog("..................\n");
1218 for(int i=0; i<256; i++)
1220 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1221 uint32 address = (uint32)JaguarGetHandler(i);
1224 WriteLog(".........\n");
1226 WriteLog("$%08X\n", address);
1231 // Unknown read/write byte/word routines
1234 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1235 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1237 // 807EC4: movea.l #$f1b000, A1
1238 // 807ECA: movea.l #$8129e0, A0
1239 // 807ED0: move.l A0, D0
1240 // 807ED2: move.l #$f1bb94, D1
1241 // 807ED8: sub.l D0, D1
1242 // 807EDA: lsr.l #2, D1
1243 // 807EDC: move.l (A0)+, (A1)+
1244 // 807EDE: dbra D1, 807edc
1246 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1247 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1248 // space! (That is, unless the 68K causes a bus error...)
1250 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1252 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1253 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));
1255 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1256 // extern bool finished;
1258 // extern bool doDSPDis;
1264 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1266 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1267 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));
1269 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1270 // extern bool finished;
1272 // extern bool doDSPDis;
1278 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1280 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1281 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1283 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1284 // extern bool finished;
1286 // extern bool doDSPDis;
1293 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1295 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1296 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1298 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1299 // extern bool finished;
1301 // extern bool doDSPDis;
1309 // Disassemble M68K instructions at the given offset
1312 unsigned int m68k_read_disassembler_8(unsigned int address)
1314 return m68k_read_memory_8(address);
1317 unsigned int m68k_read_disassembler_16(unsigned int address)
1319 return m68k_read_memory_16(address);
1322 unsigned int m68k_read_disassembler_32(unsigned int address)
1324 return m68k_read_memory_32(address);
1327 void JaguarDasm(uint32 offset, uint32 qt)
1330 static char buffer[2048];//, mem[64];
1331 int pc = offset, oldpc;
1333 for(uint32 i=0; i<qt; i++)
1336 for(int j=0; j<64; j++)
1337 mem[j^0x01] = jaguar_byte_read(pc + j);
1339 pc += Dasm68000((char *)mem, buffer, 0);
1340 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1342 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
1343 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1348 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1353 if (offset < 0x400000)
1354 data = jaguarMainRAM[offset & 0x3FFFFF];
1355 else if ((offset >= 0x800000) && (offset < 0xC00000))
1356 data = jaguarMainROM[offset - 0x800000];
1357 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1358 data = CDROMReadByte(offset, who);
1359 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1360 // data = jaguarBootROM[offset & 0x3FFFF];
1361 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1362 data = jagMemSpace[offset];
1363 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1364 data = TOMReadByte(offset, who);
1365 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1366 data = JERRYReadByte(offset, who);
1368 data = jaguar_unknown_readbyte(offset, who);
1373 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1376 if (offset <= 0x3FFFFE)
1378 return (jaguarMainRAM[(offset+0) & 0x3FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x3FFFFF];
1380 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1383 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1385 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1386 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1387 return CDROMReadWord(offset, who);
1388 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1389 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1390 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1391 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1392 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1393 return TOMReadWord(offset, who);
1394 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1395 return JERRYReadWord(offset, who);
1397 return jaguar_unknown_readword(offset, who);
1400 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1402 /* if (offset >= 0x4E00 && offset < 0x4E04)
1403 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1404 //Need to check for writes in the range of $18FA70 + 8000...
1406 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1407 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1410 if (offset < 0x400000)
1412 jaguarMainRAM[offset & 0x3FFFFF] = data;
1415 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1417 CDROMWriteByte(offset, data, who);
1420 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1422 TOMWriteByte(offset, data, who);
1425 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1427 JERRYWriteByte(offset, data, who);
1431 jaguar_unknown_writebyte(offset, data, who);
1435 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1437 /* if (offset >= 0x4E00 && offset < 0x4E04)
1438 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1439 /*if (offset == 0x0100)//64*4)
1440 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1441 if (offset == 0x0102)//64*4)
1442 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1443 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1444 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1445 //Need to check for writes in the range of $18FA70 + 8000...
1447 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1448 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1449 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1450 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1454 if (offset <= 0x3FFFFE)
1459 1A 69 F0 ($0000) -> Starfield
1460 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1463 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1472 //This MUST be done by the 68K!
1473 /*if (offset == 0x670C)
1474 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1476 /*extern bool doGPUDis;
1477 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1478 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1479 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1480 doGPUDis = true;//*/
1481 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1482 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1483 if ((data & 0xFF00) != 0x7700)
1484 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1485 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1487 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1488 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1489 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1491 /*extern bool doGPUDis;
1492 if (offset == 0x120216 && who == GPU)
1493 doGPUDis = true;//*/
1494 /*extern uint32 gpu_pc;
1495 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1497 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1498 uint32 y = base / 0x300;
1499 uint32 x = (base - (y * 0x300)) / 2;
1500 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1503 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1505 //if (offset == (0x001E17F8 + 0x34))
1506 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1508 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1509 /*extern uint32 gpu_pc;
1510 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1512 extern int objectPtr;
1513 // if (offset > 0x148000)
1516 if (starCount > objectPtr)
1519 // if (starCount == 1)
1520 // WriteLog("--> Drawing 1st star...\n");
1522 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1523 // uint32 y = base / 0x300;
1524 // uint32 x = (base - (y * 0x300)) / 2;
1525 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1527 //A star of interest...
1528 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1529 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1530 //JWW: Blitter writing echo 77B3 at 0011D022...
1532 //extern bool doGPUDis;
1533 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1536 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1539 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1540 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1542 jaguarMainRAM[(offset+0) & 0x3FFFFF] = data >> 8;
1543 jaguarMainRAM[(offset+1) & 0x3FFFFF] = data & 0xFF;
1546 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1548 CDROMWriteWord(offset, data, who);
1551 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1553 TOMWriteWord(offset, data, who);
1556 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1558 JERRYWriteWord(offset, data, who);
1561 // Don't bomb on attempts to write to ROM
1562 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1565 jaguar_unknown_writeword(offset, data, who);
1568 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1569 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1571 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1574 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1575 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1577 /* extern bool doDSPDis;
1578 if (offset < 0x400 && !doDSPDis)
1580 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1583 /*if (offset == 0x0100)//64*4)
1584 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1586 JaguarWriteWord(offset, data >> 16, who);
1587 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1591 // Jaguar console initialization
1593 void JaguarInit(void)
1595 #ifdef CPU_DEBUG_MEMORY
1596 memset(readMem, 0x00, 0x400000);
1597 memset(writeMemMin, 0xFF, 0x400000);
1598 memset(writeMemMax, 0x00, 0x400000);
1600 memset(jaguarMainRAM, 0x00, 0x400000);
1601 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1602 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1603 //NOTE: This *doesn't* fix FlipOut...
1604 //Or does it? Hmm...
1605 //Seems to want $01010101... Dunno why. Investigate!
1606 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1607 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1609 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1617 //New timer based code stuffola...
1618 void ScanlineCallback(void);
1619 void RenderCallback(void);
1620 //extern uint32 * backbuffer;
1621 void JaguarReset(void)
1623 //Need to change this so it uses the single RAM space and load the BIOS
1624 //into it somewhere...
1625 //Also, have to change this here and in JaguarReadXX() currently
1626 // Only use the system BIOS if it's available...! (it's always available now!)
1627 if (vjs.useJaguarBIOS && !vjs.hardwareTypeAlpine)
1628 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1630 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1632 // WriteLog("jaguar_reset():\n");
1638 m68k_pulse_reset(); // Reset the 68000
1639 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1641 // New timer base code stuffola...
1642 InitializeEventList();
1643 TOMResetBackbuffer(backbuffer);
1644 // SetCallbackTime(ScanlineCallback, 63.5555);
1645 SetCallbackTime(ScanlineCallback, 31.77775);
1646 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1647 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time
1650 void JaguarDone(void)
1652 #ifdef CPU_DEBUG_MEMORY
1653 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1655 for(uint32 i=0; i<=raPtr; i++)
1657 WriteLog("\t%08X\n", returnAddr[i]);
1658 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1659 jaguar_dasm(returnAddr[i] - 16, 16);
1664 /* int start = 0, end = 0;
1665 bool endTriggered = false, startTriggered = false;
1666 for(int i=0; i<0x400000; i++)
1668 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1670 if (!startTriggered)
1671 startTriggered = true, endTriggered = false, start = i;
1673 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1679 end = i - 1, endTriggered = true, startTriggered = false;
1680 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1687 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1688 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1689 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1690 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1691 for(int i=-2; i<9; i++)
1692 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1694 /* WriteLog("\nM68000 disassembly at $802288...\n");
1695 jaguar_dasm(0x802288, 3);
1696 WriteLog("\nM68000 disassembly at $802200...\n");
1697 jaguar_dasm(0x802200, 500);
1698 WriteLog("\nM68000 disassembly at $802518...\n");
1699 jaguar_dasm(0x802518, 100);//*/
1701 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1702 jaguar_dasm(0x803F00, 500);
1705 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1706 jaguar_dasm(0x802B00, 500);
1709 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1710 jaguar_dasm(0x809900, 500);
1713 /* WriteLog("\n\nDump of $8093C8:\n\n");
1714 for(int i=0x8093C8; i<0x809900; i+=4)
1715 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1716 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1717 jaguar_dasm(0x90006C, 500);
1719 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1720 jaguar_dasm(0x1AC000, 6000);
1723 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1724 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1725 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VBLANK))
1726 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1727 M68K_show_context();
1730 #if 0 // This is drawn already...
1731 WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1732 for(uint32 i=0x64; i<=0x7C; i+=4)
1733 WriteLog(" #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1742 // temp, until debugger is in place
1743 //00802016: jsr $836F1A.l
1744 //0080201C: jsr $836B30.l
1745 //00802022: jsr $836B18.l
1746 //00802028: jsr $8135F0.l
1747 //00813C1E: jsr $813F76.l
1748 //00802038: jsr $836D00.l
1749 //00802098: jsr $8373A4.l
1750 //008020A2: jsr $83E24A.l
1751 //008020BA: jsr $83E156.l
1752 //008020C6: jsr $83E19C.l
1753 //008020E6: jsr $8445E8.l
1754 //008020EC: jsr $838C20.l
1755 //0080211A: jsr $838ED6.l
1756 //00802124: jsr $89CA56.l
1757 //0080212A: jsr $802B48.l
1759 WriteLog("-------------------------------------------\n");
1760 JaguarDasm(0x8445E8, 0x200);
1761 WriteLog("-------------------------------------------\n");
1762 JaguarDasm(0x838C20, 0x200);
1763 WriteLog("-------------------------------------------\n");
1764 JaguarDasm(0x838ED6, 0x200);
1765 WriteLog("-------------------------------------------\n");
1766 JaguarDasm(0x89CA56, 0x200);
1767 WriteLog("-------------------------------------------\n");
1768 JaguarDasm(0x802B48, 0x200);
1769 WriteLog("\n\nM68000 disassembly at $802000...\n");
1770 JaguarDasm(0x802000, 6000);
1776 // Main Jaguar execution loop (1 frame)
1778 void JaguarExecute(uint32 * backbuffer, bool render)
1780 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
1781 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
1782 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1783 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1785 // uint16 vdb = TOMReadWord(0xF00046, JAGUAR);
1786 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1787 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
1788 //It seems that they mean it when they say that VDE is the end of object processing.
1789 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1790 //buffer and not to write any more pixels... !!! FIX !!!
1791 // uint16 vde = TOMReadWord(0xF00048, JAGUAR);
1793 uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1794 uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1795 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1796 //seem to indicate the refresh rate is *half* the above...
1797 // uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1798 // Should these be hardwired or read from VP? Yes, from VP!
1799 uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1800 uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1802 TOMResetBackbuffer(backbuffer);
1803 /*extern int effect_start;
1805 WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1807 //extern int start_logging;
1808 for(uint16 i=0; i<vp; i++)
1810 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1811 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004, JAGUAR) + 1) & 0x7FF, JAGUAR);
1813 TOMWriteWord(0xF00006, i, JAGUAR); // Write the VC
1815 // if (i == vi) // Time for Vertical Interrupt?
1816 //Not sure if this is correct...
1817 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1818 //Which means that it normally wouldn't go when it's zero.
1819 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1821 // We don't have to worry about autovectors & whatnot because the Jaguar
1822 // tells you through its HW registers who sent the interrupt...
1823 TOMSetPendingVideoInt();
1827 //if (start_logging)
1828 // WriteLog("About to execute M68K (%u)...\n", i);
1829 m68k_execute(M68KCyclesPerScanline);
1830 //if (start_logging)
1831 // WriteLog("About to execute TOM's PIT (%u)...\n", i);
1832 TOMExecPIT(RISCCyclesPerScanline);
1833 //if (start_logging)
1834 // WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1835 JERRYExecPIT(RISCCyclesPerScanline);
1836 //if (start_logging)
1837 // WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1838 JERRYI2SExec(RISCCyclesPerScanline);
1839 BUTCHExec(RISCCyclesPerScanline);
1840 //if (start_logging)
1841 // WriteLog("About to execute GPU (%u)...\n", i);
1843 GPUExec(RISCCyclesPerScanline);
1847 if (vjs.usePipelinedDSP)
1848 DSPExecP2(RISCCyclesPerScanline); // Pipelined DSP execution (3 stage)...
1850 DSPExec(RISCCyclesPerScanline); // Ordinary non-pipelined DSP
1851 // DSPExecComp(RISCCyclesPerScanline); // Comparison core
1854 //if (start_logging)
1855 // WriteLog("About to execute OP (%u)...\n", i);
1856 TOMExecScanline(i, render);
1860 // Temp debugging stuff
1862 void DumpMainMemory(void)
1864 FILE * fp = fopen("./memdump.bin", "wb");
1869 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1873 uint8 * GetRamPtr(void)
1875 return jaguarMainRAM;
1879 // New Jaguar execution stack
1884 void JaguarExecuteNew(void)
1886 extern bool finished, showGUI;
1887 extern bool debounceRunKey;
1888 // Pass a message to the "joystick" code to debounce the ESC key...
1889 debounceRunKey = true;
1891 /* InitializeEventList();
1892 TOMResetBackbuffer(backbuffer);
1893 // SetCallbackTime(ScanlineCallback, 63.5555);
1894 SetCallbackTime(ScanlineCallback, 31.77775);
1895 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1896 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1897 // uint8 * keystate = SDL_GetKeyState(NULL);
1901 double timeToNextEvent = GetTimeToNextEvent();
1902 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1904 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1905 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1909 if (vjs.usePipelinedDSP)
1910 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
1912 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
1917 // if (keystate[SDLK_ESCAPE])
1920 // SDL_PumpEvents(); // Needed to keep the keystate current...
1925 void ScanlineCallback(void)
1927 uint16 vc = TOMReadWord(0xF00006, JAGUAR);
1928 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
1929 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
1930 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
1936 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1937 TOMWriteWord(0xF00006, vc, JAGUAR);
1939 //This is a crappy kludge, but maybe it'll work for now...
1940 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1941 if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
1943 // We don't have to worry about autovectors & whatnot because the Jaguar
1944 // tells you through its HW registers who sent the interrupt...
1945 tom_set_pending_video_int();
1949 TOMExecScanline(vc, true);
1951 //Change this to VBB???
1952 //Doesn't seem to matter (at least for Flip Out & I-War)
1959 TOMResetBackbuffer(backbuffer);
1963 // TOMResetBackbuffer(backbuffer);
1965 // SetCallbackTime(ScanlineCallback, 63.5555);
1966 SetCallbackTime(ScanlineCallback, 31.77775);
1972 void JaguarExecuteNew(void)
1974 // extern bool finished, showGUI;
1975 // extern bool debounceRunKey;
1976 // Pass a message to the "joystick" code to debounce the ESC key...
1977 // debounceRunKey = true;
1978 // finished = false;
1979 /* InitializeEventList();
1980 TOMResetBackbuffer(backbuffer);
1981 // SetCallbackTime(ScanlineCallback, 63.5555);
1982 SetCallbackTime(ScanlineCallback, 31.77775);
1983 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
1984 // SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time//*/
1985 // uint8 * keystate = SDL_GetKeyState(NULL);
1990 double timeToNextEvent = GetTimeToNextEvent();
1991 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1993 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1996 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2000 if (vjs.usePipelinedDSP)
2001 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)...
2003 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP
2008 // if (keystate[SDLK_ESCAPE])
2011 // SDL_PumpEvents(); // Needed to keep the keystate current...
2016 void ScanlineCallback(void)
2018 uint16 vc = TOMReadWord(0xF00006, JAGUAR);
2019 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2020 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
2021 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
2027 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2028 TOMWriteWord(0xF00006, vc, JAGUAR);
2030 //This is a crappy kludge, but maybe it'll work for now...
2031 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2032 if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK)) // Time for Vertical Interrupt?
2034 // We don't have to worry about autovectors & whatnot because the Jaguar
2035 // tells you through its HW registers who sent the interrupt...
2036 TOMSetPendingVideoInt();
2040 TOMExecScanline(vc, true);
2042 //Change this to VBB???
2043 //Doesn't seem to matter (at least for Flip Out & I-War)
2048 //We comment this out so that the GUI can manage this instead. Which is how it should be anyway.
2049 // RenderBackbuffer();
2050 TOMResetBackbuffer(backbuffer);
2055 // TOMResetBackbuffer(backbuffer);
2057 // SetCallbackTime(ScanlineCallback, 63.5555);
2058 SetCallbackTime(ScanlineCallback, 31.77775);
2063 // This isn't currently used, but maybe it should be...
2064 void RenderCallback(void)
2066 // RenderBackbuffer();
2067 TOMResetBackbuffer(backbuffer);
2068 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2069 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time