]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
We can now compile, but still doesn't work at this point... Lots of cleanup
[virtualjaguar] / src / jaguar.cpp
1 //
2 // JAGUAR.CPP
3 //
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 L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 //       the braindead way in which MAME handles memory. :-)
9 //
10 // JLH = James L. Hammons
11 //
12 // WHO  WHEN        WHAT
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  11/25/2009  Major rewrite of memory subsystem and handlers
15 //
16
17 #include "jaguar.h"
18
19 #include <SDL.h>
20 #include "SDL_opengl.h"
21 #include "blitter.h"
22 #include "cdrom.h"
23 #include "dac.h"
24 #include "dsp.h"
25 #include "eeprom.h"
26 #include "event.h"
27 #include "gpu.h"
28 #include "gui.h"
29 #include "jerry.h"
30 #include "joystick.h"
31 #include "log.h"
32 #include "m68k.h"
33 #include "memory.h"
34 #include "mmu.h"
35 #include "settings.h"
36 #include "tom.h"
37 #include "video.h"
38
39 #define CPU_DEBUG
40 //Do this in makefile??? Yes! Could, but it's easier to define here...
41 //#define LOG_UNMAPPED_MEMORY_ACCESSES
42 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
43 #define ABORT_ON_ILLEGAL_INSTRUCTIONS
44 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
45 #define CPU_DEBUG_MEMORY
46
47 // Private function prototypes
48
49 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
50 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
51 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
52 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
53 void M68K_show_context(void);
54
55 // External variables
56
57 #ifdef CPU_DEBUG_MEMORY
58 extern bool startMemLog;                                                        // Set by "e" key
59 extern int effect_start;
60 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
61 #endif
62
63 // Memory debugging identifiers
64
65 const char * whoName[9] =
66         { "Unknown", "Jaguar", "DSP", "GPU", "TOM", "JERRY", "M68K", "Blitter", "OP" };
67
68 uint32 jaguar_active_memory_dumps = 0;
69
70 uint32 jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
71
72 uint8 jaguarMainRAM[0x400000];                                          // 68K CPU RAM
73 uint8 jaguarMainROM[0x600000];                                          // 68K CPU ROM
74 uint8 jaguarBootROM[0x040000];                                          // 68K CPU BIOS ROM--uses only half of this!
75 uint8 jaguarCDBootROM[0x040000];                                        // 68K CPU CD BIOS ROM
76 bool BIOSLoaded = false;
77 bool CDBIOSLoaded = false;
78
79 //uint8 cdRAM[0x100];
80 uint8 * cdRAM = &jaguarMainROM[0x5FFF00];
81 uint8 tomRAM[0x4000];
82 uint8 jerryRAM[0x10000];
83
84 #ifdef CPU_DEBUG_MEMORY
85 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
86 uint8 readMem[0x400000];
87 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
88 #endif
89
90 uint32 pcQueue[0x400];
91 uint32 pcQPtr = 0;
92
93 //
94 // Callback function to detect illegal instructions
95 //
96 void GPUDumpDisassembly(void);
97 void GPUDumpRegisters(void);
98 static bool start = false;
99
100 void M68KInstructionHook(void)
101 {
102         uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
103
104 // For tracebacks...
105 // Ideally, we'd save all the registers as well...
106         pcQueue[pcQPtr++] = m68kPC;
107         pcQPtr &= 0x3FF;
108
109         if (m68kPC & 0x01)              // Oops! We're fetching an odd address!
110         {
111                 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
112
113                 static char buffer[2048];
114                 for(int i=0; i<0x400; i++)
115                 {
116                         m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
117                         WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
118                 }
119                 WriteLog("\n");
120
121                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
122                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
123                 for(int i=0; i<10; i++)
124                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
125                 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
126                 M68K_show_context();
127                 LogDone();
128                 exit(0);
129         }
130
131 /*      if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
132         {
133                 static char buffer[2048];
134                 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
135                 WriteLog("%08X: %s", m68kPC, buffer);
136                 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
137                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
138                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
139         }//*/
140 /*      if (m68kPC == 0x8D0E48 && effect_start5)
141         {
142                 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
143                 GPUDumpRegisters();
144                 GPUDumpDisassembly();
145                 log_done();
146                 exit(0);
147         }//*/
148 /*      uint16 opcode = JaguarReadWord(m68kPC);
149         if (opcode == 0x4E75)   // RTS
150         {
151                 if (startMemLog)
152 //                      WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
153                 {
154                         uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
155                         bool found = false;
156                         if (raPtr != 0xFFFFFFFF)
157                         {
158                                 for(uint32 i=0; i<=raPtr; i++)
159                                 {
160                                         if (returnAddr[i] == addr)
161                                         {
162                                                 found = true;
163                                                 break;
164                                         }
165                                 }
166                         }
167
168                         if (!found)
169                                 returnAddr[++raPtr] = addr;
170                 }
171         }//*/
172
173 //Flip Out! debugging...
174 //805F46, 806486
175 /*
176 00805FDC: movea.l #$9c6f8, A0           D0=00100010, A0=00100000
177 00805FE2: move.w  #$10, (A0)+           D0=00100010, A0=0009C6F8
178 00805FE6: cmpa.l  #$c96f8, A0           D0=00100010, A0=0009C6FA
179 00805FEC: bne     805fe2                D0=00100010, A0=0009C6FA
180
181 0080603A: move.l  #$11ed7c, $100.w              D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
182
183 0012314C: move.l  (A0)+, (A1)+          D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
184 0012314E: cmpa.l  #$f04000, A1          D0=61700080, A0=00124178, D1=00000000, A1=00F04000
185 00123154: blt     12314c                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
186 00123156: move.l  #$0, $f035d0.l                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
187 00123160: move.l  #$f03000, $f02110.l           D0=61700080, A0=00124178, D1=00000000, A1=00F04000
188 0012316A: move.l  #$1, $f02114.l                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
189 00123174: rts           D0=61700080, A0=00124178, D1=00000000, A1=00F04000
190 */
191 /*      static char buffer[2048];
192 //if (m68kPC > 0x805F48) start = true;
193 //if (m68kPC > 0x806486) start = true;
194 //if (m68kPC == 0x805FEE) start = true;
195 //if (m68kPC == 0x80600C)// start = true;
196 if (m68kPC == 0x802058) start = true;
197 //{
198 //      GPUDumpRegisters();
199 //      GPUDumpDisassembly();
200 //
201 //      M68K_show_context();
202 //      log_done();
203 //      exit(0);
204 //}
205         if (start)
206         {
207         m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
208         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));
209         }//*/
210
211 /*      if (m68kPC == 0x803F16)
212         {
213                 WriteLog("M68K: Registers found at $803F16:\n");
214                 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
215                 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
216                         WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
217                 WriteLog("\n");
218                 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
219                         WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
220         }*/
221 //Looks like the DSP is supposed to return $12345678 when it finishes its validation routine...
222 // !!! Investigate !!!
223 /*extern bool doDSPDis;
224         static bool disgo = false;
225         if (m68kPC == 0x50222)
226         {
227                 // CD BIOS hacking
228 //              WriteLog("M68K: About to stuff $12345678 into $F1B000 (=%08X)...\n", DSPReadLong(0xF1B000, M68K));
229 //              DSPWriteLong(0xF1B000, 0x12345678, M68K);
230 //              disgo = true;
231         }
232         if (m68kPC == 0x5000)
233 //              doDSPDis = true;
234                 disgo = true;
235         if (disgo)
236         {
237                 static char buffer[2048];
238                 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
239                 WriteLog("%08X: %s", m68kPC, buffer);
240                 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
241                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
242                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
243         }//*/
244         if (m68kPC == 0x82E1A)
245         {
246                 static char buffer[2048];
247                 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
248                 WriteLog("--> [Routine start] %08X: %s", m68kPC, buffer);
249                 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X(cmd), D1=%08X(# bytes), D2=%08X\n",
250                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
251                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
252         }//*/
253         if (m68kPC == 0x82E58)
254                 WriteLog("--> [Routine end]\n");
255         if (m68kPC == 0x80004)
256         {
257                 WriteLog("--> [Calling BusWrite2] D2: %08X\n", m68k_get_reg(NULL, M68K_REG_D2));
258 //              m68k_set_reg(M68K_REG_D2, 0x12345678);
259         }//*/
260 /*
261 CD_init::       -> $3000
262 BIOS_VER::      -> $3004
263 CD_mode::       -> $3006
264 CD_ack::        -> $300C
265 CD_jeri::       -> $3012
266 CD_spin::       -> $3018
267 CD_stop::       -> $301E
268 CD_mute::       -> $3024
269 CD_umute::      -> $302A
270 CD_paus::       -> $3030
271 CD_upaus::      -> $3036
272 CD_read::       -> $303C
273 CD_uread::      -> $3042
274 CD_setup::      -> $3048
275 CD_ptr::        -> $304E
276 CD_osamp::      -> $3054
277 CD_getoc::      -> $305A
278 CD_initm::      -> $3060
279 CD_initf::      -> $3066
280 CD_switch::     -> $306C
281 */
282         if (m68kPC == 0x3000)
283                 WriteLog("M68K: CD_init\n");
284         else if (m68kPC == 0x3006 + (6 * 0))
285                 WriteLog("M68K: CD_mode\n");
286         else if (m68kPC == 0x3006 + (6 * 1))
287                 WriteLog("M68K: CD_ack\n");
288         else if (m68kPC == 0x3006 + (6 * 2))
289                 WriteLog("M68K: CD_jeri\n");
290         else if (m68kPC == 0x3006 + (6 * 3))
291                 WriteLog("M68K: CD_spin\n");
292         else if (m68kPC == 0x3006 + (6 * 4))
293                 WriteLog("M68K: CD_stop\n");
294         else if (m68kPC == 0x3006 + (6 * 5))
295                 WriteLog("M68K: CD_mute\n");
296         else if (m68kPC == 0x3006 + (6 * 6))
297                 WriteLog("M68K: CD_umute\n");
298         else if (m68kPC == 0x3006 + (6 * 7))
299                 WriteLog("M68K: CD_paus\n");
300         else if (m68kPC == 0x3006 + (6 * 8))
301                 WriteLog("M68K: CD_upaus\n");
302         else if (m68kPC == 0x3006 + (6 * 9))
303                 WriteLog("M68K: CD_read\n");
304         else if (m68kPC == 0x3006 + (6 * 10))
305                 WriteLog("M68K: CD_uread\n");
306         else if (m68kPC == 0x3006 + (6 * 11))
307                 WriteLog("M68K: CD_setup\n");
308         else if (m68kPC == 0x3006 + (6 * 12))
309                 WriteLog("M68K: CD_ptr\n");
310         else if (m68kPC == 0x3006 + (6 * 13))
311                 WriteLog("M68K: CD_osamp\n");
312         else if (m68kPC == 0x3006 + (6 * 14))
313                 WriteLog("M68K: CD_getoc\n");
314         else if (m68kPC == 0x3006 + (6 * 15))
315                 WriteLog("M68K: CD_initm\n");
316         else if (m68kPC == 0x3006 + (6 * 16))
317                 WriteLog("M68K: CD_initf\n");
318         else if (m68kPC == 0x3006 + (6 * 17))
319                 WriteLog("M68K: CD_switch\n");
320
321         if (m68kPC >= 0x3000 && m68kPC <= 0x306C)
322                 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X, D2=%08X\n",
323                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
324                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2));
325 //*/
326 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
327         if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
328         {
329 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
330                 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
331                 {
332                         // This is a kludge to let homebrew programs work properly (i.e., let the other processors
333                         // keep going even when the 68K dumped back to the debugger or what have you).
334 //dis no wok right!
335 //                      m68k_set_reg(M68K_REG_PC, m68kPC - 2);
336 // Try setting the vector to the illegal instruction...
337 //This doesn't work right either! Do something else! Quick!
338 //                      SET32(jaguar_mainRam, 0x10, m68kPC);
339
340                         return;
341                 }
342 #endif
343
344                 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
345                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
346                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
347                 for(int i=0; i<10; i++)
348                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
349                 WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
350                 M68K_show_context();
351
352 //temp
353 //      WriteLog("\n\n68K disasm\n\n");
354 //      jaguar_dasm(0x802000, 0x50C);
355 //      WriteLog("\n\n");
356 //endoftemp
357
358                 LogDone();
359                 exit(0);
360         }//*/
361 #endif
362 }
363
364 #if 0
365 Now here be dragons...
366 Here is how memory ranges are defined in the CoJag driver.
367 Note that we only have to be concerned with 3 entities read/writing anything:
368 The main CPU, the GPU, and the DSP. Everything else is unnecessary. So we can keep our main memory
369 checking in jaguar.cpp, gpu.cpp and dsp.cpp. There should be NO checking in TOM, JERRY, etc. other than
370 things that are entirely internal to those modules. This way we should be able to get a handle on all
371 this crap which is currently scattered over Hell's Half Acre(tm).
372
373 Also: We need to distinguish whether or not we need .b, .w, and .dw versions of everything, or if there
374 is a good way to collapse that shit (look below for inspiration). Current method works, but is error prone.
375
376 /*************************************
377  *
378  *  Main CPU memory handlers
379  *
380  *************************************/
381
382 static ADDRESS_MAP_START( m68020_map, ADDRESS_SPACE_PROGRAM, 32 )
383         AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_BASE(&jaguar_shared_ram) AM_SHARE(1)
384         AM_RANGE(0x800000, 0x9fffff) AM_ROM AM_REGION(REGION_USER1, 0) AM_BASE(&rom_base)
385         AM_RANGE(0xa00000, 0xa1ffff) AM_RAM
386         AM_RANGE(0xa20000, 0xa21fff) AM_READWRITE(eeprom_data_r, eeprom_data_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
387         AM_RANGE(0xa30000, 0xa30003) AM_WRITE(watchdog_reset32_w)
388         AM_RANGE(0xa40000, 0xa40003) AM_WRITE(eeprom_enable_w)
389         AM_RANGE(0xb70000, 0xb70003) AM_READWRITE(misc_control_r, misc_control_w)
390         AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(2)
391         AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide",  ide_controller32_r, ide_controller32_w)
392         AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
393         AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_BASE(&jaguar_gpu_clut) AM_SHARE(2)
394         AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
395         AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
396         AM_RANGE(0xf03000, 0xf03fff) AM_MIRROR(0x008000) AM_RAM AM_BASE(&jaguar_gpu_ram) AM_SHARE(3)
397         AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
398         AM_RANGE(0xf16000, 0xf1600b) AM_READ(cojag_gun_input_r) // GPI02
399         AM_RANGE(0xf17000, 0xf17003) AM_READ(status_r)                  // GPI03
400 //  AM_RANGE(0xf17800, 0xf17803) AM_WRITE(latch_w)  // GPI04
401         AM_RANGE(0xf17c00, 0xf17c03) AM_READ(jamma_r)                   // GPI05
402         AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
403         AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
404         AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_BASE(&jaguar_dsp_ram) AM_SHARE(4)
405 ADDRESS_MAP_END
406
407 /*************************************
408  *
409  *  GPU memory handlers
410  *
411  *************************************/
412
413 static ADDRESS_MAP_START( gpu_map, ADDRESS_SPACE_PROGRAM, 32 )
414         AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
415         AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
416         AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
417         AM_RANGE(0xe00000, 0xe003ff) AM_DEVREADWRITE(IDE_CONTROLLER, "ide", ide_controller32_r, ide_controller32_w)
418         AM_RANGE(0xf00000, 0xf003ff) AM_READWRITE(jaguar_tom_regs32_r, jaguar_tom_regs32_w)
419         AM_RANGE(0xf00400, 0xf007ff) AM_RAM AM_SHARE(2)
420         AM_RANGE(0xf02100, 0xf021ff) AM_READWRITE(gpuctrl_r, gpuctrl_w)
421         AM_RANGE(0xf02200, 0xf022ff) AM_READWRITE(jaguar_blitter_r, jaguar_blitter_w)
422         AM_RANGE(0xf03000, 0xf03fff) AM_RAM AM_SHARE(3)
423         AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
424 ADDRESS_MAP_END
425
426 /*************************************
427  *
428  *  DSP memory handlers
429  *
430  *************************************/
431
432 static ADDRESS_MAP_START( dsp_map, ADDRESS_SPACE_PROGRAM, 32 )
433         AM_RANGE(0x000000, 0x7fffff) AM_RAM AM_SHARE(1)
434         AM_RANGE(0x800000, 0xbfffff) AM_ROMBANK(8)
435         AM_RANGE(0xc00000, 0xdfffff) AM_ROMBANK(9)
436         AM_RANGE(0xf10000, 0xf103ff) AM_READWRITE(jaguar_jerry_regs32_r, jaguar_jerry_regs32_w)
437         AM_RANGE(0xf1a100, 0xf1a13f) AM_READWRITE(dspctrl_r, dspctrl_w)
438         AM_RANGE(0xf1a140, 0xf1a17f) AM_READWRITE(jaguar_serial_r, jaguar_serial_w)
439         AM_RANGE(0xf1b000, 0xf1cfff) AM_RAM AM_SHARE(4)
440         AM_RANGE(0xf1d000, 0xf1dfff) AM_READ(jaguar_wave_rom_r) AM_BASE(&jaguar_wave_rom)
441 ADDRESS_MAP_END
442 */
443 #endif
444
445 //#define EXPERIMENTAL_MEMORY_HANDLING
446 // Experimental memory mappage...
447 // Dunno if this is a good approach or not, but it seems to make better
448 // sense to have all this crap in one spot intstead of scattered all over
449 // the place the way it is now.
450 #ifdef EXPERIMENTAL_MEMORY_HANDLING
451 // Needed defines...
452 #define NEW_TIMER_SYSTEM
453
454 /*
455 uint8 jaguarMainRAM[0x400000];                                          // 68K CPU RAM
456 uint8 jaguarMainROM[0x600000];                                          // 68K CPU ROM
457 uint8 jaguarBootROM[0x040000];                                          // 68K CPU BIOS ROM--uses only half of this!
458 uint8 jaguarCDBootROM[0x040000];                                        // 68K CPU CD BIOS ROM
459 bool BIOSLoaded = false;
460 bool CDBIOSLoaded = false;
461
462 uint8 cdRAM[0x100];
463 uint8 tomRAM[0x4000];
464 uint8 jerryRAM[0x10000];
465 static uint16 eeprom_ram[64];
466
467 // NOTE: CD BIOS ROM is read from cartridge space @ $802000 (it's a cartridge, after all)
468 */
469
470 enum MemType { MM_NOP = 0, MM_RAM, MM_ROM, MM_IO };
471
472 // M68K Memory map/handlers
473 uint32  {
474         { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
475         { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
476 // Note that this is really memory mapped I/O region...
477 //      { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
478         { 0xDFFF00, 0xDFFF03, MM_IO,  cdBUTCH }, // base of Butch == interrupt control register, R/W
479         { 0xDFFF04, 0xDFFF07, MM_IO,  cdDSCNTRL }, // DSA control register, R/W
480         { 0xDFFF0A, 0xDFFF0B, MM_IO,  cdDS_DATA }, // DSA TX/RX data, R/W
481         { 0xDFFF10, 0xDFFF13, MM_IO,  cdI2CNTRL }, // i2s bus control register, R/W
482         { 0xDFFF14, 0xDFFF17, MM_IO,  cdSBCNTRL }, // CD subcode control register, R/W
483         { 0xDFFF18, 0xDFFF1B, MM_IO,  cdSUBDATA }, // Subcode data register A
484         { 0xDFFF1C, 0xDFFF1F, MM_IO,  cdSUBDATB }, // Subcode data register B
485         { 0xDFFF20, 0xDFFF23, MM_IO,  cdSB_TIME }, // Subcode time and compare enable (D24)
486         { 0xDFFF24, 0xDFFF27, MM_IO,  cdFIFO_DATA }, // i2s FIFO data
487         { 0xDFFF28, 0xDFFF2B, MM_IO,  cdI2SDAT2 }, // i2s FIFO data (old)
488         { 0xDFFF2C, 0xDFFF2F, MM_IO,  cdUNKNOWN }, // Seems to be some sort of I2S interface
489
490         { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
491
492 //      { 0xF00000, 0xF0FFFF, MM_IO,  TOM_REGS_RW },
493         { 0xF00050, 0xF00051, MM_IO,  tomTimerPrescaler },
494         { 0xF00052, 0xF00053, MM_IO,  tomTimerDivider },
495         { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
496         { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
497         //What about LBUF writes???
498         { 0xF02100, 0xF0211F, MM_IO,  GPUWriteByte }, // GPU CONTROL
499         { 0xF02200, 0xF0229F, MM_IO,  BlitterWriteByte }, // BLITTER
500         { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
501
502         { 0xF10000, 0xF1FFFF, MM_IO,  JERRY_REGS_RW },
503
504 /*
505         EEPROM:
506         { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
507         { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
508         { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
509
510         JOYSTICK:
511         { 0xF14000, 0xF14003, MM_IO,  joystickFoo }
512         0 = pad0/1 button values (4 bits each), RO(?)
513         1 = pad0/1 index value (4 bits each), WO
514         2 = unused, RO
515         3 = NTSC/PAL, certain button states, RO
516
517 JOYSTICK    $F14000               Read/Write
518             15.....8  7......0
519 Read        fedcba98  7654321q    f-1    Signals J15 to J1
520                                   q      Cartridge EEPROM  output data
521 Write       exxxxxxm  76543210    e      1 = enable  J7-J0 outputs
522                                          0 = disable J7-J0 outputs
523                                   x      don't care
524                                   m      Audio mute
525                                          0 = Audio muted (reset state)
526                                          1 = Audio enabled
527                                   7-4    J7-J4 outputs (port 2)
528                                   3-0    J3-J0 outputs (port 1)
529 JOYBUTS     $F14002               Read Only
530             15.....8  7......0
531 Read        xxxxxxxx  rrdv3210    x      don't care
532                                   r      Reserved
533                                   d      Reserved
534                                   v      1 = NTSC Video hardware
535                                          0 = PAL  Video hardware
536                                   3-2    Button inputs B3 & B2 (port 2)
537                                   1-0    Button inputs B1 & B0 (port 1)
538
539 J4 J5 J6 J7  Port 2    B2     B3    J12  J13   J14  J15
540 J3 J2 J1 J0  Port 1    B0     B1    J8   J9    J10  J11
541  0  0  0  0
542  0  0  0  1
543  0  0  1  0
544  0  0  1  1
545  0  1  0  0
546  0  1  0  1
547  0  1  1  0
548  0  1  1  1  Row 3     C3   Option  #     9     6     3
549  1  0  0  0
550  1  0  0  1
551  1  0  1  0
552  1  0  1  1  Row 2     C2      C    0     8     5     2
553  1  1  0  0
554  1  1  0  1  Row 1     C1      B    *     7     4     1
555  1  1  1  0  Row 0   Pause     A    Up  Down  Left  Right
556  1  1  1  1
557
558 0 bit read in any position means that button is pressed.
559 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
560 */
561 };
562
563 void WriteByte(uint32 address, uint8 byte, uint32 who/*=UNKNOWN*/)
564 {
565         // Not sure, but I think the system only has 24 address bits...
566         address &= 0x00FFFFFF;
567
568         // RAM                  ($000000 - $3FFFFF)             4M
569         if (address <= 0x3FFFFF)
570                 jaguarMainRAM[address] = byte;
571         // hole                 ($400000 - $7FFFFF)             4M
572         else if (address <= 0x7FFFFF)
573                 ;       // Do nothing
574         // GAME ROM             ($800000 - $DFFEFF)             6M - 256 bytes
575         else if (address <= 0xDFFEFF)
576                 ;       // Do nothing
577         // CDROM                ($DFFF00 - $DFFFFF)             256 bytes
578         else if (address <= 0xDFFFFF)
579         {
580                 cdRAM[address & 0xFF] = byte;
581 #ifdef CDROM_LOG
582                 if ((address & 0xFF) < 12 * 4)
583                         WriteLog("[%s] ", BReg[(address & 0xFF) / 4]);
584                 WriteLog("CDROM: %s writing byte $%02X at $%08X [68K PC=$%08X]\n", whoName[who], data, offset, m68k_get_reg(NULL, M68K_REG_PC));
585 #endif
586         }
587         // BIOS ROM             ($E00000 - $E3FFFF)             256K
588         else if (address <= 0xE3FFFF)
589                 ;       // Do nothing
590         // hole                 ($E40000 - $EFFFFF)             768K
591         else if (address <= 0xEFFFFF)
592                 ;       // Do nothing
593         // TOM                  ($F00000 - $F0FFFF)             64K
594         else if (address <= 0xF0FFFF)
595 //              ;       // Do nothing
596         {
597                 if (address == 0xF00050)
598                 {
599                         tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | ((uint16)byte << 8);
600                         TOMResetPIT();
601                         return;
602                 }
603                 else if (address == 0xF00051)
604                 {
605                         tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | byte;
606                         TOMResetPIT();
607                         return;
608                 }
609                 else if (address == 0xF00052)
610                 {
611                         tomTimerDivider = (tomTimerDivider & 0x00FF) | ((uint16)byte << 8);
612                         TOMResetPIT();
613                         return;
614                 }
615                 else if (address == 0xF00053)
616                 {
617                         tomTimerDivider = (tomTimerDivider & 0xFF00) | byte;
618                         TOMResetPIT();
619                         return;
620                 }
621                 else if (address >= 0xF00400 && address <= 0xF007FF)    // CLUT (A & B)
622                 {
623                         // Writing to one CLUT writes to the other
624                         address &= 0x5FF;               // Mask out $F00600 (restrict to $F00400-5FF)
625                         tomRAM[address] = tomRAM[address + 0x200] = byte;
626                         return;
627                 }
628                 //What about LBUF writes???
629                 else if ((address >= 0xF02100) && (address <= 0xF0211F))        // GPU CONTROL
630                 {
631                         GPUWriteByte(address, byte, who);
632                         return;
633                 }
634                 else if ((address >= 0xF02200) && (address <= 0xF0229F))        // BLITTER
635                 {
636                         BlitterWriteByte(address, byte, who);
637                         return;
638                 }
639                 else if ((address >= 0xF03000) && (address <= 0xF03FFF))        // GPU RAM
640                 {
641                         GPUWriteByte(address, byte, who);
642                         return;
643                 }
644
645                 tomRAM[address & 0x3FFF] = byte;
646         }
647         // JERRY                ($F10000 - $F1FFFF)             64K
648         else if (address <= 0xF1FFFF)
649 //              ;       // Do nothing
650         {
651 #ifdef JERRY_DEBUG
652                 WriteLog("jerry: writing byte %.2x at 0x%.6x\n", byte, address);
653 #endif
654                 if ((address >= DSP_CONTROL_RAM_BASE) && (address < DSP_CONTROL_RAM_BASE+0x20))
655                 {
656                         DSPWriteByte(address, byte, who);
657                         return;
658                 }
659                 else if ((address >= DSP_WORK_RAM_BASE) && (address < DSP_WORK_RAM_BASE+0x2000))
660                 {
661                         DSPWriteByte(address, byte, who);
662                         return;
663                 }
664                 // SCLK ($F1A150--8 bits wide)
665 //NOTE: This should be taken care of in DAC...
666                 else if ((address >= 0xF1A152) && (address <= 0xF1A153))
667                 {
668 //              WriteLog("JERRY: Writing %02X to SCLK...\n", data);
669                         if ((address & 0x03) == 2)
670                                 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0x00FF) | ((uint32)byte << 8);
671                         else
672                                 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)byte;
673
674                         JERRYI2SInterruptTimer = -1;
675 #ifndef NEW_TIMER_SYSTEM
676                         jerry_i2s_exec(0);
677 #else
678                         RemoveCallback(JERRYI2SCallback);
679                         JERRYI2SCallback();
680 #endif
681 //                      return;
682                 }
683                 // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
684                 else if (address >= 0xF1A148 && address <= 0xF1A157)
685                 {
686                         DACWriteByte(address, byte, who);
687                         return;
688                 }
689                 else if (address >= 0xF10000 && address <= 0xF10007)
690                 {
691 #ifndef NEW_TIMER_SYSTEM
692                         switch (address & 0x07)
693                         {
694                         case 0:
695                                 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (byte << 8);
696                                 JERRYResetPIT1();
697                                 break;
698                         case 1:
699                                 JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | byte;
700                                 JERRYResetPIT1();
701                                 break;
702                         case 2:
703                                 JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (byte << 8);
704                                 JERRYResetPIT1();
705                                 break;
706                         case 3:
707                                 JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | byte;
708                                 JERRYResetPIT1();
709                                 break;
710                         case 4:
711                                 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (byte << 8);
712                                 JERRYResetPIT2();
713                                 break;
714                         case 5:
715                                 JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | byte;
716                                 JERRYResetPIT2();
717                                 break;
718                         case 6:
719                                 JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (byte << 8);
720                                 JERRYResetPIT2();
721                                 break;
722                         case 7:
723                                 JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | byte;
724                                 JERRYResetPIT2();
725                         }
726 #else
727 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", address);
728 #endif
729                         return;
730                 }
731 /*      else if ((offset >= 0xF10010) && (offset <= 0xF10015))
732         {
733                 clock_byte_write(offset, byte);
734                 return;
735         }//*/
736         // JERRY -> 68K interrupt enables/latches (need to be handled!)
737                 else if (address >= 0xF10020 && address <= 0xF10023)
738                 {
739 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", byte, address);
740                 }
741 /*      else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
742         {
743                 anajoy_byte_write(offset, byte);
744                 return;
745         }*/
746                 else if ((address >= 0xF14000) && (address <= 0xF14003))
747                 {
748                         JoystickWriteByte(address, byte);
749                         EepromWriteByte(address, byte);
750                         return;
751                 }
752                 else if ((address >= 0xF14004) && (address <= 0xF1A0FF))
753                 {
754                         EepromWriteByte(address, byte);
755                         return;
756                 }
757 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
758                 else if (address >= 0xF1D000 && address <= 0xF1DFFF)
759                         return;
760
761                 jerryRAM[address & 0xFFFF] = byte;
762         }
763         // hole                 ($F20000 - $FFFFFF)             1M - 128K
764         else
765                 ;       // Do nothing
766 }
767
768 void WriteWord(uint32 adddress, uint16 word)
769 {
770 }
771
772 void WriteDWord(uint32 adddress, uint32 dword)
773 {
774 }
775
776 uint8 ReadByte(uint32 adddress)
777 {
778 }
779
780 uint16 ReadWord(uint32 adddress)
781 {
782 }
783
784 uint32 ReadDWord(uint32 adddress)
785 {
786 }
787 #endif
788
789 //
790 // Musashi 68000 read/write/IRQ functions
791 //
792
793 int irq_ack_handler(int level)
794 {
795         int vector = M68K_INT_ACK_AUTOVECTOR;
796
797         // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
798
799         if (level == 7)
800         {
801                 m68k_set_irq(0);                                                // Clear the IRQ...
802                 vector = 64;                                                    // Set user interrupt #0
803         }
804
805         return vector;
806 }
807
808 #define USE_NEW_MMU
809
810 unsigned int m68k_read_memory_8(unsigned int address)
811 {
812 #ifdef CPU_DEBUG_MEMORY
813         if ((address >= 0x000000) && (address <= 0x3FFFFF))
814         {
815                 if (startMemLog)
816                         readMem[address] = 1;
817         }
818 #endif
819 //WriteLog("[RM8] Addr: %08X\n", address);
820 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
821 /*      if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
822                 || address == 0x1AF05E)
823                 WriteLog("[RM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
824 #ifndef USE_NEW_MMU
825         unsigned int retVal = 0;
826
827         if ((address >= 0x000000) && (address <= 0x3FFFFF))
828                 retVal = jaguarMainRAM[address];
829 //      else if ((address >= 0x800000) && (address <= 0xDFFFFF))
830         else if ((address >= 0x800000) && (address <= 0xDFFEFF))
831                 retVal = jaguarMainROM[address - 0x800000];
832         else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
833                 retVal = jaguarBootROM[address - 0xE00000];
834         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
835                 retVal = CDROMReadByte(address);
836         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
837                 retVal = TOMReadByte(address, M68K);
838         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
839                 retVal = JERRYReadByte(address, M68K);
840         else
841                 retVal = jaguar_unknown_readbyte(address, M68K);
842
843 //if (address >= 0x2800 && address <= 0x281F)
844 //      WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
845 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
846 //      WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
847     return retVal;
848 #else
849         return MMURead8(address, M68K);
850 #endif
851 }
852
853 void gpu_dump_disassembly(void);
854 void gpu_dump_registers(void);
855
856 unsigned int m68k_read_memory_16(unsigned int address)
857 {
858 #ifdef CPU_DEBUG_MEMORY
859 /*      if ((address >= 0x000000) && (address <= 0x3FFFFE))
860         {
861                 if (startMemLog)
862                         readMem[address] = 1, readMem[address + 1] = 1;
863         }//*/
864 /*      if (effect_start && (address >= 0x8064FC && address <= 0x806501))
865         {
866                 return 0x4E71;  // NOP
867         }
868         if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
869         {
870                 return 0x4E71;  // NOP
871         }
872         if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
873         {
874                 return 0x4E71;  // NOP
875         }
876         if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
877         {
878                 return 0x4E71;  // NOP
879         }
880         if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
881         {
882                 return 0x4E71;  // NOP
883         }
884         if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
885         {
886                 return 0x4E71;  // NOP
887         }//*/
888 #endif
889 //WriteLog("[RM16] Addr: %08X\n", address);
890 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
891 //      for(int i=0; i<10000; i++)
892         WriteLog("[M68K] In routine #6!\n");//*/
893 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
894 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C)    // GPU Program #2
895 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8)    // GPU Program #3
896 {
897         WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
898         gpu_dump_registers();
899         gpu_dump_disassembly();
900 //      for(int i=0; i<10000; i++)
901 //              WriteLog("[M68K] About to run GPU!\n");
902 }//*/
903 //WriteLog("[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
904 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
905 {
906         if (address == 0x000066A0)
907         {
908                 gpu_dump_registers();
909                 gpu_dump_disassembly();
910         }
911         for(int i=0; i<10000; i++)
912                 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
913 }//*/
914 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
915 /*      if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
916                 || address == 0x1AF05E)
917                 WriteLog("[RM16  PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
918 #ifndef USE_NEW_MMU
919     unsigned int retVal = 0;
920
921         if ((address >= 0x000000) && (address <= 0x3FFFFE))
922 //              retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
923                 retVal = GET16(jaguarMainRAM, address);
924 //      else if ((address >= 0x800000) && (address <= 0xDFFFFE))
925         else if ((address >= 0x800000) && (address <= 0xDFFEFE))
926                 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
927         else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
928                 retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
929         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
930                 retVal = CDROMReadWord(address, M68K);
931         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
932                 retVal = TOMReadWord(address, M68K);
933         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
934                 retVal = JERRYReadWord(address, M68K);
935         else
936                 retVal = jaguar_unknown_readword(address, M68K);
937
938 //if (address >= 0xF1B000 && address <= 0xF1CFFF)
939 //      WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
940 //if (address >= 0x2800 && address <= 0x281F)
941 //      WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
942 //$8B3AE -> Transferred from $F1C010
943 //$8B5E4 -> Only +1 read at $808AA
944 //if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
945 //      WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
946     return retVal;
947 #else
948         return MMURead16(address, M68K);
949 #endif
950 }
951
952 unsigned int m68k_read_memory_32(unsigned int address)
953 {
954 //; So, it seems that it stores the returned DWORD at $51136 and $FB074.
955 /*      if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
956                 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));//*/
957
958 //WriteLog("--> [RM32]\n");
959 #ifndef USE_NEW_MMU
960     return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
961 #else
962         return MMURead32(address, M68K);
963 #endif
964 }
965
966 void m68k_write_memory_8(unsigned int address, unsigned int value)
967 {
968 #ifdef CPU_DEBUG_MEMORY
969         if ((address >= 0x000000) && (address <= 0x3FFFFF))
970         {
971                 if (startMemLog)
972                 {
973                         if (value > writeMemMax[address])
974                                 writeMemMax[address] = value;
975                         if (value < writeMemMin[address])
976                                 writeMemMin[address] = value;
977                 }
978         }
979 #endif
980 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
981 //      WriteLog("M68K: Writing %02X at %08X\n", value, address);
982 //WriteLog("[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
983 /*if (effect_start)
984         if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
985                 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
986
987 #ifndef USE_NEW_MMU
988         if ((address >= 0x000000) && (address <= 0x3FFFFF))
989                 jaguarMainRAM[address] = value;
990         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
991                 CDROMWriteByte(address, value, M68K);
992         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
993                 TOMWriteByte(address, value, M68K);
994         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
995                 JERRYWriteByte(address, value, M68K);
996         else
997                 jaguar_unknown_writebyte(address, value, M68K);
998 #else
999         MMUWrite8(address, value, M68K);
1000 #endif
1001 }
1002
1003 void m68k_write_memory_16(unsigned int address, unsigned int value)
1004 {
1005 #ifdef CPU_DEBUG_MEMORY
1006         if ((address >= 0x000000) && (address <= 0x3FFFFE))
1007         {
1008                 if (startMemLog)
1009                 {
1010                         uint8 hi = value >> 8, lo = value & 0xFF;
1011
1012                         if (hi > writeMemMax[address])
1013                                 writeMemMax[address] = hi;
1014                         if (hi < writeMemMin[address])
1015                                 writeMemMin[address] = hi;
1016
1017                         if (lo > writeMemMax[address+1])
1018                                 writeMemMax[address+1] = lo;
1019                         if (lo < writeMemMin[address+1])
1020                                 writeMemMin[address+1] = lo;
1021                 }
1022         }
1023 #endif
1024 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1025 //      WriteLog("M68K: Writing %04X at %08X\n", value, address);
1026 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1027 //if (address >= 0xF02200 && address <= 0xF0229F)
1028 //      WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1029 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
1030 //      WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1031 /*extern uint32 totalFrames;
1032 if (address == 0xF02114)
1033         WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1034 if (address == 0xF02110)
1035         WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1036 //if (address >= 0xF03B00 && address <= 0xF03DFF)
1037 //      WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1038
1039 /*if (address == 0x0100)//64*4)
1040         WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1041 /*if (effect_start)
1042         if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1043                 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1044 /*      if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1045                 || address == 0x1AF05E)
1046                 WriteLog("[WM16  PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1047
1048 #ifndef USE_NEW_MMU
1049         if ((address >= 0x000000) && (address <= 0x3FFFFE))
1050         {
1051 /*              jaguar_mainRam[address] = value >> 8;
1052                 jaguar_mainRam[address + 1] = value & 0xFF;*/
1053                 SET16(jaguarMainRAM, address, value);
1054         }
1055         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1056                 CDROMWriteWord(address, value, M68K);
1057         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1058                 TOMWriteWord(address, value, M68K);
1059         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1060                 JERRYWriteWord(address, value, M68K);
1061         else
1062         {
1063                 jaguar_unknown_writeword(address, value, M68K);
1064 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1065                 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1066                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1067                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
1068         }
1069 #endif
1070 #else
1071         MMUWrite16(address, value, M68K);
1072 #endif
1073 }
1074
1075 void m68k_write_memory_32(unsigned int address, unsigned int value)
1076 {
1077 //WriteLog("--> [WM32]\n");
1078 /*if (address == 0x0100)//64*4)
1079         WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1080 /*if (address >= 0xF03214 && address < 0xF0321F)
1081         WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1082 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1083 /*extern bool doGPUDis;
1084 if (address == 0xF03214 && value == 0x88E30047)
1085 //      start = true;
1086         doGPUDis = true;//*/
1087 /*      if (address == 0x51136 || address == 0xFB074)
1088                 WriteLog("[WM32  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1089
1090 #ifndef USE_NEW_MMU
1091         m68k_write_memory_16(address, value >> 16);
1092         m68k_write_memory_16(address + 2, value & 0xFFFF);
1093 #else
1094         MMUWrite32(address, value, M68K);
1095 #endif
1096 }
1097
1098
1099 uint32 JaguarGetHandler(uint32 i)
1100 {
1101         return JaguarReadLong(i * 4);
1102 }
1103
1104 bool JaguarInterruptHandlerIsValid(uint32 i) // Debug use only...
1105 {
1106         uint32 handler = JaguarGetHandler(i);
1107         return (handler && (handler != 0xFFFFFFFF) ? true : false);
1108 }
1109
1110 void M68K_show_context(void)
1111 {
1112         WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1113         for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1114                 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1115         WriteLog("\n");
1116         for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1117                 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1118
1119         WriteLog("68K disasm\n");
1120 //      jaguar_dasm(s68000readPC()-0x1000,0x20000);
1121         JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1122 //      jaguar_dasm(0x5000, 0x14414);
1123
1124 //      WriteLog("\n.......[Cart start]...........\n\n");
1125 //      jaguar_dasm(0x192000, 0x1000);//0x200);
1126
1127         WriteLog("..................\n");
1128
1129         if (TOMIRQEnabled(IRQ_VBLANK))
1130         {
1131                 WriteLog("vblank int: enabled\n");
1132                 JaguarDasm(JaguarGetHandler(64), 0x200);
1133         }
1134         else
1135                 WriteLog("vblank int: disabled\n");
1136
1137         WriteLog("..................\n");
1138
1139         for(int i=0; i<256; i++)
1140                 WriteLog("handler %03i at $%08X\n", i, (unsigned int)JaguarGetHandler(i));
1141 }
1142
1143 //
1144 // Unknown read/write byte/word routines
1145 //
1146
1147 // It's hard to believe that developers would be sloppy with their memory writes, yet in
1148 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
1149 //
1150 // 807EC4: movea.l #$f1b000, A1
1151 // 807ECA: movea.l #$8129e0, A0
1152 // 807ED0: move.l  A0, D0
1153 // 807ED2: move.l  #$f1bb94, D1
1154 // 807ED8: sub.l   D0, D1
1155 // 807EDA: lsr.l   #2, D1
1156 // 807EDC: move.l  (A0)+, (A1)+
1157 // 807EDE: dbra    D1, 807edc
1158 //
1159 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
1160 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
1161 // space! (That is, unless the 68K causes a bus error...)
1162
1163 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1164 {
1165 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1166         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));
1167 #endif
1168 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1169 //      extern bool finished;
1170         finished = true;
1171 //      extern bool doDSPDis;
1172         if (who == DSP)
1173                 doDSPDis = true;
1174 #endif
1175 }
1176
1177 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
1178 {
1179 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1180         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));
1181 #endif
1182 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1183 //      extern bool finished;
1184         finished = true;
1185 //      extern bool doDSPDis;
1186         if (who == DSP)
1187                 doDSPDis = true;
1188 #endif
1189 }
1190
1191 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
1192 {
1193 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1194         WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1195 #endif
1196 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1197 //      extern bool finished;
1198         finished = true;
1199 //      extern bool doDSPDis;
1200         if (who == DSP)
1201                 doDSPDis = true;
1202 #endif
1203     return 0xFF;
1204 }
1205
1206 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
1207 {
1208 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1209         WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1210 #endif
1211 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1212 //      extern bool finished;
1213         finished = true;
1214 //      extern bool doDSPDis;
1215         if (who == DSP)
1216                 doDSPDis = true;
1217 #endif
1218     return 0xFFFF;
1219 }
1220
1221 //
1222 // Disassemble M68K instructions at the given offset
1223 //
1224
1225 unsigned int m68k_read_disassembler_8(unsigned int address)
1226 {
1227         return m68k_read_memory_8(address);
1228 }
1229
1230 unsigned int m68k_read_disassembler_16(unsigned int address)
1231 {
1232         return m68k_read_memory_16(address);
1233 }
1234
1235 unsigned int m68k_read_disassembler_32(unsigned int address)
1236 {
1237         return m68k_read_memory_32(address);
1238 }
1239
1240 void JaguarDasm(uint32 offset, uint32 qt)
1241 {
1242 #ifdef CPU_DEBUG
1243         static char buffer[2048];//, mem[64];
1244         int pc = offset, oldpc;
1245
1246         for(uint32 i=0; i<qt; i++)
1247         {
1248 /*              oldpc = pc;
1249                 for(int j=0; j<64; j++)
1250                         mem[j^0x01] = jaguar_byte_read(pc + j);
1251
1252                 pc += Dasm68000((char *)mem, buffer, 0);
1253                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1254                 oldpc = pc;
1255                 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
1256                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1257         }
1258 #endif
1259 }
1260
1261 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1262 {
1263         uint8 data = 0x00;
1264
1265         offset &= 0xFFFFFF;
1266         if (offset < 0x400000)
1267                 data = jaguarMainRAM[offset & 0x3FFFFF];
1268         else if ((offset >= 0x800000) && (offset < 0xC00000))
1269                 data = jaguarMainROM[offset - 0x800000];
1270         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1271                 data = CDROMReadByte(offset, who);
1272         else if ((offset >= 0xE00000) && (offset < 0xE40000))
1273                 data = jaguarBootROM[offset & 0x3FFFF];
1274         else if ((offset >= 0xF00000) && (offset < 0xF10000))
1275                 data = TOMReadByte(offset, who);
1276         else if ((offset >= 0xF10000) && (offset < 0xF20000))
1277                 data = JERRYReadByte(offset, who);
1278         else
1279                 data = jaguar_unknown_readbyte(offset, who);
1280
1281         return data;
1282 }
1283
1284 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1285 {
1286         offset &= 0xFFFFFF;
1287         if (offset <= 0x3FFFFE)
1288         {
1289                 return (jaguarMainRAM[(offset+0) & 0x3FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x3FFFFF];
1290         }
1291         else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
1292         {
1293                 offset -= 0x800000;
1294                 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1295         }
1296 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1297         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1298                 return CDROMReadWord(offset, who);
1299         else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1300                 return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1301         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1302                 return TOMReadWord(offset, who);
1303         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1304                 return JERRYReadWord(offset, who);
1305
1306         return jaguar_unknown_readword(offset, who);
1307 }
1308
1309 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1310 {
1311 //Need to check for writes in the range of $18FA70 + 8000...
1312 /*if (effect_start)
1313         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1314                 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1315
1316         offset &= 0xFFFFFF;
1317         if (offset < 0x400000)
1318         {
1319                 jaguarMainRAM[offset & 0x3FFFFF] = data;
1320                 return;
1321         }
1322         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1323         {
1324                 CDROMWriteByte(offset, data, who);
1325                 return;
1326         }
1327         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1328         {
1329                 TOMWriteByte(offset, data, who);
1330                 return;
1331         }
1332         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1333         {
1334                 JERRYWriteByte(offset, data, who);
1335                 return;
1336         }
1337
1338         jaguar_unknown_writebyte(offset, data, who);
1339 }
1340
1341 uint32 starCount;
1342 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1343 {
1344 /*if (offset == 0x0100)//64*4)
1345         WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1346 if (offset == 0x0102)//64*4)
1347         WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1348 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1349 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1350 //Need to check for writes in the range of $18FA70 + 8000...
1351 /*if (effect_start)
1352         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1353                 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1354 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1355         WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1356
1357         offset &= 0xFFFFFF;
1358
1359         if (offset <= 0x3FFFFE)
1360         {
1361 /*
1362 GPU Table (CD BIOS)
1363
1364 1A 69 F0 ($0000) -> Starfield
1365 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1366 1A 79 F0 ($0002)
1367 1A 88 C0 ($0003)
1368 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1369 1A 95 20 ($0005)
1370 1A 9F 08 ($0006)
1371 1A A1 38 ($0007)
1372 1A AB 38 ($0008)
1373 1A B3 C8 ($0009)
1374 1A B9 C0 ($000A)
1375 */
1376
1377 //This MUST be done by the 68K!
1378 /*if (offset == 0x670C)
1379         WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1380
1381 /*extern bool doGPUDis;
1382 //if ((offset == 0x100000 + 75522) && who == GPU)       // 76,226 -> 75522
1383 if ((offset == 0x100000 + 128470) && who == GPU)        // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1384 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1385         doGPUDis = true;//*/
1386 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1387         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1388 if ((data & 0xFF00) != 0x7700)
1389         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1390 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1391         return;//*/
1392 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1393         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1394 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1395         return;//*/
1396 /*extern bool doGPUDis;
1397 if (offset == 0x120216 && who == GPU)
1398         doGPUDis = true;//*/
1399 /*extern uint32 gpu_pc;
1400 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1401 {
1402         uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1403         uint32 y = base / 0x300;
1404         uint32 x = (base - (y * 0x300)) / 2;
1405         WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1406 }//*/
1407 /*
1408 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1409 */
1410 //if (offset == (0x001E17F8 + 0x34))
1411 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1412         data = 0xFE3C;//*/
1413 //      WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1414 /*extern uint32 gpu_pc;
1415 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1416 {
1417         extern int objectPtr;
1418 //      if (offset > 0x148000)
1419 //              return;
1420         starCount++;
1421         if (starCount > objectPtr)
1422                 return;
1423
1424 //      if (starCount == 1)
1425 //              WriteLog("--> Drawing 1st star...\n");
1426 //
1427 //      uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1428 //      uint32 y = base / 0x300;
1429 //      uint32 x = (base - (y * 0x300)) / 2;
1430 //      WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1431
1432 //A star of interest...
1433 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1434 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1435 //JWW: Blitter writing echo 77B3 at 0011D022...
1436 }//*/
1437 //extern bool doGPUDis;
1438 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1439 {
1440 //      doGPUDis = true;
1441         WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1442 //      LogBlit();
1443 }
1444 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1445         WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1446
1447                 jaguarMainRAM[(offset+0) & 0x3FFFFF] = data >> 8;
1448                 jaguarMainRAM[(offset+1) & 0x3FFFFF] = data & 0xFF;
1449                 return;
1450         }
1451         else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1452         {
1453                 CDROMWriteWord(offset, data, who);
1454                 return;
1455         }
1456         else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1457         {
1458                 TOMWriteWord(offset, data, who);
1459                 return;
1460         }
1461         else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1462         {
1463                 JERRYWriteWord(offset, data, who);
1464                 return;
1465         }
1466         // Don't bomb on attempts to write to ROM
1467         else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1468                 return;
1469
1470         jaguar_unknown_writeword(offset, data, who);
1471 }
1472
1473 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1474 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1475 {
1476         return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1477 }
1478
1479 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1480 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1481 {
1482 /*      extern bool doDSPDis;
1483         if (offset < 0x400 && !doDSPDis)
1484         {
1485                 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1486                 doDSPDis = true;
1487         }//*/
1488 /*if (offset == 0x0100)//64*4)
1489         WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1490
1491         JaguarWriteWord(offset, data >> 16, who);
1492         JaguarWriteWord(offset+2, data & 0xFFFF, who);
1493 }
1494
1495 //
1496 // Jaguar console initialization
1497 //
1498 void JaguarInit(void)
1499 {
1500 #ifdef CPU_DEBUG_MEMORY
1501         memset(readMem, 0x00, 0x400000);
1502         memset(writeMemMin, 0xFF, 0x400000);
1503         memset(writeMemMax, 0x00, 0x400000);
1504 #endif
1505         memset(jaguarMainRAM, 0x00, 0x400000);
1506 //      memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1507 //      memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1508 //NOTE: This *doesn't* fix FlipOut...
1509 //Or does it? Hmm...
1510 //Seems to want $01010101... Dunno why. Investigate!
1511         memset(jaguarMainROM, 0x01, 0x600000);  // & set it to all 01s...
1512 //      memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1513
1514         m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1515         GPUInit();
1516         DSPInit();
1517         TOMInit();
1518         JERRYInit();
1519         CDROMInit();
1520 }
1521
1522 //New timer based code stuffola...
1523 void ScanlineCallback(void);
1524 void RenderCallback(void);
1525 //extern uint32 * backbuffer;
1526 void JaguarReset(void)
1527 {
1528 //NOTE: This causes a (virtual) crash if this is set in the config but not found... !!! FIX !!!
1529         if (vjs.useJaguarBIOS)
1530                 memcpy(jaguarMainRAM, jaguarBootROM, 8);
1531         else
1532                 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1533
1534 //      WriteLog("jaguar_reset():\n");
1535         TOMReset();
1536         JERRYReset();
1537         GPUReset();
1538         DSPReset();
1539         CDROMReset();
1540     m68k_pulse_reset();                                                         // Reset the 68000
1541         WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1542
1543         // New timer base code stuffola...
1544         InitializeEventList();
1545         TOMResetBackbuffer(backbuffer);
1546 //      SetCallbackTime(ScanlineCallback, 63.5555);
1547         SetCallbackTime(ScanlineCallback, 31.77775);
1548 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1549 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
1550 }
1551
1552 void JaguarDone(void)
1553 {
1554 #ifdef CPU_DEBUG_MEMORY
1555 /*      WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1556
1557         for(uint32 i=0; i<=raPtr; i++)
1558         {
1559                 WriteLog("\t%08X\n", returnAddr[i]);
1560                 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1561                 jaguar_dasm(returnAddr[i] - 16, 16);
1562                 WriteLog("\n");
1563         }
1564         WriteLog("\n");//*/
1565
1566 /*      int start = 0, end = 0;
1567         bool endTriggered = false, startTriggered = false;
1568         for(int i=0; i<0x400000; i++)
1569         {
1570                 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1571                 {
1572                         if (!startTriggered)
1573                                 startTriggered = true, endTriggered = false, start = i;
1574
1575                         WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1576                 }
1577                 else
1578                 {
1579                         if (!endTriggered)
1580                         {
1581                                 end = i - 1, endTriggered = true, startTriggered = false;
1582                                 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1583                         }
1584                 }
1585         }
1586         WriteLog("\n");//*/
1587 #endif
1588 //#ifdef CPU_DEBUG
1589 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1590 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1591         int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1592         WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1593         for(int i=-2; i<9; i++)
1594                 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1595
1596 /*      WriteLog("\nM68000 disassembly at $802288...\n");
1597         jaguar_dasm(0x802288, 3);
1598         WriteLog("\nM68000 disassembly at $802200...\n");
1599         jaguar_dasm(0x802200, 500);
1600         WriteLog("\nM68000 disassembly at $802518...\n");
1601         jaguar_dasm(0x802518, 100);//*/
1602
1603 /*      WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1604         jaguar_dasm(0x803F00, 500);
1605         WriteLog("\n");//*/
1606
1607 /*      WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1608         jaguar_dasm(0x802B00, 500);
1609         WriteLog("\n");//*/
1610
1611 /*      WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1612         jaguar_dasm(0x809900, 500);
1613         WriteLog("\n");//*/
1614 //8099F8
1615 /*      WriteLog("\n\nDump of $8093C8:\n\n");
1616         for(int i=0x8093C8; i<0x809900; i+=4)
1617                 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1618 /*      WriteLog("\n\nM68000 disassembly at $90006C...\n");
1619         jaguar_dasm(0x90006C, 500);
1620         WriteLog("\n");//*/
1621 /*      WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1622         jaguar_dasm(0x1AC000, 6000);
1623         WriteLog("\n");//*/
1624
1625 //      WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1626         WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
1627         WriteLog("Jaguar: VBL interrupt is %s\n", ((TOMIRQEnabled(IRQ_VBLANK)) && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled");
1628         M68K_show_context();
1629 //#endif
1630
1631         CDROMDone();
1632         GPUDone();
1633         DSPDone();
1634         TOMDone();
1635         JERRYDone();
1636 }
1637
1638 //
1639 // Main Jaguar execution loop (1 frame)
1640 //
1641 void JaguarExecute(uint32 * backbuffer, bool render)
1642 {
1643         uint16 vp = TOMReadWord(0xF0003E) + 1;
1644         uint16 vi = TOMReadWord(0xF0004E);
1645 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1646 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1647
1648 //      uint16 vdb = TOMReadWord(0xF00046);
1649 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1650 //      uint16 vbb = TOMReadWord(0xF00040);
1651 //It seems that they mean it when they say that VDE is the end of object processing.
1652 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1653 //buffer and not to write any more pixels... !!! FIX !!!
1654 //      uint16 vde = TOMReadWord(0xF00048);
1655
1656         uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1657         uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1658 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1659 //seem to indicate the refresh rate is *half* the above...
1660 //      uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1661         // Should these be hardwired or read from VP? Yes, from VP!
1662         uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1663         uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1664
1665         TOMResetBackbuffer(backbuffer);
1666 /*extern int effect_start;
1667 if (effect_start)
1668         WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1669
1670 //extern int start_logging;
1671         for(uint16 i=0; i<vp; i++)
1672         {
1673                 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1674                 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004) + 1) & 0x7FF);
1675
1676                 TOMWriteWord(0xF00006, i);                                      // Write the VC
1677
1678 //              if (i == vi)                                                            // Time for Vertical Interrupt?
1679 //Not sure if this is correct...
1680 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1681 //Which means that it normally wouldn't go when it's zero.
1682                 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK))      // Time for Vertical Interrupt?
1683                 {
1684                         // We don't have to worry about autovectors & whatnot because the Jaguar
1685                         // tells you through its HW registers who sent the interrupt...
1686                         TOMSetPendingVideoInt();
1687                         m68k_set_irq(7);
1688                 }
1689
1690 //if (start_logging)
1691 //      WriteLog("About to execute M68K (%u)...\n", i);
1692                 m68k_execute(M68KCyclesPerScanline);
1693 //if (start_logging)
1694 //      WriteLog("About to execute TOM's PIT (%u)...\n", i);
1695                 TOMExecPIT(RISCCyclesPerScanline);
1696 //if (start_logging)
1697 //      WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1698                 JERRYExecPIT(RISCCyclesPerScanline);
1699 //if (start_logging)
1700 //      WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1701                 JERRYI2SExec(RISCCyclesPerScanline);
1702                 BUTCHExec(RISCCyclesPerScanline);
1703 //if (start_logging)
1704 //      WriteLog("About to execute GPU (%u)...\n", i);
1705                 GPUExec(RISCCyclesPerScanline);
1706
1707                 if (vjs.DSPEnabled)
1708                 {
1709                         if (vjs.usePipelinedDSP)
1710                                 DSPExecP2(RISCCyclesPerScanline);       // Pipelined DSP execution (3 stage)...
1711                         else
1712                                 DSPExec(RISCCyclesPerScanline);         // Ordinary non-pipelined DSP
1713 //                      DSPExecComp(RISCCyclesPerScanline);             // Comparison core
1714                 }
1715
1716 //if (start_logging)
1717 //      WriteLog("About to execute OP (%u)...\n", i);
1718                 TOMExecScanline(i, render);
1719         }
1720 }
1721
1722 // Temp debugging stuff
1723
1724 void DumpMainMemory(void)
1725 {
1726         FILE * fp = fopen("./memdump.bin", "wb");
1727
1728         if (fp == NULL)
1729                 return;
1730
1731         fwrite(jaguarMainRAM, 1, 0x400000, fp);
1732         fclose(fp);
1733 }
1734
1735 uint8 * GetRamPtr(void)
1736 {
1737         return jaguarMainRAM;
1738 }
1739
1740 //
1741 // New Jaguar execution stack
1742 //
1743
1744 #if 0
1745
1746 void JaguarExecuteNew(void)
1747 {
1748         extern bool finished, showGUI;
1749         extern bool debounceRunKey;
1750         // Pass a message to the "joystick" code to debounce the ESC key...
1751         debounceRunKey = true;
1752         finished = false;
1753 /*      InitializeEventList();
1754         TOMResetBackbuffer(backbuffer);
1755 //      SetCallbackTime(ScanlineCallback, 63.5555);
1756         SetCallbackTime(ScanlineCallback, 31.77775);
1757 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1758 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time//*/
1759 //      uint8 * keystate = SDL_GetKeyState(NULL);
1760
1761         do
1762         {
1763                 double timeToNextEvent = GetTimeToNextEvent();
1764 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1765
1766                 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1767                 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1768
1769                 if (vjs.DSPEnabled)
1770                 {
1771                         if (vjs.usePipelinedDSP)
1772                                 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent));        // Pipelined DSP execution (3 stage)...
1773                         else
1774                                 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));          // Ordinary non-pipelined DSP
1775                 }
1776
1777                 HandleNextEvent();
1778
1779 //              if (keystate[SDLK_ESCAPE])
1780 //                      break;
1781
1782 //          SDL_PumpEvents();   // Needed to keep the keystate current...
1783         }
1784         while (!finished);
1785 }
1786
1787 void ScanlineCallback(void)
1788 {
1789         uint16 vc = TOMReadWord(0xF00006);
1790         uint16 vp = TOMReadWord(0xF0003E) + 1;
1791         uint16 vi = TOMReadWord(0xF0004E);
1792 //      uint16 vbb = TOMReadWord(0xF00040);
1793         vc++;
1794
1795         if (vc >= vp)
1796                 vc = 0;
1797
1798 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1799         TOMWriteWord(0xF00006, vc);
1800
1801 //This is a crappy kludge, but maybe it'll work for now...
1802 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1803         if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK))  // Time for Vertical Interrupt?
1804         {
1805                 // We don't have to worry about autovectors & whatnot because the Jaguar
1806                 // tells you through its HW registers who sent the interrupt...
1807                 tom_set_pending_video_int();
1808                 m68k_set_irq(7);
1809         }
1810
1811         TOMExecScanline(vc, true);
1812
1813 //Change this to VBB???
1814 //Doesn't seem to matter (at least for Flip Out & I-War)
1815         if (vc == 0)
1816 //      if (vc == vbb)
1817         {
1818 joystick_exec();
1819
1820                 RenderBackbuffer();
1821                 TOMResetBackbuffer(backbuffer);
1822         }//*/
1823
1824 //      if (vc == 0)
1825 //              TOMResetBackbuffer(backbuffer);
1826
1827 //      SetCallbackTime(ScanlineCallback, 63.5555);
1828         SetCallbackTime(ScanlineCallback, 31.77775);
1829 }
1830
1831 #else
1832
1833 bool frameDone;
1834 void JaguarExecuteNew(void)
1835 {
1836 //      extern bool finished, showGUI;
1837 //      extern bool debounceRunKey;
1838         // Pass a message to the "joystick" code to debounce the ESC key...
1839 //      debounceRunKey = true;
1840 //      finished = false;
1841 /*      InitializeEventList();
1842         TOMResetBackbuffer(backbuffer);
1843 //      SetCallbackTime(ScanlineCallback, 63.5555);
1844         SetCallbackTime(ScanlineCallback, 31.77775);
1845 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1846 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time//*/
1847 //      uint8 * keystate = SDL_GetKeyState(NULL);
1848         frameDone = false;
1849
1850         do
1851         {
1852                 double timeToNextEvent = GetTimeToNextEvent();
1853 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1854
1855                 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1856                 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1857
1858                 if (vjs.DSPEnabled)
1859                 {
1860                         if (vjs.usePipelinedDSP)
1861                                 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent));        // Pipelined DSP execution (3 stage)...
1862                         else
1863                                 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));          // Ordinary non-pipelined DSP
1864                 }
1865
1866                 HandleNextEvent();
1867
1868 //              if (keystate[SDLK_ESCAPE])
1869 //                      break;
1870
1871 //          SDL_PumpEvents();   // Needed to keep the keystate current...
1872         }
1873         while (!frameDone);
1874 }
1875
1876 void ScanlineCallback(void)
1877 {
1878         uint16 vc = TOMReadWord(0xF00006);
1879         uint16 vp = TOMReadWord(0xF0003E) + 1;
1880         uint16 vi = TOMReadWord(0xF0004E);
1881 //      uint16 vbb = TOMReadWord(0xF00040);
1882         vc++;
1883
1884         if (vc >= vp)
1885                 vc = 0;
1886
1887 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1888         TOMWriteWord(0xF00006, vc);
1889
1890 //This is a crappy kludge, but maybe it'll work for now...
1891 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1892         if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK))    // Time for Vertical Interrupt?
1893         {
1894                 // We don't have to worry about autovectors & whatnot because the Jaguar
1895                 // tells you through its HW registers who sent the interrupt...
1896                 TOMSetPendingVideoInt();
1897                 m68k_set_irq(7);
1898         }
1899
1900         TOMExecScanline(vc, true);
1901
1902 //Change this to VBB???
1903 //Doesn't seem to matter (at least for Flip Out & I-War)
1904         if (vc == 0)
1905 //      if (vc == vbb)
1906         {
1907                 JoystickExec();
1908                 RenderBackbuffer();
1909                 TOMResetBackbuffer(backbuffer);
1910                 frameDone = true;
1911         }//*/
1912
1913 //      if (vc == 0)
1914 //              TOMResetBackbuffer(backbuffer);
1915
1916 //      SetCallbackTime(ScanlineCallback, 63.5555);
1917         SetCallbackTime(ScanlineCallback, 31.77775);
1918 }
1919
1920 #endif
1921
1922 // This isn't currently used, but maybe it should be...
1923 void RenderCallback(void)
1924 {
1925         RenderBackbuffer();
1926         TOMResetBackbuffer(backbuffer);
1927 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1928         SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
1929 }