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