]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
Lots of commentary/minor updates
[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 L. Hammons
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and
8 //       the braindead way in which MAME handles memory. :-)
9 // 
10
11 #include "jaguar.h"
12 #include "video.h"
13 #include "settings.h"
14 //#include "m68kdasmAG.h"
15
16 #define CPU_DEBUG
17 //Do this in makefile??? Yes! Could, but it's easier to define here...
18 //#define LOG_UNMAPPED_MEMORY_ACCESSES
19 //#define ABORT_ON_UNMAPPED_MEMORY_ACCESS
20 #define ABORT_ON_ILLEGAL_INSTRUCTIONS
21 //#define ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
22 #define CPU_DEBUG_MEMORY
23
24 // Private function prototypes
25
26 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who = UNKNOWN);
27 unsigned jaguar_unknown_readword(unsigned address, uint32 who = UNKNOWN);
28 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who = UNKNOWN);
29 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who = UNKNOWN);
30 void M68K_show_context(void);
31
32 // External variables
33
34 //extern bool hardwareTypeNTSC;                                         // Set to false for PAL
35 #ifdef CPU_DEBUG_MEMORY
36 extern bool startMemLog;                                                        // Set by "e" key
37 extern int effect_start;
38 extern int effect_start2, effect_start3, effect_start4, effect_start5, effect_start6;
39 #endif
40
41 // Memory debugging identifiers
42
43 char * whoName[9] =
44         { "Unknown", "Jaguar", "DSP", "GPU", "TOM", "JERRY", "M68K", "Blitter", "OP" };
45
46 uint32 jaguar_active_memory_dumps = 0;
47
48 uint32 jaguar_mainRom_crc32, jaguarRomSize, jaguarRunAddress;
49
50 /*static*/ uint8 * jaguar_mainRam = NULL;
51 /*static*/ uint8 * jaguar_mainRom = NULL;
52 /*static*/ uint8 * jaguar_bootRom = NULL;
53 /*static*/ uint8 * jaguar_CDBootROM = NULL;
54
55 #ifdef CPU_DEBUG_MEMORY
56 uint8 writeMemMax[0x400000], writeMemMin[0x400000];
57 uint8 readMem[0x400000];
58 uint32 returnAddr[4000], raPtr = 0xFFFFFFFF;
59 #endif
60
61 uint32 pcQueue[0x400];
62 uint32 pcQPtr = 0;
63
64 //
65 // Callback function to detect illegal instructions
66 //
67 void GPUDumpDisassembly(void);
68 void GPUDumpRegisters(void);
69         static bool start = false;
70 void M68KInstructionHook(void)
71 {
72         uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
73
74 // For tracebacks...
75 // Ideally, we'd save all the registers as well...
76         pcQueue[pcQPtr++] = m68kPC;
77         pcQPtr &= 0x3FF;
78
79         if (m68kPC & 0x01)              // Oops! We're fetching an odd address!
80         {
81                 WriteLog("M68K: Attempted to execute from an odd adress!\n\nBacktrace:\n\n");
82
83                 static char buffer[2048];
84                 for(int i=0; i<0x400; i++)
85                 {
86                         m68k_disassemble(buffer, pcQueue[(pcQPtr + i) & 0x3FF], M68K_CPU_TYPE_68000);
87                         WriteLog("\t%08X: %s\n", pcQueue[(pcQPtr + i) & 0x3FF], buffer);
88                 }
89                 WriteLog("\n");
90
91                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
92                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
93                 for(int i=0; i<10; i++)
94                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
95                 WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
96                 M68K_show_context();
97                 log_done();
98                 exit(0);
99         }
100
101 /*      if (m68kPC >= 0x807EC4 && m68kPC <= 0x807EDB)
102         {
103                 static char buffer[2048];
104                 m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
105                 WriteLog("%08X: %s", m68kPC, buffer);
106                 WriteLog("\t\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
107                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
108                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
109         }//*/
110 /*      if (m68kPC == 0x8D0E48 && effect_start5)
111         {
112                 WriteLog("\nM68K: At collision detection code. Exiting!\n\n");
113                 GPUDumpRegisters();
114                 GPUDumpDisassembly();
115                 log_done();
116                 exit(0);
117         }//*/
118 /*      uint16 opcode = JaguarReadWord(m68kPC);
119         if (opcode == 0x4E75)   // RTS
120         {
121                 if (startMemLog)
122 //                      WriteLog("Jaguar: Returning from subroutine to %08X\n", JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7)));
123                 {
124                         uint32 addr = JaguarReadLong(m68k_get_reg(NULL, M68K_REG_A7));
125                         bool found = false;
126                         if (raPtr != 0xFFFFFFFF)
127                         {
128                                 for(uint32 i=0; i<=raPtr; i++)
129                                 {
130                                         if (returnAddr[i] == addr)
131                                         {
132                                                 found = true;
133                                                 break;
134                                         }
135                                 }
136                         }
137
138                         if (!found)
139                                 returnAddr[++raPtr] = addr;
140                 }
141         }//*/
142
143 //Flip Out! debugging...
144 //805F46, 806486
145 /*
146 00805FDC: movea.l #$9c6f8, A0           D0=00100010, A0=00100000
147 00805FE2: move.w  #$10, (A0)+           D0=00100010, A0=0009C6F8
148 00805FE6: cmpa.l  #$c96f8, A0           D0=00100010, A0=0009C6FA
149 00805FEC: bne     805fe2                D0=00100010, A0=0009C6FA
150
151 0080603A: move.l  #$11ed7c, $100.w              D0=61700080, A0=000C96F8, D1=00000000, A1=000040D8
152
153 0012314C: move.l  (A0)+, (A1)+          D0=61700080, A0=00124174, D1=00000000, A1=00F03FFC
154 0012314E: cmpa.l  #$f04000, A1          D0=61700080, A0=00124178, D1=00000000, A1=00F04000
155 00123154: blt     12314c                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
156 00123156: move.l  #$0, $f035d0.l                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
157 00123160: move.l  #$f03000, $f02110.l           D0=61700080, A0=00124178, D1=00000000, A1=00F04000
158 0012316A: move.l  #$1, $f02114.l                D0=61700080, A0=00124178, D1=00000000, A1=00F04000
159 00123174: rts           D0=61700080, A0=00124178, D1=00000000, A1=00F04000
160 */
161 /*      static char buffer[2048];
162 //if (m68kPC > 0x805F48) start = true;
163 //if (m68kPC > 0x806486) start = true;
164 //if (m68kPC == 0x805FEE) start = true;
165 //if (m68kPC == 0x80600C)// start = true;
166 if (m68kPC == 0x802058) start = true;
167 //{
168 //      GPUDumpRegisters();
169 //      GPUDumpDisassembly();
170 //
171 //      M68K_show_context();
172 //      log_done();
173 //      exit(0);
174 //}
175         if (start)
176         {
177         m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
178         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));
179         }//*/
180
181 /*      if (m68kPC == 0x803F16)
182         {
183                 WriteLog("M68K: Registers found at $803F16:\n");
184                 WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
185                 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
186                         WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
187                 WriteLog("\n");
188                 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
189                         WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
190         }*/
191
192 #ifdef ABORT_ON_ILLEGAL_INSTRUCTIONS
193         if (!m68k_is_valid_instruction(m68k_read_memory_16(m68kPC), M68K_CPU_TYPE_68000))
194         {
195 #ifndef ABORT_ON_OFFICIAL_ILLEGAL_INSTRUCTION
196                 if (m68k_read_memory_16(m68kPC) == 0x4AFC)
197                 {
198                         // This is a kludge to let homebrew programs work properly (i.e., let the other processors
199                         // keep going even when the 68K dumped back to the debugger or what have you).
200 //dis no wok right!
201 //                      m68k_set_reg(M68K_REG_PC, m68kPC - 2);
202 // Try setting the vector to the illegal instruction...
203 //This doesn't work right either! Do something else! Quick!
204 //                      SET32(jaguar_mainRam, 0x10, m68kPC);
205
206                         return;
207                 }
208 #endif
209
210                 WriteLog("\nM68K encountered an illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
211                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
212                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
213                 for(int i=0; i<10; i++)
214                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), JaguarReadLong(topOfStack - (i * 4)));
215                 WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
216                 M68K_show_context();
217
218 //temp
219 //      WriteLog("\n\n68K disasm\n\n");
220 //      jaguar_dasm(0x802000, 0x50C);
221 //      WriteLog("\n\n");
222 //endoftemp
223
224                 log_done();
225                 exit(0);
226         }//*/
227 #endif
228 }
229
230 //
231 // Musashi 68000 read/write/IRQ functions
232 //
233
234 int irq_ack_handler(int level)
235 {
236         int vector = M68K_INT_ACK_AUTOVECTOR;
237
238         // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
239
240         if (level == 7)
241         {
242                 m68k_set_irq(0);                                                // Clear the IRQ...
243                 vector = 64;                                                    // Set user interrupt #0
244         }
245
246         return vector;
247 }
248
249 unsigned int m68k_read_memory_8(unsigned int address)
250 {
251 #ifdef CPU_DEBUG_MEMORY
252         if ((address >= 0x000000) && (address <= 0x3FFFFF))
253         {
254                 if (startMemLog)
255                         readMem[address] = 1;
256         }
257 #endif
258 //WriteLog("[RM8] Addr: %08X\n", address);
259         unsigned int retVal = 0;
260
261         if ((address >= 0x000000) && (address <= 0x3FFFFF))
262                 retVal = jaguar_mainRam[address];
263 //      else if ((address >= 0x800000) && (address <= 0xDFFFFF))
264         else if ((address >= 0x800000) && (address <= 0xDFFEFF))
265                 retVal = jaguar_mainRom[address - 0x800000];
266         else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
267                 retVal = jaguar_bootRom[address - 0xE00000];
268         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
269                 retVal = CDROMReadByte(address);
270         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
271                 retVal = TOMReadByte(address, M68K);
272         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
273                 retVal = JERRYReadByte(address, M68K);
274         else
275                 retVal = jaguar_unknown_readbyte(address, M68K);
276
277     return retVal;
278 }
279
280 void gpu_dump_disassembly(void);
281 void gpu_dump_registers(void);
282
283 unsigned int m68k_read_memory_16(unsigned int address)
284 {
285 #ifdef CPU_DEBUG_MEMORY
286 /*      if ((address >= 0x000000) && (address <= 0x3FFFFE))
287         {
288                 if (startMemLog)
289                         readMem[address] = 1, readMem[address + 1] = 1;
290         }//*/
291 /*      if (effect_start && (address >= 0x8064FC && address <= 0x806501))
292         {
293                 return 0x4E71;  // NOP
294         }
295         if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
296         {
297                 return 0x4E71;  // NOP
298         }
299         if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
300         {
301                 return 0x4E71;  // NOP
302         }
303         if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
304         {
305                 return 0x4E71;  // NOP
306         }
307         if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
308         {
309                 return 0x4E71;  // NOP
310         }
311         if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
312         {
313                 return 0x4E71;  // NOP
314         }//*/
315 #endif
316 //WriteLog("[RM16] Addr: %08X\n", address);
317 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
318 //      for(int i=0; i<10000; i++)
319         WriteLog("[M68K] In routine #6!\n");//*/
320 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
321 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C)    // GPU Program #2
322 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8)    // GPU Program #3
323 {
324         WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
325         gpu_dump_registers();
326         gpu_dump_disassembly();
327 //      for(int i=0; i<10000; i++)
328 //              WriteLog("[M68K] About to run GPU!\n");
329 }//*/
330 //WriteLog("[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
331 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
332 {
333         if (address == 0x000066A0)
334         {
335                 gpu_dump_registers();
336                 gpu_dump_disassembly();
337         }
338         for(int i=0; i<10000; i++)
339                 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
340 }//*/
341     unsigned int retVal = 0;
342
343         if ((address >= 0x000000) && (address <= 0x3FFFFE))
344                 retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
345 //      else if ((address >= 0x800000) && (address <= 0xDFFFFE))
346         else if ((address >= 0x800000) && (address <= 0xDFFEFE))
347                 retVal = (jaguar_mainRom[address - 0x800000] << 8) | jaguar_mainRom[address - 0x800000 + 1];
348         else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
349                 retVal = (jaguar_bootRom[address - 0xE00000] << 8) | jaguar_bootRom[address - 0xE00000 + 1];
350         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
351                 retVal = CDROMReadWord(address, M68K);
352         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
353                 retVal = TOMReadWord(address, M68K);
354         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
355                 retVal = JERRYReadWord(address, M68K);
356         else
357                 retVal = jaguar_unknown_readword(address, M68K);
358
359     return retVal;
360 }
361
362 unsigned int m68k_read_memory_32(unsigned int address)
363 {
364 //WriteLog("--> [RM32]\n");
365     return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
366 }
367
368 void m68k_write_memory_8(unsigned int address, unsigned int value)
369 {
370 #ifdef CPU_DEBUG_MEMORY
371         if ((address >= 0x000000) && (address <= 0x3FFFFF))
372         {
373                 if (startMemLog)
374                 {
375                         if (value > writeMemMax[address])
376                                 writeMemMax[address] = value;
377                         if (value < writeMemMin[address])
378                                 writeMemMin[address] = value;
379                 }
380         }
381 #endif
382 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
383 //      WriteLog("M68K: Writing %02X at %08X\n", value, address);
384 //WriteLog("[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
385 /*if (effect_start)
386         if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
387                 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
388
389         if ((address >= 0x000000) && (address <= 0x3FFFFF))
390                 jaguar_mainRam[address] = value;
391         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
392                 CDROMWriteByte(address, value, M68K);
393         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
394                 TOMWriteByte(address, value, M68K);
395         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
396                 JERRYWriteByte(address, value, M68K);
397         else
398                 jaguar_unknown_writebyte(address, value, M68K);
399 }
400
401 void m68k_write_memory_16(unsigned int address, unsigned int value)
402 {
403 #ifdef CPU_DEBUG_MEMORY
404         if ((address >= 0x000000) && (address <= 0x3FFFFE))
405         {
406                 if (startMemLog)
407                 {
408                         uint8 hi = value >> 8, lo = value & 0xFF;
409
410                         if (hi > writeMemMax[address])
411                                 writeMemMax[address] = hi;
412                         if (hi < writeMemMin[address])
413                                 writeMemMin[address] = hi;
414
415                         if (lo > writeMemMax[address+1])
416                                 writeMemMax[address+1] = lo;
417                         if (lo < writeMemMin[address+1])
418                                 writeMemMin[address+1] = lo;
419                 }
420         }
421 #endif
422 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
423 //      WriteLog("M68K: Writing %04X at %08X\n", value, address);
424 //WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
425 //if (address >= 0xF02200 && address <= 0xF0229F)
426 //      WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
427 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
428 //      WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
429 /*extern uint32 totalFrames;
430 if (address == 0xF02114)
431         WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
432 if (address == 0xF02110)
433         WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
434 //if (address >= 0xF03B00 && address <= 0xF03DFF)
435 //      WriteLog("M68K: Writing %04X to %08X...\n", value, address);
436
437 /*if (address == 0x0100)//64*4)
438         WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
439 /*if (effect_start)
440         if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
441                 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
442
443         if ((address >= 0x000000) && (address <= 0x3FFFFE))
444         {
445 /*              jaguar_mainRam[address] = value >> 8;
446                 jaguar_mainRam[address + 1] = value & 0xFF;*/
447                 SET16(jaguar_mainRam, address, value);
448         }
449         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
450                 CDROMWriteWord(address, value, M68K);
451         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
452                 TOMWriteWord(address, value, M68K);
453         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
454                 JERRYWriteWord(address, value, M68K);
455         else
456         {
457                 jaguar_unknown_writeword(address, value, M68K);
458 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
459                 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
460                         m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
461                         m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
462 #endif
463         }
464 }
465
466 void m68k_write_memory_32(unsigned int address, unsigned int value)
467 {
468 //WriteLog("--> [WM32]\n");
469 /*if (address == 0x0100)//64*4)
470         WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
471 /*if (address >= 0xF03214 && address < 0xF0321F)
472         WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
473 //M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
474 /*extern bool doGPUDis;
475 if (address == 0xF03214 && value == 0x88E30047)
476 //      start = true;
477         doGPUDis = true;//*/
478         m68k_write_memory_16(address, value >> 16);
479         m68k_write_memory_16(address + 2, value & 0xFFFF);
480 }
481
482
483 uint32 jaguar_get_handler(uint32 i)
484 {
485         return JaguarReadLong(i * 4);
486 }
487
488 uint32 jaguar_interrupt_handler_is_valid(uint32 i)
489 {
490         uint32 handler = jaguar_get_handler(i);
491         if (handler && (handler != 0xFFFFFFFF))
492                 return 1;
493         else
494                 return 0;
495 }
496
497 void M68K_show_context(void)
498 {
499         WriteLog("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
500         for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
501                 WriteLog("\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
502         WriteLog("\n");
503         for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
504                 WriteLog("\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
505
506         WriteLog("68K disasm\n");
507 //      jaguar_dasm(s68000readPC()-0x1000,0x20000);
508         jaguar_dasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
509 //      jaguar_dasm(0x5000, 0x14414);
510
511 //      WriteLog("\n.......[Cart start]...........\n\n");
512 //      jaguar_dasm(0x192000, 0x1000);//0x200);
513
514         WriteLog("..................\n");
515
516         if (tom_irq_enabled(IRQ_VBLANK))
517         {
518                 WriteLog("vblank int: enabled\n");
519                 jaguar_dasm(jaguar_get_handler(64), 0x200);
520         }
521         else
522                 WriteLog("vblank int: disabled\n");
523
524         WriteLog("..................\n");
525
526         for(int i=0; i<256; i++)
527                 WriteLog("handler %03i at $%08X\n", i, (unsigned int)jaguar_get_handler(i));
528 }
529
530 //
531 // Unknown read/write byte/word routines
532 //
533
534 // It's hard to believe that developers would be sloppy with their memory writes, yet in
535 // some cases the developers screwed up royal. E.g., Club Drive has the following code:
536 //
537 // 807EC4: movea.l #$f1b000, A1
538 // 807ECA: movea.l #$8129e0, A0
539 // 807ED0: move.l  A0, D0
540 // 807ED2: move.l  #$f1bb94, D1
541 // 807ED8: sub.l   D0, D1
542 // 807EDA: lsr.l   #2, D1
543 // 807EDC: move.l  (A0)+, (A1)+
544 // 807EDE: dbra    D1, 807edc
545 //
546 // The problem is at $807ED0--instead of putting A0 into D0, they really meant to put A1
547 // in. This mistake causes it to try and overwrite approximately $700000 worth of address
548 // space! (That is, unless the 68K causes a bus error...)
549
550 void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
551 {
552 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
553         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));
554 #endif
555 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
556         extern bool finished;
557         finished = true;
558         extern bool doDSPDis;
559         if (who == DSP)
560                 doDSPDis = true;
561 #endif
562 }
563
564 void jaguar_unknown_writeword(unsigned address, unsigned data, uint32 who/*=UNKNOWN*/)
565 {
566 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
567         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));
568 #endif
569 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
570         extern bool finished;
571         finished = true;
572         extern bool doDSPDis;
573         if (who == DSP)
574                 doDSPDis = true;
575 #endif
576 }
577
578 unsigned jaguar_unknown_readbyte(unsigned address, uint32 who/*=UNKNOWN*/)
579 {
580 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
581         WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
582 #endif
583 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
584         extern bool finished;
585         finished = true;
586         extern bool doDSPDis;
587         if (who == DSP)
588                 doDSPDis = true;
589 #endif
590     return 0xFF;
591 }
592
593 unsigned jaguar_unknown_readword(unsigned address, uint32 who/*=UNKNOWN*/)
594 {
595 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
596         WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
597 #endif
598 #ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
599         extern bool finished;
600         finished = true;
601         extern bool doDSPDis;
602         if (who == DSP)
603                 doDSPDis = true;
604 #endif
605     return 0xFFFF;
606 }
607
608 //
609 // Disassemble M68K instructions at the given offset
610 //
611
612 unsigned int m68k_read_disassembler_8(unsigned int address)
613 {
614         return m68k_read_memory_8(address);
615 }
616
617 unsigned int m68k_read_disassembler_16(unsigned int address)
618 {
619         return m68k_read_memory_16(address);
620 }
621
622 unsigned int m68k_read_disassembler_32(unsigned int address)
623 {
624         return m68k_read_memory_32(address);
625 }
626
627 void jaguar_dasm(uint32 offset, uint32 qt)
628 {
629 #ifdef CPU_DEBUG
630         static char buffer[2048];//, mem[64];
631         int pc = offset, oldpc;
632
633         for(uint32 i=0; i<qt; i++)
634         {
635 /*              oldpc = pc;
636                 for(int j=0; j<64; j++)
637                         mem[j^0x01] = jaguar_byte_read(pc + j);
638
639                 pc += Dasm68000((char *)mem, buffer, 0);
640                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
641                 oldpc = pc;
642                 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
643                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
644         }
645 #endif
646 }
647
648 uint8 JaguarReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
649 {
650         uint8 data = 0x00;
651
652         offset &= 0xFFFFFF;
653         if (offset < 0x400000)
654                 data = jaguar_mainRam[offset & 0x3FFFFF];
655         else if ((offset >= 0x800000) && (offset < 0xC00000))
656                 data = jaguar_mainRom[offset - 0x800000];
657         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
658                 data = CDROMReadByte(offset, who);
659         else if ((offset >= 0xE00000) && (offset < 0xE40000))
660                 data = jaguar_bootRom[offset & 0x3FFFF];
661         else if ((offset >= 0xF00000) && (offset < 0xF10000))
662                 data = TOMReadByte(offset, who);
663         else if ((offset >= 0xF10000) && (offset < 0xF20000))
664                 data = JERRYReadByte(offset, who);
665         else
666                 data = jaguar_unknown_readbyte(offset, who);
667
668         return data;
669 }
670
671 uint16 JaguarReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
672 {
673         offset &= 0xFFFFFF;
674         if (offset <= 0x3FFFFE)
675         {
676                 return (jaguar_mainRam[(offset+0) & 0x3FFFFF] << 8) | jaguar_mainRam[(offset+1) & 0x3FFFFF];
677         }
678         else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
679         {
680                 offset -= 0x800000;
681                 return (jaguar_mainRom[offset+0] << 8) | jaguar_mainRom[offset+1];
682         }
683 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
684         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
685                 return CDROMReadWord(offset, who);
686         else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
687                 return (jaguar_bootRom[(offset+0) & 0x3FFFF] << 8) | jaguar_bootRom[(offset+1) & 0x3FFFF];
688         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
689                 return TOMReadWord(offset, who);
690         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
691                 return JERRYReadWord(offset, who);
692
693         return jaguar_unknown_readword(offset, who);
694 }
695
696 void JaguarWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
697 {
698 //Need to check for writes in the range of $18FA70 + 8000...
699 /*if (effect_start)
700         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
701                 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
702
703         offset &= 0xFFFFFF;
704         if (offset < 0x400000)
705         {
706                 jaguar_mainRam[offset & 0x3FFFFF] = data;
707                 return;
708         }
709         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
710         {
711                 CDROMWriteByte(offset, data, who);
712                 return;
713         }
714         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
715         {
716                 TOMWriteByte(offset, data, who);
717                 return;
718         }
719         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
720         {
721                 JERRYWriteByte(offset, data, who);
722                 return;
723         }
724     
725         jaguar_unknown_writebyte(offset, data, who);
726 }
727
728 uint32 starCount;
729 void JaguarWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
730 {
731 /*if (offset == 0x0100)//64*4)
732         WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
733 if (offset == 0x0102)//64*4)
734         WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
735 //TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
736 // PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
737 //Need to check for writes in the range of $18FA70 + 8000...
738 /*if (effect_start)
739         if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
740                 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
741
742         offset &= 0xFFFFFF;
743
744         if (offset <= 0x3FFFFE)
745         {
746 /*
747 GPU Table (CD BIOS)
748
749 1A 69 F0 ($0000) -> Starfield
750 1A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
751 1A 79 F0 ($0002)
752 1A 88 C0 ($0003)
753 1A 8F E8 ($0004) -> "Jaguar" small color logo?
754 1A 95 20 ($0005)
755 1A 9F 08 ($0006)
756 1A A1 38 ($0007)
757 1A AB 38 ($0008)
758 1A B3 C8 ($0009)
759 1A B9 C0 ($000A)
760 */
761
762 //This MUST be done by the 68K!
763 /*if (offset == 0x670C)
764         WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
765
766 /*extern bool doGPUDis;
767 //if ((offset == 0x100000 + 75522) && who == GPU)       // 76,226 -> 75522
768 if ((offset == 0x100000 + 128470) && who == GPU)        // 107,167 -> 128470 (384 x 250 screen size 16BPP)
769 //if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
770         doGPUDis = true;//*/
771 /*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
772         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
773 if ((data & 0xFF00) != 0x7700)
774         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
775 /*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
776         return;//*/
777 /*if ((data & 0xFF00) != 0x7700 && who == GPU)
778         WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
779 /*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
780         return;//*/
781 /*extern bool doGPUDis;
782 if (offset == 0x120216 && who == GPU)
783         doGPUDis = true;//*/
784 /*extern uint32 gpu_pc;
785 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
786 {
787         uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
788         uint32 y = base / 0x300;
789         uint32 x = (base - (y * 0x300)) / 2;
790         WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
791 }//*/
792 /*
793 JWW: Writing starfield star 775E at 0011F650 (555984/1447)
794 */
795 //if (offset == (0x001E17F8 + 0x34))
796 /*if (who == GPU && offset == (0x001E17F8 + 0x34))
797         data = 0xFE3C;//*/
798 //      WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
799 /*extern uint32 gpu_pc;
800 if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
801 {
802         extern int objectPtr;
803 //      if (offset > 0x148000)
804 //              return;
805         starCount++;
806         if (starCount > objectPtr)
807                 return;
808
809 //      if (starCount == 1)
810 //              WriteLog("--> Drawing 1st star...\n");
811 //
812 //      uint32 base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
813 //      uint32 y = base / 0x300;
814 //      uint32 x = (base - (y * 0x300)) / 2;
815 //      WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
816
817 //A star of interest...
818 //-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
819 //1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
820 //JWW: Blitter writing echo 77B3 at 0011D022...
821 }//*/
822 //extern bool doGPUDis;
823 /*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
824 {
825 //      doGPUDis = true;
826         WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
827 //      LogBlit();
828 }
829 if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
830         WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
831
832                 jaguar_mainRam[(offset+0) & 0x3FFFFF] = data >> 8;
833                 jaguar_mainRam[(offset+1) & 0x3FFFFF] = data & 0xFF;
834                 return;
835         }
836         else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
837         {
838                 CDROMWriteWord(offset, data, who);
839                 return;
840         }
841         else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
842         {
843                 TOMWriteWord(offset, data, who);
844                 return;
845         }
846         else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
847         {
848                 JERRYWriteWord(offset, data, who);
849                 return;
850         }
851         // Don't bomb on attempts to write to ROM
852         else if (offset >= 0x800000 && offset <= 0xEFFFFF)
853                 return;
854
855         jaguar_unknown_writeword(offset, data, who);
856 }
857
858 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
859 uint32 JaguarReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
860 {
861         return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
862 }
863
864 // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
865 void JaguarWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
866 {
867 /*      extern bool doDSPDis;
868         if (offset < 0x400 && !doDSPDis)
869         {
870                 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
871                 doDSPDis = true;
872         }//*/
873 /*if (offset == 0x0100)//64*4)
874         WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
875
876         JaguarWriteWord(offset, data >> 16, who);
877         JaguarWriteWord(offset+2, data & 0xFFFF, who);
878 }
879
880 //
881 // Jaguar console initialization
882 //
883 void jaguar_init(void)
884 {
885 #ifdef CPU_DEBUG_MEMORY
886         memset(readMem, 0x00, 0x400000);
887         memset(writeMemMin, 0xFF, 0x400000);
888         memset(writeMemMax, 0x00, 0x400000);
889 #endif
890         memory_malloc_secure((void **)&jaguar_mainRam, 0x400000, "Jaguar 68K CPU RAM");
891         memory_malloc_secure((void **)&jaguar_mainRom, 0x600000, "Jaguar 68K CPU ROM");
892         memory_malloc_secure((void **)&jaguar_bootRom, 0x040000, "Jaguar 68K CPU BIOS ROM"); // Only uses half of this!
893         memory_malloc_secure((void **)&jaguar_CDBootROM, 0x040000, "Jaguar 68K CPU CD BIOS ROM");
894         memset(jaguar_mainRam, 0x00, 0x400000);
895 //      memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
896 //      memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
897 //NOTE: This *doesn't* fix FlipOut...
898 //Or does it? Hmm...
899 //Seems to want $01010101... Dunno why. Investigate!
900         memset(jaguar_mainRom, 0x01, 0x600000); // & set it to all 01s...
901 //      memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
902
903 WriteLog("Jaguar: m68k_set_cpu_type...");
904         m68k_set_cpu_type(M68K_CPU_TYPE_68000);
905 WriteLog("OK\nJaguar: gpu_init...");
906         gpu_init();
907 WriteLog("OK\nJaguar: DSPInit...");
908         DSPInit();
909 WriteLog("OK\nJaguar: tom_init...");
910         tom_init();
911 WriteLog("OK\nJaguar: jerry_init...");
912         jerry_init();
913 WriteLog("OK\nJaguar: cdrom_init...");
914         cdrom_init();
915 WriteLog("OK\n");
916 }
917
918 void jaguar_done(void)
919 {
920 #ifdef CPU_DEBUG_MEMORY
921 /*      WriteLog("\n\nM68000 disassembly at $8D0D44 (collision routine!)...\n");
922         jaguar_dasm(0x8D0D44, 5000);
923         WriteLog("\n");//*/
924 /*      WriteLog("\n\nM68000 disassembly at $806300 (look @ $806410)...\n");
925         jaguar_dasm(0x806300, 5000);
926         WriteLog("\n");//*/
927
928 /*      WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
929
930         for(uint32 i=0; i<=raPtr; i++)
931         {
932                 WriteLog("\t%08X\n", returnAddr[i]);
933                 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
934                 jaguar_dasm(returnAddr[i] - 16, 16);
935                 WriteLog("\n");
936         }
937         WriteLog("\n");//*/
938
939 /*      int start = 0, end = 0;
940         bool endTriggered = false, startTriggered = false;
941         for(int i=0; i<0x400000; i++)
942         {
943                 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
944                 {
945                         if (!startTriggered)
946                                 startTriggered = true, endTriggered = false, start = i;
947
948                         WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
949                 }
950                 else
951                 {
952                         if (!endTriggered)
953                         {
954                                 end = i - 1, endTriggered = true, startTriggered = false;
955                                 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
956                         }
957                 }
958         }
959         WriteLog("\n");//*/
960 #endif
961 //#ifdef CPU_DEBUG
962 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
963 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
964         int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
965         WriteLog("M68K: Top of stack: %08X. Stack trace:\n", JaguarReadLong(topOfStack));
966         for(int i=-2; i<9; i++)
967                 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
968
969 /*      WriteLog("\nM68000 disassembly at $802288...\n");
970         jaguar_dasm(0x802288, 3);
971         WriteLog("\nM68000 disassembly at $802200...\n");
972         jaguar_dasm(0x802200, 500);
973         WriteLog("\nM68000 disassembly at $802518...\n");
974         jaguar_dasm(0x802518, 100);//*/
975
976 /*      WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
977         jaguar_dasm(0x803F00, 500);
978         WriteLog("\n");//*/
979
980 /*      WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
981         jaguar_dasm(0x802B00, 500);
982         WriteLog("\n");//*/
983
984 /*      WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
985         jaguar_dasm(0x809900, 500);
986         WriteLog("\n");//*/
987 //8099F8
988 /*      WriteLog("\n\nDump of $8093C8:\n\n");
989         for(int i=0x8093C8; i<0x809900; i+=4)
990                 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
991 /*      WriteLog("\n\nM68000 disassembly at $90006C...\n");
992         jaguar_dasm(0x90006C, 500);
993         WriteLog("\n");//*/
994
995 //      WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
996         WriteLog("Jaguar: Interrupt enable = %02X\n", TOMReadByte(0xF000E1) & 0x1F);
997         WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
998         M68K_show_context();
999 //#endif
1000
1001 //      cd_bios_done();
1002         cdrom_done();
1003         gpu_done();
1004         DSPDone();
1005         tom_done();
1006         jerry_done();
1007
1008         memory_free(jaguar_mainRom);
1009         memory_free(jaguar_mainRam);
1010         memory_free(jaguar_bootRom);
1011         memory_free(jaguar_CDBootROM);
1012 }
1013
1014 void jaguar_reset(void)
1015 {
1016         if (vjs.useJaguarBIOS)
1017                 memcpy(jaguar_mainRam, jaguar_bootRom, 8);
1018         else
1019         {
1020 // Should also make a run address global as well, for when we reset the jag (PD mainly)
1021 /*              SET32(jaguar_mainRam, 4, 0x00802000);
1022                 // Handle PD stuff...
1023                 // This should definitely go elsewhere (like in the cart load section)!
1024 //NOTE: The bytes 'JAGR' should also be at position $1C...
1025                 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
1026                 {
1027                         uint32 loadAddress = GET32(jaguar_mainRom, 0x22), runAddress = GET32(jaguar_mainRom, 0x2A);
1028 //This is not always right! Especially when converted via bin2jag1!!!
1029 //We should have access to the length of the furshlumiger file that was loaded anyway!
1030 //Now, we do! ;-)
1031 //                      uint32 progLength = GET32(jaguar_mainRom, 0x02);
1032 //jaguarRomSize
1033 //jaguarRunAddress
1034 //                      WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
1035 //                      memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, progLength);
1036                         WriteLog("Jaguar: Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, jaguarRomSize - 0x2E);
1037                         memcpy(jaguar_mainRam + loadAddress, jaguar_mainRom + 0x2E, jaguarRomSize - 0x2E);
1038                         SET32(jaguar_mainRam, 4, runAddress);
1039                 }//*/
1040                 SET32(jaguar_mainRam, 4, jaguarRunAddress);
1041         }
1042
1043 //      WriteLog("jaguar_reset():\n");
1044 //#ifdef SOUND_OUTPUT
1045 //      ws_audio_reset();
1046 //#endif
1047 //      cd_bios_reset();
1048         tom_reset();
1049         jerry_reset();
1050         gpu_reset();
1051         DSPReset();
1052         cdrom_reset();
1053     m68k_pulse_reset();                         // Reset the 68000
1054         WriteLog("\t68K PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
1055 }
1056
1057 //
1058 // Main Jaguar execution loop (1 frame)
1059 //
1060 void JaguarExecute(int16 * backbuffer, bool render)
1061 {
1062         uint16 vp = TOMReadWord(0xF0003E) + 1;//Hmm. This is a WO register. Will work? Looks like. But wrong behavior!
1063         uint16 vi = TOMReadWord(0xF0004E);//Another WO register...
1064 //      uint16 vdb = TOMReadWord(0xF00046);
1065 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
1066 //      uint16 vbb = TOMReadWord(0xF00040);
1067 //It seems that they mean it when they say that VDE is the end of object processing.
1068 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
1069 //buffer and not to write any more pixels... !!! FIX !!!
1070 //      uint16 vde = TOMReadWord(0xF00048);
1071
1072         uint16 refreshRate = (vjs.hardwareTypeNTSC ? 60 : 50);
1073         // Should these be hardwired or read from VP? Yes, from VP!
1074         uint32 M68KCyclesPerScanline
1075                 = (vjs.hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL) / (vp * refreshRate);
1076         uint32 RISCCyclesPerScanline
1077                 = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL) / (vp * refreshRate);
1078
1079         TOMResetBackbuffer(backbuffer);
1080 /*extern int effect_start;
1081 if (effect_start)
1082 {
1083         WriteLog("JagExe: VP=%u, VI=%u, CPU CPS=%u, GPU CPS=%u\n", vp, vi, M68KCyclesPerScanline, RISCCyclesPerScanline);
1084 }//*/
1085
1086 //extern int start_logging;
1087         for(uint16 i=0; i<vp; i++)
1088         {
1089                 // Increment the horizontal count (why? RNG?)
1090                 TOMWriteWord(0xF00004, (TOMReadWord(0xF00004) + 1) & 0x7FF);
1091
1092                 TOMWriteWord(0xF00006, i);                                      // Write the VC
1093
1094 //              if (i == vi)                                                            // Time for Vertical Interrupt?
1095 //Not sure if this is correct...
1096 //Seems to be, kinda. According to the JTRM, this should only fire on odd lines in non-interlace mode...
1097 //Which means that it normally wouldn't go when it's zero.
1098                 if (i == vi && i > 0)                                           // Time for Vertical Interrupt?
1099                 {
1100                         if (tom_irq_enabled(IRQ_VBLANK))// && jaguar_interrupt_handler_is_valid(64))
1101                         {
1102                                 // We don't have to worry about autovectors & whatnot because the Jaguar
1103                                 // tells you through its HW registers who sent the interrupt...
1104                                 tom_set_pending_video_int();
1105                                 m68k_set_irq(7);
1106                         }
1107                 }
1108
1109 //              uint32 invalid_instruction_address = s68000exec(M68KCyclesPerScanline);
1110 //              if (invalid_instruction_address != 0x80000000)
1111 //                      cd_bios_process(invalid_instruction_address);
1112 //if (start_logging)
1113 //      WriteLog("About to execute M68K (%u)...\n", i);
1114                 m68k_execute(M68KCyclesPerScanline);
1115                 // No CD handling... !!! FIX !!!
1116                 //This isn't the right to go about it anyway.
1117 //if (start_logging)
1118 //      WriteLog("About to execute CD BIOS (%u)...\n", i);
1119 //              cd_bios_exec(i);        // NOTE: Ignores parameter...
1120 //if (start_logging)
1121 //      WriteLog("About to execute TOM's PIT (%u)...\n", i);
1122                 TOMExecPIT(RISCCyclesPerScanline);
1123 //if (start_logging)
1124 //      WriteLog("About to execute JERRY's PIT (%u)...\n", i);
1125                 JERRYExecPIT(RISCCyclesPerScanline);
1126 //if (start_logging)
1127 //      WriteLog("About to execute JERRY's SSI (%u)...\n", i);
1128                 jerry_i2s_exec(RISCCyclesPerScanline);
1129 //if (start_logging)
1130 //      WriteLog("About to execute GPU (%u)...\n", i);
1131                 gpu_exec(RISCCyclesPerScanline);
1132
1133                 if (vjs.DSPEnabled)
1134                         if (vjs.usePipelinedDSP)
1135                                 DSPExecP2(RISCCyclesPerScanline);       // Pipelined DSP execution (3 stage)...
1136                         else
1137                                 DSPExec(RISCCyclesPerScanline);         // Ordinary non-pipelined DSP
1138 //                      DSPExecComp(RISCCyclesPerScanline);             // Comparison core
1139
1140 //if (start_logging)
1141 //      WriteLog("About to execute OP (%u)...\n", i);
1142                 TOMExecScanline(i, render);
1143         }
1144 }
1145
1146 // Temp debugging stuff
1147
1148 void DumpMainMemory(void)
1149 {
1150         FILE * fp = fopen("./memdump.bin", "wb");
1151
1152         if (fp == NULL)
1153                 return;
1154
1155         fwrite(jaguar_mainRam, 1, 0x400000, fp);
1156         fclose(fp);
1157 }
1158
1159 uint8 * GetRamPtr(void)
1160 {
1161         return jaguar_mainRam;
1162 }