]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
72802f518ce117b6895c2e9db4e2c0ff364083d3
[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_t who = UNKNOWN);
50 unsigned jaguar_unknown_readword(unsigned address, uint32_t who = UNKNOWN);
51 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who = UNKNOWN);
52 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t 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_t jagMemSpace[];
65
66 // Internal variables
67
68 uint32_t jaguar_active_memory_dumps = 0;
69
70 uint32_t jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress;
71 bool jaguarCartInserted = false;
72 bool lowerField = false;
73
74 #ifdef CPU_DEBUG_MEMORY
75 uint8_t writeMemMax[0x400000], writeMemMin[0x400000];
76 uint8_t readMem[0x400000];
77 uint32_t returnAddr[4000], raPtr = 0xFFFFFFFF;
78 #endif
79
80 uint32_t pcQueue[0x400];
81 uint32_t 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_t 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_t 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_t 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_t addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
197                         bool found = false;
198                         if (raPtr != 0xFFFFFFFF)
199                         {
200                                 for(uint32_t 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_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
391                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
392                 uint32_t 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_t jaguarMainRAM[0x400000];                                                // 68K CPU RAM
514 uint8_t jaguarMainROM[0x600000];                                                // 68K CPU ROM
515 uint8_t jaguarBootROM[0x040000];                                                // 68K CPU BIOS ROM--uses only half of this!
516 uint8_t jaguarCDBootROM[0x040000];                                      // 68K CPU CD BIOS ROM
517 bool BIOSLoaded = false;
518 bool CDBIOSLoaded = false;
519
520 uint8_t cdRAM[0x100];
521 uint8_t tomRAM[0x4000];
522 uint8_t jerryRAM[0x10000];
523 static uint16_t 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_t        {
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_t address, uint8_t byte, uint32_t 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_t)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_t)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_t)byte << 8);
729                         else
730                                 JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32_t)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_t adddress, uint16_t word)
827 {
828 }
829
830 void WriteDWord(uint32_t adddress, uint32_t dword)
831 {
832 }
833
834 uint8_t ReadByte(uint32_t adddress)
835 {
836 }
837
838 uint16_t ReadWord(uint32_t adddress)
839 {
840 }
841
842 uint32_t ReadDWord(uint32_t 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_t 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_t 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_t JaguarGetHandler(uint32_t i)
1316 {
1317         return JaguarReadLong(i * 4);
1318 }
1319
1320 bool JaguarInterruptHandlerIsValid(uint32_t i) // Debug use only...
1321 {
1322         uint32_t 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_t address = (uint32_t)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_t 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_t 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_t 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_t 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_t offset, uint32_t qt)
1476 {
1477 #ifdef CPU_DEBUG
1478         static char buffer[2048];//, mem[64];
1479         int pc = offset, oldpc;
1480
1481         for(uint32_t 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_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1497 {
1498         uint8_t data = 0x00;
1499         offset &= 0xFFFFFF;
1500
1501         // First 2M is mirrored in the $0 - $7FFFFF range
1502         if (offset < 0x800000)
1503                 data = jaguarMainRAM[offset & 0x1FFFFF];
1504         else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1505                 data = jaguarMainROM[offset - 0x800000];
1506         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1507                 data = CDROMReadByte(offset, who);
1508         else if ((offset >= 0xE00000) && (offset < 0xE40000))
1509 //              data = jaguarBootROM[offset & 0x3FFFF];
1510 //              data = jaguarDevBootROM1[offset & 0x3FFFF];
1511                 data = jagMemSpace[offset];
1512         else if ((offset >= 0xF00000) && (offset < 0xF10000))
1513                 data = TOMReadByte(offset, who);
1514         else if ((offset >= 0xF10000) && (offset < 0xF20000))
1515                 data = JERRYReadByte(offset, who);
1516         else
1517                 data = jaguar_unknown_readbyte(offset, who);
1518
1519         return data;
1520 }
1521
1522 uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1523 {
1524         offset &= 0xFFFFFF;
1525
1526         // First 2M is mirrored in the $0 - $7FFFFF range
1527         if (offset < 0x800000)
1528         {
1529                 return (jaguarMainRAM[(offset+0) & 0x1FFFFF] << 8) | jaguarMainRAM[(offset+1) & 0x1FFFFF];
1530         }
1531         else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1532         {
1533                 offset -= 0x800000;
1534                 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1535         }
1536 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1537         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1538                 return CDROMReadWord(offset, who);
1539         else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1540 //              return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1541 //              return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1542                 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1543         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1544                 return TOMReadWord(offset, who);
1545         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1546                 return JERRYReadWord(offset, who);
1547
1548         return jaguar_unknown_readword(offset, who);
1549 }
1550
1551 void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1552 {
1553 /*      if (offset >= 0x4E00 && offset < 0x4E04)
1554                 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1555 //Need to check for writes in the range of $18FA70 + 8000...
1556 /*if (effect_start)
1557         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1558                 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1559
1560         offset &= 0xFFFFFF;
1561
1562         // First 2M is mirrored in the $0 - $7FFFFF range
1563         if (offset < 0x800000)
1564         {
1565                 jaguarMainRAM[offset & 0x1FFFFF] = data;
1566                 return;
1567         }
1568         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1569         {
1570                 CDROMWriteByte(offset, data, who);
1571                 return;
1572         }
1573         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1574         {
1575                 TOMWriteByte(offset, data, who);
1576                 return;
1577         }
1578         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1579         {
1580                 JERRYWriteByte(offset, data, who);
1581                 return;
1582         }
1583
1584         jaguar_unknown_writebyte(offset, data, who);
1585 }
1586
1587 uint32_t starCount;
1588 void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1589 {
1590 /*      if (offset >= 0x4E00 && offset < 0x4E04)
1591                 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1592 /*if (offset == 0x0100)//64*4)
1593         WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
1594 if (offset == 0x0102)//64*4)
1595         WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
1596 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
1597 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
1598 //Need to check for writes in the range of $18FA70 + 8000...
1599 /*if (effect_start)
1600         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1601                 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
1602 /*if (offset >= 0x2C00 && offset <= 0x2CFF)
1603         WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
1604
1605         offset &= 0xFFFFFF;
1606
1607         // First 2M is mirrored in the $0 - $7FFFFF range
1608         if (offset <= 0x7FFFFE)
1609         {
1610 /*
1611 GPU Table (CD BIOS)
1612
1613 1A 69 F0 ($0000) -> Starfield
1614 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
1615 1A 79 F0 ($0002)
1616 1A 88 C0 ($0003)
1617 1A 8F E8 ($0004) -> "Jaguar" small color logo?
1618 1A 95 20 ($0005)
1619 1A 9F 08 ($0006)
1620 1A A1 38 ($0007)
1621 1A AB 38 ($0008)
1622 1A B3 C8 ($0009)
1623 1A B9 C0 ($000A)
1624 */
1625
1626 //This MUST be done by the 68K!
1627 /*if (offset == 0x670C)
1628         WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
1629
1630 /*extern bool doGPUDis;
1631 //if ((offset == 0x100000 + 75522) && who == GPU)       // 76,226 -> 75522
1632 if ((offset == 0x100000 + 128470) && who == GPU)        // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1633 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
1634         doGPUDis = true;//*/
1635 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
1636         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
1637 if ((data & 0xFF00) != 0x7700)
1638         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1639 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
1640         return;//*/
1641 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
1642         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
1643 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
1644         return;//*/
1645 /*extern bool doGPUDis;
1646 if (offset == 0x120216 && who == GPU)
1647         doGPUDis = true;//*/
1648 /*extern uint32_t gpu_pc;
1649 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1650 {
1651         uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1652         uint32_t y = base / 0x300;
1653         uint32_t x = (base - (y * 0x300)) / 2;
1654         WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1655 }//*/
1656 /*
1657 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
1658 */
1659 //if (offset == (0x001E17F8 + 0x34))
1660 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
1661         data = 0xFE3C;//*/
1662 //      WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
1663 /*extern uint32_t gpu_pc;
1664 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
1665 {
1666         extern int objectPtr;
1667 //      if (offset > 0x148000)
1668 //              return;
1669         starCount++;
1670         if (starCount > objectPtr)
1671                 return;
1672
1673 //      if (starCount == 1)
1674 //              WriteLog("--> Drawing 1st star...\n");
1675 //
1676 //      uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
1677 //      uint32_t y = base / 0x300;
1678 //      uint32_t x = (base - (y * 0x300)) / 2;
1679 //      WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
1680
1681 //A star of interest...
1682 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
1683 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
1684 //JWW: Blitter writing echo 77B3 at 0011D022...
1685 }//*/
1686 //extern bool doGPUDis;
1687 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
1688 {
1689 //      doGPUDis = true;
1690         WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
1691 //      LogBlit();
1692 }
1693 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
1694         WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
1695
1696                 jaguarMainRAM[(offset+0) & 0x1FFFFF] = data >> 8;
1697                 jaguarMainRAM[(offset+1) & 0x1FFFFF] = data & 0xFF;
1698                 return;
1699         }
1700         else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
1701         {
1702                 CDROMWriteWord(offset, data, who);
1703                 return;
1704         }
1705         else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
1706         {
1707                 TOMWriteWord(offset, data, who);
1708                 return;
1709         }
1710         else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
1711         {
1712                 JERRYWriteWord(offset, data, who);
1713                 return;
1714         }
1715         // Don't bomb on attempts to write to ROM
1716         else if (offset >= 0x800000 && offset <= 0xEFFFFF)
1717                 return;
1718
1719         jaguar_unknown_writeword(offset, data, who);
1720 }
1721
1722 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1723 uint32_t JaguarReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1724 {
1725         return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
1726 }
1727
1728 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
1729 void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
1730 {
1731 /*      extern bool doDSPDis;
1732         if (offset < 0x400 && !doDSPDis)
1733         {
1734                 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
1735                 doDSPDis = true;
1736         }//*/
1737 /*if (offset == 0x0100)//64*4)
1738         WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
1739
1740         JaguarWriteWord(offset, data >> 16, who);
1741         JaguarWriteWord(offset+2, data & 0xFFFF, who);
1742 }
1743
1744 void JaguarSetScreenBuffer(uint32_t * buffer)
1745 {
1746         // This is in TOM, but we set it here...
1747         screenBuffer = buffer;
1748 }
1749
1750 void JaguarSetScreenPitch(uint32_t pitch)
1751 {
1752         // This is in TOM, but we set it here...
1753         screenPitch = pitch;
1754 }
1755
1756 //
1757 // Jaguar console initialization
1758 //
1759 void JaguarInit(void)
1760 {
1761 #ifdef CPU_DEBUG_MEMORY
1762         memset(readMem, 0x00, 0x400000);
1763         memset(writeMemMin, 0xFF, 0x400000);
1764         memset(writeMemMax, 0x00, 0x400000);
1765 #endif
1766         memset(jaguarMainRAM, 0x00, 0x200000);
1767 //      memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
1768 //      memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
1769 //NOTE: This *doesn't* fix FlipOut...
1770 //Or does it? Hmm...
1771 //Seems to want $01010101... Dunno why. Investigate!
1772         memset(jaguarMainROM, 0x01, 0x600000);  // & set it to all 01s...
1773 //      memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
1774         lowerField = false;                                                     // Reset the lower field flag
1775 //temp, for crappy crap that sux
1776 memset(jaguarMainRAM + 0x804, 0xFF, 4);
1777
1778 //      m68k_set_cpu_type(M68K_CPU_TYPE_68000);
1779         m68k_pulse_reset();                                                     // Need to do this so UAE disasm doesn't segfault on exit
1780         GPUInit();
1781         DSPInit();
1782         TOMInit();
1783         JERRYInit();
1784         CDROMInit();
1785 }
1786
1787 //New timer based code stuffola...
1788 void HalflineCallback(void);
1789 void RenderCallback(void);
1790 void JaguarReset(void)
1791 {
1792         // New timer base code stuffola...
1793         InitializeEventList();
1794 //Need to change this so it uses the single RAM space and load the BIOS
1795 //into it somewhere...
1796 //Also, have to change this here and in JaguarReadXX() currently
1797         // Only use the system BIOS if it's available...! (it's always available now!)
1798         // AND only if a jaguar cartridge has been inserted.
1799         if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine)
1800                 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
1801         else
1802                 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1803
1804 //      WriteLog("jaguar_reset():\n");
1805         TOMReset();
1806         JERRYReset();
1807         GPUReset();
1808         DSPReset();
1809         CDROMReset();
1810     m68k_pulse_reset();                                                         // Reset the 68000
1811         WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1812
1813         lowerField = false;                                                             // Reset the lower field flag
1814 //      SetCallbackTime(ScanlineCallback, 63.5555);
1815 //      SetCallbackTime(ScanlineCallback, 31.77775);
1816         SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
1817 }
1818
1819 void JaguarDone(void)
1820 {
1821 #ifdef CPU_DEBUG_MEMORY
1822 /*      WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
1823
1824         for(uint32_t i=0; i<=raPtr; i++)
1825         {
1826                 WriteLog("\t%08X\n", returnAddr[i]);
1827                 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
1828                 jaguar_dasm(returnAddr[i] - 16, 16);
1829                 WriteLog("\n");
1830         }
1831         WriteLog("\n");//*/
1832
1833 /*      int start = 0, end = 0;
1834         bool endTriggered = false, startTriggered = false;
1835         for(int i=0; i<0x400000; i++)
1836         {
1837                 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
1838                 {
1839                         if (!startTriggered)
1840                                 startTriggered = true, endTriggered = false, start = i;
1841
1842                         WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
1843                 }
1844                 else
1845                 {
1846                         if (!endTriggered)
1847                         {
1848                                 end = i - 1, endTriggered = true, startTriggered = false;
1849                                 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
1850                         }
1851                 }
1852         }
1853         WriteLog("\n");//*/
1854 #endif
1855 //#ifdef CPU_DEBUG
1856 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1857 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1858         int32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
1859         WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
1860 #if 0
1861         for(int i=-2; i<9; i++)
1862                 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
1863 #else
1864         uint32_t address = topOfStack - (4 * 4 * 3);
1865
1866         for(int i=0; i<10; i++)
1867         {
1868                 WriteLog("%06X:", address);
1869
1870                 for(int j=0; j<4; j++)
1871                 {
1872                         WriteLog(" %08X", JaguarReadLong(address));
1873                         address += 4;
1874                 }
1875
1876                 WriteLog("\n");
1877         }
1878 #endif
1879
1880 /*      WriteLog("\nM68000 disassembly at $802288...\n");
1881         jaguar_dasm(0x802288, 3);
1882         WriteLog("\nM68000 disassembly at $802200...\n");
1883         jaguar_dasm(0x802200, 500);
1884         WriteLog("\nM68000 disassembly at $802518...\n");
1885         jaguar_dasm(0x802518, 100);//*/
1886
1887 /*      WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
1888         jaguar_dasm(0x803F00, 500);
1889         WriteLog("\n");//*/
1890
1891 /*      WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
1892         jaguar_dasm(0x802B00, 500);
1893         WriteLog("\n");//*/
1894
1895 /*      WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
1896         jaguar_dasm(0x809900, 500);
1897         WriteLog("\n");//*/
1898 //8099F8
1899 /*      WriteLog("\n\nDump of $8093C8:\n\n");
1900         for(int i=0x8093C8; i<0x809900; i+=4)
1901                 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
1902 /*      WriteLog("\n\nM68000 disassembly at $90006C...\n");
1903         jaguar_dasm(0x90006C, 500);
1904         WriteLog("\n");//*/
1905 /*      WriteLog("\n\nM68000 disassembly at $1AC000...\n");
1906         jaguar_dasm(0x1AC000, 6000);
1907         WriteLog("\n");//*/
1908
1909 //      WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
1910         WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
1911         WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
1912                 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
1913         M68K_show_context();
1914 //#endif
1915
1916 #if 0   // This is drawn already...
1917         WriteLog("Jaguar: 68K AutoVector table:\n", JaguarReadWord(0x3004));
1918         for(uint32_t i=0x64; i<=0x7C; i+=4)
1919                 WriteLog("  #%u: %08X\n", (i-0x64)/4, JaguarReadLong(i));
1920 #endif
1921
1922         CDROMDone();
1923         GPUDone();
1924         DSPDone();
1925         TOMDone();
1926         JERRYDone();
1927
1928         // temp, until debugger is in place
1929 //00802016: jsr     $836F1A.l
1930 //0080201C: jsr     $836B30.l
1931 //00802022: jsr     $836B18.l
1932 //00802028: jsr     $8135F0.l
1933 //00813C1E: jsr     $813F76.l
1934 //00802038: jsr     $836D00.l
1935 //00802098: jsr     $8373A4.l
1936 //008020A2: jsr     $83E24A.l
1937 //008020BA: jsr     $83E156.l
1938 //008020C6: jsr     $83E19C.l
1939 //008020E6: jsr     $8445E8.l
1940 //008020EC: jsr     $838C20.l
1941 //0080211A: jsr     $838ED6.l
1942 //00802124: jsr     $89CA56.l
1943 //0080212A: jsr     $802B48.l
1944 #if 0
1945         WriteLog("-------------------------------------------\n");
1946         JaguarDasm(0x8445E8, 0x200);
1947         WriteLog("-------------------------------------------\n");
1948         JaguarDasm(0x838C20, 0x200);
1949         WriteLog("-------------------------------------------\n");
1950         JaguarDasm(0x838ED6, 0x200);
1951         WriteLog("-------------------------------------------\n");
1952         JaguarDasm(0x89CA56, 0x200);
1953         WriteLog("-------------------------------------------\n");
1954         JaguarDasm(0x802B48, 0x200);
1955         WriteLog("\n\nM68000 disassembly at $802000...\n");
1956         JaguarDasm(0x802000, 6000);
1957         WriteLog("\n");//*/
1958 #endif
1959 /*      WriteLog("\n\nM68000 disassembly at $6004...\n");
1960         JaguarDasm(0x6004, 10000);
1961         WriteLog("\n");//*/
1962 //      WriteLog("\n\nM68000 disassembly at $802000...\n");
1963 //      JaguarDasm(0x802000, 0x1000);
1964 //      WriteLog("\n\nM68000 disassembly at $4100...\n");
1965 //      JaguarDasm(0x4100, 200);
1966 //      WriteLog("\n\nM68000 disassembly at $800800...\n");
1967 //      JaguarDasm(0x800800, 0x1000);
1968 }
1969
1970
1971 // Temp debugging stuff
1972
1973 void DumpMainMemory(void)
1974 {
1975         FILE * fp = fopen("./memdump.bin", "wb");
1976
1977         if (fp == NULL)
1978                 return;
1979
1980         fwrite(jaguarMainRAM, 1, 0x400000, fp);
1981         fclose(fp);
1982 }
1983
1984
1985 uint8_t * GetRamPtr(void)
1986 {
1987         return jaguarMainRAM;
1988 }
1989
1990
1991 //
1992 // New Jaguar execution stack
1993 // This executes 1 frame's worth of code.
1994 //
1995 bool frameDone;
1996 void JaguarExecuteNew(void)
1997 {
1998         frameDone = false;
1999
2000         do
2001         {
2002                 double timeToNextEvent = GetTimeToNextEvent();
2003 //WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
2004
2005                 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2006
2007                 if (vjs.GPUEnabled)
2008                         GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2009
2010                 HandleNextEvent();
2011         }
2012         while (!frameDone);
2013 }
2014
2015
2016 #define USE_CORRECT_PAL_TIMINGS
2017 // A lot of confusion comes from here...
2018 // The thing to keep in mind is that the VC is advanced every HALF line, regardless
2019 // of whether the display is interlaced or not. The only difference with an
2020 // interlaced display is that the high bit of VC will be set when the lower
2021 // field is being rendered. (NB: The high bit of VC is ALWAYS set on the lower field,
2022 // regardless of whether it's in interlace mode or not.
2023 // NB2: Seems it doens't always, not sure what the constraint is...)
2024 //
2025 // Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2026 // rendering two fields that are slighty vertically offset from each other.
2027 // Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2028 // is rendered in this mode so that each field, when overlaid on each other,
2029 // will yield the final picture at the full resolution for the full frame.
2030 //
2031 // We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2032 // Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2033 // it will be half this number for a half frame. BUT, since we're counting
2034 // HALF lines, we double this number and we're back at 525 for NTSC, 625 for PAL.
2035 //
2036 // Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2037 // Half line times are, naturally, half of this. :-P
2038 void HalflineCallback(void)
2039 {
2040 //OK, this is hardwired to run in NTSC, and for who knows how long.
2041 //Need to fix this so that it does a half-line in the correct amount of time
2042 //and number of lines, depending on which mode we're in. [FIXED]
2043         uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
2044         uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2045         uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);
2046 //      uint16_t vbb = TOMReadWord(0xF00040, JAGUAR);
2047         vc++;
2048
2049 #ifdef USE_CORRECT_PAL_TIMINGS
2050         // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2051         // So we cut the number of half-lines in a frame in half. :-P
2052         uint16_t numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2053
2054         if ((vc & 0x7FF) >= numHalfLines)
2055 #else
2056         if ((vc & 0x7FF) >= vp)
2057 #endif
2058         {
2059                 vc = 0;
2060 //              lowerField = !lowerField;
2061
2062                 // If we're rendering the lower field, set the high bit (#12, counting
2063                 // from 1) of VC
2064                 if (lowerField)
2065                         vc = 0x0800;
2066         }
2067
2068 //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp);
2069         TOMWriteWord(0xF00006, vc, JAGUAR);
2070
2071 //This is a crappy kludge, but maybe it'll work for now...
2072 //Maybe it's not so bad, since the IRQ happens on a scanline boundary...
2073         if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt?
2074         {
2075                 // We don't have to worry about autovectors & whatnot because the Jaguar
2076                 // tells you through its HW registers who sent the interrupt...
2077                 TOMSetPendingVideoInt();
2078                 m68k_set_irq(2);
2079         }
2080
2081         TOMExecHalfline(vc, true);
2082
2083 //Change this to VBB???
2084 //Doesn't seem to matter (at least for Flip Out & I-War)
2085         if ((vc & 0x7FF) == 0)
2086 //      if (vc == vbb)
2087         {
2088                 JoystickExec();
2089                 frameDone = true;
2090         }//*/
2091
2092 #ifdef USE_CORRECT_PAL_TIMINGS
2093         SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2094 #else
2095 //      SetCallbackTime(HalflineCallback, 63.5555);
2096         SetCallbackTime(HalflineCallback, 31.77775);
2097 #endif
2098 }
2099
2100
2101 // This isn't currently used, but maybe it should be...
2102 /*
2103 Nah, the scanline based code is good enough, and runs in 1 frame. The GUI
2104 handles all the rest, so this isn't needed. :-P
2105 */
2106 void RenderCallback(void)
2107 {
2108 //      SetCallbackTime(RenderCallback, 33303.082);     // # Scanlines * scanline time
2109         SetCallbackTime(RenderCallback, 16651.541);     // # Scanlines * scanline time
2110 }