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
20 #include "SDL_opengl.h"
31 #include "m68000/m68kinterface.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
45 #define CPU_DEBUG_TRACING
47 // Private function prototypes
49 unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who = UNKNOWN);
50 unsigned jaguar_unknown_readword(unsigned address, uint32_t who = UNKNOWN);
51 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who = UNKNOWN);
52 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who = UNKNOWN);
53 void M68K_show_context(void);
57 #ifdef CPU_DEBUG_MEMORY
58 extern bool startMemLog; // Set by "e" key
59 extern int effect_start;
60 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
63 // Really, need to include memory.h for this, but it might interfere with some stuff...
64 extern uint8_t jagMemSpace[];
68 uint32_t jaguar_active_memory_dumps = 0;
70 uint32_t jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
71 bool jaguarCartInserted = false;
72 bool lowerField = false;
74 #ifdef CPU_DEBUG_MEMORY
75 uint8_t writeMemMax[0x400000], writeMemMin[0x400000];
76 uint8_t readMem[0x400000];
77 uint32_t returnAddr[4000], raPtr = 0xFFFFFFFF;
80 uint32_t pcQueue[0x400];
82 bool startM68KTracing = false;
85 // Callback function to detect illegal instructions
87 void GPUDumpDisassembly(void);
88 void GPUDumpRegisters(void);
89 static bool start = false;
91 void M68KInstructionHook(void)
93 uint32_t m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
94 // Temp, for comparing...
96 /* static char buffer[2048];//, mem[64];
97 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
98 printf("%08X: %s\n", m68kPC, buffer);//*/
100 //JaguarDasm(m68kPC, 1);
101 //Testing Hover Strike...
104 static int hitCount = 0;
105 static int inRoutine = 0;
108 //if (regs.pc == 0x80340A)
109 if (m68kPC == 0x803416)
114 printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1));
116 else if (m68kPC == 0x803422)
119 printf("(%i instructions)\n", instSeen);
126 // For code tracing...
127 #ifdef CPU_DEBUG_TRACING
128 if (startM68KTracing)
130 static char buffer[2048];
132 m68k_disassemble(buffer, m68kPC, 0);
133 WriteLog("%06X: %s\n", m68kPC, buffer);
138 // Ideally, we'd save all the registers as well...
139 pcQueue[pcQPtr++] = m68kPC;
142 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
144 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
146 static char buffer[2048];
147 for(int i=0; i<0x400; i++)
149 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], 0);//M68K_CPU_TYPE_68000);
150 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
154 uint32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
155 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
156 for(int i=0; i<10; i++)
157 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
158 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
164 // Disassemble everything
166 static char buffer[2048];
167 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
168 WriteLog("%08X: %s", m68kPC, buffer);
169 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
170 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
171 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
173 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
175 static char buffer[2048];
176 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
177 WriteLog("%08X: %s", m68kPC, buffer);
178 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
179 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
180 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
182 /* if (m68kPC == 0x8D0E48 && effect_start5)
184 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
186 GPUDumpDisassembly();
190 /* uint16_t opcode = JaguarReadWord(m68kPC);
191 if (opcode == 0x4E75) // RTS
194 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
196 uint32_t addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
198 if (raPtr != 0xFFFFFFFF)
200 for(uint32_t i=0; i<=raPtr; i++)
202 if (returnAddr[i] == addr)
211 returnAddr[++raPtr] = addr;
215 //Flip Out! debugging...
218 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
219 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
220 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
221 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
223 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
225 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
226 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
227 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
228 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
229 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
230 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
231 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
233 /* static char buffer[2048];
234 //if (m68kPC > 0x805F48) start = true;
235 //if (m68kPC > 0x806486) start = true;
236 //if (m68kPC == 0x805FEE) start = true;
237 //if (m68kPC == 0x80600C)// start = true;
238 if (m68kPC == 0x802058) start = true;
240 // GPUDumpRegisters();
241 // GPUDumpDisassembly();
243 // M68K_show_context();
249 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
250 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));
253 /* if (m68kPC == 0x803F16)
255 WriteLog("M68K: Registers found at $803F16:\n");
256 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
257 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
258 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
260 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
261 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
263 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
264 // !!! Investigate !!!
265 /*extern bool doDSPDis;
266 static bool disgo = false;
267 if (m68kPC == 0x50222)
270 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
271 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
274 if (m68kPC == 0x5000)
279 static char buffer[2048];
280 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
281 WriteLog("%08X: %s", m68kPC, buffer);
282 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
283 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
284 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
286 /* if (m68kPC == 0x82E1A)
288 static char buffer[2048];
289 m68k_disassemble(buffer, m68kPC, 0);//M68K_CPU_TYPE_68000);
290 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
291 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
292 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
293 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
295 /* if (m68kPC == 0x82E58)
296 WriteLog("--> [Routine end]\n");
297 if (m68kPC == 0x80004)
299 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
300 // m68k_set_reg(M68K_REG_D2, 0x12345678);
303 #ifdef LOG_CD_BIOS_CALLS
326 if (m68kPC == 0x3000)
327 WriteLog("M68K: CD_init\n");
328 else if (m68kPC == 0x3006 + (6 * 0))
329 WriteLog("M68K: CD_mode\n");
330 else if (m68kPC == 0x3006 + (6 * 1))
331 WriteLog("M68K: CD_ack\n");
332 else if (m68kPC == 0x3006 + (6 * 2))
333 WriteLog("M68K: CD_jeri\n");
334 else if (m68kPC == 0x3006 + (6 * 3))
335 WriteLog("M68K: CD_spin\n");
336 else if (m68kPC == 0x3006 + (6 * 4))
337 WriteLog("M68K: CD_stop\n");
338 else if (m68kPC == 0x3006 + (6 * 5))
339 WriteLog("M68K: CD_mute\n");
340 else if (m68kPC == 0x3006 + (6 * 6))
341 WriteLog("M68K: CD_umute\n");
342 else if (m68kPC == 0x3006 + (6 * 7))
343 WriteLog("M68K: CD_paus\n");
344 else if (m68kPC == 0x3006 + (6 * 8))
345 WriteLog("M68K: CD_upaus\n");
346 else if (m68kPC == 0x3006 + (6 * 9))
347 WriteLog("M68K: CD_read\n");
348 else if (m68kPC == 0x3006 + (6 * 10))
349 WriteLog("M68K: CD_uread\n");
350 else if (m68kPC == 0x3006 + (6 * 11))
351 WriteLog("M68K: CD_setup\n");
352 else if (m68kPC == 0x3006 + (6 * 12))
353 WriteLog("M68K: CD_ptr\n");
354 else if (m68kPC == 0x3006 + (6 * 13))
355 WriteLog("M68K: CD_osamp\n");
356 else if (m68kPC == 0x3006 + (6 * 14))
357 WriteLog("M68K: CD_getoc\n");
358 else if (m68kPC == 0x3006 + (6 * 15))
359 WriteLog("M68K: CD_initm\n");
360 else if (m68kPC == 0x3006 + (6 * 16))
361 WriteLog("M68K: CD_initf\n");
362 else if (m68kPC == 0x3006 + (6 * 17))
363 WriteLog("M68K: CD_switch\n");
365 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
366 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
367 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
368 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
371 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
372 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), 0))//M68K_CPU_TYPE_68000))
374 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
375 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
377 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
378 // keep going even when the 68K dumped back to the debugger or what have you).
380 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
381 // Try setting the vector to the illegal instruction...
382 //This doesn't work right either! Do something else! Quick!
383 // SET32(jaguar_mainRam, 0x10, m68kPC);
389 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
390 uint32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
391 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
392 uint32_t address = topOfStack - (4 * 4 * 3);
394 for(int i=0; i<10; i++)
396 WriteLog("%06X:", address);
398 for(int j=0; j<4; j++)
400 WriteLog(" %08X", JaguarReadLong(address));
407 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
411 // WriteLog("\n\n68K disasm\n\n");
412 // jaguar_dasm(0x802000, 0x50C);
423 Now here be dragons...
424 Here is how memory ranges are defined in the CoJag driver.
425 Note that we only have to be concerned with 3 entities read/writing anything:
426 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
427 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
428 things that are entirely internal to those modules. This way we should be able to get a handle on all
429 this crap which is currently scattered over Hell's Half Acre(tm).
431 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
432 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
434 /*************************************
436 * Main CPU memory handlers
438 *************************************/
440 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
441 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
442 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
443 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
444 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
445 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
446 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
447 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
448 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
449 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
450 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
451 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
452 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
453 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
454 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
455 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
456 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
457 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
458 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
459 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
460 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
461 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
462 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
465 /*************************************
467 * GPU memory handlers
469 *************************************/
471 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
472 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
473 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
474 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
475 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
476 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
477 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
478 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
479 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
480 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
481 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
484 /*************************************
486 * DSP memory handlers
488 *************************************/
490 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
491 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
492 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
493 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
494 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
495 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
496 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
497 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
498 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
503 //#define EXPERIMENTAL_MEMORY_HANDLING
504 // Experimental memory mappage...
505 // Dunno if this is a good approach or not, but it seems to make better
506 // sense to have all this crap in one spot intstead of scattered all over
507 // the place the way it is now.
508 #ifdef EXPERIMENTAL_MEMORY_HANDLING
510 #define NEW_TIMER_SYSTEM
513 uint8_t jaguarMainRAM[0x400000]; // 68K CPU RAM
514 uint8_t jaguarMainROM[0x600000]; // 68K CPU ROM
515 uint8_t jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
516 uint8_t jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
517 bool BIOSLoaded = false;
518 bool CDBIOSLoaded = false;
520 uint8_t cdRAM[0x100];
521 uint8_t tomRAM[0x4000];
522 uint8_t jerryRAM[0x10000];
523 static uint16_t eeprom_ram[64];
525 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
528 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
530 // M68K Memory map/handlers
532 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
533 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
534 // Note that this is really memory mapped I/O region...
535 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
536 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
537 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
538 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
539 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
540 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
541 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
542 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
543 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
544 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
545 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
546 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
548 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
550 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
551 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
552 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
553 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
554 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
555 //What about LBUF writes???
556 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
557 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
558 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
560 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
564 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
565 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
566 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
569 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
570 0 = pad0/1 button values (4 bits each), RO(?)
571 1 = pad0/1 index value (4 bits each), WO
573 3 = NTSC/PAL, certain button states, RO
575 JOYSTICK $F14000 Read/Write
577 Read fedcba98 7654321q f-1 Signals J15 to J1
578 q Cartridge EEPROM output data
579 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
580 0 = disable J7-J0 outputs
583 0 = Audio muted (reset state)
585 7-4 J7-J4 outputs (port 2)
586 3-0 J3-J0 outputs (port 1)
587 JOYBUTS $F14002 Read Only
589 Read xxxxxxxx rrdv3210 x don't care
592 v 1 = NTSC Video hardware
593 0 = PAL Video hardware
594 3-2 Button inputs B3 & B2 (port 2)
595 1-0 Button inputs B1 & B0 (port 1)
597 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
598 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
606 0 1 1 1 Row 3 C3 Option # 9 6 3
610 1 0 1 1 Row 2 C2 C 0 8 5 2
612 1 1 0 1 Row 1 C1 B * 7 4 1
613 1 1 1 0 Row 0 Pause A Up Down Left Right
616 0 bit read in any position means that button is pressed.
617 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
621 void WriteByte(uint32_t address, uint8_t byte, uint32_t who/*=UNKNOWN*/)
623 // Not sure, but I think the system only has 24 address bits...
624 address &= 0x00FFFFFF;
626 // RAM ($000000 - $3FFFFF) 4M
627 if (address <= 0x3FFFFF)
628 jaguarMainRAM[address] = byte;
629 // hole ($400000 - $7FFFFF) 4M
630 else if (address <= 0x7FFFFF)
632 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
633 else if (address <= 0xDFFEFF)
635 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
636 else if (address <= 0xDFFFFF)
638 cdRAM[address & 0xFF] = byte;
640 if ((address & 0xFF) < 12 * 4)
641 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
642 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
645 // BIOS ROM ($E00000 - $E3FFFF) 256K
646 else if (address <= 0xE3FFFF)
648 // hole ($E40000 - $EFFFFF) 768K
649 else if (address <= 0xEFFFFF)
651 // TOM ($F00000 - $F0FFFF) 64K
652 else if (address <= 0xF0FFFF)
655 if (address == 0xF00050)
657 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16_t)byte << 8);
661 else if (address == 0xF00051)
663 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
667 else if (address == 0xF00052)
669 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16_t)byte << 8);
673 else if (address == 0xF00053)
675 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
679 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
681 // Writing to one CLUT writes to the other
682 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
683 tomRAM[address] = tomRAM[address + 0x200] = byte;
686 //What about LBUF writes???
687 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
689 GPUWriteByte(address, byte, who);
692 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
694 BlitterWriteByte(address, byte, who);
697 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
699 GPUWriteByte(address, byte, who);
703 tomRAM[address & 0x3FFF] = byte;
705 // JERRY ($F10000 - $F1FFFF) 64K
706 else if (address <= 0xF1FFFF)
710 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
712 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
714 DSPWriteByte(address, byte, who);
717 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
719 DSPWriteByte(address, byte, who);
722 // SCLK ($F1A150--8 bits wide)
723 //NOTE: This should be taken care of in DAC...
724 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
726 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
727 if ((address & 0x03) == 2)
728 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32_t)byte << 8);
730 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32_t)byte;
732 JERRYI2SInterruptTimer = -1;
733 #ifndef NEW_TIMER_SYSTEM
736 RemoveCallback(JERRYI2SCallback);
741 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
742 else if (address >= 0xF1A148 && address <= 0xF1A157)
744 DACWriteByte(address, byte, who);
747 else if (address >= 0xF10000 && address <= 0xF10007)
749 #ifndef NEW_TIMER_SYSTEM
750 switch (address & 0x07)
753 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
757 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
761 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
765 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
769 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
773 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
777 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
781 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
785 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
789 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
791 clock_byte_write(offset, byte);
794 // JERRY -> 68K interrupt enables/latches (need to be handled!)
795 else if (address >= 0xF10020 && address <= 0xF10023)
797 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
799 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
801 anajoy_byte_write(offset, byte);
804 else if ((address >= 0xF14000) && (address <= 0xF14003))
806 JoystickWriteByte(address, byte);
807 EepromWriteByte(address, byte);
810 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
812 EepromWriteByte(address, byte);
815 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
816 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
819 jerryRAM[address & 0xFFFF] = byte;
821 // hole ($F20000 - $FFFFFF) 1M - 128K
826 void WriteWord(uint32_t adddress, uint16_t word)
830 void WriteDWord(uint32_t adddress, uint32_t dword)
834 uint8_t ReadByte(uint32_t adddress)
838 uint16_t ReadWord(uint32_t adddress)
842 uint32_t ReadDWord(uint32_t adddress)
847 void ShowM68KContext(void)
849 printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
851 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
853 printf("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
855 if (i == M68K_REG_D3 || i == M68K_REG_D7)
859 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
861 printf("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
863 if (i == M68K_REG_A3 || i == M68K_REG_A7)
867 uint32_t currpc = m68k_get_reg(NULL, M68K_REG_PC);
868 uint32_t disPC = currpc - 30;
873 uint32_t oldpc = disPC;
874 disPC += m68k_disassemble(buffer, disPC, 0);
875 printf("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
877 while (disPC < (currpc + 10));
881 // Custom UAE 68000 read/write/IRQ functions
888 IPL Name Vector Control
889 ---------+---------------+---------------+---------------
890 2 VBLANK IRQ $100 INT1 bit #0
891 2 GPU IRQ $100 INT1 bit #1
892 2 HBLANK IRQ $100 INT1 bit #2
893 2 Timer IRQ $100 INT1 bit #3
895 Note: Both timer interrupts (JPIT && PIT) are on the same INT1 bit.
896 and are therefore indistinguishable.
898 A typical way to install a LEVEL2 handler for the 68000 would be
899 something like this, you gotta supply "last_line" and "handler".
900 Note that the interrupt is auto vectored thru $100 (not $68)
908 IRQS_HANDLED=$909 ;; VBLANK and TIMER
910 move.w #$2700,sr ;; no IRQs please
911 move.l #handler,V_AUTO ;; install our routine
913 move.w #last_line,VI ;; scanline where IRQ should occur
914 ;; should be 'odd' BTW
915 move.w #IRQS_HANDLE&$FF,INT1 ;; enable VBLANK + TIMER
916 move.w #$2100,sr ;; enable IRQs on the 68K
934 move.w #IRQS_HANDLED,INT1 ; clear latch, keep IRQ alive
935 move.w #0,INT2 ; let GPU run again
939 As you can see, if you have multiple INT1 interrupts coming in,
940 you need to check the lower byte of INT1, to see which interrupt
943 int irq_ack_handler(int level)
945 #ifdef CPU_DEBUG_TRACING
946 if (startM68KTracing)
948 WriteLog("irq_ack_handler: M68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
952 // Tracing the IPL lines on the Jaguar schematic yields the following:
953 // IPL1 is connected to INTL on TOM (OUT to 68K)
954 // IPL0-2 are also tied to Vcc via 4.7K resistors!
955 // (DINT on TOM goes into DINT on JERRY (IN Tom from Jerry))
956 // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
957 // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
959 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
960 // They aren't, and this causes problems with a, err, specific ROM. :-D
964 m68k_set_irq(0); // Clear the IRQ (NOTE: Without this, the BIOS fails)...
965 return 64; // Set user interrupt #0
968 return M68K_INT_ACK_AUTOVECTOR;
971 //#define USE_NEW_MMU
973 unsigned int m68k_read_memory_8(unsigned int address)
975 // Musashi does this automagically for you, UAE core does not :-P
976 address &= 0x00FFFFFF;
977 #ifdef CPU_DEBUG_MEMORY
978 // Note that the Jaguar only has 2M of RAM, not 4!
979 if ((address >= 0x000000) && (address <= 0x1FFFFF))
982 readMem[address] = 1;
985 //WriteLog("[RM8] Addr: %08X\n", address);
986 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
987 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
988 || address == 0x1AF05E)
989 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
991 unsigned int retVal = 0;
993 // Note that the Jaguar only has 2M of RAM, not 4!
994 if ((address >= 0x000000) && (address <= 0x1FFFFF))
995 retVal = jaguarMainRAM[address];
996 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
997 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
998 retVal = jaguarMainROM[address - 0x800000];
999 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
1000 // retVal = jaguarBootROM[address - 0xE00000];
1001 // retVal = jaguarDevBootROM1[address - 0xE00000];
1002 retVal = jagMemSpace[address];
1003 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1004 retVal = CDROMReadByte(address);
1005 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1006 retVal = TOMReadByte(address, M68K);
1007 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1008 retVal = JERRYReadByte(address, M68K);
1010 retVal = jaguar_unknown_readbyte(address, M68K);
1012 //if (address >= 0x2800 && address <= 0x281F)
1013 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1014 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1015 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1018 return MMURead8(address, M68K);
1022 void gpu_dump_disassembly(void);
1023 void gpu_dump_registers(void);
1025 unsigned int m68k_read_memory_16(unsigned int address)
1027 // Musashi does this automagically for you, UAE core does not :-P
1028 address &= 0x00FFFFFF;
1029 #ifdef CPU_DEBUG_MEMORY
1030 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
1033 readMem[address] = 1, readMem[address + 1] = 1;
1035 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
1037 return 0x4E71; // NOP
1039 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
1041 return 0x4E71; // NOP
1043 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
1045 return 0x4E71; // NOP
1047 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
1049 return 0x4E71; // NOP
1051 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
1053 return 0x4E71; // NOP
1055 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
1057 return 0x4E71; // NOP
1060 //WriteLog("[RM16] Addr: %08X\n", address);
1061 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
1062 // for(int i=0; i<10000; i++)
1063 WriteLog("[M68K] In routine #6!\n");//*/
1064 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
1065 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
1066 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
1068 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1069 gpu_dump_registers();
1070 gpu_dump_disassembly();
1071 // for(int i=0; i<10000; i++)
1072 // WriteLog("[M68K] About to run GPU!\n");
1074 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1075 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
1077 if (address == 0x000066A0)
1079 gpu_dump_registers();
1080 gpu_dump_disassembly();
1082 for(int i=0; i<10000; i++)
1083 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1085 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1086 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1087 || address == 0x1AF05E)
1088 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
1090 unsigned int retVal = 0;
1092 // Note that the Jaguar only has 2M of RAM, not 4!
1093 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1094 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
1095 retVal = GET16(jaguarMainRAM, address);
1096 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
1097 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
1098 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
1099 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
1100 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1101 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1102 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1103 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1104 retVal = CDROMReadWord(address, M68K);
1105 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1106 retVal = TOMReadWord(address, M68K);
1107 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1108 retVal = JERRYReadWord(address, M68K);
1110 retVal = jaguar_unknown_readword(address, M68K);
1112 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
1113 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1114 //if (address >= 0x2800 && address <= 0x281F)
1115 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1116 //$8B3AE -> Transferred from $F1C010
1117 //$8B5E4 -> Only +1 read at $808AA
1118 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1119 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1122 return MMURead16(address, M68K);
1126 unsigned int m68k_read_memory_32(unsigned int address)
1128 // Musashi does this automagically for you, UAE core does not :-P
1129 address &= 0x00FFFFFF;
1130 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1131 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1132 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));//*/
1134 //WriteLog("--> [RM32]\n");
1136 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1138 return MMURead32(address, M68K);
1142 void m68k_write_memory_8(unsigned int address, unsigned int value)
1144 // Musashi does this automagically for you, UAE core does not :-P
1145 address &= 0x00FFFFFF;
1146 #ifdef CPU_DEBUG_MEMORY
1147 // Note that the Jaguar only has 2M of RAM, not 4!
1148 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1152 if (value > writeMemMax[address])
1153 writeMemMax[address] = value;
1154 if (value < writeMemMin[address])
1155 writeMemMin[address] = value;
1159 /*if (address == 0x4E00)
1160 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1161 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1162 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
1163 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1165 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1166 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1168 /*if (address >= 0x53D0 && address <= 0x53FF)
1169 printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1170 //Testing AvP on UAE core...
1171 //000075A0: FFFFF80E B6320220 (BITMAP)
1172 /*if (address == 0x75A0 && value == 0xFF)
1173 printf("M68K: (8) Tripwire hit...\n");//*/
1176 // Note that the Jaguar only has 2M of RAM, not 4!
1177 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1178 jaguarMainRAM[address] = value;
1179 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1180 CDROMWriteByte(address, value, M68K);
1181 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1182 TOMWriteByte(address, value, M68K);
1183 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1184 JERRYWriteByte(address, value, M68K);
1186 jaguar_unknown_writebyte(address, value, M68K);
1188 MMUWrite8(address, value, M68K);
1192 void m68k_write_memory_16(unsigned int address, unsigned int value)
1194 // Musashi does this automagically for you, UAE core does not :-P
1195 address &= 0x00FFFFFF;
1196 #ifdef CPU_DEBUG_MEMORY
1197 // Note that the Jaguar only has 2M of RAM, not 4!
1198 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1202 uint8_t hi = value >> 8, lo = value & 0xFF;
1204 if (hi > writeMemMax[address])
1205 writeMemMax[address] = hi;
1206 if (hi < writeMemMin[address])
1207 writeMemMin[address] = hi;
1209 if (lo > writeMemMax[address+1])
1210 writeMemMax[address+1] = lo;
1211 if (lo < writeMemMin[address+1])
1212 writeMemMin[address+1] = lo;
1216 /*if (address == 0x4E00)
1217 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1218 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1219 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1220 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1221 //if (address >= 0xF02200 && address <= 0xF0229F)
1222 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1223 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1224 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1225 /*extern uint32_t totalFrames;
1226 if (address == 0xF02114)
1227 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1228 if (address == 0xF02110)
1229 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1230 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1231 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1233 /*if (address == 0x0100)//64*4)
1234 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1236 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1237 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1238 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1239 || address == 0x1AF05E)
1240 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1242 /*if (address >= 0x53D0 && address <= 0x53FF)
1243 printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1244 //Testing AvP on UAE core...
1245 //000075A0: FFFFF80E B6320220 (BITMAP)
1246 /*if (address == 0x75A0 && value == 0xFFFF)
1248 printf("\nM68K: (16) Tripwire hit...\n");
1253 // Note that the Jaguar only has 2M of RAM, not 4!
1254 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1256 /* jaguar_mainRam[address] = value >> 8;
1257 jaguar_mainRam[address + 1] = value & 0xFF;*/
1258 SET16(jaguarMainRAM, address, value);
1260 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1261 CDROMWriteWord(address, value, M68K);
1262 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1263 TOMWriteWord(address, value, M68K);
1264 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1265 JERRYWriteWord(address, value, M68K);
1268 jaguar_unknown_writeword(address, value, M68K);
1269 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1270 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1271 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1272 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1276 MMUWrite16(address, value, M68K);
1280 void m68k_write_memory_32(unsigned int address, unsigned int value)
1282 // Musashi does this automagically for you, UAE core does not :-P
1283 address &= 0x00FFFFFF;
1284 /*if (address == 0x4E00)
1285 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1286 //WriteLog("--> [WM32]\n");
1287 /*if (address == 0x0100)//64*4)
1288 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1289 /*if (address >= 0xF03214 && address < 0xF0321F)
1290 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1291 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1292 /*extern bool doGPUDis;
1293 if (address == 0xF03214 && value == 0x88E30047)
1295 doGPUDis = true;//*/
1296 /* if (address == 0x51136 || address == 0xFB074)
1297 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1298 //Testing AvP on UAE core...
1299 //000075A0: FFFFF80E B6320220 (BITMAP)
1300 /*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
1302 printf("\nM68K: (32) Tripwire hit...\n");
1307 m68k_write_memory_16(address, value >> 16);
1308 m68k_write_memory_16(address + 2, value & 0xFFFF);
1310 MMUWrite32(address, value, M68K);
1315 uint32_t JaguarGetHandler(uint32_t i)
1317 return JaguarReadLong(i * 4);
1320 bool JaguarInterruptHandlerIsValid(uint32_t i) // Debug use only...
1322 uint32_t handler = JaguarGetHandler(i);
1323 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1326 void M68K_show_context(void)
1328 WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1330 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1332 WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1334 if (i == M68K_REG_D3 || i == M68K_REG_D7)
1338 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1340 WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1342 if (i == M68K_REG_A3 || i == M68K_REG_A7)
1346 WriteLog("68K disasm\n");
1347 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1348 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1349 // jaguar_dasm(0x5000, 0x14414);
1351 // WriteLog("\n.......[Cart start]...........\n\n");
1352 // jaguar_dasm(0x192000, 0x1000);//0x200);
1354 WriteLog("..................\n");
1356 if (TOMIRQEnabled(IRQ_VIDEO))
1358 WriteLog("video int: enabled\n");
1359 JaguarDasm(JaguarGetHandler(64), 0x200);
1362 WriteLog("video int: disabled\n");
1364 WriteLog("..................\n");
1366 for(int i=0; i<256; i++)
1368 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1369 uint32_t address = (uint32_t)JaguarGetHandler(i);
1372 WriteLog(".........\n");
1374 WriteLog("$%08X\n", address);
1379 // Unknown read/write byte/word routines
1382 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1383 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1385 // 807EC4: movea.l #$f1b000, A1
1386 // 807ECA: movea.l #$8129e0, A0
1387 // 807ED0: move.l A0, D0
1388 // 807ED2: move.l #$f1bb94, D1
1389 // 807ED8: sub.l D0, D1
1390 // 807EDA: lsr.l #2, D1
1391 // 807EDC: move.l (A0)+, (A1)+
1392 // 807EDE: dbra D1, 807edc
1394 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1395 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1396 // space! (That is, unless the 68K causes a bus error...)
1398 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1400 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1401 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));
1403 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1404 // extern bool finished;
1406 // extern bool doDSPDis;
1412 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1414 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1415 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));
1417 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1418 // extern bool finished;
1420 // extern bool doDSPDis;
1426 unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who/*=UNKNOWN*/)
1428 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1429 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1431 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1432 // extern bool finished;
1434 // extern bool doDSPDis;
1441 unsigned jaguar_unknown_readword(unsigned address, uint32_t who/*=UNKNOWN*/)
1443 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1444 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1446 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1447 // extern bool finished;
1449 // extern bool doDSPDis;
1457 // Disassemble M68K instructions at the given offset
1460 unsigned int m68k_read_disassembler_8(unsigned int address)
1462 return m68k_read_memory_8(address);
1465 unsigned int m68k_read_disassembler_16(unsigned int address)
1467 return m68k_read_memory_16(address);
1470 unsigned int m68k_read_disassembler_32(unsigned int address)
1472 return m68k_read_memory_32(address);
1475 void JaguarDasm(uint32_t offset, uint32_t qt)
1478 static char buffer[2048];//, mem[64];
1479 int pc = offset, oldpc;
1481 for(uint32_t i=0; i<qt; i++)
1484 for(int j=0; j<64; j++)
1485 mem[j^0x01] = jaguar_byte_read(pc + j);
1487 pc += Dasm68000((char *)mem, buffer, 0);
1488 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1490 pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
1491 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1496 uint8_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1498 uint8_t data = 0x00;
1501 // First 2M is mirrored in the $0 - $7FFFFF range
1502 if (offset < 0x800000)
1503 data = jaguarMainRAM[offset & 0x1FFFFF];
1504 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1505 data = jaguarMainROM[offset - 0x800000];
1506 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1507 data = CDROMReadByte(offset, who);
1508 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1509 // data = jaguarBootROM[offset & 0x3FFFF];
1510 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1511 data = jagMemSpace[offset];
1512 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1513 data = TOMReadByte(offset, who);
1514 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1515 data = JERRYReadByte(offset, who);
1517 data = jaguar_unknown_readbyte(offset, who);
1522 uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1526 // First 2M is mirrored in the $0 - $7FFFFF range
1527 if (offset < 0x800000)
1529 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1531 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1534 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1536 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1537 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1538 return CDROMReadWord(offset, who);
1539 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1540 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1541 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1542 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1543 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1544 return TOMReadWord(offset, who);
1545 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1546 return JERRYReadWord(offset, who);
1548 return jaguar_unknown_readword(offset, who);
1551 void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1553 /* if (offset >= 0x4E00 && offset < 0x4E04)
1554 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1555 //Need to check for writes in the range of $18FA70 + 8000...
1557 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1558 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1562 // First 2M is mirrored in the $0 - $7FFFFF range
1563 if (offset < 0x800000)
1565 jaguarMainRAM[offset & 0x1FFFFF] = data;
1568 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1570 CDROMWriteByte(offset, data, who);
1573 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1575 TOMWriteByte(offset, data, who);
1578 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1580 JERRYWriteByte(offset, data, who);
1584 jaguar_unknown_writebyte(offset, data, who);
1588 void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1590 /* if (offset >= 0x4E00 && offset < 0x4E04)
1591 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1592 /*if (offset == 0x0100)//64*4)
1593 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1594 if (offset == 0x0102)//64*4)
1595 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1596 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1597 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1598 //Need to check for writes in the range of $18FA70 + 8000...
1600 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1601 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1602 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1603 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1607 // First 2M is mirrored in the $0 - $7FFFFF range
1608 if (offset <= 0x7FFFFE)
1613 1A 69 F0 ($0000) -> Starfield
1614 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1617 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1626 //This MUST be done by the 68K!
1627 /*if (offset == 0x670C)
1628 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1630 /*extern bool doGPUDis;
1631 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1632 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1633 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1634 doGPUDis = true;//*/
1635 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1636 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1637 if ((data & 0xFF00) != 0x7700)
1638 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1639 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1641 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1642 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1643 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1645 /*extern bool doGPUDis;
1646 if (offset == 0x120216 && who == GPU)
1647 doGPUDis = true;//*/
1648 /*extern uint32_t gpu_pc;
1649 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1651 uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1652 uint32_t y = base / 0x300;
1653 uint32_t x = (base - (y * 0x300)) / 2;
1654 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1657 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1659 //if (offset == (0x001E17F8 + 0x34))
1660 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1662 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1663 /*extern uint32_t gpu_pc;
1664 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1666 extern int objectPtr;
1667 // if (offset > 0x148000)
1670 if (starCount > objectPtr)
1673 // if (starCount == 1)
1674 // WriteLog("--> Drawing 1st star...\n");
1676 // uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1677 // uint32_t y = base / 0x300;
1678 // uint32_t x = (base - (y * 0x300)) / 2;
1679 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1681 //A star of interest...
1682 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1683 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1684 //JWW: Blitter writing echo 77B3 at 0011D022...
1686 //extern bool doGPUDis;
1687 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1690 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1693 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1694 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1696 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1697 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1700 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1702 CDROMWriteWord(offset, data, who);
1705 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1707 TOMWriteWord(offset, data, who);
1710 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1712 JERRYWriteWord(offset, data, who);
1715 // Don't bomb on attempts to write to ROM
1716 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1719 jaguar_unknown_writeword(offset, data, who);
1722 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1723 uint32_t JaguarReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1725 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1728 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1729 void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
1731 /* extern bool doDSPDis;
1732 if (offset < 0x400 && !doDSPDis)
1734 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1737 /*if (offset == 0x0100)//64*4)
1738 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1740 JaguarWriteWord(offset, data >> 16, who);
1741 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1744 void JaguarSetScreenBuffer(uint32_t * buffer)
1746 // This is in TOM, but we set it here...
1747 screenBuffer = buffer;
1750 void JaguarSetScreenPitch(uint32_t pitch)
1752 // This is in TOM, but we set it here...
1753 screenPitch = pitch;
1757 // Jaguar console initialization
1759 void JaguarInit(void)
1761 #ifdef CPU_DEBUG_MEMORY
1762 memset(readMem, 0x00, 0x400000);
1763 memset(writeMemMin, 0xFF, 0x400000);
1764 memset(writeMemMax, 0x00, 0x400000);
1766 memset(jaguarMainRAM, 0x00, 0x200000);
1767 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1768 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1769 //NOTE: This *doesn't* fix FlipOut...
1770 //Or does it? Hmm...
1771 //Seems to want $01010101... Dunno why. Investigate!
1772 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1773 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1774 lowerField = false; // Reset the lower field flag
1775 //temp, for crappy crap that sux
1776 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1778 // m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1779 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
1787 //New timer based code stuffola...
1788 void HalflineCallback(void);
1789 void RenderCallback(void);
1790 void JaguarReset(void)
1792 // New timer base code stuffola...
1793 InitializeEventList();
1794 //Need to change this so it uses the single RAM space and load the BIOS
1795 //into it somewhere...
1796 //Also, have to change this here and in JaguarReadXX() currently
1797 // Only use the system BIOS if it's available...! (it's always available now!)
1798 // AND only if a jaguar cartridge has been inserted.
1799 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1800 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1802 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1804 // WriteLog("jaguar_reset():\n");
1810 m68k_pulse_reset(); // Reset the 68000
1811 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1813 lowerField = false; // Reset the lower field flag
1814 // SetCallbackTime(ScanlineCallback, 63.5555);
1815 // SetCallbackTime(ScanlineCallback, 31.77775);
1816 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1819 void JaguarDone(void)
1821 #ifdef CPU_DEBUG_MEMORY
1822 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1824 for(uint32_t i=0; i<=raPtr; i++)
1826 WriteLog("\t%08X\n", returnAddr[i]);
1827 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1828 jaguar_dasm(returnAddr[i] - 16, 16);
1833 /* int start = 0, end = 0;
1834 bool endTriggered = false, startTriggered = false;
1835 for(int i=0; i<0x400000; i++)
1837 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1839 if (!startTriggered)
1840 startTriggered = true, endTriggered = false, start = i;
1842 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1848 end = i - 1, endTriggered = true, startTriggered = false;
1849 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1856 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1857 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1858 int32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1859 WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
1861 for(int i=-2; i<9; i++)
1862 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1864 uint32_t address = topOfStack - (4 * 4 * 3);
1866 for(int i=0; i<10; i++)
1868 WriteLog("%06X:", address);
1870 for(int j=0; j<4; j++)
1872 WriteLog(" %08X", JaguarReadLong(address));
1880 /* WriteLog("\nM68000 disassembly at $802288...\n");
1881 jaguar_dasm(0x802288, 3);
1882 WriteLog("\nM68000 disassembly at $802200...\n");
1883 jaguar_dasm(0x802200, 500);
1884 WriteLog("\nM68000 disassembly at $802518...\n");
1885 jaguar_dasm(0x802518, 100);//*/
1887 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1888 jaguar_dasm(0x803F00, 500);
1891 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1892 jaguar_dasm(0x802B00, 500);
1895 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1896 jaguar_dasm(0x809900, 500);
1899 /* WriteLog("\n\nDump of $8093C8:\n\n");
1900 for(int i=0x8093C8; i<0x809900; i+=4)
1901 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1902 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1903 jaguar_dasm(0x90006C, 500);
1905 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1906 jaguar_dasm(0x1AC000, 6000);
1909 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1910 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1911 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1912 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1913 M68K_show_context();
1916 #if 0 // This is drawn already...
1917 WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1918 for(uint32_t i=0x64; i<=0x7C; i+=4)
1919 WriteLog(" #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1928 // temp, until debugger is in place
1929 //00802016: jsr $836F1A.l
1930 //0080201C: jsr $836B30.l
1931 //00802022: jsr $836B18.l
1932 //00802028: jsr $8135F0.l
1933 //00813C1E: jsr $813F76.l
1934 //00802038: jsr $836D00.l
1935 //00802098: jsr $8373A4.l
1936 //008020A2: jsr $83E24A.l
1937 //008020BA: jsr $83E156.l
1938 //008020C6: jsr $83E19C.l
1939 //008020E6: jsr $8445E8.l
1940 //008020EC: jsr $838C20.l
1941 //0080211A: jsr $838ED6.l
1942 //00802124: jsr $89CA56.l
1943 //0080212A: jsr $802B48.l
1945 WriteLog("-------------------------------------------\n");
1946 JaguarDasm(0x8445E8, 0x200);
1947 WriteLog("-------------------------------------------\n");
1948 JaguarDasm(0x838C20, 0x200);
1949 WriteLog("-------------------------------------------\n");
1950 JaguarDasm(0x838ED6, 0x200);
1951 WriteLog("-------------------------------------------\n");
1952 JaguarDasm(0x89CA56, 0x200);
1953 WriteLog("-------------------------------------------\n");
1954 JaguarDasm(0x802B48, 0x200);
1955 WriteLog("\n\nM68000 disassembly at $802000...\n");
1956 JaguarDasm(0x802000, 6000);
1959 /* WriteLog("\n\nM68000 disassembly at $6004...\n");
1960 JaguarDasm(0x6004, 10000);
1962 // WriteLog("\n\nM68000 disassembly at $802000...\n");
1963 // JaguarDasm(0x802000, 0x1000);
1964 // WriteLog("\n\nM68000 disassembly at $4100...\n");
1965 // JaguarDasm(0x4100, 200);
1966 // WriteLog("\n\nM68000 disassembly at $800800...\n");
1967 // JaguarDasm(0x800800, 0x1000);
1971 // Temp debugging stuff
1973 void DumpMainMemory(void)
1975 FILE * fp = fopen("./memdump.bin", "wb");
1980 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1985 uint8_t * GetRamPtr(void)
1987 return jaguarMainRAM;
1992 // New Jaguar execution stack
1993 // This executes 1 frame's worth of code.
1996 void JaguarExecuteNew(void)
2002 double timeToNextEvent = GetTimeToNextEvent();
2003 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
2005 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2008 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2016 #define USE_CORRECT_PAL_TIMINGS
2017 // A lot of confusion comes from here...
2018 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
2019 // of whether the display is interlaced or not. The only difference with an
2020 // interlaced display is that the high bit of VC will be set when the lower
2021 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
2022 // regardless of whether it's in interlace mode or not.
2023 // NB2: Seems it doens't always, not sure what the constraint is...)
2025 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2026 // rendering two fields that are slighty vertically offset from each other.
2027 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2028 // is rendered in this mode so that each field, when overlaid on each other,
2029 // will yield the final picture at the full resolution for the full frame.
2031 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2032 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2033 // it will be half this number for a half frame. BUT, since we're counting
2034 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
2036 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2037 // Half line times are, naturally, half of this. :-P
2038 void HalflineCallback(void)
2040 //OK, this is hardwired to run in NTSC, and for who knows how long.
2041 //Need to fix this so that it does a half-line in the correct amount of time
2042 //and number of lines, depending on which mode we're in. [FIXED]
2043 uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
2044 uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2045 uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);
2046 // uint16_t vbb = TOMReadWord(0xF00040, JAGUAR);
2049 #ifdef USE_CORRECT_PAL_TIMINGS
2050 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2051 // So we cut the number of half-lines in a frame in half. :-P
2052 uint16_t numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2054 if ((vc & 0x7FF) >= numHalfLines)
2056 if ((vc & 0x7FF) >= vp)
2060 // lowerField = !lowerField;
2062 // If we're rendering the lower field, set the high bit (#12, counting
2068 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2069 TOMWriteWord(0xF00006, vc, JAGUAR);
2071 //This is a crappy kludge, but maybe it'll work for now...
2072 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2073 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2075 // We don't have to worry about autovectors & whatnot because the Jaguar
2076 // tells you through its HW registers who sent the interrupt...
2077 TOMSetPendingVideoInt();
2081 TOMExecHalfline(vc, true);
2083 //Change this to VBB???
2084 //Doesn't seem to matter (at least for Flip Out & I-War)
2085 if ((vc & 0x7FF) == 0)
2092 #ifdef USE_CORRECT_PAL_TIMINGS
2093 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2095 // SetCallbackTime(HalflineCallback, 63.5555);
2096 SetCallbackTime(HalflineCallback, 31.77775);
2101 // This isn't currently used, but maybe it should be...
2103 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2104 handles all the rest, so this isn't needed. :-P
2106 void RenderCallback(void)
2108 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2109 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time