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 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 Hammons
13 // --- ---------- -----------------------------------------------------------
14 // JLH 11/25/2009 Major rewrite of memory subsystem and handlers
21 #include "SDL_opengl.h"
32 #include "m68000/m68kinterface.h"
39 //Do this in makefile??? Yes! Could, but it's easier to define here...
40 //#define LOG_UNMAPPED_MEMORY_ACCESSES
41 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
42 //#define ABORT_ON_ILLEGAL_INSTRUCTIONS
43 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
44 #define CPU_DEBUG_MEMORY
45 //#define LOG_CD_BIOS_CALLS
46 #define CPU_DEBUG_TRACING
48 // Private function prototypes
50 unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who = UNKNOWN);
51 unsigned jaguar_unknown_readword(unsigned address, uint32_t who = UNKNOWN);
52 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who = UNKNOWN);
53 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who = UNKNOWN);
54 void M68K_show_context(void);
58 #ifdef CPU_DEBUG_MEMORY
59 extern bool startMemLog; // Set by "e" key
60 extern int effect_start;
61 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
64 // Really, need to include memory.h for this, but it might interfere with some stuff...
65 extern uint8_t jagMemSpace[];
69 uint32_t jaguar_active_memory_dumps = 0;
71 uint32_t jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
72 bool jaguarCartInserted = false;
73 bool lowerField = false;
75 #ifdef CPU_DEBUG_MEMORY
76 uint8_t writeMemMax[0x400000], writeMemMin[0x400000];
77 uint8_t readMem[0x400000];
78 uint32_t returnAddr[4000], raPtr = 0xFFFFFFFF;
81 uint32_t pcQueue[0x400];
83 bool startM68KTracing = false;
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_t m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
95 // Temp, for comparing...
97 /* static char buffer[2048];//, mem[64];
98 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
99 printf("%08X: %s\n", m68kPC, buffer);//*/
101 //JaguarDasm(m68kPC, 1);
102 //Testing Hover Strike...
105 static int hitCount = 0;
106 static int inRoutine = 0;
109 //if (regs.pc == 0x80340A)
110 if (m68kPC == 0x803416)
115 printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1));
117 else if (m68kPC == 0x803422)
120 printf("(%i instructions)\n", instSeen);
127 // For code tracing...
128 #ifdef CPU_DEBUG_TRACING
129 if (startM68KTracing)
131 static char buffer[2048];
133 m68k_disassemble(buffer, m68kPC, 0);
134 WriteLog("%06X: %s\n", m68kPC, buffer);
139 // Ideally, we'd save all the registers as well...
140 pcQueue[pcQPtr++] = m68kPC;
143 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
145 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
147 static char buffer[2048];
148 for(int i=0; i<0x400; i++)
150 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], 0);//M68K_CPU_TYPE_68000);
151 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
155 uint32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
156 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
157 for(int i=0; i<10; i++)
158 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
159 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
165 // Disassemble everything
167 static char buffer[2048];
168 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
169 WriteLog("%08X: %s", m68kPC, buffer);
170 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
171 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
172 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
174 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
176 static char buffer[2048];
177 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
178 WriteLog("%08X: %s", m68kPC, buffer);
179 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
180 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
181 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
183 /* if (m68kPC == 0x8D0E48 && effect_start5)
185 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
187 GPUDumpDisassembly();
191 /* uint16_t opcode = JaguarReadWord(m68kPC);
192 if (opcode == 0x4E75) // RTS
195 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
197 uint32_t addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
199 if (raPtr != 0xFFFFFFFF)
201 for(uint32_t i=0; i<=raPtr; i++)
203 if (returnAddr[i] == addr)
212 returnAddr[++raPtr] = addr;
216 //Flip Out! debugging...
219 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
220 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
221 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
222 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
224 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
226 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
227 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
228 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
229 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
230 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
231 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
232 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
234 /* static char buffer[2048];
235 //if (m68kPC > 0x805F48) start = true;
236 //if (m68kPC > 0x806486) start = true;
237 //if (m68kPC == 0x805FEE) start = true;
238 //if (m68kPC == 0x80600C)// start = true;
239 if (m68kPC == 0x802058) start = true;
241 // GPUDumpRegisters();
242 // GPUDumpDisassembly();
244 // M68K_show_context();
250 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
251 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));
254 /* if (m68kPC == 0x803F16)
256 WriteLog("M68K: Registers found at $803F16:\n");
257 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
258 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
259 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
261 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
262 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
264 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
265 // !!! Investigate !!!
266 /*extern bool doDSPDis;
267 static bool disgo = false;
268 if (m68kPC == 0x50222)
271 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
272 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
275 if (m68kPC == 0x5000)
280 static char buffer[2048];
281 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
282 WriteLog("%08X: %s", m68kPC, buffer);
283 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
284 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
285 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
287 /* if (m68kPC == 0x82E1A)
289 static char buffer[2048];
290 m68k_disassemble(buffer, m68kPC, 0);//M68K_CPU_TYPE_68000);
291 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
292 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
293 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
294 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
296 /* if (m68kPC == 0x82E58)
297 WriteLog("--> [Routine end]\n");
298 if (m68kPC == 0x80004)
300 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
301 // m68k_set_reg(M68K_REG_D2, 0x12345678);
304 #ifdef LOG_CD_BIOS_CALLS
327 if (m68kPC == 0x3000)
328 WriteLog("M68K: CD_init\n");
329 else if (m68kPC == 0x3006 + (6 * 0))
330 WriteLog("M68K: CD_mode\n");
331 else if (m68kPC == 0x3006 + (6 * 1))
332 WriteLog("M68K: CD_ack\n");
333 else if (m68kPC == 0x3006 + (6 * 2))
334 WriteLog("M68K: CD_jeri\n");
335 else if (m68kPC == 0x3006 + (6 * 3))
336 WriteLog("M68K: CD_spin\n");
337 else if (m68kPC == 0x3006 + (6 * 4))
338 WriteLog("M68K: CD_stop\n");
339 else if (m68kPC == 0x3006 + (6 * 5))
340 WriteLog("M68K: CD_mute\n");
341 else if (m68kPC == 0x3006 + (6 * 6))
342 WriteLog("M68K: CD_umute\n");
343 else if (m68kPC == 0x3006 + (6 * 7))
344 WriteLog("M68K: CD_paus\n");
345 else if (m68kPC == 0x3006 + (6 * 8))
346 WriteLog("M68K: CD_upaus\n");
347 else if (m68kPC == 0x3006 + (6 * 9))
348 WriteLog("M68K: CD_read\n");
349 else if (m68kPC == 0x3006 + (6 * 10))
350 WriteLog("M68K: CD_uread\n");
351 else if (m68kPC == 0x3006 + (6 * 11))
352 WriteLog("M68K: CD_setup\n");
353 else if (m68kPC == 0x3006 + (6 * 12))
354 WriteLog("M68K: CD_ptr\n");
355 else if (m68kPC == 0x3006 + (6 * 13))
356 WriteLog("M68K: CD_osamp\n");
357 else if (m68kPC == 0x3006 + (6 * 14))
358 WriteLog("M68K: CD_getoc\n");
359 else if (m68kPC == 0x3006 + (6 * 15))
360 WriteLog("M68K: CD_initm\n");
361 else if (m68kPC == 0x3006 + (6 * 16))
362 WriteLog("M68K: CD_initf\n");
363 else if (m68kPC == 0x3006 + (6 * 17))
364 WriteLog("M68K: CD_switch\n");
366 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
367 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
368 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
369 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
372 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
373 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), 0))//M68K_CPU_TYPE_68000))
375 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
376 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
378 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
379 // keep going even when the 68K dumped back to the debugger or what have you).
381 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
382 // Try setting the vector to the illegal instruction...
383 //This doesn't work right either! Do something else! Quick!
384 // SET32(jaguar_mainRam, 0x10, m68kPC);
390 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
391 uint32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
392 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
393 uint32_t address = topOfStack - (4 * 4 * 3);
395 for(int i=0; i<10; i++)
397 WriteLog("%06X:", address);
399 for(int j=0; j<4; j++)
401 WriteLog(" %08X", JaguarReadLong(address));
408 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
412 // WriteLog("\n\n68K disasm\n\n");
413 // jaguar_dasm(0x802000, 0x50C);
424 Now here be dragons...
425 Here is how memory ranges are defined in the CoJag driver.
426 Note that we only have to be concerned with 3 entities read/writing anything:
427 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
428 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
429 things that are entirely internal to those modules. This way we should be able to get a handle on all
430 this crap which is currently scattered over Hell's Half Acre(tm).
432 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
433 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
435 /*************************************
437 * Main CPU memory handlers
439 *************************************/
441 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
442 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
443 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
444 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
445 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
446 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
447 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
448 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
449 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
450 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
451 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
452 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
453 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
454 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
455 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
456 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
457 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
458 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
459 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
460 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
461 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
462 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
463 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
466 /*************************************
468 * GPU memory handlers
470 *************************************/
472 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
473 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
474 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
475 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
476 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
477 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
478 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
479 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
480 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
481 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
482 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
485 /*************************************
487 * DSP memory handlers
489 *************************************/
491 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
492 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
493 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
494 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
495 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
496 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
497 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
498 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
499 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
504 //#define EXPERIMENTAL_MEMORY_HANDLING
505 // Experimental memory mappage...
506 // Dunno if this is a good approach or not, but it seems to make better
507 // sense to have all this crap in one spot intstead of scattered all over
508 // the place the way it is now.
509 #ifdef EXPERIMENTAL_MEMORY_HANDLING
511 #define NEW_TIMER_SYSTEM
514 uint8_t jaguarMainRAM[0x400000]; // 68K CPU RAM
515 uint8_t jaguarMainROM[0x600000]; // 68K CPU ROM
516 uint8_t jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
517 uint8_t jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
518 bool BIOSLoaded = false;
519 bool CDBIOSLoaded = false;
521 uint8_t cdRAM[0x100];
522 uint8_t tomRAM[0x4000];
523 uint8_t jerryRAM[0x10000];
524 static uint16_t eeprom_ram[64];
526 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
529 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
531 // M68K Memory map/handlers
533 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
534 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
535 // Note that this is really memory mapped I/O region...
536 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
537 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
538 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
539 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
540 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
541 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
542 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
543 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
544 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
545 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
546 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
547 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
549 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
551 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
552 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
553 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
554 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
555 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
556 //What about LBUF writes???
557 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
558 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
559 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
561 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
565 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
566 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
567 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
570 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
571 0 = pad0/1 button values (4 bits each), RO(?)
572 1 = pad0/1 index value (4 bits each), WO
574 3 = NTSC/PAL, certain button states, RO
576 JOYSTICK $F14000 Read/Write
578 Read fedcba98 7654321q f-1 Signals J15 to J1
579 q Cartridge EEPROM output data
580 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
581 0 = disable J7-J0 outputs
584 0 = Audio muted (reset state)
586 7-4 J7-J4 outputs (port 2)
587 3-0 J3-J0 outputs (port 1)
588 JOYBUTS $F14002 Read Only
590 Read xxxxxxxx rrdv3210 x don't care
593 v 1 = NTSC Video hardware
594 0 = PAL Video hardware
595 3-2 Button inputs B3 & B2 (port 2)
596 1-0 Button inputs B1 & B0 (port 1)
598 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
599 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
607 0 1 1 1 Row 3 C3 Option # 9 6 3
611 1 0 1 1 Row 2 C2 C 0 8 5 2
613 1 1 0 1 Row 1 C1 B * 7 4 1
614 1 1 1 0 Row 0 Pause A Up Down Left Right
617 0 bit read in any position means that button is pressed.
618 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
622 void WriteByte(uint32_t address, uint8_t byte, uint32_t who/*=UNKNOWN*/)
624 // Not sure, but I think the system only has 24 address bits...
625 address &= 0x00FFFFFF;
627 // RAM ($000000 - $3FFFFF) 4M
628 if (address <= 0x3FFFFF)
629 jaguarMainRAM[address] = byte;
630 // hole ($400000 - $7FFFFF) 4M
631 else if (address <= 0x7FFFFF)
633 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
634 else if (address <= 0xDFFEFF)
636 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
637 else if (address <= 0xDFFFFF)
639 cdRAM[address & 0xFF] = byte;
641 if ((address & 0xFF) < 12 * 4)
642 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
643 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
646 // BIOS ROM ($E00000 - $E3FFFF) 256K
647 else if (address <= 0xE3FFFF)
649 // hole ($E40000 - $EFFFFF) 768K
650 else if (address <= 0xEFFFFF)
652 // TOM ($F00000 - $F0FFFF) 64K
653 else if (address <= 0xF0FFFF)
656 if (address == 0xF00050)
658 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16_t)byte << 8);
662 else if (address == 0xF00051)
664 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
668 else if (address == 0xF00052)
670 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16_t)byte << 8);
674 else if (address == 0xF00053)
676 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
680 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
682 // Writing to one CLUT writes to the other
683 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
684 tomRAM[address] = tomRAM[address + 0x200] = byte;
687 //What about LBUF writes???
688 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
690 GPUWriteByte(address, byte, who);
693 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
695 BlitterWriteByte(address, byte, who);
698 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
700 GPUWriteByte(address, byte, who);
704 tomRAM[address & 0x3FFF] = byte;
706 // JERRY ($F10000 - $F1FFFF) 64K
707 else if (address <= 0xF1FFFF)
711 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
713 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
715 DSPWriteByte(address, byte, who);
718 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
720 DSPWriteByte(address, byte, who);
723 // SCLK ($F1A150--8 bits wide)
724 //NOTE: This should be taken care of in DAC...
725 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
727 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
728 if ((address & 0x03) == 2)
729 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32_t)byte << 8);
731 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32_t)byte;
733 JERRYI2SInterruptTimer = -1;
734 #ifndef NEW_TIMER_SYSTEM
737 RemoveCallback(JERRYI2SCallback);
742 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
743 else if (address >= 0xF1A148 && address <= 0xF1A157)
745 DACWriteByte(address, byte, who);
748 else if (address >= 0xF10000 && address <= 0xF10007)
750 #ifndef NEW_TIMER_SYSTEM
751 switch (address & 0x07)
754 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
758 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
762 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
766 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
770 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
774 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
778 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
782 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
786 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
790 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
792 clock_byte_write(offset, byte);
795 // JERRY -> 68K interrupt enables/latches (need to be handled!)
796 else if (address >= 0xF10020 && address <= 0xF10023)
798 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
800 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
802 anajoy_byte_write(offset, byte);
805 else if ((address >= 0xF14000) && (address <= 0xF14003))
807 JoystickWriteByte(address, byte);
808 EepromWriteByte(address, byte);
811 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
813 EepromWriteByte(address, byte);
816 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
817 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
820 jerryRAM[address & 0xFFFF] = byte;
822 // hole ($F20000 - $FFFFFF) 1M - 128K
827 void WriteWord(uint32_t adddress, uint16_t word)
831 void WriteDWord(uint32_t adddress, uint32_t dword)
835 uint8_t ReadByte(uint32_t adddress)
839 uint16_t ReadWord(uint32_t adddress)
843 uint32_t ReadDWord(uint32_t adddress)
848 void ShowM68KContext(void)
850 printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
852 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
854 printf("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
856 if (i == M68K_REG_D3 || i == M68K_REG_D7)
860 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
862 printf("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
864 if (i == M68K_REG_A3 || i == M68K_REG_A7)
868 uint32_t currpc = m68k_get_reg(NULL, M68K_REG_PC);
869 uint32_t disPC = currpc - 30;
874 uint32_t oldpc = disPC;
875 disPC += m68k_disassemble(buffer, disPC, 0);
876 printf("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
878 while (disPC < (currpc + 10));
882 // Custom UAE 68000 read/write/IRQ functions
889 IPL Name Vector Control
890 ---------+---------------+---------------+---------------
891 2 VBLANK IRQ $100 INT1 bit #0
892 2 GPU IRQ $100 INT1 bit #1
893 2 HBLANK IRQ $100 INT1 bit #2
894 2 Timer IRQ $100 INT1 bit #3
896 Note: Both timer interrupts (JPIT && PIT) are on the same INT1 bit.
897 and are therefore indistinguishable.
899 A typical way to install a LEVEL2 handler for the 68000 would be
900 something like this, you gotta supply "last_line" and "handler".
901 Note that the interrupt is auto vectored thru $100 (not $68)
909 IRQS_HANDLED=$909 ;; VBLANK and TIMER
911 move.w #$2700,sr ;; no IRQs please
912 move.l #handler,V_AUTO ;; install our routine
914 move.w #last_line,VI ;; scanline where IRQ should occur
915 ;; should be 'odd' BTW
916 move.w #IRQS_HANDLE&$FF,INT1 ;; enable VBLANK + TIMER
917 move.w #$2100,sr ;; enable IRQs on the 68K
935 move.w #IRQS_HANDLED,INT1 ; clear latch, keep IRQ alive
936 move.w #0,INT2 ; let GPU run again
940 As you can see, if you have multiple INT1 interrupts coming in,
941 you need to check the lower byte of INT1, to see which interrupt
944 int irq_ack_handler(int level)
946 #ifdef CPU_DEBUG_TRACING
947 if (startM68KTracing)
949 WriteLog("irq_ack_handler: M68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
953 // Tracing the IPL lines on the Jaguar schematic yields the following:
954 // IPL1 is connected to INTL on TOM (OUT to 68K)
955 // IPL0-2 are also tied to Vcc via 4.7K resistors!
956 // (DINT on TOM goes into DINT on JERRY (IN Tom from Jerry))
957 // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
958 // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
960 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
961 // They aren't, and this causes problems with a, err, specific ROM. :-D
965 m68k_set_irq(0); // Clear the IRQ (NOTE: Without this, the BIOS fails)...
966 return 64; // Set user interrupt #0
969 return M68K_INT_ACK_AUTOVECTOR;
972 //#define USE_NEW_MMU
974 unsigned int m68k_read_memory_8(unsigned int address)
976 // Musashi does this automagically for you, UAE core does not :-P
977 address &= 0x00FFFFFF;
978 #ifdef CPU_DEBUG_MEMORY
979 // Note that the Jaguar only has 2M of RAM, not 4!
980 if ((address >= 0x000000) && (address <= 0x1FFFFF))
983 readMem[address] = 1;
986 //WriteLog("[RM8] Addr: %08X\n", address);
987 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
988 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
989 || address == 0x1AF05E)
990 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
992 unsigned int retVal = 0;
994 // Note that the Jaguar only has 2M of RAM, not 4!
995 if ((address >= 0x000000) && (address <= 0x1FFFFF))
996 retVal = jaguarMainRAM[address];
997 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
998 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
999 retVal = jaguarMainROM[address - 0x800000];
1000 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
1001 // retVal = jaguarBootROM[address - 0xE00000];
1002 // retVal = jaguarDevBootROM1[address - 0xE00000];
1003 retVal = jagMemSpace[address];
1004 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1005 retVal = CDROMReadByte(address);
1006 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1007 retVal = TOMReadByte(address, M68K);
1008 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1009 retVal = JERRYReadByte(address, M68K);
1011 retVal = jaguar_unknown_readbyte(address, M68K);
1013 //if (address >= 0x2800 && address <= 0x281F)
1014 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1015 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1016 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1019 return MMURead8(address, M68K);
1023 void gpu_dump_disassembly(void);
1024 void gpu_dump_registers(void);
1026 unsigned int m68k_read_memory_16(unsigned int address)
1028 // Musashi does this automagically for you, UAE core does not :-P
1029 address &= 0x00FFFFFF;
1030 #ifdef CPU_DEBUG_MEMORY
1031 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
1034 readMem[address] = 1, readMem[address + 1] = 1;
1036 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
1038 return 0x4E71; // NOP
1040 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
1042 return 0x4E71; // NOP
1044 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
1046 return 0x4E71; // NOP
1048 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
1050 return 0x4E71; // NOP
1052 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
1054 return 0x4E71; // NOP
1056 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
1058 return 0x4E71; // NOP
1061 //WriteLog("[RM16] Addr: %08X\n", address);
1062 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
1063 // for(int i=0; i<10000; i++)
1064 WriteLog("[M68K] In routine #6!\n");//*/
1065 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
1066 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
1067 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
1069 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1070 gpu_dump_registers();
1071 gpu_dump_disassembly();
1072 // for(int i=0; i<10000; i++)
1073 // WriteLog("[M68K] About to run GPU!\n");
1075 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1076 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
1078 if (address == 0x000066A0)
1080 gpu_dump_registers();
1081 gpu_dump_disassembly();
1083 for(int i=0; i<10000; i++)
1084 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1086 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1087 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1088 || address == 0x1AF05E)
1089 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
1091 unsigned int retVal = 0;
1093 // Note that the Jaguar only has 2M of RAM, not 4!
1094 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1095 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
1096 retVal = GET16(jaguarMainRAM, address);
1097 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
1098 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
1099 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
1100 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
1101 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1102 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1103 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1104 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1105 retVal = CDROMReadWord(address, M68K);
1106 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1107 retVal = TOMReadWord(address, M68K);
1108 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1109 retVal = JERRYReadWord(address, M68K);
1111 retVal = jaguar_unknown_readword(address, M68K);
1113 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
1114 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1115 //if (address >= 0x2800 && address <= 0x281F)
1116 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1117 //$8B3AE -> Transferred from $F1C010
1118 //$8B5E4 -> Only +1 read at $808AA
1119 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1120 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1123 return MMURead16(address, M68K);
1127 unsigned int m68k_read_memory_32(unsigned int address)
1129 // Musashi does this automagically for you, UAE core does not :-P
1130 address &= 0x00FFFFFF;
1131 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1132 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1133 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));//*/
1135 //WriteLog("--> [RM32]\n");
1137 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1139 return MMURead32(address, M68K);
1143 void m68k_write_memory_8(unsigned int address, unsigned int value)
1145 // Musashi does this automagically for you, UAE core does not :-P
1146 address &= 0x00FFFFFF;
1147 #ifdef CPU_DEBUG_MEMORY
1148 // Note that the Jaguar only has 2M of RAM, not 4!
1149 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1153 if (value > writeMemMax[address])
1154 writeMemMax[address] = value;
1155 if (value < writeMemMin[address])
1156 writeMemMin[address] = value;
1160 /*if (address == 0x4E00)
1161 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1162 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1163 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
1164 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1166 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1167 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1169 /*if (address >= 0x53D0 && address <= 0x53FF)
1170 printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1171 //Testing AvP on UAE core...
1172 //000075A0: FFFFF80E B6320220 (BITMAP)
1173 /*if (address == 0x75A0 && value == 0xFF)
1174 printf("M68K: (8) Tripwire hit...\n");//*/
1177 // Note that the Jaguar only has 2M of RAM, not 4!
1178 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1179 jaguarMainRAM[address] = value;
1180 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1181 CDROMWriteByte(address, value, M68K);
1182 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1183 TOMWriteByte(address, value, M68K);
1184 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1185 JERRYWriteByte(address, value, M68K);
1187 jaguar_unknown_writebyte(address, value, M68K);
1189 MMUWrite8(address, value, M68K);
1193 void m68k_write_memory_16(unsigned int address, unsigned int value)
1195 // Musashi does this automagically for you, UAE core does not :-P
1196 address &= 0x00FFFFFF;
1197 #ifdef CPU_DEBUG_MEMORY
1198 // Note that the Jaguar only has 2M of RAM, not 4!
1199 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1203 uint8_t hi = value >> 8, lo = value & 0xFF;
1205 if (hi > writeMemMax[address])
1206 writeMemMax[address] = hi;
1207 if (hi < writeMemMin[address])
1208 writeMemMin[address] = hi;
1210 if (lo > writeMemMax[address+1])
1211 writeMemMax[address+1] = lo;
1212 if (lo < writeMemMin[address+1])
1213 writeMemMin[address+1] = lo;
1217 /*if (address == 0x4E00)
1218 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1219 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1220 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1221 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1222 //if (address >= 0xF02200 && address <= 0xF0229F)
1223 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1224 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1225 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1226 /*extern uint32_t totalFrames;
1227 if (address == 0xF02114)
1228 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1229 if (address == 0xF02110)
1230 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1231 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1232 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1234 /*if (address == 0x0100)//64*4)
1235 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1237 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1238 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1239 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1240 || address == 0x1AF05E)
1241 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1243 /*if (address >= 0x53D0 && address <= 0x53FF)
1244 printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1245 //Testing AvP on UAE core...
1246 //000075A0: FFFFF80E B6320220 (BITMAP)
1247 /*if (address == 0x75A0 && value == 0xFFFF)
1249 printf("\nM68K: (16) Tripwire hit...\n");
1254 // Note that the Jaguar only has 2M of RAM, not 4!
1255 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1257 /* jaguar_mainRam[address] = value >> 8;
1258 jaguar_mainRam[address + 1] = value & 0xFF;*/
1259 SET16(jaguarMainRAM, address, value);
1261 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1262 CDROMWriteWord(address, value, M68K);
1263 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1264 TOMWriteWord(address, value, M68K);
1265 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1266 JERRYWriteWord(address, value, M68K);
1269 jaguar_unknown_writeword(address, value, M68K);
1270 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1271 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1272 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1273 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1277 MMUWrite16(address, value, M68K);
1281 void m68k_write_memory_32(unsigned int address, unsigned int value)
1283 // Musashi does this automagically for you, UAE core does not :-P
1284 address &= 0x00FFFFFF;
1285 /*if (address == 0x4E00)
1286 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1287 //WriteLog("--> [WM32]\n");
1288 /*if (address == 0x0100)//64*4)
1289 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1290 /*if (address >= 0xF03214 && address < 0xF0321F)
1291 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1292 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1293 /*extern bool doGPUDis;
1294 if (address == 0xF03214 && value == 0x88E30047)
1296 doGPUDis = true;//*/
1297 /* if (address == 0x51136 || address == 0xFB074)
1298 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1299 //Testing AvP on UAE core...
1300 //000075A0: FFFFF80E B6320220 (BITMAP)
1301 /*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
1303 printf("\nM68K: (32) Tripwire hit...\n");
1308 m68k_write_memory_16(address, value >> 16);
1309 m68k_write_memory_16(address + 2, value & 0xFFFF);
1311 MMUWrite32(address, value, M68K);
1316 uint32_t JaguarGetHandler(uint32_t i)
1318 return JaguarReadLong(i * 4);
1321 bool JaguarInterruptHandlerIsValid(uint32_t i) // Debug use only...
1323 uint32_t handler = JaguarGetHandler(i);
1324 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1327 void M68K_show_context(void)
1329 WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1331 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1333 WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1335 if (i == M68K_REG_D3 || i == M68K_REG_D7)
1339 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1341 WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1343 if (i == M68K_REG_A3 || i == M68K_REG_A7)
1347 WriteLog("68K disasm\n");
1348 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1349 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1350 // jaguar_dasm(0x5000, 0x14414);
1352 // WriteLog("\n.......[Cart start]...........\n\n");
1353 // jaguar_dasm(0x192000, 0x1000);//0x200);
1355 WriteLog("..................\n");
1357 if (TOMIRQEnabled(IRQ_VIDEO))
1359 WriteLog("video int: enabled\n");
1360 JaguarDasm(JaguarGetHandler(64), 0x200);
1363 WriteLog("video int: disabled\n");
1365 WriteLog("..................\n");
1367 for(int i=0; i<256; i++)
1369 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1370 uint32_t address = (uint32_t)JaguarGetHandler(i);
1373 WriteLog(".........\n");
1375 WriteLog("$%08X\n", address);
1380 // Unknown read/write byte/word routines
1383 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1384 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1386 // 807EC4: movea.l #$f1b000, A1
1387 // 807ECA: movea.l #$8129e0, A0
1388 // 807ED0: move.l A0, D0
1389 // 807ED2: move.l #$f1bb94, D1
1390 // 807ED8: sub.l D0, D1
1391 // 807EDA: lsr.l #2, D1
1392 // 807EDC: move.l (A0)+, (A1)+
1393 // 807EDE: dbra D1, 807edc
1395 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1396 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1397 // space! (That is, unless the 68K causes a bus error...)
1399 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1401 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1402 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));
1404 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1405 // extern bool finished;
1407 // extern bool doDSPDis;
1413 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1415 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1416 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));
1418 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1419 // extern bool finished;
1421 // extern bool doDSPDis;
1427 unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who/*=UNKNOWN*/)
1429 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1430 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1432 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1433 // extern bool finished;
1435 // extern bool doDSPDis;
1442 unsigned jaguar_unknown_readword(unsigned address, uint32_t who/*=UNKNOWN*/)
1444 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1445 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1447 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1448 // extern bool finished;
1450 // extern bool doDSPDis;
1458 // Disassemble M68K instructions at the given offset
1461 unsigned int m68k_read_disassembler_8(unsigned int address)
1463 return m68k_read_memory_8(address);
1466 unsigned int m68k_read_disassembler_16(unsigned int address)
1468 return m68k_read_memory_16(address);
1471 unsigned int m68k_read_disassembler_32(unsigned int address)
1473 return m68k_read_memory_32(address);
1476 void JaguarDasm(uint32_t offset, uint32_t qt)
1479 static char buffer[2048];//, mem[64];
1480 int pc = offset, oldpc;
1482 for(uint32_t i=0; i<qt; i++)
1485 for(int j=0; j<64; j++)
1486 mem[j^0x01] = jaguar_byte_read(pc + j);
1488 pc += Dasm68000((char *)mem, buffer, 0);
1489 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1491 pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
1492 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1497 uint8_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1499 uint8_t data = 0x00;
1502 // First 2M is mirrored in the $0 - $7FFFFF range
1503 if (offset < 0x800000)
1504 data = jaguarMainRAM[offset & 0x1FFFFF];
1505 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1506 data = jaguarMainROM[offset - 0x800000];
1507 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1508 data = CDROMReadByte(offset, who);
1509 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1510 // data = jaguarBootROM[offset & 0x3FFFF];
1511 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1512 data = jagMemSpace[offset];
1513 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1514 data = TOMReadByte(offset, who);
1515 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1516 data = JERRYReadByte(offset, who);
1518 data = jaguar_unknown_readbyte(offset, who);
1523 uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1527 // First 2M is mirrored in the $0 - $7FFFFF range
1528 if (offset < 0x800000)
1530 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1532 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1535 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1537 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1538 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1539 return CDROMReadWord(offset, who);
1540 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1541 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1542 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1543 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1544 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1545 return TOMReadWord(offset, who);
1546 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1547 return JERRYReadWord(offset, who);
1549 return jaguar_unknown_readword(offset, who);
1552 void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1554 /* if (offset >= 0x4E00 && offset < 0x4E04)
1555 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1556 //Need to check for writes in the range of $18FA70 + 8000...
1558 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1559 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1563 // First 2M is mirrored in the $0 - $7FFFFF range
1564 if (offset < 0x800000)
1566 jaguarMainRAM[offset & 0x1FFFFF] = data;
1569 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1571 CDROMWriteByte(offset, data, who);
1574 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1576 TOMWriteByte(offset, data, who);
1579 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1581 JERRYWriteByte(offset, data, who);
1585 jaguar_unknown_writebyte(offset, data, who);
1589 void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1591 /* if (offset >= 0x4E00 && offset < 0x4E04)
1592 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1593 /*if (offset == 0x0100)//64*4)
1594 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1595 if (offset == 0x0102)//64*4)
1596 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1597 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1598 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1599 //Need to check for writes in the range of $18FA70 + 8000...
1601 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1602 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1603 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1604 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1608 // First 2M is mirrored in the $0 - $7FFFFF range
1609 if (offset <= 0x7FFFFE)
1614 1A 69 F0 ($0000) -> Starfield
1615 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1618 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1627 //This MUST be done by the 68K!
1628 /*if (offset == 0x670C)
1629 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1631 /*extern bool doGPUDis;
1632 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1633 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1634 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1635 doGPUDis = true;//*/
1636 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1637 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1638 if ((data & 0xFF00) != 0x7700)
1639 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1640 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1642 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1643 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1644 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1646 /*extern bool doGPUDis;
1647 if (offset == 0x120216 && who == GPU)
1648 doGPUDis = true;//*/
1649 /*extern uint32_t gpu_pc;
1650 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1652 uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1653 uint32_t y = base / 0x300;
1654 uint32_t x = (base - (y * 0x300)) / 2;
1655 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1658 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1660 //if (offset == (0x001E17F8 + 0x34))
1661 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1663 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1664 /*extern uint32_t gpu_pc;
1665 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1667 extern int objectPtr;
1668 // if (offset > 0x148000)
1671 if (starCount > objectPtr)
1674 // if (starCount == 1)
1675 // WriteLog("--> Drawing 1st star...\n");
1677 // uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1678 // uint32_t y = base / 0x300;
1679 // uint32_t x = (base - (y * 0x300)) / 2;
1680 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1682 //A star of interest...
1683 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1684 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1685 //JWW: Blitter writing echo 77B3 at 0011D022...
1687 //extern bool doGPUDis;
1688 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1691 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1694 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1695 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1697 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1698 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1701 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1703 CDROMWriteWord(offset, data, who);
1706 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1708 TOMWriteWord(offset, data, who);
1711 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1713 JERRYWriteWord(offset, data, who);
1716 // Don't bomb on attempts to write to ROM
1717 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1720 jaguar_unknown_writeword(offset, data, who);
1723 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1724 uint32_t JaguarReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1726 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1729 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1730 void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
1732 /* extern bool doDSPDis;
1733 if (offset < 0x400 && !doDSPDis)
1735 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1738 /*if (offset == 0x0100)//64*4)
1739 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1741 JaguarWriteWord(offset, data >> 16, who);
1742 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1745 void JaguarSetScreenBuffer(uint32_t * buffer)
1747 // This is in TOM, but we set it here...
1748 screenBuffer = buffer;
1751 void JaguarSetScreenPitch(uint32_t pitch)
1753 // This is in TOM, but we set it here...
1754 screenPitch = pitch;
1758 // Jaguar console initialization
1760 void JaguarInit(void)
1762 // For randomizing RAM
1765 // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
1766 for(uint32_t i=0; i<0x200000; i+=4)
1767 *((uint32_t *)(&jaguarMainRAM[i])) = rand();
1769 #ifdef CPU_DEBUG_MEMORY
1770 memset(readMem, 0x00, 0x400000);
1771 memset(writeMemMin, 0xFF, 0x400000);
1772 memset(writeMemMax, 0x00, 0x400000);
1774 // memset(jaguarMainRAM, 0x00, 0x200000);
1775 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1776 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1777 //NOTE: This *doesn't* fix FlipOut...
1778 //Or does it? Hmm...
1779 //Seems to want $01010101... Dunno why. Investigate!
1780 // memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1781 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1782 lowerField = false; // Reset the lower field flag
1783 //temp, for crappy crap that sux
1784 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1786 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
1795 //New timer based code stuffola...
1796 void HalflineCallback(void);
1797 void RenderCallback(void);
1798 void JaguarReset(void)
1800 // Only problem with this approach: It wipes out RAM loaded files...!
1801 // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
1802 for(uint32_t i=8; i<0x200000; i+=4)
1803 *((uint32_t *)(&jaguarMainRAM[i])) = rand();
1805 // New timer base code stuffola...
1806 InitializeEventList();
1807 //Need to change this so it uses the single RAM space and load the BIOS
1808 //into it somewhere...
1809 //Also, have to change this here and in JaguarReadXX() currently
1810 // Only use the system BIOS if it's available...! (it's always available now!)
1811 // AND only if a jaguar cartridge has been inserted.
1812 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1813 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1815 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1817 // WriteLog("jaguar_reset():\n");
1823 m68k_pulse_reset(); // Reset the 68000
1824 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1826 lowerField = false; // Reset the lower field flag
1827 // SetCallbackTime(ScanlineCallback, 63.5555);
1828 // SetCallbackTime(ScanlineCallback, 31.77775);
1829 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1833 void JaguarDone(void)
1835 #ifdef CPU_DEBUG_MEMORY
1836 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1838 for(uint32_t i=0; i<=raPtr; i++)
1840 WriteLog("\t%08X\n", returnAddr[i]);
1841 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1842 jaguar_dasm(returnAddr[i] - 16, 16);
1847 /* int start = 0, end = 0;
1848 bool endTriggered = false, startTriggered = false;
1849 for(int i=0; i<0x400000; i++)
1851 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1853 if (!startTriggered)
1854 startTriggered = true, endTriggered = false, start = i;
1856 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1862 end = i - 1, endTriggered = true, startTriggered = false;
1863 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1870 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1871 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1872 int32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1873 WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
1875 for(int i=-2; i<9; i++)
1876 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1878 uint32_t address = topOfStack - (4 * 4 * 3);
1880 for(int i=0; i<10; i++)
1882 WriteLog("%06X:", address);
1884 for(int j=0; j<4; j++)
1886 WriteLog(" %08X", JaguarReadLong(address));
1894 /* WriteLog("\nM68000 disassembly at $802288...\n");
1895 jaguar_dasm(0x802288, 3);
1896 WriteLog("\nM68000 disassembly at $802200...\n");
1897 jaguar_dasm(0x802200, 500);
1898 WriteLog("\nM68000 disassembly at $802518...\n");
1899 jaguar_dasm(0x802518, 100);//*/
1901 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1902 jaguar_dasm(0x803F00, 500);
1905 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1906 jaguar_dasm(0x802B00, 500);
1909 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1910 jaguar_dasm(0x809900, 500);
1913 /* WriteLog("\n\nDump of $8093C8:\n\n");
1914 for(int i=0x8093C8; i<0x809900; i+=4)
1915 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1916 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1917 jaguar_dasm(0x90006C, 500);
1919 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1920 jaguar_dasm(0x1AC000, 6000);
1923 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1924 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1925 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1926 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1927 M68K_show_context();
1936 // temp, until debugger is in place
1937 //00802016: jsr $836F1A.l
1938 //0080201C: jsr $836B30.l
1939 //00802022: jsr $836B18.l
1940 //00802028: jsr $8135F0.l
1941 //00813C1E: jsr $813F76.l
1942 //00802038: jsr $836D00.l
1943 //00802098: jsr $8373A4.l
1944 //008020A2: jsr $83E24A.l
1945 //008020BA: jsr $83E156.l
1946 //008020C6: jsr $83E19C.l
1947 //008020E6: jsr $8445E8.l
1948 //008020EC: jsr $838C20.l
1949 //0080211A: jsr $838ED6.l
1950 //00802124: jsr $89CA56.l
1951 //0080212A: jsr $802B48.l
1953 WriteLog("-------------------------------------------\n");
1954 JaguarDasm(0x8445E8, 0x200);
1955 WriteLog("-------------------------------------------\n");
1956 JaguarDasm(0x838C20, 0x200);
1957 WriteLog("-------------------------------------------\n");
1958 JaguarDasm(0x838ED6, 0x200);
1959 WriteLog("-------------------------------------------\n");
1960 JaguarDasm(0x89CA56, 0x200);
1961 WriteLog("-------------------------------------------\n");
1962 JaguarDasm(0x802B48, 0x200);
1963 WriteLog("\n\nM68000 disassembly at $802000...\n");
1964 JaguarDasm(0x802000, 6000);
1967 /* WriteLog("\n\nM68000 disassembly at $6004...\n");
1968 JaguarDasm(0x6004, 10000);
1970 // WriteLog("\n\nM68000 disassembly at $802000...\n");
1971 // JaguarDasm(0x802000, 0x1000);
1972 // WriteLog("\n\nM68000 disassembly at $4100...\n");
1973 // JaguarDasm(0x4100, 200);
1974 // WriteLog("\n\nM68000 disassembly at $800800...\n");
1975 // JaguarDasm(0x800800, 0x1000);
1979 // Temp debugging stuff
1981 void DumpMainMemory(void)
1983 FILE * fp = fopen("./memdump.bin", "wb");
1988 fwrite(jaguarMainRAM, 1, 0x200000, fp);
1993 uint8_t * GetRamPtr(void)
1995 return jaguarMainRAM;
2000 // New Jaguar execution stack
2001 // This executes 1 frame's worth of code.
2004 void JaguarExecuteNew(void)
2010 double timeToNextEvent = GetTimeToNextEvent();
2011 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
2013 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2016 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2024 #define USE_CORRECT_PAL_TIMINGS
2025 // A lot of confusion comes from here...
2026 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
2027 // of whether the display is interlaced or not. The only difference with an
2028 // interlaced display is that the high bit of VC will be set when the lower
2029 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
2030 // regardless of whether it's in interlace mode or not.
2031 // NB2: Seems it doens't always, not sure what the constraint is...)
2033 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2034 // rendering two fields that are slighty vertically offset from each other.
2035 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2036 // is rendered in this mode so that each field, when overlaid on each other,
2037 // will yield the final picture at the full resolution for the full frame.
2039 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2040 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2041 // it will be half this number for a half frame. BUT, since we're counting
2042 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
2044 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2045 // Half line times are, naturally, half of this. :-P
2046 void HalflineCallback(void)
2048 //OK, this is hardwired to run in NTSC, and for who knows how long.
2049 //Need to fix this so that it does a half-line in the correct amount of time
2050 //and number of lines, depending on which mode we're in. [FIXED]
2051 uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
2052 uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2053 uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);
2054 // uint16_t vbb = TOMReadWord(0xF00040, JAGUAR);
2057 #ifdef USE_CORRECT_PAL_TIMINGS
2058 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2059 // So we cut the number of half-lines in a frame in half. :-P
2060 uint16_t numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2062 if ((vc & 0x7FF) >= numHalfLines)
2064 if ((vc & 0x7FF) >= vp)
2068 // lowerField = !lowerField;
2070 // If we're rendering the lower field, set the high bit (#12, counting
2076 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2077 TOMWriteWord(0xF00006, vc, JAGUAR);
2079 //This is a crappy kludge, but maybe it'll work for now...
2080 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2081 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2083 // We don't have to worry about autovectors & whatnot because the Jaguar
2084 // tells you through its HW registers who sent the interrupt...
2085 TOMSetPendingVideoInt();
2089 TOMExecHalfline(vc, true);
2091 //Change this to VBB???
2092 //Doesn't seem to matter (at least for Flip Out & I-War)
2093 if ((vc & 0x7FF) == 0)
2100 #ifdef USE_CORRECT_PAL_TIMINGS
2101 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2103 // SetCallbackTime(HalflineCallback, 63.5555);
2104 SetCallbackTime(HalflineCallback, 31.77775);
2109 // This isn't currently used, but maybe it should be...
2111 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2112 handles all the rest, so this isn't needed. :-P
2114 void RenderCallback(void)
2116 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2117 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time