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 who = UNKNOWN);
50 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
51 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
52 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
53 void M68K_show_context(void);
57 #ifdef CPU_DEBUG_MEMORY
58 extern bool startMemLog; // Set by "e" key
59 extern int effect_start;
60 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
63 // Really, need to include memory.h for this, but it might interfere with some stuff...
64 extern uint8 jagMemSpace[];
68 uint32 jaguar_active_memory_dumps = 0;
70 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
71 bool jaguarCartInserted = false;
72 bool lowerField = false;
74 #ifdef CPU_DEBUG_MEMORY
75 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
76 uint8 readMem[0x400000];
77 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
80 uint32 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 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 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 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 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
198 if (raPtr != 0xFFFFFFFF)
200 for(uint32 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 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
391 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
392 uint32 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 jaguarMainRAM[0x400000]; // 68K CPU RAM
514 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
515 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
516 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
517 bool BIOSLoaded = false;
518 bool CDBIOSLoaded = false;
521 uint8 tomRAM[0x4000];
522 uint8 jerryRAM[0x10000];
523 static uint16 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 address, uint8 byte, uint32 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)byte << 8);
661 else if (address == 0xF00051)
663 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
667 else if (address == 0xF00052)
669 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)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)byte << 8);
730 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)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 adddress, uint16 word)
830 void WriteDWord(uint32 adddress, uint32 dword)
834 uint8 ReadByte(uint32 adddress)
838 uint16 ReadWord(uint32 adddress)
842 uint32 ReadDWord(uint32 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 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 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 JaguarGetHandler(uint32 i)
1317 return JaguarReadLong(i * 4);
1320 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1322 uint32 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 address = (uint32)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 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 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 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 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 offset, uint32 qt)
1478 static char buffer[2048];//, mem[64];
1479 int pc = offset, oldpc;
1481 for(uint32 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 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1501 if (offset < 0x200000)
1502 data = jaguarMainRAM[offset & 0x3FFFFF];
1503 else if ((offset >= 0x800000) && (offset < 0xC00000))
1504 data = jaguarMainROM[offset - 0x800000];
1505 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1506 data = CDROMReadByte(offset, who);
1507 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1508 // data = jaguarBootROM[offset & 0x3FFFF];
1509 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1510 data = jagMemSpace[offset];
1511 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1512 data = TOMReadByte(offset, who);
1513 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1514 data = JERRYReadByte(offset, who);
1516 data = jaguar_unknown_readbyte(offset, who);
1521 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1524 if (offset <= 0x1FFFFE)
1526 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1528 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1531 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1533 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1534 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1535 return CDROMReadWord(offset, who);
1536 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1537 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1538 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1539 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1540 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1541 return TOMReadWord(offset, who);
1542 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1543 return JERRYReadWord(offset, who);
1545 return jaguar_unknown_readword(offset, who);
1548 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1550 /* if (offset >= 0x4E00 && offset < 0x4E04)
1551 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1552 //Need to check for writes in the range of $18FA70 + 8000...
1554 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1555 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1558 if (offset < 0x200000)
1560 jaguarMainRAM[offset & 0x1FFFFF] = data;
1563 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1565 CDROMWriteByte(offset, data, who);
1568 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1570 TOMWriteByte(offset, data, who);
1573 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1575 JERRYWriteByte(offset, data, who);
1579 jaguar_unknown_writebyte(offset, data, who);
1583 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1585 /* if (offset >= 0x4E00 && offset < 0x4E04)
1586 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1587 /*if (offset == 0x0100)//64*4)
1588 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1589 if (offset == 0x0102)//64*4)
1590 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1591 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1592 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1593 //Need to check for writes in the range of $18FA70 + 8000...
1595 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1596 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1597 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1598 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1602 if (offset <= 0x1FFFFE)
1607 1A 69 F0 ($0000) -> Starfield
1608 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1611 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1620 //This MUST be done by the 68K!
1621 /*if (offset == 0x670C)
1622 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1624 /*extern bool doGPUDis;
1625 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1626 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1627 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1628 doGPUDis = true;//*/
1629 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1630 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1631 if ((data & 0xFF00) != 0x7700)
1632 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1633 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1635 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1636 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1637 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1639 /*extern bool doGPUDis;
1640 if (offset == 0x120216 && who == GPU)
1641 doGPUDis = true;//*/
1642 /*extern uint32 gpu_pc;
1643 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1645 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1646 uint32 y = base / 0x300;
1647 uint32 x = (base - (y * 0x300)) / 2;
1648 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1651 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1653 //if (offset == (0x001E17F8 + 0x34))
1654 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1656 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1657 /*extern uint32 gpu_pc;
1658 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1660 extern int objectPtr;
1661 // if (offset > 0x148000)
1664 if (starCount > objectPtr)
1667 // if (starCount == 1)
1668 // WriteLog("--> Drawing 1st star...\n");
1670 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1671 // uint32 y = base / 0x300;
1672 // uint32 x = (base - (y * 0x300)) / 2;
1673 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1675 //A star of interest...
1676 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1677 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1678 //JWW: Blitter writing echo 77B3 at 0011D022...
1680 //extern bool doGPUDis;
1681 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1684 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1687 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1688 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1690 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1691 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1694 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1696 CDROMWriteWord(offset, data, who);
1699 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1701 TOMWriteWord(offset, data, who);
1704 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1706 JERRYWriteWord(offset, data, who);
1709 // Don't bomb on attempts to write to ROM
1710 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1713 jaguar_unknown_writeword(offset, data, who);
1716 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1717 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1719 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1722 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1723 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1725 /* extern bool doDSPDis;
1726 if (offset < 0x400 && !doDSPDis)
1728 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1731 /*if (offset == 0x0100)//64*4)
1732 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1734 JaguarWriteWord(offset, data >> 16, who);
1735 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1738 void JaguarSetScreenBuffer(uint32 * buffer)
1740 // This is in TOM, but we set it here...
1741 screenBuffer = buffer;
1744 void JaguarSetScreenPitch(uint32 pitch)
1746 // This is in TOM, but we set it here...
1747 screenPitch = pitch;
1751 // Jaguar console initialization
1753 void JaguarInit(void)
1755 #ifdef CPU_DEBUG_MEMORY
1756 memset(readMem, 0x00, 0x400000);
1757 memset(writeMemMin, 0xFF, 0x400000);
1758 memset(writeMemMax, 0x00, 0x400000);
1760 memset(jaguarMainRAM, 0x00, 0x200000);
1761 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1762 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1763 //NOTE: This *doesn't* fix FlipOut...
1764 //Or does it? Hmm...
1765 //Seems to want $01010101... Dunno why. Investigate!
1766 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1767 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1768 lowerField = false; // Reset the lower field flag
1769 //temp, for crappy crap that sux
1770 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1772 // m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1773 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
1781 //New timer based code stuffola...
1782 void HalflineCallback(void);
1783 void RenderCallback(void);
1784 void JaguarReset(void)
1786 // New timer base code stuffola...
1787 InitializeEventList();
1788 //Need to change this so it uses the single RAM space and load the BIOS
1789 //into it somewhere...
1790 //Also, have to change this here and in JaguarReadXX() currently
1791 // Only use the system BIOS if it's available...! (it's always available now!)
1792 // AND only if a jaguar cartridge has been inserted.
1793 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1794 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1796 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1798 // WriteLog("jaguar_reset():\n");
1804 m68k_pulse_reset(); // Reset the 68000
1805 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1807 lowerField = false; // Reset the lower field flag
1808 // SetCallbackTime(ScanlineCallback, 63.5555);
1809 // SetCallbackTime(ScanlineCallback, 31.77775);
1810 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1813 void JaguarDone(void)
1815 #ifdef CPU_DEBUG_MEMORY
1816 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1818 for(uint32 i=0; i<=raPtr; i++)
1820 WriteLog("\t%08X\n", returnAddr[i]);
1821 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1822 jaguar_dasm(returnAddr[i] - 16, 16);
1827 /* int start = 0, end = 0;
1828 bool endTriggered = false, startTriggered = false;
1829 for(int i=0; i<0x400000; i++)
1831 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1833 if (!startTriggered)
1834 startTriggered = true, endTriggered = false, start = i;
1836 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1842 end = i - 1, endTriggered = true, startTriggered = false;
1843 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1850 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1851 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1852 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1853 WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
1855 for(int i=-2; i<9; i++)
1856 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1858 uint32 address = topOfStack - (4 * 4 * 3);
1860 for(int i=0; i<10; i++)
1862 WriteLog("%06X:", address);
1864 for(int j=0; j<4; j++)
1866 WriteLog(" %08X", JaguarReadLong(address));
1874 /* WriteLog("\nM68000 disassembly at $802288...\n");
1875 jaguar_dasm(0x802288, 3);
1876 WriteLog("\nM68000 disassembly at $802200...\n");
1877 jaguar_dasm(0x802200, 500);
1878 WriteLog("\nM68000 disassembly at $802518...\n");
1879 jaguar_dasm(0x802518, 100);//*/
1881 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1882 jaguar_dasm(0x803F00, 500);
1885 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1886 jaguar_dasm(0x802B00, 500);
1889 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1890 jaguar_dasm(0x809900, 500);
1893 /* WriteLog("\n\nDump of $8093C8:\n\n");
1894 for(int i=0x8093C8; i<0x809900; i+=4)
1895 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1896 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1897 jaguar_dasm(0x90006C, 500);
1899 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1900 jaguar_dasm(0x1AC000, 6000);
1903 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1904 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1905 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1906 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1907 M68K_show_context();
1910 #if 0 // This is drawn already...
1911 WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1912 for(uint32 i=0x64; i<=0x7C; i+=4)
1913 WriteLog(" #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1922 // temp, until debugger is in place
1923 //00802016: jsr $836F1A.l
1924 //0080201C: jsr $836B30.l
1925 //00802022: jsr $836B18.l
1926 //00802028: jsr $8135F0.l
1927 //00813C1E: jsr $813F76.l
1928 //00802038: jsr $836D00.l
1929 //00802098: jsr $8373A4.l
1930 //008020A2: jsr $83E24A.l
1931 //008020BA: jsr $83E156.l
1932 //008020C6: jsr $83E19C.l
1933 //008020E6: jsr $8445E8.l
1934 //008020EC: jsr $838C20.l
1935 //0080211A: jsr $838ED6.l
1936 //00802124: jsr $89CA56.l
1937 //0080212A: jsr $802B48.l
1939 WriteLog("-------------------------------------------\n");
1940 JaguarDasm(0x8445E8, 0x200);
1941 WriteLog("-------------------------------------------\n");
1942 JaguarDasm(0x838C20, 0x200);
1943 WriteLog("-------------------------------------------\n");
1944 JaguarDasm(0x838ED6, 0x200);
1945 WriteLog("-------------------------------------------\n");
1946 JaguarDasm(0x89CA56, 0x200);
1947 WriteLog("-------------------------------------------\n");
1948 JaguarDasm(0x802B48, 0x200);
1949 WriteLog("\n\nM68000 disassembly at $802000...\n");
1950 JaguarDasm(0x802000, 6000);
1953 /* WriteLog("\n\nM68000 disassembly at $6004...\n");
1954 JaguarDasm(0x6004, 10000);
1956 // WriteLog("\n\nM68000 disassembly at $802000...\n");
1957 // JaguarDasm(0x802000, 0x1000);
1958 // WriteLog("\n\nM68000 disassembly at $4100...\n");
1959 // JaguarDasm(0x4100, 200);
1960 // WriteLog("\n\nM68000 disassembly at $800800...\n");
1961 // JaguarDasm(0x800800, 0x1000);
1965 // Temp debugging stuff
1967 void DumpMainMemory(void)
1969 FILE * fp = fopen("./memdump.bin", "wb");
1974 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1979 uint8 * GetRamPtr(void)
1981 return jaguarMainRAM;
1986 // New Jaguar execution stack
1987 // This executes 1 frame's worth of code.
1990 void JaguarExecuteNew(void)
1996 double timeToNextEvent = GetTimeToNextEvent();
1997 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1999 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2002 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2010 #define USE_CORRECT_PAL_TIMINGS
2011 // A lot of confusion comes from here...
2012 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
2013 // of whether the display is interlaced or not. The only difference with an
2014 // interlaced display is that the high bit of VC will be set when the lower
2015 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
2016 // regardless of whether it's in interlace mode or not.
2017 // NB2: Seems it doens't always, not sure what the constraint is...)
2019 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2020 // rendering two fields that are slighty vertically offset from each other.
2021 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2022 // is rendered in this mode so that each field, when overlaid on each other,
2023 // will yield the final picture at the full resolution for the full frame.
2025 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2026 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2027 // it will be half this number for a half frame. BUT, since we're counting
2028 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
2030 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2031 // Half line times are, naturally, half of this. :-P
2032 void HalflineCallback(void)
2034 //OK, this is hardwired to run in NTSC, and for who knows how long.
2035 //Need to fix this so that it does a half-line in the correct amount of time
2036 //and number of lines, depending on which mode we're in. [FIXED]
2037 uint16 vc = TOMReadWord(0xF00006, JAGUAR);
2038 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2039 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
2040 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
2043 #ifdef USE_CORRECT_PAL_TIMINGS
2044 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2045 // So we cut the number of half-lines in a frame in half. :-P
2046 uint16 numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2048 if ((vc & 0x7FF) >= numHalfLines)
2050 if ((vc & 0x7FF) >= vp)
2054 // lowerField = !lowerField;
2056 // If we're rendering the lower field, set the high bit (#12, counting
2062 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2063 TOMWriteWord(0xF00006, vc, JAGUAR);
2065 //This is a crappy kludge, but maybe it'll work for now...
2066 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2067 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2069 // We don't have to worry about autovectors & whatnot because the Jaguar
2070 // tells you through its HW registers who sent the interrupt...
2071 TOMSetPendingVideoInt();
2075 TOMExecHalfline(vc, true);
2077 //Change this to VBB???
2078 //Doesn't seem to matter (at least for Flip Out & I-War)
2079 if ((vc & 0x7FF) == 0)
2086 #ifdef USE_CORRECT_PAL_TIMINGS
2087 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2089 // SetCallbackTime(HalflineCallback, 63.5555);
2090 SetCallbackTime(HalflineCallback, 31.77775);
2095 // This isn't currently used, but maybe it should be...
2097 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2098 handles all the rest, so this isn't needed. :-P
2100 void RenderCallback(void)
2102 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2103 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time