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