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