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 uint32 address = topOfStack - (4 * 4 * 3);
381 for(int i=0; i<10; i++)
383 WriteLog("%06X:", address);
385 for(int j=0; j<4; j++)
387 WriteLog(" %08X", JaguarReadLong(address));
394 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VIDEO)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
398 // WriteLog("\n\n68K disasm\n\n");
399 // jaguar_dasm(0x802000, 0x50C);
410 Now here be dragons...
411 Here is how memory ranges are defined in the CoJag driver.
412 Note that we only have to be concerned with 3 entities read/writing anything:
413 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
414 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
415 things that are entirely internal to those modules. This way we should be able to get a handle on all
416 this crap which is currently scattered over Hell's Half Acre(tm).
418 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
419 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
421 /*************************************
423 * Main CPU memory handlers
425 *************************************/
427 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
428 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
429 AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
430 AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
431 AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
432 AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
433 AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
434 AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
435 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
436 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
437 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
438 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
439 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
440 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
441 AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
442 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
443 AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
444 AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r) // GPI03
445 // AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w) // GPI04
446 AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r) // GPI05
447 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
448 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
449 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
452 /*************************************
454 * GPU memory handlers
456 *************************************/
458 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
459 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
460 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
461 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
462 AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
463 AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
464 AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
465 AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
466 AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
467 AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
468 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
471 /*************************************
473 * DSP memory handlers
475 *************************************/
477 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
478 AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
479 AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
480 AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
481 AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
482 AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
483 AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
484 AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
485 AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
490 //#define EXPERIMENTAL_MEMORY_HANDLING
491 // Experimental memory mappage...
492 // Dunno if this is a good approach or not, but it seems to make better
493 // sense to have all this crap in one spot intstead of scattered all over
494 // the place the way it is now.
495 #ifdef EXPERIMENTAL_MEMORY_HANDLING
497 #define NEW_TIMER_SYSTEM
500 uint8 jaguarMainRAM[0x400000]; // 68K CPU RAM
501 uint8 jaguarMainROM[0x600000]; // 68K CPU ROM
502 uint8 jaguarBootROM[0x040000]; // 68K CPU BIOS ROM--uses only half of this!
503 uint8 jaguarCDBootROM[0x040000]; // 68K CPU CD BIOS ROM
504 bool BIOSLoaded = false;
505 bool CDBIOSLoaded = false;
508 uint8 tomRAM[0x4000];
509 uint8 jerryRAM[0x10000];
510 static uint16 eeprom_ram[64];
512 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
515 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
517 // M68K Memory map/handlers
519 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
520 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
521 // Note that this is really memory mapped I/O region...
522 // { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
523 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
524 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
525 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
526 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
527 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
528 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
529 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
530 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
531 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
532 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
533 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
535 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
537 // { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
538 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
539 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
540 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
541 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
542 //What about LBUF writes???
543 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
544 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
545 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
547 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
551 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
552 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
553 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
556 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
557 0 = pad0/1 button values (4 bits each), RO(?)
558 1 = pad0/1 index value (4 bits each), WO
560 3 = NTSC/PAL, certain button states, RO
562 JOYSTICK $F14000 Read/Write
564 Read fedcba98 7654321q f-1 Signals J15 to J1
565 q Cartridge EEPROM output data
566 Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
567 0 = disable J7-J0 outputs
570 0 = Audio muted (reset state)
572 7-4 J7-J4 outputs (port 2)
573 3-0 J3-J0 outputs (port 1)
574 JOYBUTS $F14002 Read Only
576 Read xxxxxxxx rrdv3210 x don't care
579 v 1 = NTSC Video hardware
580 0 = PAL Video hardware
581 3-2 Button inputs B3 & B2 (port 2)
582 1-0 Button inputs B1 & B0 (port 1)
584 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
585 J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
593 0 1 1 1 Row 3 C3 Option # 9 6 3
597 1 0 1 1 Row 2 C2 C 0 8 5 2
599 1 1 0 1 Row 1 C1 B * 7 4 1
600 1 1 1 0 Row 0 Pause A Up Down Left Right
603 0 bit read in any position means that button is pressed.
604 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
608 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
610 // Not sure, but I think the system only has 24 address bits...
611 address &= 0x00FFFFFF;
613 // RAM ($000000 - $3FFFFF) 4M
614 if (address <= 0x3FFFFF)
615 jaguarMainRAM[address] = byte;
616 // hole ($400000 - $7FFFFF) 4M
617 else if (address <= 0x7FFFFF)
619 // GAME ROM ($800000 - $DFFEFF) 6M - 256 bytes
620 else if (address <= 0xDFFEFF)
622 // CDROM ($DFFF00 - $DFFFFF) 256 bytes
623 else if (address <= 0xDFFFFF)
625 cdRAM[address & 0xFF] = byte;
627 if ((address & 0xFF) < 12 * 4)
628 WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
629 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
632 // BIOS ROM ($E00000 - $E3FFFF) 256K
633 else if (address <= 0xE3FFFF)
635 // hole ($E40000 - $EFFFFF) 768K
636 else if (address <= 0xEFFFFF)
638 // TOM ($F00000 - $F0FFFF) 64K
639 else if (address <= 0xF0FFFF)
642 if (address == 0xF00050)
644 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
648 else if (address == 0xF00051)
650 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
654 else if (address == 0xF00052)
656 tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
660 else if (address == 0xF00053)
662 tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
666 else if (address >= 0xF00400 && address <= 0xF007FF) // CLUT (A & B)
668 // Writing to one CLUT writes to the other
669 address &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
670 tomRAM[address] = tomRAM[address + 0x200] = byte;
673 //What about LBUF writes???
674 else if ((address >= 0xF02100) && (address <= 0xF0211F)) // GPU CONTROL
676 GPUWriteByte(address, byte, who);
679 else if ((address >= 0xF02200) && (address <= 0xF0229F)) // BLITTER
681 BlitterWriteByte(address, byte, who);
684 else if ((address >= 0xF03000) && (address <= 0xF03FFF)) // GPU RAM
686 GPUWriteByte(address, byte, who);
690 tomRAM[address & 0x3FFF] = byte;
692 // JERRY ($F10000 - $F1FFFF) 64K
693 else if (address <= 0xF1FFFF)
697 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
699 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
701 DSPWriteByte(address, byte, who);
704 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
706 DSPWriteByte(address, byte, who);
709 // SCLK ($F1A150--8 bits wide)
710 //NOTE: This should be taken care of in DAC...
711 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
713 // WriteLog("JERRY: Writing %02X to SCLK...\n", data);
714 if ((address & 0x03) == 2)
715 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
717 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
719 JERRYI2SInterruptTimer = -1;
720 #ifndef NEW_TIMER_SYSTEM
723 RemoveCallback(JERRYI2SCallback);
728 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
729 else if (address >= 0xF1A148 && address <= 0xF1A157)
731 DACWriteByte(address, byte, who);
734 else if (address >= 0xF10000 && address <= 0xF10007)
736 #ifndef NEW_TIMER_SYSTEM
737 switch (address & 0x07)
740 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
744 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
748 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
752 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
756 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
760 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
764 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
768 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
772 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
776 /* else if ((offset >= 0xF10010) && (offset <= 0xF10015))
778 clock_byte_write(offset, byte);
781 // JERRY -> 68K interrupt enables/latches (need to be handled!)
782 else if (address >= 0xF10020 && address <= 0xF10023)
784 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
786 /* else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
788 anajoy_byte_write(offset, byte);
791 else if ((address >= 0xF14000) && (address <= 0xF14003))
793 JoystickWriteByte(address, byte);
794 EepromWriteByte(address, byte);
797 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
799 EepromWriteByte(address, byte);
802 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
803 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
806 jerryRAM[address & 0xFFFF] = byte;
808 // hole ($F20000 - $FFFFFF) 1M - 128K
813 void WriteWord(uint32 adddress, uint16 word)
817 void WriteDWord(uint32 adddress, uint32 dword)
821 uint8 ReadByte(uint32 adddress)
825 uint16 ReadWord(uint32 adddress)
829 uint32 ReadDWord(uint32 adddress)
834 void ShowM68KContext(void)
836 printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
838 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
840 printf("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
842 if (i == M68K_REG_D3 || i == M68K_REG_D7)
846 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
848 printf("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
850 if (i == M68K_REG_A3 || i == M68K_REG_A7)
854 uint32_t currpc = m68k_get_reg(NULL, M68K_REG_PC);
855 uint32_t disPC = currpc - 30;
860 uint32_t oldpc = disPC;
861 disPC += m68k_disassemble(buffer, disPC, 0);
862 printf("%s%08X: %s\n", (oldpc == currpc ? ">" : " "), oldpc, buffer);
864 while (disPC < (currpc + 10));
868 // Custom UAE 68000 read/write/IRQ functions
875 IPL Name Vector Control
876 ---------+---------------+---------------+---------------
877 2 VBLANK IRQ $100 INT1 bit #0
878 2 GPU IRQ $100 INT1 bit #1
879 2 HBLANK IRQ $100 INT1 bit #2
880 2 Timer IRQ $100 INT1 bit #3
882 Note: Both timer interrupts (JPIT && PIT) are on the same INT1 bit.
883 and are therefore indistinguishable.
885 A typical way to install a LEVEL2 handler for the 68000 would be
886 something like this, you gotta supply "last_line" and "handler".
887 Note that the interrupt is auto vectored thru $100 (not $68)
895 IRQS_HANDLED=$909 ;; VBLANK and TIMER
897 move.w #$2700,sr ;; no IRQs please
898 move.l #handler,V_AUTO ;; install our routine
900 move.w #last_line,VI ;; scanline where IRQ should occur
901 ;; should be 'odd' BTW
902 move.w #IRQS_HANDLE&$FF,INT1 ;; enable VBLANK + TIMER
903 move.w #$2100,sr ;; enable IRQs on the 68K
921 move.w #IRQS_HANDLED,INT1 ; clear latch, keep IRQ alive
922 move.w #0,INT2 ; let GPU run again
926 As you can see, if you have multiple INT1 interrupts coming in,
927 you need to check the lower byte of INT1, to see which interrupt
930 int irq_ack_handler(int level)
932 // Tracing the IPL lines on the Jaguar schematic yields the following:
933 // IPL1 is connected to INTL on TOM (OUT to 68K)
934 // IPL0-2 are also tied to Vcc via 4.7K resistors!
935 // (DINT on TOM goes into DINT on JERRY (IN Tom from Jerry))
936 // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
937 // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
939 // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
940 // They aren't, and this causes problems with a, err, specific ROM. :-D
944 m68k_set_irq(0); // Clear the IRQ (NOTE: Without this, the BIOS fails)...
945 return 64; // Set user interrupt #0
948 return M68K_INT_ACK_AUTOVECTOR;
951 //#define USE_NEW_MMU
953 unsigned int m68k_read_memory_8(unsigned int address)
955 // Musashi does this automagically for you, UAE core does not :-P
956 address &= 0x00FFFFFF;
957 #ifdef CPU_DEBUG_MEMORY
958 // Note that the Jaguar only has 2M of RAM, not 4!
959 if ((address >= 0x000000) && (address <= 0x1FFFFF))
962 readMem[address] = 1;
965 //WriteLog("[RM8] Addr: %08X\n", address);
966 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
967 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
968 || address == 0x1AF05E)
969 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
971 unsigned int retVal = 0;
973 // Note that the Jaguar only has 2M of RAM, not 4!
974 if ((address >= 0x000000) && (address <= 0x1FFFFF))
975 retVal = jaguarMainRAM[address];
976 // else if ((address >= 0x800000) && (address <= 0xDFFFFF))
977 else if ((address >= 0x800000) && (address <= 0xDFFEFF))
978 retVal = jaguarMainROM[address - 0x800000];
979 else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
980 // retVal = jaguarBootROM[address - 0xE00000];
981 // retVal = jaguarDevBootROM1[address - 0xE00000];
982 retVal = jagMemSpace[address];
983 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
984 retVal = CDROMReadByte(address);
985 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
986 retVal = TOMReadByte(address, M68K);
987 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
988 retVal = JERRYReadByte(address, M68K);
990 retVal = jaguar_unknown_readbyte(address, M68K);
992 //if (address >= 0x2800 && address <= 0x281F)
993 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
994 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
995 // WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
998 return MMURead8(address, M68K);
1002 void gpu_dump_disassembly(void);
1003 void gpu_dump_registers(void);
1005 unsigned int m68k_read_memory_16(unsigned int address)
1007 // Musashi does this automagically for you, UAE core does not :-P
1008 address &= 0x00FFFFFF;
1009 #ifdef CPU_DEBUG_MEMORY
1010 /* if ((address >= 0x000000) && (address <= 0x3FFFFE))
1013 readMem[address] = 1, readMem[address + 1] = 1;
1015 /* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
1017 return 0x4E71; // NOP
1019 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
1021 return 0x4E71; // NOP
1023 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
1025 return 0x4E71; // NOP
1027 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
1029 return 0x4E71; // NOP
1031 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
1033 return 0x4E71; // NOP
1035 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
1037 return 0x4E71; // NOP
1040 //WriteLog("[RM16] Addr: %08X\n", address);
1041 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
1042 // for(int i=0; i<10000; i++)
1043 WriteLog("[M68K] In routine #6!\n");//*/
1044 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
1045 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
1046 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
1048 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1049 gpu_dump_registers();
1050 gpu_dump_disassembly();
1051 // for(int i=0; i<10000; i++)
1052 // WriteLog("[M68K] About to run GPU!\n");
1054 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1055 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
1057 if (address == 0x000066A0)
1059 gpu_dump_registers();
1060 gpu_dump_disassembly();
1062 for(int i=0; i<10000; i++)
1063 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1065 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1066 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1067 || address == 0x1AF05E)
1068 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
1070 unsigned int retVal = 0;
1072 // Note that the Jaguar only has 2M of RAM, not 4!
1073 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1074 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
1075 retVal = GET16(jaguarMainRAM, address);
1076 // else if ((address >= 0x800000) && (address <= 0xDFFFFE))
1077 else if ((address >= 0x800000) && (address <= 0xDFFEFE))
1078 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
1079 else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
1080 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1081 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1082 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1083 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1084 retVal = CDROMReadWord(address, M68K);
1085 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1086 retVal = TOMReadWord(address, M68K);
1087 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1088 retVal = JERRYReadWord(address, M68K);
1090 retVal = jaguar_unknown_readword(address, M68K);
1092 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
1093 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1094 //if (address >= 0x2800 && address <= 0x281F)
1095 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1096 //$8B3AE -> Transferred from $F1C010
1097 //$8B5E4 -> Only +1 read at $808AA
1098 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1099 // WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1102 return MMURead16(address, M68K);
1106 unsigned int m68k_read_memory_32(unsigned int address)
1108 // Musashi does this automagically for you, UAE core does not :-P
1109 address &= 0x00FFFFFF;
1110 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1111 /* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1112 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));//*/
1114 //WriteLog("--> [RM32]\n");
1116 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1118 return MMURead32(address, M68K);
1122 void m68k_write_memory_8(unsigned int address, unsigned int value)
1124 // Musashi does this automagically for you, UAE core does not :-P
1125 address &= 0x00FFFFFF;
1126 #ifdef CPU_DEBUG_MEMORY
1127 // Note that the Jaguar only has 2M of RAM, not 4!
1128 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1132 if (value > writeMemMax[address])
1133 writeMemMax[address] = value;
1134 if (value < writeMemMin[address])
1135 writeMemMin[address] = value;
1139 /*if (address == 0x4E00)
1140 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1141 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1142 // WriteLog("M68K: Writing %02X at %08X\n", value, address);
1143 //WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1145 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1146 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1148 /*if (address >= 0x53D0 && address <= 0x53FF)
1149 printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1150 //Testing AvP on UAE core...
1151 //000075A0: FFFFF80E B6320220 (BITMAP)
1152 /*if (address == 0x75A0 && value == 0xFF)
1153 printf("M68K: (8) Tripwire hit...\n");//*/
1156 // Note that the Jaguar only has 2M of RAM, not 4!
1157 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1158 jaguarMainRAM[address] = value;
1159 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1160 CDROMWriteByte(address, value, M68K);
1161 else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1162 TOMWriteByte(address, value, M68K);
1163 else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1164 JERRYWriteByte(address, value, M68K);
1166 jaguar_unknown_writebyte(address, value, M68K);
1168 MMUWrite8(address, value, M68K);
1172 void m68k_write_memory_16(unsigned int address, unsigned int value)
1174 // Musashi does this automagically for you, UAE core does not :-P
1175 address &= 0x00FFFFFF;
1176 #ifdef CPU_DEBUG_MEMORY
1177 // Note that the Jaguar only has 2M of RAM, not 4!
1178 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1182 uint8 hi = value >> 8, lo = value & 0xFF;
1184 if (hi > writeMemMax[address])
1185 writeMemMax[address] = hi;
1186 if (hi < writeMemMin[address])
1187 writeMemMin[address] = hi;
1189 if (lo > writeMemMax[address+1])
1190 writeMemMax[address+1] = lo;
1191 if (lo < writeMemMin[address+1])
1192 writeMemMin[address+1] = lo;
1196 /*if (address == 0x4E00)
1197 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1198 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1199 // WriteLog("M68K: Writing %04X at %08X\n", value, address);
1200 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1201 //if (address >= 0xF02200 && address <= 0xF0229F)
1202 // WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1203 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1204 // WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1205 /*extern uint32 totalFrames;
1206 if (address == 0xF02114)
1207 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1208 if (address == 0xF02110)
1209 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1210 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1211 // WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1213 /*if (address == 0x0100)//64*4)
1214 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1216 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1217 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1218 /* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1219 || address == 0x1AF05E)
1220 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1222 /*if (address >= 0x53D0 && address <= 0x53FF)
1223 printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1224 //Testing AvP on UAE core...
1225 //000075A0: FFFFF80E B6320220 (BITMAP)
1226 /*if (address == 0x75A0 && value == 0xFFFF)
1228 printf("\nM68K: (16) Tripwire hit...\n");
1233 // Note that the Jaguar only has 2M of RAM, not 4!
1234 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1236 /* jaguar_mainRam[address] = value >> 8;
1237 jaguar_mainRam[address + 1] = value & 0xFF;*/
1238 SET16(jaguarMainRAM, address, value);
1240 else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1241 CDROMWriteWord(address, value, M68K);
1242 else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1243 TOMWriteWord(address, value, M68K);
1244 else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1245 JERRYWriteWord(address, value, M68K);
1248 jaguar_unknown_writeword(address, value, M68K);
1249 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1250 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1251 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1252 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1256 MMUWrite16(address, value, M68K);
1260 void m68k_write_memory_32(unsigned int address, unsigned int value)
1262 // Musashi does this automagically for you, UAE core does not :-P
1263 address &= 0x00FFFFFF;
1264 /*if (address == 0x4E00)
1265 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1266 //WriteLog("--> [WM32]\n");
1267 /*if (address == 0x0100)//64*4)
1268 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1269 /*if (address >= 0xF03214 && address < 0xF0321F)
1270 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1271 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1272 /*extern bool doGPUDis;
1273 if (address == 0xF03214 && value == 0x88E30047)
1275 doGPUDis = true;//*/
1276 /* if (address == 0x51136 || address == 0xFB074)
1277 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1278 //Testing AvP on UAE core...
1279 //000075A0: FFFFF80E B6320220 (BITMAP)
1280 /*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
1282 printf("\nM68K: (32) Tripwire hit...\n");
1287 m68k_write_memory_16(address, value >> 16);
1288 m68k_write_memory_16(address + 2, value & 0xFFFF);
1290 MMUWrite32(address, value, M68K);
1295 uint32 JaguarGetHandler(uint32 i)
1297 return JaguarReadLong(i * 4);
1300 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1302 uint32 handler = JaguarGetHandler(i);
1303 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1306 void M68K_show_context(void)
1308 WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1310 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1312 WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1314 if (i == M68K_REG_D3 || i == M68K_REG_D7)
1318 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1320 WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1322 if (i == M68K_REG_A3 || i == M68K_REG_A7)
1326 WriteLog("68K disasm\n");
1327 // jaguar_dasm(s68000readPC()-0x1000,0x20000);
1328 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1329 // jaguar_dasm(0x5000, 0x14414);
1331 // WriteLog("\n.......[Cart start]...........\n\n");
1332 // jaguar_dasm(0x192000, 0x1000);//0x200);
1334 WriteLog("..................\n");
1336 if (TOMIRQEnabled(IRQ_VIDEO))
1338 WriteLog("video int: enabled\n");
1339 JaguarDasm(JaguarGetHandler(64), 0x200);
1342 WriteLog("video int: disabled\n");
1344 WriteLog("..................\n");
1346 for(int i=0; i<256; i++)
1348 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1349 uint32 address = (uint32)JaguarGetHandler(i);
1352 WriteLog(".........\n");
1354 WriteLog("$%08X\n", address);
1359 // Unknown read/write byte/word routines
1362 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1363 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1365 // 807EC4: movea.l #$f1b000, A1
1366 // 807ECA: movea.l #$8129e0, A0
1367 // 807ED0: move.l A0, D0
1368 // 807ED2: move.l #$f1bb94, D1
1369 // 807ED8: sub.l D0, D1
1370 // 807EDA: lsr.l #2, D1
1371 // 807EDC: move.l (A0)+, (A1)+
1372 // 807EDE: dbra D1, 807edc
1374 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1375 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1376 // space! (That is, unless the 68K causes a bus error...)
1378 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1380 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1381 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));
1383 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1384 // extern bool finished;
1386 // extern bool doDSPDis;
1392 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1394 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1395 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));
1397 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1398 // extern bool finished;
1400 // extern bool doDSPDis;
1406 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1408 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1409 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1411 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1412 // extern bool finished;
1414 // extern bool doDSPDis;
1421 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1423 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1424 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1426 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1427 // extern bool finished;
1429 // extern bool doDSPDis;
1437 // Disassemble M68K instructions at the given offset
1440 unsigned int m68k_read_disassembler_8(unsigned int address)
1442 return m68k_read_memory_8(address);
1445 unsigned int m68k_read_disassembler_16(unsigned int address)
1447 return m68k_read_memory_16(address);
1450 unsigned int m68k_read_disassembler_32(unsigned int address)
1452 return m68k_read_memory_32(address);
1455 void JaguarDasm(uint32 offset, uint32 qt)
1458 static char buffer[2048];//, mem[64];
1459 int pc = offset, oldpc;
1461 for(uint32 i=0; i<qt; i++)
1464 for(int j=0; j<64; j++)
1465 mem[j^0x01] = jaguar_byte_read(pc + j);
1467 pc += Dasm68000((char *)mem, buffer, 0);
1468 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1470 pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
1471 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1476 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1481 if (offset < 0x200000)
1482 data = jaguarMainRAM[offset & 0x3FFFFF];
1483 else if ((offset >= 0x800000) && (offset < 0xC00000))
1484 data = jaguarMainROM[offset - 0x800000];
1485 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1486 data = CDROMReadByte(offset, who);
1487 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1488 // data = jaguarBootROM[offset & 0x3FFFF];
1489 // data = jaguarDevBootROM1[offset & 0x3FFFF];
1490 data = jagMemSpace[offset];
1491 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1492 data = TOMReadByte(offset, who);
1493 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1494 data = JERRYReadByte(offset, who);
1496 data = jaguar_unknown_readbyte(offset, who);
1501 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1504 if (offset <= 0x1FFFFE)
1506 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1508 else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1511 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1513 // else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1514 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1515 return CDROMReadWord(offset, who);
1516 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1517 // return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1518 // return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1519 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1520 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1521 return TOMReadWord(offset, who);
1522 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1523 return JERRYReadWord(offset, who);
1525 return jaguar_unknown_readword(offset, who);
1528 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1530 /* if (offset >= 0x4E00 && offset < 0x4E04)
1531 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1532 //Need to check for writes in the range of $18FA70 + 8000...
1534 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1535 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1538 if (offset < 0x200000)
1540 jaguarMainRAM[offset & 0x1FFFFF] = data;
1543 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1545 CDROMWriteByte(offset, data, who);
1548 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1550 TOMWriteByte(offset, data, who);
1553 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1555 JERRYWriteByte(offset, data, who);
1559 jaguar_unknown_writebyte(offset, data, who);
1563 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1565 /* if (offset >= 0x4E00 && offset < 0x4E04)
1566 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1567 /*if (offset == 0x0100)//64*4)
1568 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1569 if (offset == 0x0102)//64*4)
1570 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1571 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1572 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1573 //Need to check for writes in the range of $18FA70 + 8000...
1575 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1576 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1577 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1578 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1582 if (offset <= 0x1FFFFE)
1587 1A 69 F0 ($0000) -> Starfield
1588 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1591 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1600 //This MUST be done by the 68K!
1601 /*if (offset == 0x670C)
1602 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1604 /*extern bool doGPUDis;
1605 //if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
1606 if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1607 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1608 doGPUDis = true;//*/
1609 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1610 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1611 if ((data & 0xFF00) != 0x7700)
1612 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1613 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1615 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1616 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1617 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1619 /*extern bool doGPUDis;
1620 if (offset == 0x120216 && who == GPU)
1621 doGPUDis = true;//*/
1622 /*extern uint32 gpu_pc;
1623 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1625 uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1626 uint32 y = base / 0x300;
1627 uint32 x = (base - (y * 0x300)) / 2;
1628 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1631 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1633 //if (offset == (0x001E17F8 + 0x34))
1634 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1636 // WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1637 /*extern uint32 gpu_pc;
1638 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1640 extern int objectPtr;
1641 // if (offset > 0x148000)
1644 if (starCount > objectPtr)
1647 // if (starCount == 1)
1648 // WriteLog("--> Drawing 1st star...\n");
1650 // uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1651 // uint32 y = base / 0x300;
1652 // uint32 x = (base - (y * 0x300)) / 2;
1653 // WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1655 //A star of interest...
1656 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1657 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1658 //JWW: Blitter writing echo 77B3 at 0011D022...
1660 //extern bool doGPUDis;
1661 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1664 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1667 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1668 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1670 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1671 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1674 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1676 CDROMWriteWord(offset, data, who);
1679 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1681 TOMWriteWord(offset, data, who);
1684 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1686 JERRYWriteWord(offset, data, who);
1689 // Don't bomb on attempts to write to ROM
1690 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1693 jaguar_unknown_writeword(offset, data, who);
1696 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1697 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1699 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1702 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1703 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1705 /* extern bool doDSPDis;
1706 if (offset < 0x400 && !doDSPDis)
1708 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1711 /*if (offset == 0x0100)//64*4)
1712 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1714 JaguarWriteWord(offset, data >> 16, who);
1715 JaguarWriteWord(offset+2, data & 0xFFFF, who);
1718 void JaguarSetScreenBuffer(uint32 * buffer)
1720 // This is in TOM, but we set it here...
1721 screenBuffer = buffer;
1724 void JaguarSetScreenPitch(uint32 pitch)
1726 // This is in TOM, but we set it here...
1727 screenPitch = pitch;
1731 // Jaguar console initialization
1733 void JaguarInit(void)
1735 #ifdef CPU_DEBUG_MEMORY
1736 memset(readMem, 0x00, 0x400000);
1737 memset(writeMemMin, 0xFF, 0x400000);
1738 memset(writeMemMax, 0x00, 0x400000);
1740 memset(jaguarMainRAM, 0x00, 0x200000);
1741 // memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1742 // memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1743 //NOTE: This *doesn't* fix FlipOut...
1744 //Or does it? Hmm...
1745 //Seems to want $01010101... Dunno why. Investigate!
1746 memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
1747 // memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1748 lowerField = false; // Reset the lower field flag
1749 //temp, for crappy crap that sux
1750 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1752 // m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1753 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
1761 //New timer based code stuffola...
1762 void HalflineCallback(void);
1763 void RenderCallback(void);
1764 void JaguarReset(void)
1766 // New timer base code stuffola...
1767 InitializeEventList();
1768 //Need to change this so it uses the single RAM space and load the BIOS
1769 //into it somewhere...
1770 //Also, have to change this here and in JaguarReadXX() currently
1771 // Only use the system BIOS if it's available...! (it's always available now!)
1772 // AND only if a jaguar cartridge has been inserted.
1773 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1774 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1776 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1778 // WriteLog("jaguar_reset():\n");
1784 m68k_pulse_reset(); // Reset the 68000
1785 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1787 lowerField = false; // Reset the lower field flag
1788 // SetCallbackTime(ScanlineCallback, 63.5555);
1789 // SetCallbackTime(ScanlineCallback, 31.77775);
1790 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1793 void JaguarDone(void)
1795 #ifdef CPU_DEBUG_MEMORY
1796 /* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1798 for(uint32 i=0; i<=raPtr; i++)
1800 WriteLog("\t%08X\n", returnAddr[i]);
1801 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1802 jaguar_dasm(returnAddr[i] - 16, 16);
1807 /* int start = 0, end = 0;
1808 bool endTriggered = false, startTriggered = false;
1809 for(int i=0; i<0x400000; i++)
1811 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1813 if (!startTriggered)
1814 startTriggered = true, endTriggered = false, start = i;
1816 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1822 end = i - 1, endTriggered = true, startTriggered = false;
1823 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1830 // for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1831 // WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1832 int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1833 WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
1835 for(int i=-2; i<9; i++)
1836 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1838 uint32 address = topOfStack - (4 * 4 * 3);
1840 for(int i=0; i<10; i++)
1842 WriteLog("%06X:", address);
1844 for(int j=0; j<4; j++)
1846 WriteLog(" %08X", JaguarReadLong(address));
1854 /* WriteLog("\nM68000 disassembly at $802288...\n");
1855 jaguar_dasm(0x802288, 3);
1856 WriteLog("\nM68000 disassembly at $802200...\n");
1857 jaguar_dasm(0x802200, 500);
1858 WriteLog("\nM68000 disassembly at $802518...\n");
1859 jaguar_dasm(0x802518, 100);//*/
1861 /* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1862 jaguar_dasm(0x803F00, 500);
1865 /* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1866 jaguar_dasm(0x802B00, 500);
1869 /* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1870 jaguar_dasm(0x809900, 500);
1873 /* WriteLog("\n\nDump of $8093C8:\n\n");
1874 for(int i=0x8093C8; i<0x809900; i+=4)
1875 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1876 /* WriteLog("\n\nM68000 disassembly at $90006C...\n");
1877 jaguar_dasm(0x90006C, 500);
1879 /* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1880 jaguar_dasm(0x1AC000, 6000);
1883 // WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1884 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1885 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1886 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1887 M68K_show_context();
1890 #if 0 // This is drawn already...
1891 WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1892 for(uint32 i=0x64; i<=0x7C; i+=4)
1893 WriteLog(" #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1902 // temp, until debugger is in place
1903 //00802016: jsr $836F1A.l
1904 //0080201C: jsr $836B30.l
1905 //00802022: jsr $836B18.l
1906 //00802028: jsr $8135F0.l
1907 //00813C1E: jsr $813F76.l
1908 //00802038: jsr $836D00.l
1909 //00802098: jsr $8373A4.l
1910 //008020A2: jsr $83E24A.l
1911 //008020BA: jsr $83E156.l
1912 //008020C6: jsr $83E19C.l
1913 //008020E6: jsr $8445E8.l
1914 //008020EC: jsr $838C20.l
1915 //0080211A: jsr $838ED6.l
1916 //00802124: jsr $89CA56.l
1917 //0080212A: jsr $802B48.l
1919 WriteLog("-------------------------------------------\n");
1920 JaguarDasm(0x8445E8, 0x200);
1921 WriteLog("-------------------------------------------\n");
1922 JaguarDasm(0x838C20, 0x200);
1923 WriteLog("-------------------------------------------\n");
1924 JaguarDasm(0x838ED6, 0x200);
1925 WriteLog("-------------------------------------------\n");
1926 JaguarDasm(0x89CA56, 0x200);
1927 WriteLog("-------------------------------------------\n");
1928 JaguarDasm(0x802B48, 0x200);
1929 WriteLog("\n\nM68000 disassembly at $802000...\n");
1930 JaguarDasm(0x802000, 6000);
1933 /* WriteLog("\n\nM68000 disassembly at $6004...\n");
1934 JaguarDasm(0x6004, 10000);
1936 // WriteLog("\n\nM68000 disassembly at $802000...\n");
1937 // JaguarDasm(0x802000, 0x1000);
1938 // WriteLog("\n\nM68000 disassembly at $4100...\n");
1939 // JaguarDasm(0x4100, 200);
1940 // WriteLog("\n\nM68000 disassembly at $800800...\n");
1941 // JaguarDasm(0x800800, 0x1000);
1945 // Temp debugging stuff
1947 void DumpMainMemory(void)
1949 FILE * fp = fopen("./memdump.bin", "wb");
1954 fwrite(jaguarMainRAM, 1, 0x400000, fp);
1959 uint8 * GetRamPtr(void)
1961 return jaguarMainRAM;
1966 // New Jaguar execution stack
1967 // This executes 1 frame's worth of code.
1970 void JaguarExecuteNew(void)
1976 double timeToNextEvent = GetTimeToNextEvent();
1977 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1979 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1982 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1990 #define USE_CORRECT_PAL_TIMINGS
1991 // A lot of confusion comes from here...
1992 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
1993 // of whether the display is interlaced or not. The only difference with an
1994 // interlaced display is that the high bit of VC will be set when the lower
1995 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
1996 // regardless of whether it's in interlace mode or not.
1997 // NB2: Seems it doens't always, not sure what the constraint is...)
1999 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2000 // rendering two fields that are slighty vertically offset from each other.
2001 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2002 // is rendered in this mode so that each field, when overlaid on each other,
2003 // will yield the final picture at the full resolution for the full frame.
2005 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2006 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2007 // it will be half this number for a half frame. BUT, since we're counting
2008 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
2010 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2011 // Half line times are, naturally, half of this. :-P
2012 void HalflineCallback(void)
2014 //OK, this is hardwired to run in NTSC, and for who knows how long.
2015 //Need to fix this so that it does a half-line in the correct amount of time
2016 //and number of lines, depending on which mode we're in. [FIXED]
2017 uint16 vc = TOMReadWord(0xF00006, JAGUAR);
2018 uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2019 uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
2020 // uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
2023 #ifdef USE_CORRECT_PAL_TIMINGS
2024 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2025 // So we cut the number of half-lines in a frame in half. :-P
2026 uint16 numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2028 if ((vc & 0x7FF) >= numHalfLines)
2030 if ((vc & 0x7FF) >= vp)
2034 // lowerField = !lowerField;
2036 // If we're rendering the lower field, set the high bit (#12, counting
2042 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2043 TOMWriteWord(0xF00006, vc, JAGUAR);
2045 //This is a crappy kludge, but maybe it'll work for now...
2046 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2047 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2049 // We don't have to worry about autovectors & whatnot because the Jaguar
2050 // tells you through its HW registers who sent the interrupt...
2051 TOMSetPendingVideoInt();
2055 TOMExecHalfline(vc, true);
2057 //Change this to VBB???
2058 //Doesn't seem to matter (at least for Flip Out & I-War)
2059 if ((vc & 0x7FF) == 0)
2066 #ifdef USE_CORRECT_PAL_TIMINGS
2067 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2069 // SetCallbackTime(HalflineCallback, 63.5555);
2070 SetCallbackTime(HalflineCallback, 31.77775);
2075 // This isn't currently used, but maybe it should be...
2077 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2078 handles all the rest, so this isn't needed. :-P
2080 void RenderCallback(void)
2082 // SetCallbackTime(RenderCallback, 33303.082); // # Scanlines * scanline time
2083 SetCallbackTime(RenderCallback, 16651.541); // # Scanlines * scanline time