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