]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
Fixed software loading to load independently of Jaguar ROM space, added new
[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...!
1608         if (vjs.useJaguarBIOS && (biosAvailable & (BIOS_NORMAL | BIOS_STUB1 | BIOS_STUB2)))
1609 //              memcpy(jaguarMainRAM, jaguarBootROM, 8);
1610 //              memcpy(jaguarMainRAM, jaguarDevBootROM1, 8);
1611                 memcpy(jaguarMainRAM, &jagMemSpace[0xE00000], 8);
1612         else
1613                 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1614
1615         if (vjs.useJaguarBIOS && !(biosAvailable & (BIOS_NORMAL | BIOS_STUB1 | BIOS_STUB2)))
1616                 WriteLog("Jaguar: Requested BIOS, but none available.\n");
1617
1618 //      WriteLog("jaguar_reset():\n");
1619         TOMReset();
1620         JERRYReset();
1621         GPUReset();
1622         DSPReset();
1623         CDROMReset();
1624     m68k_pulse_reset();                                                         // Reset the 68000
1625         WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1626
1627         // New timer base code stuffola...
1628         InitializeEventList();
1629         TOMResetBackbuffer(backbuffer);
1630 //      SetCallbackTime(ScanlineCallback, 63.5555);
1631         SetCallbackTime(ScanlineCallback, 31.77775);
1632 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1633 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
1634 }
1635
1636 void JaguarDone(void)
1637 {
1638 #ifdef CPU_DEBUG_MEMORY
1639 /*      WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1640
1641         for(uint32 i=0; i<=raPtr; i++)
1642         {
1643                 WriteLog("\t%08X\n", returnAddr[i]);
1644                 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1645                 jaguar_dasm(returnAddr[i] - 16, 16);
1646                 WriteLog("\n");
1647         }
1648         WriteLog("\n");//*/
1649
1650 /*      int start = 0, end = 0;
1651         bool endTriggered = false, startTriggered = false;
1652         for(int i=0; i<0x400000; i++)
1653         {
1654                 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1655                 {
1656                         if (!startTriggered)
1657                                 startTriggered = true, endTriggered = false, start = i;
1658
1659                         WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1660                 }
1661                 else
1662                 {
1663                         if (!endTriggered)
1664                         {
1665                                 end = i - 1, endTriggered = true, startTriggered = false;
1666                                 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1667                         }
1668                 }
1669         }
1670         WriteLog("\n");//*/
1671 #endif
1672 //#ifdef CPU_DEBUG
1673 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1674 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1675         int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1676         WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
1677         for(int i=-2; i<9; i++)
1678                 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1679
1680 /*      WriteLog("\nM68000 disassembly at $802288...\n");
1681         jaguar_dasm(0x802288, 3);
1682         WriteLog("\nM68000 disassembly at $802200...\n");
1683         jaguar_dasm(0x802200, 500);
1684         WriteLog("\nM68000 disassembly at $802518...\n");
1685         jaguar_dasm(0x802518, 100);//*/
1686
1687 /*      WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1688         jaguar_dasm(0x803F00, 500);
1689         WriteLog("\n");//*/
1690
1691 /*      WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1692         jaguar_dasm(0x802B00, 500);
1693         WriteLog("\n");//*/
1694
1695 /*      WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1696         jaguar_dasm(0x809900, 500);
1697         WriteLog("\n");//*/
1698 //8099F8
1699 /*      WriteLog("\n\nDump of $8093C8:\n\n");
1700         for(int i=0x8093C8; i<0x809900; i+=4)
1701                 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1702 /*      WriteLog("\n\nM68000 disassembly at $90006C...\n");
1703         jaguar_dasm(0x90006C, 500);
1704         WriteLog("\n");//*/
1705 /*      WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1706         jaguar_dasm(0x1AC000, 6000);
1707         WriteLog("\n");//*/
1708
1709 //      WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1710         WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1711         WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VBLANK))
1712                 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1713         M68K_show_context();
1714 //#endif
1715
1716 #if 0   // This is drawn already...
1717         WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1718         for(uint32 i=0x64; i<=0x7C; i+=4)
1719                 WriteLog("  #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1720 #endif
1721
1722         CDROMDone();
1723         GPUDone();
1724         DSPDone();
1725         TOMDone();
1726         JERRYDone();
1727
1728         // temp, until debugger is in place
1729 //00802016: jsr     $836F1A.l
1730 //0080201C: jsr     $836B30.l
1731 //00802022: jsr     $836B18.l
1732 //00802028: jsr     $8135F0.l
1733 //00813C1E: jsr     $813F76.l
1734 //00802038: jsr     $836D00.l
1735 //00802098: jsr     $8373A4.l
1736 //008020A2: jsr     $83E24A.l
1737 //008020BA: jsr     $83E156.l
1738 //008020C6: jsr     $83E19C.l
1739 //008020E6: jsr     $8445E8.l
1740 //008020EC: jsr     $838C20.l
1741 //0080211A: jsr     $838ED6.l
1742 //00802124: jsr     $89CA56.l
1743 //0080212A: jsr     $802B48.l
1744 #if 0
1745         WriteLog("-------------------------------------------\n");
1746         JaguarDasm(0x8445E8, 0x200);
1747         WriteLog("-------------------------------------------\n");
1748         JaguarDasm(0x838C20, 0x200);
1749         WriteLog("-------------------------------------------\n");
1750         JaguarDasm(0x838ED6, 0x200);
1751         WriteLog("-------------------------------------------\n");
1752         JaguarDasm(0x89CA56, 0x200);
1753         WriteLog("-------------------------------------------\n");
1754         JaguarDasm(0x802B48, 0x200);
1755 #endif
1756 }
1757
1758 //
1759 // Main Jaguar execution loop (1 frame)
1760 //
1761 void JaguarExecute(uint32 * backbuffer, bool render)
1762 {
1763         uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
1764         uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
1765 //Using WO registers is OK, since we're the ones controlling access--there's nothing wrong here! ;-)
1766 //Though we shouldn't be able to do it using TOMReadWord... !!! FIX !!!
1767
1768 //      uint16 vdb = TOMReadWord(0xF00046, JAGUAR);
1769 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1770 //      uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
1771 //It seems that they mean it when they say that VDE is the end of object processing.
1772 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1773 //buffer and not to write any more pixels... !!! FIX !!!
1774 //      uint16 vde = TOMReadWord(0xF00048, JAGUAR);
1775
1776         uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1777         uint32 m68kClockRate = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL);
1778 //Not sure the above is correct, since the number of lines and timings given in the JTRM
1779 //seem to indicate the refresh rate is *half* the above...
1780 //      uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25);
1781         // Should these be hardwired or read from VP? Yes, from VP!
1782         uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1783         uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate);
1784
1785         TOMResetBackbuffer(backbuffer);
1786 /*extern int effect_start;
1787 if (effect_start)
1788         WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);//*/
1789
1790 //extern int start_logging;
1791         for(uint16 i=0; i<vp; i++)
1792         {
1793                 // Increment the horizontal count (why? RNG? Besides which, this is *NOT* cycle accurate!)
1794                 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004, JAGUAR) + 1) & 0x7FF, JAGUAR);
1795
1796                 TOMWriteWord(0xF00006, i, JAGUAR);                      // Write the VC
1797
1798 //              if (i == vi)                                                            // Time for Vertical Interrupt?
1799 //Not sure if this is correct...
1800 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1801 //Which means that it normally wouldn't go when it's zero.
1802                 if (i == vi && i > 0 && TOMIRQEnabled(IRQ_VBLANK))      // Time for Vertical Interrupt?
1803                 {
1804                         // We don't have to worry about autovectors & whatnot because the Jaguar
1805                         // tells you through its HW registers who sent the interrupt...
1806                         TOMSetPendingVideoInt();
1807                         m68k_set_irq(2);
1808                 }
1809
1810 //if (start_logging)
1811 //      WriteLog("About to execute M68K (%u)...\n", i);
1812                 m68k_execute(M68KCyclesPerScanline);
1813 //if (start_logging)
1814 //      WriteLog("About to execute TOM's PIT (%u)...\n", i);
1815                 TOMExecPIT(RISCCyclesPerScanline);
1816 //if (start_logging)
1817 //      WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1818                 JERRYExecPIT(RISCCyclesPerScanline);
1819 //if (start_logging)
1820 //      WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1821                 JERRYI2SExec(RISCCyclesPerScanline);
1822                 BUTCHExec(RISCCyclesPerScanline);
1823 //if (start_logging)
1824 //      WriteLog("About to execute GPU (%u)...\n", i);
1825                 GPUExec(RISCCyclesPerScanline);
1826
1827                 if (vjs.DSPEnabled)
1828                 {
1829                         if (vjs.usePipelinedDSP)
1830                                 DSPExecP2(RISCCyclesPerScanline);       // Pipelined DSP execution (3 stage)...
1831                         else
1832                                 DSPExec(RISCCyclesPerScanline);         // Ordinary non-pipelined DSP
1833 //                      DSPExecComp(RISCCyclesPerScanline);             // Comparison core
1834                 }
1835
1836 //if (start_logging)
1837 //      WriteLog("About to execute OP (%u)...\n", i);
1838                 TOMExecScanline(i, render);
1839         }
1840 }
1841
1842 // Temp debugging stuff
1843
1844 void DumpMainMemory(void)
1845 {
1846         FILE * fp = fopen("./memdump.bin", "wb");
1847
1848         if (fp == NULL)
1849                 return;
1850
1851         fwrite(jaguarMainRAM, 1, 0x400000, fp);
1852         fclose(fp);
1853 }
1854
1855 uint8 * GetRamPtr(void)
1856 {
1857         return jaguarMainRAM;
1858 }
1859
1860 //
1861 // New Jaguar execution stack
1862 //
1863
1864 #if 0
1865
1866 void JaguarExecuteNew(void)
1867 {
1868         extern bool finished, showGUI;
1869         extern bool debounceRunKey;
1870         // Pass a message to the "joystick" code to debounce the ESC key...
1871         debounceRunKey = true;
1872         finished = false;
1873 /*      InitializeEventList();
1874         TOMResetBackbuffer(backbuffer);
1875 //      SetCallbackTime(ScanlineCallback, 63.5555);
1876         SetCallbackTime(ScanlineCallback, 31.77775);
1877 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1878 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time//*/
1879 //      uint8 * keystate = SDL_GetKeyState(NULL);
1880
1881         do
1882         {
1883                 double timeToNextEvent = GetTimeToNextEvent();
1884 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1885
1886                 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1887                 gpu_exec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1888
1889                 if (vjs.DSPEnabled)
1890                 {
1891                         if (vjs.usePipelinedDSP)
1892                                 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent));        // Pipelined DSP execution (3 stage)...
1893                         else
1894                                 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));          // Ordinary non-pipelined DSP
1895                 }
1896
1897                 HandleNextEvent();
1898
1899 //              if (keystate[SDLK_ESCAPE])
1900 //                      break;
1901
1902 //          SDL_PumpEvents();   // Needed to keep the keystate current...
1903         }
1904         while (!finished);
1905 }
1906
1907 void ScanlineCallback(void)
1908 {
1909         uint16 vc = TOMReadWord(0xF00006, JAGUAR);
1910         uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
1911         uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
1912 //      uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
1913         vc++;
1914
1915         if (vc >= vp)
1916                 vc = 0;
1917
1918 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
1919         TOMWriteWord(0xF00006, vc, JAGUAR);
1920
1921 //This is a crappy kludge, but maybe it'll work for now...
1922 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
1923         if (vc == vi && vc > 0 && tom_irq_enabled(IRQ_VBLANK))  // Time for Vertical Interrupt?
1924         {
1925                 // We don't have to worry about autovectors & whatnot because the Jaguar
1926                 // tells you through its HW registers who sent the interrupt...
1927                 tom_set_pending_video_int();
1928                 m68k_set_irq(2);
1929         }
1930
1931         TOMExecScanline(vc, true);
1932
1933 //Change this to VBB???
1934 //Doesn't seem to matter (at least for Flip Out & I-War)
1935         if (vc == 0)
1936 //      if (vc == vbb)
1937         {
1938 joystick_exec();
1939
1940                 RenderBackbuffer();
1941                 TOMResetBackbuffer(backbuffer);
1942         }//*/
1943
1944 //      if (vc == 0)
1945 //              TOMResetBackbuffer(backbuffer);
1946
1947 //      SetCallbackTime(ScanlineCallback, 63.5555);
1948         SetCallbackTime(ScanlineCallback, 31.77775);
1949 }
1950
1951 #else
1952
1953 bool frameDone;
1954 void JaguarExecuteNew(void)
1955 {
1956 //      extern bool finished, showGUI;
1957 //      extern bool debounceRunKey;
1958         // Pass a message to the "joystick" code to debounce the ESC key...
1959 //      debounceRunKey = true;
1960 //      finished = false;
1961 /*      InitializeEventList();
1962         TOMResetBackbuffer(backbuffer);
1963 //      SetCallbackTime(ScanlineCallback, 63.5555);
1964         SetCallbackTime(ScanlineCallback, 31.77775);
1965 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
1966 //      SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time//*/
1967 //      uint8 * keystate = SDL_GetKeyState(NULL);
1968         frameDone = false;
1969
1970         do
1971         {
1972                 double timeToNextEvent = GetTimeToNextEvent();
1973 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
1974
1975                 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
1976                 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
1977
1978                 if (vjs.DSPEnabled)
1979                 {
1980                         if (vjs.usePipelinedDSP)
1981                                 DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent));        // Pipelined DSP execution (3 stage)...
1982                         else
1983                                 DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));          // Ordinary non-pipelined DSP
1984                 }
1985
1986                 HandleNextEvent();
1987
1988 //              if (keystate[SDLK_ESCAPE])
1989 //                      break;
1990
1991 //          SDL_PumpEvents();   // Needed to keep the keystate current...
1992         }
1993         while (!frameDone);
1994 }
1995
1996 void ScanlineCallback(void)
1997 {
1998         uint16 vc = TOMReadWord(0xF00006, JAGUAR);
1999         uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2000         uint16 vi = TOMReadWord(0xF0004E, JAGUAR);
2001 //      uint16 vbb = TOMReadWord(0xF00040, JAGUAR);
2002         vc++;
2003
2004         if (vc >= vp)
2005                 vc = 0;
2006
2007 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2008         TOMWriteWord(0xF00006, vc, JAGUAR);
2009
2010 //This is a crappy kludge, but maybe it'll work for now...
2011 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2012         if (vc == vi && vc > 0 && TOMIRQEnabled(IRQ_VBLANK))    // Time for Vertical Interrupt?
2013         {
2014                 // We don't have to worry about autovectors & whatnot because the Jaguar
2015                 // tells you through its HW registers who sent the interrupt...
2016                 TOMSetPendingVideoInt();
2017                 m68k_set_irq(2);
2018         }
2019
2020         TOMExecScanline(vc, true);
2021
2022 //Change this to VBB???
2023 //Doesn't seem to matter (at least for Flip Out & I-War)
2024         if (vc == 0)
2025 //      if (vc == vbb)
2026         {
2027                 JoystickExec();
2028 //We comment this out so that the GUI can manage this instead. Which is how it should be anyway.
2029 //              RenderBackbuffer();
2030                 TOMResetBackbuffer(backbuffer);
2031                 frameDone = true;
2032         }//*/
2033
2034 //      if (vc == 0)
2035 //              TOMResetBackbuffer(backbuffer);
2036
2037 //      SetCallbackTime(ScanlineCallback, 63.5555);
2038         SetCallbackTime(ScanlineCallback, 31.77775);
2039 }
2040
2041 #endif
2042
2043 // This isn't currently used, but maybe it should be...
2044 void RenderCallback(void)
2045 {
2046 //      RenderBackbuffer();
2047         TOMResetBackbuffer(backbuffer);
2048 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
2049         SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
2050 }