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