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