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