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