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