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
46 // Private function prototypes
48 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
49 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
50 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
51 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
52 void M68K_show_context(void);
56 #ifdef CPU_DEBUG_MEMORY
57 extern bool startMemLog; // Set by "e" key
58 extern int effect_start;
59 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
62 // Really, need to include memory.h for this, but it might interfere with some stuff...
63 extern uint8 jagMemSpace[];
67 uint32 jaguar_active_memory_dumps = 0;
69 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
70 bool jaguarCartInserted = false;
71 bool lowerField = false;
73 #ifdef CPU_DEBUG_MEMORY
74 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
75 uint8 readMem[0x400000];
76 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
79 uint32 pcQueue[0x400];
83 // Callback function to detect illegal instructions
85 void GPUDumpDisassembly(void);
86 void GPUDumpRegisters(void);
87 static bool start = false;
89 void M68KInstructionHook(void)
91 uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
92 // Temp, for comparing...
94 /* static char buffer[2048];//, mem[64];
95 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
96 printf("%08X: %s\n", m68kPC, buffer);//*/
98 //JaguarDasm(m68kPC, 1);
99 //Testing Hover Strike...
102 static int hitCount = 0;
103 static int inRoutine = 0;
106 //if (regs.pc == 0x80340A)
107 if (m68kPC == 0x803416)
112 printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1));
114 else if (m68kPC == 0x803422)
117 printf("(%i instructions)\n", instSeen);
125 // Ideally, we'd save all the registers as well...
126 pcQueue[pcQPtr++] = m68kPC;
129 if (m68kPC & 0x01) // Oops! We're fetching an odd address!
131 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
133 static char buffer[2048];
134 for(int i=0; i<0x400; i++)
136 m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], 0);//M68K_CPU_TYPE_68000);
137 WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
141 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
142 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
143 for(int i=0; i<10; i++)
144 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
145 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
151 // Disassemble everything
153 static char buffer[2048];
154 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
155 WriteLog("%08X: %s", m68kPC, buffer);
156 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
157 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
158 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
160 /* if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
162 static char buffer[2048];
163 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
164 WriteLog("%08X: %s", m68kPC, buffer);
165 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
166 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
167 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
169 /* if (m68kPC == 0x8D0E48 && effect_start5)
171 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
173 GPUDumpDisassembly();
177 /* uint16 opcode = JaguarReadWord(m68kPC);
178 if (opcode == 0x4E75) // RTS
181 // WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
183 uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
185 if (raPtr != 0xFFFFFFFF)
187 for(uint32 i=0; i<=raPtr; i++)
189 if (returnAddr[i] == addr)
198 returnAddr[++raPtr] = addr;
202 //Flip Out! debugging...
205 00805FDC: movea.l #$9c6f8, A0 D0=00100010, A0=00100000
206 00805FE2: move.w #$10, (A0)+ D0=00100010, A0=0009C6F8
207 00805FE6: cmpa.l #$c96f8, A0 D0=00100010, A0=0009C6FA
208 00805FEC: bne 805fe2 D0=00100010, A0=0009C6FA
210 0080603A: move.l #$11ed7c, $100.w D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
212 0012314C: move.l (A0)+, (A1)+ D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
213 0012314E: cmpa.l #$f04000, A1 D0=61700080, A0=00124178, D1=00000000, A1=00F04000
214 00123154: blt 12314c D0=61700080, A0=00124178, D1=00000000, A1=00F04000
215 00123156: move.l #$0, $f035d0.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
216 00123160: move.l #$f03000, $f02110.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
217 0012316A: move.l #$1, $f02114.l D0=61700080, A0=00124178, D1=00000000, A1=00F04000
218 00123174: rts D0=61700080, A0=00124178, D1=00000000, A1=00F04000
220 /* static char buffer[2048];
221 //if (m68kPC > 0x805F48) start = true;
222 //if (m68kPC > 0x806486) start = true;
223 //if (m68kPC == 0x805FEE) start = true;
224 //if (m68kPC == 0x80600C)// start = true;
225 if (m68kPC == 0x802058) start = true;
227 // GPUDumpRegisters();
228 // GPUDumpDisassembly();
230 // M68K_show_context();
236 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
237 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));
240 /* if (m68kPC == 0x803F16)
242 WriteLog("M68K: Registers found at $803F16:\n");
243 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
244 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
245 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
247 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
248 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
250 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
251 // !!! Investigate !!!
252 /*extern bool doDSPDis;
253 static bool disgo = false;
254 if (m68kPC == 0x50222)
257 // WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
258 // DSPWriteLong(0xF1B000, 0x12345678, M68K);
261 if (m68kPC == 0x5000)
266 static char buffer[2048];
267 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
268 WriteLog("%08X: %s", m68kPC, buffer);
269 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
270 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
271 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
273 if (m68kPC == 0x82E1A)
275 static char buffer[2048];
276 m68k_disassemble(buffer, m68kPC, 0);//M68K_CPU_TYPE_68000);
277 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
278 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
279 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
280 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
282 if (m68kPC == 0x82E58)
283 WriteLog("--> [Routine end]\n");
284 if (m68kPC == 0x80004)
286 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
287 // m68k_set_reg(M68K_REG_D2, 0x12345678);
290 #ifdef LOG_CD_BIOS_CALLS
313 if (m68kPC == 0x3000)
314 WriteLog("M68K: CD_init\n");
315 else if (m68kPC == 0x3006 + (6 * 0))
316 WriteLog("M68K: CD_mode\n");
317 else if (m68kPC == 0x3006 + (6 * 1))
318 WriteLog("M68K: CD_ack\n");
319 else if (m68kPC == 0x3006 + (6 * 2))
320 WriteLog("M68K: CD_jeri\n");
321 else if (m68kPC == 0x3006 + (6 * 3))
322 WriteLog("M68K: CD_spin\n");
323 else if (m68kPC == 0x3006 + (6 * 4))
324 WriteLog("M68K: CD_stop\n");
325 else if (m68kPC == 0x3006 + (6 * 5))
326 WriteLog("M68K: CD_mute\n");
327 else if (m68kPC == 0x3006 + (6 * 6))
328 WriteLog("M68K: CD_umute\n");
329 else if (m68kPC == 0x3006 + (6 * 7))
330 WriteLog("M68K: CD_paus\n");
331 else if (m68kPC == 0x3006 + (6 * 8))
332 WriteLog("M68K: CD_upaus\n");
333 else if (m68kPC == 0x3006 + (6 * 9))
334 WriteLog("M68K: CD_read\n");
335 else if (m68kPC == 0x3006 + (6 * 10))
336 WriteLog("M68K: CD_uread\n");
337 else if (m68kPC == 0x3006 + (6 * 11))
338 WriteLog("M68K: CD_setup\n");
339 else if (m68kPC == 0x3006 + (6 * 12))
340 WriteLog("M68K: CD_ptr\n");
341 else if (m68kPC == 0x3006 + (6 * 13))
342 WriteLog("M68K: CD_osamp\n");
343 else if (m68kPC == 0x3006 + (6 * 14))
344 WriteLog("M68K: CD_getoc\n");
345 else if (m68kPC == 0x3006 + (6 * 15))
346 WriteLog("M68K: CD_initm\n");
347 else if (m68kPC == 0x3006 + (6 * 16))
348 WriteLog("M68K: CD_initf\n");
349 else if (m68kPC == 0x3006 + (6 * 17))
350 WriteLog("M68K: CD_switch\n");
352 if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
353 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
354 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
355 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
358 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
359 if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), 0))//M68K_CPU_TYPE_68000))
361 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
362 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
364 // This is a kludge to let homebrew programs work properly (i.e., let the other processors
365 // keep going even when the 68K dumped back to the debugger or what have you).
367 // m68k_set_reg(M68K_REG_PC, m68kPC - 2);
368 // Try setting the vector to the illegal instruction...
369 //This doesn't work right either! Do something else! Quick!
370 // SET32(jaguar_mainRam, 0x10, m68kPC);
376 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
377 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
378 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
379 for(int i=0; i<10; i++)
380 WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
381 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
385 // WriteLog("\n\n68K disasm\n\n");
386 // jaguar_dasm(0x802000, 0x50C);
397 Now here be dragons...
398 Here is how memory ranges are defined in the CoJag driver.
399 Note that we only have to be concerned with 3 entities read/writing anything:
400 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
401 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
402 things that are entirely internal to those modules. This way we should be able to get a handle on all
403 this crap which is currently scattered over Hell's Half Acre(tm).
405 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
406 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
408 /*************************************
410 * Main CPU memory handlers
412 *************************************/
414 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
415 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
416 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
417 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
418 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
419 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
420 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
421 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
422 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
423 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
424 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
425 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
426 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
427 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
428 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
429 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
430 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
431 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
432 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
433 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
434 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
435 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
436 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
439 /*************************************
441 * GPU memory handlers
443 *************************************/
445 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
446 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
447 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
448 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
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_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_RAM AM_SHARE(3)
455 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
458 /*************************************
460 * DSP memory handlers
462 *************************************/
464 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
465 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
466 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
467 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
468 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
469 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
470 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
471 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
472 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
477 //#define EXPERIMENTAL_MEMORY_HANDLING
478 // Experimental memory mappage...
479 // Dunno if this is a good approach or not, but it seems to make better
480 // sense to have all this crap in one spot intstead of scattered all over
481 // the place the way it is now.
482 #ifdef EXPERIMENTAL_MEMORY_HANDLING
484 #define NEW_TIMER_SYSTEM
487 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
488 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
489 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
490 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
491 bool BIOSLoaded = false;
492 bool CDBIOSLoaded = false;
495 uint8 tomRAM[0x4000];
496 uint8 jerryRAM[0x10000];
497 static uint16 eeprom_ram[64];
499 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
502 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
504 // M68K Memory map/handlers
506 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
507 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
508 // Note that this is really memory mapped I/O region...
509 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
510 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
511 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
512 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
513 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
514 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
515 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
516 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
517 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
518 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
519 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
520 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
522 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
524 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
525 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
526 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
527 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
528 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
529 //What about LBUF writes???
530 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
531 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
532 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
534 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
538 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
539 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
540 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
543 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
544 0 = pad0/1 button values (4 bits each), RO(?)
545 1 = pad0/1 index value (4 bits each), WO
547 3 = NTSC/PAL, certain button states, RO
549 JOYSTICK $F14000 Read/Write
551 Read fedcba98 7654321q f-1 Signals J15 to J1
552 q Cartridge EEPROM output data
553 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
554 0 = disable J7-J0 outputs
557 0 = Audio muted (reset state)
559 7-4 J7-J4 outputs (port 2)
560 3-0 J3-J0 outputs (port 1)
561 JOYBUTS $F14002 Read Only
563 Read xxxxxxxx rrdv3210 x don't care
566 v 1 = NTSC Video hardware
567 0 = PAL Video hardware
568 3-2 Button inputs B3 & B2 (port 2)
569 1-0 Button inputs B1 & B0 (port 1)
571 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
572 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
580 0 1 1 1 Row 3 C3 Option # 9 6 3
584 1 0 1 1 Row 2 C2 C 0 8 5 2
586 1 1 0 1 Row 1 C1 B * 7 4 1
587 1 1 1 0 Row 0 Pause A Up Down Left Right
590 0 bit read in any position means that button is pressed.
591 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
595 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
597 // Not sure, but I think the system only has 24 address bits...
598 address &= 0x00FFFFFF;
600 // RAM ($000000 - $3FFFFF) 4M
601 if (address <= 0x3FFFFF)
602 jaguarMainRAM[address] = byte;
603 // hole ($400000 - $7FFFFF) 4M
604 else if (address <= 0x7FFFFF)
606 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
607 else if (address <= 0xDFFEFF)
609 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
610 else if (address <= 0xDFFFFF)
612 cdRAM[address & 0xFF] = byte;
614 if ((address & 0xFF) < 12 * 4)
615 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
616 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
619 // BIOS ROM ($E00000 - $E3FFFF) 256K
620 else if (address <= 0xE3FFFF)
622 // hole ($E40000 - $EFFFFF) 768K
623 else if (address <= 0xEFFFFF)
625 // TOM ($F00000 - $F0FFFF) 64K
626 else if (address <= 0xF0FFFF)
629 if (address == 0xF00050)
631 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
635 else if (address == 0xF00051)
637 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
641 else if (address == 0xF00052)
643 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
647 else if (address == 0xF00053)
649 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
653 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
655 // Writing to one CLUT writes to the other
656 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
657 tomRAM[address] = tomRAM[address + 0x200] = byte;
660 //What about LBUF writes???
661 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
663 GPUWriteByte(address, byte, who);
666 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
668 BlitterWriteByte(address, byte, who);
671 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
673 GPUWriteByte(address, byte, who);
677 tomRAM[address & 0x3FFF] = byte;
679 // JERRY ($F10000 - $F1FFFF) 64K
680 else if (address <= 0xF1FFFF)
684 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
686 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
688 DSPWriteByte(address, byte, who);
691 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
693 DSPWriteByte(address, byte, who);
696 // SCLK ($F1A150--8 bits wide)
697 //NOTE: This should be taken care of in DAC...
698 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
700 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
701 if ((address & 0x03) == 2)
702 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
704 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
706 JERRYI2SInterruptTimer = -1;
707 #ifndef NEW_TIMER_SYSTEM
710 RemoveCallback(JERRYI2SCallback);
715 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
716 else if (address >= 0xF1A148 && address <= 0xF1A157)
718 DACWriteByte(address, byte, who);
721 else if (address >= 0xF10000 && address <= 0xF10007)
723 #ifndef NEW_TIMER_SYSTEM
724 switch (address & 0x07)
727 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
731 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
735 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
739 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
743 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
747 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
751 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
755 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
759 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
763 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
765 clock_byte_write(offset, byte);
768 // JERRY -> 68K interrupt enables/latches (need to be handled!)
769 else if (address >= 0xF10020 && address <= 0xF10023)
771 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
773 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
775 anajoy_byte_write(offset, byte);
778 else if ((address >= 0xF14000) && (address <= 0xF14003))
780 JoystickWriteByte(address, byte);
781 EepromWriteByte(address, byte);
784 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
786 EepromWriteByte(address, byte);
789 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
790 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
793 jerryRAM[address & 0xFFFF] = byte;
795 // hole ($F20000 - $FFFFFF) 1M - 128K
800 void WriteWord(uint32 adddress, uint16 word)
804 void WriteDWord(uint32 adddress, uint32 dword)
808 uint8 ReadByte(uint32 adddress)
812 uint16 ReadWord(uint32 adddress)
816 uint32 ReadDWord(uint32 adddress)
821 void ShowM68KContext(void)
823 printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
825 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
827 printf("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
829 if (i == M68K_REG_D3 || i == M68K_REG_D7)
833 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
835 printf("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
837 if (i == M68K_REG_A3 || i == M68K_REG_A7)
841 uint32_t currpc = m68k_get_reg(NULL, M68K_REG_PC);
842 uint32_t disPC = currpc - 30;
847 uint32_t oldpc = disPC;
848 disPC += m68k_disassemble(buffer, disPC, 0);
849 printf("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
851 while (disPC < (currpc + 10));
855 // Custom UAE 68000 read/write/IRQ functions
862 IPL Name Vector Control
863 ---------+---------------+---------------+---------------
864 2 VBLANK IRQ $100 INT1 bit #0
865 2 GPU IRQ $100 INT1 bit #1
866 2 HBLANK IRQ $100 INT1 bit #2
867 2 Timer IRQ $100 INT1 bit #3
869 Note: Both timer interrupts (JPIT && PIT) are on the same INT1 bit.
870 and are therefore indistinguishable.
872 A typical way to install a LEVEL2 handler for the 68000 would be
873 something like this, you gotta supply "last_line" and "handler".
874 Note that the interrupt is auto vectored thru $100 (not $68)
882 IRQS_HANDLED=$909 ;; VBLANK and TIMER
884 move.w #$2700,sr ;; no IRQs please
885 move.l #handler,V_AUTO ;; install our routine
887 move.w #last_line,VI ;; scanline where IRQ should occur
888 ;; should be 'odd' BTW
889 move.w #IRQS_HANDLE&$FF,INT1 ;; enable VBLANK + TIMER
890 move.w #$2100,sr ;; enable IRQs on the 68K
908 move.w #IRQS_HANDLED,INT1 ; clear latch, keep IRQ alive
909 move.w #0,INT2 ; let GPU run again
913 As you can see, if you have multiple INT1 interrupts coming in,
914 you need to check the lower byte of INT1, to see which interrupt
917 int irq_ack_handler(int level)
919 // Tracing the IPL lines on the Jaguar schematic yields the following:
920 // IPL1 is connected to INTL on TOM (OUT to 68K)
921 // IPL0-2 are also tied to Vcc via 4.7K resistors!
922 // (DINT on TOM goes into DINT on JERRY (IN Tom from Jerry))
923 // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
924 // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
926 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
927 // They aren't, and this causes problems with a, err, specific ROM. :-D
931 m68k_set_irq(0); // Clear the IRQ (NOTE: Without this, the BIOS fails)...
932 return 64; // Set user interrupt #0
935 return M68K_INT_ACK_AUTOVECTOR;
938 //#define USE_NEW_MMU
940 unsigned int m68k_read_memory_8(unsigned int address)
942 // Musashi does this automagically for you, UAE core does not :-P
943 address &= 0x00FFFFFF;
944 #ifdef CPU_DEBUG_MEMORY
945 // Note that the Jaguar only has 2M of RAM, not 4!
946 if ((address >= 0x000000) && (address <= 0x1FFFFF))
949 readMem[address] = 1;
952 //WriteLog("[RM8] Addr: %08X\n", address);
953 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
954 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
955 || address == 0x1AF05E)
956 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
958 unsigned int retVal = 0;
960 // Note that the Jaguar only has 2M of RAM, not 4!
961 if ((address >= 0x000000) && (address <= 0x1FFFFF))
962 retVal = jaguarMainRAM[address];
963 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
964 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
965 retVal = jaguarMainROM[address - 0x800000];
966 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
967 // retVal = jaguarBootROM[address - 0xE00000];
968 // retVal = jaguarDevBootROM1[address - 0xE00000];
969 retVal = jagMemSpace[address];
970 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
971 retVal = CDROMReadByte(address);
972 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
973 retVal = TOMReadByte(address, M68K);
974 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
975 retVal = JERRYReadByte(address, M68K);
977 retVal = jaguar_unknown_readbyte(address, M68K);
979 //if (address >= 0x2800 && address <= 0x281F)
980 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
981 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
982 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
985 return MMURead8(address, M68K);
989 void gpu_dump_disassembly(void);
990 void gpu_dump_registers(void);
992 unsigned int m68k_read_memory_16(unsigned int address)
994 // Musashi does this automagically for you, UAE core does not :-P
995 address &= 0x00FFFFFF;
996 #ifdef CPU_DEBUG_MEMORY
997 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
1000 readMem[address] = 1, readMem[address + 1] = 1;
1002 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
1004 return 0x4E71; // NOP
1006 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
1008 return 0x4E71; // NOP
1010 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
1012 return 0x4E71; // NOP
1014 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
1016 return 0x4E71; // NOP
1018 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
1020 return 0x4E71; // NOP
1022 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
1024 return 0x4E71; // NOP
1027 //WriteLog("[RM16] Addr: %08X\n", address);
1028 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
1029 // for(int i=0; i<10000; i++)
1030 WriteLog("[M68K] In routine #6!\n");//*/
1031 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
1032 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
1033 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
1035 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1036 gpu_dump_registers();
1037 gpu_dump_disassembly();
1038 // for(int i=0; i<10000; i++)
1039 // WriteLog("[M68K] About to run GPU!\n");
1041 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1042 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
1044 if (address == 0x000066A0)
1046 gpu_dump_registers();
1047 gpu_dump_disassembly();
1049 for(int i=0; i<10000; i++)
1050 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1052 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1053 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1054 || address == 0x1AF05E)
1055 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
1057 unsigned int retVal = 0;
1059 // Note that the Jaguar only has 2M of RAM, not 4!
1060 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1061 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
1062 retVal = GET16(jaguarMainRAM, address);
1063 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
1064 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
1065 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
1066 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
1067 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1068 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1069 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1070 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1071 retVal = CDROMReadWord(address, M68K);
1072 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1073 retVal = TOMReadWord(address, M68K);
1074 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1075 retVal = JERRYReadWord(address, M68K);
1077 retVal = jaguar_unknown_readword(address, M68K);
1079 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
1080 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1081 //if (address >= 0x2800 && address <= 0x281F)
1082 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1083 //$8B3AE -> Transferred from $F1C010
1084 //$8B5E4 -> Only +1 read at $808AA
1085 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1086 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1089 return MMURead16(address, M68K);
1093 unsigned int m68k_read_memory_32(unsigned int address)
1095 // Musashi does this automagically for you, UAE core does not :-P
1096 address &= 0x00FFFFFF;
1097 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1098 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1099 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));//*/
1101 //WriteLog("--> [RM32]\n");
1103 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1105 return MMURead32(address, M68K);
1109 void m68k_write_memory_8(unsigned int address, unsigned int value)
1111 // Musashi does this automagically for you, UAE core does not :-P
1112 address &= 0x00FFFFFF;
1113 #ifdef CPU_DEBUG_MEMORY
1114 // Note that the Jaguar only has 2M of RAM, not 4!
1115 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1119 if (value > writeMemMax[address])
1120 writeMemMax[address] = value;
1121 if (value < writeMemMin[address])
1122 writeMemMin[address] = value;
1126 /*if (address == 0x4E00)
1127 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1128 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1129 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
1130 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1132 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1133 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1135 /*if (address >= 0x53D0 && address <= 0x53FF)
1136 printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1137 //Testing AvP on UAE core...
1138 //000075A0: FFFFF80E B6320220 (BITMAP)
1139 /*if (address == 0x75A0 && value == 0xFF)
1140 printf("M68K: (8) Tripwire hit...\n");//*/
1143 // Note that the Jaguar only has 2M of RAM, not 4!
1144 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1145 jaguarMainRAM[address] = value;
1146 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1147 CDROMWriteByte(address, value, M68K);
1148 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1149 TOMWriteByte(address, value, M68K);
1150 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1151 JERRYWriteByte(address, value, M68K);
1153 jaguar_unknown_writebyte(address, value, M68K);
1155 MMUWrite8(address, value, M68K);
1159 void m68k_write_memory_16(unsigned int address, unsigned int value)
1161 // Musashi does this automagically for you, UAE core does not :-P
1162 address &= 0x00FFFFFF;
1163 #ifdef CPU_DEBUG_MEMORY
1164 // Note that the Jaguar only has 2M of RAM, not 4!
1165 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1169 uint8 hi = value >> 8, lo = value & 0xFF;
1171 if (hi > writeMemMax[address])
1172 writeMemMax[address] = hi;
1173 if (hi < writeMemMin[address])
1174 writeMemMin[address] = hi;
1176 if (lo > writeMemMax[address+1])
1177 writeMemMax[address+1] = lo;
1178 if (lo < writeMemMin[address+1])
1179 writeMemMin[address+1] = lo;
1183 /*if (address == 0x4E00)
1184 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1185 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1186 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1187 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1188 //if (address >= 0xF02200 && address <= 0xF0229F)
1189 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1190 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1191 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1192 /*extern uint32 totalFrames;
1193 if (address == 0xF02114)
1194 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1195 if (address == 0xF02110)
1196 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1197 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1198 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1200 /*if (address == 0x0100)//64*4)
1201 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1203 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1204 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1205 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1206 || address == 0x1AF05E)
1207 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1209 /*if (address >= 0x53D0 && address <= 0x53FF)
1210 printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1211 //Testing AvP on UAE core...
1212 //000075A0: FFFFF80E B6320220 (BITMAP)
1213 /*if (address == 0x75A0 && value == 0xFFFF)
1215 printf("\nM68K: (16) Tripwire hit...\n");
1220 // Note that the Jaguar only has 2M of RAM, not 4!
1221 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1223 /* jaguar_mainRam[address] = value >> 8;
1224 jaguar_mainRam[address + 1] = value & 0xFF;*/
1225 SET16(jaguarMainRAM, address, value);
1227 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1228 CDROMWriteWord(address, value, M68K);
1229 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1230 TOMWriteWord(address, value, M68K);
1231 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1232 JERRYWriteWord(address, value, M68K);
1235 jaguar_unknown_writeword(address, value, M68K);
1236 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1237 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1238 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1239 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1243 MMUWrite16(address, value, M68K);
1247 void m68k_write_memory_32(unsigned int address, unsigned int value)
1249 // Musashi does this automagically for you, UAE core does not :-P
1250 address &= 0x00FFFFFF;
1251 /*if (address == 0x4E00)
1252 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1253 //WriteLog("--> [WM32]\n");
1254 /*if (address == 0x0100)//64*4)
1255 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1256 /*if (address >= 0xF03214 && address < 0xF0321F)
1257 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1258 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1259 /*extern bool doGPUDis;
1260 if (address == 0xF03214 && value == 0x88E30047)
1262 doGPUDis = true;//*/
1263 /* if (address == 0x51136 || address == 0xFB074)
1264 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1265 //Testing AvP on UAE core...
1266 //000075A0: FFFFF80E B6320220 (BITMAP)
1267 /*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
1269 printf("\nM68K: (32) Tripwire hit...\n");
1274 m68k_write_memory_16(address, value >> 16);
1275 m68k_write_memory_16(address + 2, value & 0xFFFF);
1277 MMUWrite32(address, value, M68K);
1282 uint32 JaguarGetHandler(uint32 i)
1284 return JaguarReadLong(i * 4);
1287 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1289 uint32 handler = JaguarGetHandler(i);
1290 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1293 void M68K_show_context(void)
1295 WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1297 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1299 WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1301 if (i == M68K_REG_D3 || i == M68K_REG_D7)
1305 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1307 WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1309 if (i == M68K_REG_A3 || i == M68K_REG_A7)
1313 WriteLog("68K disasm\n");
1314 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1315 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1316 // jaguar_dasm(0x5000, 0x14414);
1318 // WriteLog("\n.......[Cart start]...........\n\n");
1319 // jaguar_dasm(0x192000, 0x1000);//0x200);
1321 WriteLog("..................\n");
1323 if (TOMIRQEnabled(IRQ_VIDEO))
1325 WriteLog("video int: enabled\n");
1326 JaguarDasm(JaguarGetHandler(64), 0x200);
1329 WriteLog("video int: disabled\n");
1331 WriteLog("..................\n");
1333 for(int i=0; i<256; i++)
1335 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1336 uint32 address = (uint32)JaguarGetHandler(i);
1339 WriteLog(".........\n");
1341 WriteLog("$%08X\n", address);
1346 // Unknown read/write byte/word routines
1349 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1350 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1352 // 807EC4: movea.l #$f1b000, A1
1353 // 807ECA: movea.l #$8129e0, A0
1354 // 807ED0: move.l A0, D0
1355 // 807ED2: move.l #$f1bb94, D1
1356 // 807ED8: sub.l D0, D1
1357 // 807EDA: lsr.l #2, D1
1358 // 807EDC: move.l (A0)+, (A1)+
1359 // 807EDE: dbra D1, 807edc
1361 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1362 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1363 // space! (That is, unless the 68K causes a bus error...)
1365 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1367 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1368 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));
1370 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1371 // extern bool finished;
1373 // extern bool doDSPDis;
1379 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1381 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1382 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));
1384 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1385 // extern bool finished;
1387 // extern bool doDSPDis;
1393 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1395 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1396 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1398 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1399 // extern bool finished;
1401 // extern bool doDSPDis;
1408 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1410 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1411 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1413 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1414 // extern bool finished;
1416 // extern bool doDSPDis;
1424 // Disassemble M68K instructions at the given offset
1427 unsigned int m68k_read_disassembler_8(unsigned int address)
1429 return m68k_read_memory_8(address);
1432 unsigned int m68k_read_disassembler_16(unsigned int address)
1434 return m68k_read_memory_16(address);
1437 unsigned int m68k_read_disassembler_32(unsigned int address)
1439 return m68k_read_memory_32(address);
1442 void JaguarDasm(uint32 offset, uint32 qt)
1445 static char buffer[2048];//, mem[64];
1446 int pc = offset, oldpc;
1448 for(uint32 i=0; i<qt; i++)
1451 for(int j=0; j<64; j++)
1452 mem[j^0x01] = jaguar_byte_read(pc + j);
1454 pc += Dasm68000((char *)mem, buffer, 0);
1455 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1457 pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
1458 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1463 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1468 if (offset < 0x200000)
1469 data = jaguarMainRAM[offset & 0x3FFFFF];
1470 else if ((offset >= 0x800000) && (offset < 0xC00000))
1471 data = jaguarMainROM[offset - 0x800000];
1472 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1473 data = CDROMReadByte(offset, who);
1474 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1475 // data = jaguarBootROM[offset & 0x3FFFF];
1476 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1477 data = jagMemSpace[offset];
1478 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1479 data = TOMReadByte(offset, who);
1480 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1481 data = JERRYReadByte(offset, who);
1483 data = jaguar_unknown_readbyte(offset, who);
1488 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1491 if (offset <= 0x1FFFFE)
1493 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1495 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1498 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1500 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1501 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1502 return CDROMReadWord(offset, who);
1503 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1504 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1505 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1506 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1507 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1508 return TOMReadWord(offset, who);
1509 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1510 return JERRYReadWord(offset, who);
1512 return jaguar_unknown_readword(offset, who);
1515 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1517 /* if (offset >= 0x4E00 && offset < 0x4E04)
1518 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1519 //Need to check for writes in the range of $18FA70 + 8000...
1521 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1522 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1525 if (offset < 0x200000)
1527 jaguarMainRAM[offset & 0x1FFFFF] = data;
1530 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1532 CDROMWriteByte(offset, data, who);
1535 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1537 TOMWriteByte(offset, data, who);
1540 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1542 JERRYWriteByte(offset, data, who);
1546 jaguar_unknown_writebyte(offset, data, who);
1550 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1552 /* if (offset >= 0x4E00 && offset < 0x4E04)
1553 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1554 /*if (offset == 0x0100)//64*4)
1555 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1556 if (offset == 0x0102)//64*4)
1557 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1558 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1559 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1560 //Need to check for writes in the range of $18FA70 + 8000...
1562 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1563 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1564 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1565 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1569 if (offset <= 0x1FFFFE)
1574 1A 69 F0 ($0000) -> Starfield
1575 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1578 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1587 //This MUST be done by the 68K!
1588 /*if (offset == 0x670C)
1589 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1591 /*extern bool doGPUDis;
1592 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1593 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1594 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1595 doGPUDis = true;//*/
1596 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1597 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1598 if ((data & 0xFF00) != 0x7700)
1599 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1600 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1602 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1603 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1604 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1606 /*extern bool doGPUDis;
1607 if (offset == 0x120216 && who == GPU)
1608 doGPUDis = true;//*/
1609 /*extern uint32 gpu_pc;
1610 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1612 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1613 uint32 y = base / 0x300;
1614 uint32 x = (base - (y * 0x300)) / 2;
1615 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1618 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1620 //if (offset == (0x001E17F8 + 0x34))
1621 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1623 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1624 /*extern uint32 gpu_pc;
1625 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1627 extern int objectPtr;
1628 // if (offset > 0x148000)
1631 if (starCount > objectPtr)
1634 // if (starCount == 1)
1635 // WriteLog("--> Drawing 1st star...\n");
1637 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1638 // uint32 y = base / 0x300;
1639 // uint32 x = (base - (y * 0x300)) / 2;
1640 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1642 //A star of interest...
1643 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1644 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1645 //JWW: Blitter writing echo 77B3 at 0011D022...
1647 //extern bool doGPUDis;
1648 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1651 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1654 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1655 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1657 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1658 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1661 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1663 CDROMWriteWord(offset, data, who);
1666 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1668 TOMWriteWord(offset, data, who);
1671 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1673 JERRYWriteWord(offset, data, who);
1676 // Don't bomb on attempts to write to ROM
1677 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1680 jaguar_unknown_writeword(offset, data, who);
1683 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1684 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1686 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1689 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1690 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1692 /* extern bool doDSPDis;
1693 if (offset < 0x400 && !doDSPDis)
1695 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1698 /*if (offset == 0x0100)//64*4)
1699 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1701 JaguarWriteWord(offset, data >> 16, who);
1702 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1705 void JaguarSetScreenBuffer(uint32 * buffer)
1707 // This is in TOM, but we set it here...
1708 screenBuffer = buffer;
1711 void JaguarSetScreenPitch(uint32 pitch)
1713 // This is in TOM, but we set it here...
1714 screenPitch = pitch;
1718 // Jaguar console initialization
1720 void JaguarInit(void)
1722 #ifdef CPU_DEBUG_MEMORY
1723 memset(readMem, 0x00, 0x400000);
1724 memset(writeMemMin, 0xFF, 0x400000);
1725 memset(writeMemMax, 0x00, 0x400000);
1727 memset(jaguarMainRAM, 0x00, 0x200000);
1728 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1729 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1730 //NOTE: This *doesn't* fix FlipOut...
1731 //Or does it? Hmm...
1732 //Seems to want $01010101... Dunno why. Investigate!
1733 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1734 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1735 lowerField = false; // Reset the lower field flag
1736 //temp, for crappy crap that sux
1737 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1739 // m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1740 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
1748 //New timer based code stuffola...
1749 void HalflineCallback(void);
1750 void RenderCallback(void);
1751 void JaguarReset(void)
1753 // New timer base code stuffola...
1754 InitializeEventList();
1755 //Need to change this so it uses the single RAM space and load the BIOS
1756 //into it somewhere...
1757 //Also, have to change this here and in JaguarReadXX() currently
1758 // Only use the system BIOS if it's available...! (it's always available now!)
1759 // AND only if a jaguar cartridge has been inserted.
1760 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1761 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1763 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1765 // WriteLog("jaguar_reset():\n");
1771 m68k_pulse_reset(); // Reset the 68000
1772 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1774 lowerField = false; // Reset the lower field flag
1775 // SetCallbackTime(ScanlineCallback, 63.5555);
1776 // SetCallbackTime(ScanlineCallback, 31.77775);
1777 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1780 void JaguarDone(void)
1782 #ifdef CPU_DEBUG_MEMORY
1783 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1785 for(uint32 i=0; i<=raPtr; i++)
1787 WriteLog("\t%08X\n", returnAddr[i]);
1788 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1789 jaguar_dasm(returnAddr[i] - 16, 16);
1794 /* int start = 0, end = 0;
1795 bool endTriggered = false, startTriggered = false;
1796 for(int i=0; i<0x400000; i++)
1798 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1800 if (!startTriggered)
1801 startTriggered = true, endTriggered = false, start = i;
1803 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1809 end = i - 1, endTriggered = true, startTriggered = false;
1810 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1817 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1818 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1819 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1820 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1821 for(int i=-2; i<9; i++)
1822 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1824 /* WriteLog("\nM68000 disassembly at $802288...\n");
1825 jaguar_dasm(0x802288, 3);
1826 WriteLog("\nM68000 disassembly at $802200...\n");
1827 jaguar_dasm(0x802200, 500);
1828 WriteLog("\nM68000 disassembly at $802518...\n");
1829 jaguar_dasm(0x802518, 100);//*/
1831 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1832 jaguar_dasm(0x803F00, 500);
1835 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1836 jaguar_dasm(0x802B00, 500);
1839 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1840 jaguar_dasm(0x809900, 500);
1843 /* WriteLog("\n\nDump of $8093C8:\n\n");
1844 for(int i=0x8093C8; i<0x809900; i+=4)
1845 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1846 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1847 jaguar_dasm(0x90006C, 500);
1849 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1850 jaguar_dasm(0x1AC000, 6000);
1853 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1854 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1855 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1856 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1857 M68K_show_context();
1860 #if 0 // This is drawn already...
1861 WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1862 for(uint32 i=0x64; i<=0x7C; i+=4)
1863 WriteLog(" #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1872 // temp, until debugger is in place
1873 //00802016: jsr $836F1A.l
1874 //0080201C: jsr $836B30.l
1875 //00802022: jsr $836B18.l
1876 //00802028: jsr $8135F0.l
1877 //00813C1E: jsr $813F76.l
1878 //00802038: jsr $836D00.l
1879 //00802098: jsr $8373A4.l
1880 //008020A2: jsr $83E24A.l
1881 //008020BA: jsr $83E156.l
1882 //008020C6: jsr $83E19C.l
1883 //008020E6: jsr $8445E8.l
1884 //008020EC: jsr $838C20.l
1885 //0080211A: jsr $838ED6.l
1886 //00802124: jsr $89CA56.l
1887 //0080212A: jsr $802B48.l
1889 WriteLog("-------------------------------------------\n");
1890 JaguarDasm(0x8445E8, 0x200);
1891 WriteLog("-------------------------------------------\n");
1892 JaguarDasm(0x838C20, 0x200);
1893 WriteLog("-------------------------------------------\n");
1894 JaguarDasm(0x838ED6, 0x200);
1895 WriteLog("-------------------------------------------\n");
1896 JaguarDasm(0x89CA56, 0x200);
1897 WriteLog("-------------------------------------------\n");
1898 JaguarDasm(0x802B48, 0x200);
1899 WriteLog("\n\nM68000 disassembly at $802000...\n");
1900 JaguarDasm(0x802000, 6000);
1903 /* WriteLog("\n\nM68000 disassembly at $6004...\n");
1904 JaguarDasm(0x6004, 10000);
1906 // WriteLog("\n\nM68000 disassembly at $802000...\n");
1907 // JaguarDasm(0x802000, 0x1000);
1908 // WriteLog("\n\nM68000 disassembly at $4100...\n");
1909 // JaguarDasm(0x4100, 200);
1910 // WriteLog("\n\nM68000 disassembly at $800800...\n");
1911 // JaguarDasm(0x800800, 0x1000);
1915 // Temp debugging stuff
1917 void DumpMainMemory(void)
1919 FILE * fp = fopen("./memdump.bin", "wb");
1924 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1929 uint8 * GetRamPtr(void)
1931 return jaguarMainRAM;
1936 // New Jaguar execution stack
1937 // This executes 1 frame's worth of code.
1940 void JaguarExecuteNew(void)
1946 double timeToNextEvent = GetTimeToNextEvent();
1947 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1949 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1952 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1960 #define USE_CORRECT_PAL_TIMINGS
1961 // A lot of confusion comes from here...
1962 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
1963 // of whether the display is interlaced or not. The only difference with an
1964 // interlaced display is that the high bit of VC will be set when the lower
1965 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
1966 // regardless of whether it's in interlace mode or not.
1967 // NB2: Seems it doens't always, not sure what the constraint is...)
1969 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
1970 // rendering two fields that are slighty vertically offset from each other.
1971 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
1972 // is rendered in this mode so that each field, when overlaid on each other,
1973 // will yield the final picture at the full resolution for the full frame.
1975 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
1976 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
1977 // it will be half this number for a half frame. BUT, since we're counting
1978 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
1980 // Scanline times are 63.5555... µs in NTSC and 64 µs in PAL
1981 // Half line times are, naturally, half of this. :-P
1982 void HalflineCallback(void)
1984 //OK, this is hardwired to run in NTSC, and for who knows how long.
1985 //Need to fix this so that it does a half-line in the correct amount of time
1986 //and number of lines, depending on which mode we're in. [FIXED]
1987 uint16 vc = TOMReadWord(0xF00006, JAGUAR);
1988 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
1989 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
1990 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
1993 #ifdef USE_CORRECT_PAL_TIMINGS
1994 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
1995 // So we cut the number of half-lines in a frame in half. :-P
1996 uint16 numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
1998 if ((vc & 0x7FF) >= numHalfLines)
2000 if ((vc & 0x7FF) >= vp)
2004 // lowerField = !lowerField;
2006 // If we're rendering the lower field, set the high bit (#12, counting
2012 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2013 TOMWriteWord(0xF00006, vc, JAGUAR);
2015 //This is a crappy kludge, but maybe it'll work for now...
2016 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2017 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2019 // We don't have to worry about autovectors & whatnot because the Jaguar
2020 // tells you through its HW registers who sent the interrupt...
2021 TOMSetPendingVideoInt();
2025 TOMExecHalfline(vc, true);
2027 //Change this to VBB???
2028 //Doesn't seem to matter (at least for Flip Out & I-War)
2029 if ((vc & 0x7FF) == 0)
2036 #ifdef USE_CORRECT_PAL_TIMINGS
2037 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2039 // SetCallbackTime(HalflineCallback, 63.5555);
2040 SetCallbackTime(HalflineCallback, 31.77775);
2045 // This isn't currently used, but maybe it should be...
2047 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2048 handles all the rest, so this isn't needed. :-P
2050 void RenderCallback(void)
2052 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2053 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time