]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
749601b2d6e575203525bd12d4f37aeab401365e
[virtualjaguar] / src / jaguar.cpp
1 //
2 // JAGUAR.CPP
3 //
4 // by cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (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 "m68kdasmAG.h"
13 //#include "crc32.h"
14
15 //#define LOG_UNMAPPED_MEMORY_ACCESSES
16 //#define SOUND_OUTPUT
17 #define CPU_DEBUG
18 #define JAGUAR_WIP_RELEASE
19 #define JAGUAR_REAL_SPEED
20 //Do this in makefile??? Yes! Could, but it's easier to define here...
21 //#define LOG_UNMAPPED_MEMORY_ACCESSES
22
23 //
24 // Private function prototypes
25 //
26
27 unsigned jaguar_unknown_readbyte(unsigned address);
28 unsigned jaguar_unknown_readword(unsigned address);
29 void jaguar_unknown_writebyte(unsigned address, unsigned data);
30 void jaguar_unknown_writeword(unsigned address, unsigned data);
31 void M68K_show_context(void);
32
33 // These values are overridden by command line switches...
34
35 bool dsp_enabled = false;
36 bool jaguar_use_bios = true;                            // Default is now to USE the BIOS
37 uint32 jaguar_active_memory_dumps = 0;
38
39 uint32 jaguar_mainRom_crc32;
40
41 static uint32 m68k_cycles_per_scanline;
42 static uint32 gpu_cycles_per_scanline;
43 static uint32 dsp_cycles_per_scanline;
44 static uint32 jaguar_screen_scanlines;
45
46 /*static*/ uint8 * jaguar_mainRam = NULL;
47 /*static*/ uint8 * jaguar_bootRom = NULL;
48 /*static*/ uint8 * jaguar_mainRom = NULL;
49
50
51 //
52 // Callback function to detect illegal instructions
53 //
54
55 void M68KInstructionHook(void)
56 {
57         uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
58         
59         if (!m68k_is_valid_instruction(jaguar_word_read(m68kPC), M68K_CPU_TYPE_68000))
60         {
61                 WriteLog("\nEncountered illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
62                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
63                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", jaguar_long_read(topOfStack));
64                 for(int i=0; i<10; i++)
65                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), jaguar_long_read(topOfStack - (i * 4)));
66                 WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
67                 M68K_show_context();
68                 log_done();
69                 exit(0);
70         }
71 }
72
73 //
74 // Musashi 68000 read/write/IRQ functions
75 //
76
77 int irq_ack_handler(int level)
78 {
79         int vector = M68K_INT_ACK_AUTOVECTOR;
80
81         // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
82
83         if (level == 7)
84         {
85                 m68k_set_irq(0);                                                // Clear the IRQ...
86                 vector = 64;                                                    // Set user interrupt #0
87         }
88
89         return vector;
90 }
91
92 unsigned int m68k_read_memory_8(unsigned int address)
93 {
94 //WriteLog( "[RM8] Addr: %08X\n", address);
95         unsigned int retVal = 0;
96
97         if ((address >= 0x000000) && (address <= 0x3FFFFF))
98                 retVal = jaguar_mainRam[address];
99         else if ((address >= 0x800000) && (address <= 0xDFFFFF))
100                 retVal = jaguar_mainRom[address - 0x800000];
101         else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
102                 retVal = jaguar_bootRom[address - 0xE00000];
103         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
104                 retVal = cdrom_byte_read(address);
105         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
106                 retVal = tom_byte_read(address);
107         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
108                 retVal = jerry_byte_read(address);
109         else
110                 retVal = jaguar_unknown_readbyte(address);
111
112     return retVal;
113 }
114
115 void gpu_dump_disassembly(void);
116 void gpu_dump_registers(void);
117
118 unsigned int m68k_read_memory_16(unsigned int address)
119 {
120 //WriteLog( "[RM16] Addr: %08X\n", address);
121 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
122 //      for(int i=0; i<10000; i++)
123         WriteLog("[M68K] In routine #6!\n");//*/
124 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
125 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C)    // GPU Program #2
126 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8)    // GPU Program #3
127 {
128         WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, tom_word_read(address));
129         gpu_dump_registers();
130         gpu_dump_disassembly();
131 //      for(int i=0; i<10000; i++)
132 //              WriteLog( "[M68K] About to run GPU!\n");
133 }//*/
134 //WriteLog( "[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
135 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
136 {
137         if (address == 0x000066A0)
138         {
139                 gpu_dump_registers();
140                 gpu_dump_disassembly();
141         }
142         for(int i=0; i<10000; i++)
143                 WriteLog( "[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, tom_word_read(address));
144 }//*/
145     unsigned int retVal = 0;
146
147         if ((address >= 0x000000) && (address <= 0x3FFFFE))
148                 retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
149         else if ((address >= 0x800000) && (address <= 0xDFFFFE))
150                 retVal = (jaguar_mainRom[address - 0x800000] << 8) | jaguar_mainRom[address - 0x800000 + 1];
151         else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
152                 retVal = (jaguar_bootRom[address - 0xE00000] << 8) | jaguar_bootRom[address - 0xE00000 + 1];
153         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
154                 retVal = cdrom_word_read(address);
155         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
156                 retVal = tom_word_read(address);
157         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
158                 retVal = jerry_word_read(address);
159         else
160 //{
161 //WriteLog( "[RM16] Unknown address: %08X\n", address);
162                 retVal = jaguar_unknown_readword(address);
163 //}
164
165     return retVal;
166 }
167
168 unsigned int m68k_read_memory_32(unsigned int address)
169 {
170 //WriteLog( "--> [RM32]\n");
171     return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
172 }
173
174 void m68k_write_memory_8(unsigned int address, unsigned int value)
175 {
176 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
177 //      WriteLog("M68K: Writing %02X at %08X\n", value, address);
178 //WriteLog( "[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
179         if ((address >= 0x000000) && (address <= 0x3FFFFF))
180                 jaguar_mainRam[address] = value;
181         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
182                 cdrom_byte_write(address, value);
183         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
184                 tom_byte_write(address, value);
185         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
186                 jerry_byte_write(address, value);
187         else
188                 jaguar_unknown_writebyte(address, value);
189 }
190
191 void m68k_write_memory_16(unsigned int address, unsigned int value)
192 {
193 extern int dsp_pc;//, dsp_control;
194 if (address == 0xF1A116 && (value & 0x01))
195 {
196         WriteLog("  M68K(16): DSP is GO! (DSP_PC: %08X)\n\n", dsp_pc);
197
198 /*      static char buffer[512];
199         uint32 j = 0xF1B000;
200         while (j <= 0xF1BFFF)
201         {
202                 uint32 oldj = j;
203                 j += dasmjag(JAGUAR_DSP, buffer, j);
204                 WriteLog( "\t%08X: %s\n", oldj, buffer);
205         }
206         WriteLog( "\n");//*/
207 }
208 //else
209 //      WriteLog("M68K(16): DSP halted... (Old value: %08X)\n", dsp_control);
210
211 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
212 //      WriteLog("M68K: Writing %04X at %08X\n", value, address);
213 //WriteLog( "[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
214 //if (address >= 0xF02200 && address <= 0xF0229F)
215 //      WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
216         if ((address >= 0x000000) && (address <= 0x3FFFFE))
217         {
218                 jaguar_mainRam[address] = value >> 8;
219                 jaguar_mainRam[address + 1] = value & 0xFF;
220         }
221         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
222                 cdrom_word_write(address, value);
223         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
224                 tom_word_write(address, value);
225         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
226                 jerry_word_write(address, value);
227         else
228                 jaguar_unknown_writeword(address, value);
229 }
230
231 void m68k_write_memory_32(unsigned int address, unsigned int value)
232 {
233 extern int dsp_pc;//, dsp_control;
234 if (address == 0xF1A114 && (value & 0x01))
235         WriteLog("M68K(32): DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
236 //else
237 //      WriteLog("M68K(32): DSP halted... (Old value: %08X)\n", dsp_control);
238
239 //WriteLog( "--> [WM32]\n");
240         m68k_write_memory_16(address, value >> 16);
241         m68k_write_memory_16(address + 2, value & 0xFFFF);
242 }
243
244
245
246 uint32 jaguar_get_handler(uint32 i)
247 {
248 //      return (jaguar_word_read(i<<2) << 16) | jaguar_word_read((i<<2) + 2);
249 //      return (jaguar_word_read(i*4) << 16) | jaguar_word_read((i*4) + 2);
250         return jaguar_long_read(i * 4);
251 }
252
253 uint32 jaguar_interrupt_handler_is_valid(uint32 i)
254 {
255         uint32 handler = jaguar_get_handler(i);
256         if (handler && (handler != 0xFFFFFFFF))
257                 return 1;
258         else
259                 return 0;
260 }
261
262 void M68K_show_context(void)
263 {
264         WriteLog( "\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
265         for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
266                 WriteLog( "\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
267         WriteLog( "\n");
268         for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
269                 WriteLog( "\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
270
271         WriteLog( "68K disasm\n");
272 //      jaguar_dasm(s68000readPC()-0x1000,0x20000);
273         jaguar_dasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
274 //      jaguar_dasm(0x5000, 0x14414);
275         WriteLog( "..................\n");
276
277
278         if (tom_irq_enabled(IRQ_VBLANK))
279         {
280                 WriteLog( "vblank int: enabled\n");
281                 jaguar_dasm(jaguar_get_handler(64), 0x200);
282         }
283         else
284                 WriteLog( "vblank int: disabled\n");
285         WriteLog( "..................\n");
286
287         for(int i=0; i<256; i++)
288                 WriteLog( "handler %03i at $%08X\n", i, (unsigned int)jaguar_get_handler(i));
289 }
290
291 //
292 // Unknown read/write byte/word routines
293 //
294
295 void jaguar_unknown_writebyte(unsigned address, unsigned data)
296 {
297 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
298         WriteLog( "jaguar: unknown byte %02X write at %08X (PC=%06X)\n", data, address, m68k_get_reg(NULL, M68K_REG_PC));
299 #endif
300 }
301
302 void jaguar_unknown_writeword(unsigned address, unsigned data)
303 {
304 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
305         WriteLog( "jaguar: unknown word %04X write at %08X (PC=%06X)\n", data, address, m68k_get_reg(NULL, M68K_REG_PC));
306 #endif
307 }
308
309 unsigned jaguar_unknown_readbyte(unsigned address)
310 {
311 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
312         WriteLog( "jaguar: unknown byte read at %08X (PC=%06X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
313 #endif
314     return 0xFF;
315 }
316
317 unsigned jaguar_unknown_readword(unsigned address)
318 {
319 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
320         WriteLog( "Jaguar: Unknown word read at %08X (PC=%06X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
321 #endif
322     return 0xFFFF;
323 }
324
325 //
326 // Disassemble M68K instructions at the given offset
327 //
328
329 unsigned int m68k_read_disassembler_8(unsigned int address)
330 {
331         return m68k_read_memory_8(address);
332 }
333
334 unsigned int m68k_read_disassembler_16(unsigned int address)
335 {
336         return m68k_read_memory_16(address);
337 }
338
339 unsigned int m68k_read_disassembler_32(unsigned int address)
340 {
341         return m68k_read_memory_32(address);
342 }
343
344 void jaguar_dasm(uint32 offset, uint32 qt)
345 {
346 #ifdef CPU_DEBUG
347         static char buffer[2048];//, mem[64];
348         int pc = offset, oldpc;
349
350         for(uint32 i=0; i<qt; i++)
351         {
352                 oldpc = pc;
353 //              for(int j=0; j<64; j++)
354 //                      mem[j^0x01] = jaguar_byte_read(pc + j);
355
356 //              pc += Dasm68000((char *)mem, buffer, 0);
357                 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
358                 WriteLog("%08X: %s\n", oldpc, buffer);
359         }
360 #endif
361 }
362
363 unsigned jaguar_byte_read(unsigned int offset)
364 {
365         uint8 data = 0x00;
366
367         offset &= 0xFFFFFF;
368         if (offset < 0x400000)
369 //              data = (jaguar_mainRam[(offset^0x01) & 0x3FFFFF]);
370                 data = jaguar_mainRam[offset & 0x3FFFFF];
371         else if ((offset >= 0x800000) && (offset < 0xC00000))
372 //              data = (jaguar_mainRom[(offset^0x01)-0x800000]);
373                 data = jaguar_mainRom[offset - 0x800000];
374 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
375         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
376                 data = cdrom_byte_read(offset);
377         else if ((offset >= 0xE00000) && (offset < 0xE40000))
378 //              data = (jaguar_bootRom[(offset^0x01) & 0x3FFFF]);
379                 data = jaguar_bootRom[offset & 0x3FFFF];
380         else if ((offset >= 0xF00000) && (offset < 0xF10000))
381                 data = tom_byte_read(offset);
382         else if ((offset >= 0xF10000) && (offset < 0xF20000))
383                 data = jerry_byte_read(offset);
384         else
385                 data = jaguar_unknown_readbyte(offset);
386
387         return data;
388 }
389
390 unsigned jaguar_word_read(unsigned int offset)
391 {
392 //TEMP--Mirror of F03000?
393 /*if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
394 WriteLog( "[JWR16] --> Possible GPU RAM mirror access! [%08X]\n", offset);//*/
395
396         offset &= 0xFFFFFF;
397         if (offset <= 0x3FFFFE)
398         {
399 //              return (jaguar_mainRam[(offset+1) & 0x3FFFFF] << 8) | jaguar_mainRam[(offset+0) & 0x3FFFFF];
400                 return (jaguar_mainRam[(offset+0) & 0x3FFFFF] << 8) | jaguar_mainRam[(offset+1) & 0x3FFFFF];
401         }
402         else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
403         {
404                 offset -= 0x800000;
405 //              return (jaguar_mainRom[offset+1] << 8) | jaguar_mainRom[offset+0];
406                 return (jaguar_mainRom[offset+0] << 8) | jaguar_mainRom[offset+1];
407         }
408 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
409         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
410                 return cdrom_word_read(offset);
411         else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
412 //              return *((uint16 *)&jaguar_bootRom[offset & 0x3FFFF]);
413                 return (jaguar_bootRom[(offset+0) & 0x3FFFF] << 8) | jaguar_bootRom[(offset+1) & 0x3FFFF];
414         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
415                 return tom_word_read(offset);
416         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
417 //{
418 //WriteLog("Reading from JERRY offset %08X...\n", offset);
419                 return jerry_word_read(offset);
420 //}
421
422         return jaguar_unknown_readword(offset);
423 }
424
425 void jaguar_byte_write(unsigned offset, unsigned data)
426 {
427         offset &= 0xFFFFFF;
428         if (offset < 0x400000)
429         {
430 //              jaguar_mainRam[(offset^0x01) & 0x3FFFFF] = data;
431                 jaguar_mainRam[offset & 0x3FFFFF] = data;
432                 return;
433         }
434 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
435         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
436         {
437                 cdrom_byte_write(offset, data);
438                 return;
439         }
440         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
441         {
442                 tom_byte_write(offset, data);
443                 return;
444         }
445         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
446         {
447                 jerry_byte_write(offset, data);
448                 return;
449         }
450     
451         jaguar_unknown_writebyte(offset, data);
452 }
453
454 void jaguar_word_write(unsigned offset, unsigned data)
455 {
456 extern int dsp_pc;//, dsp_control;
457 if (offset == 0xF1A116 && (data & 0x01))
458         WriteLog("  JagWW: DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
459 //else
460 //      WriteLog("JagWW: DSP halted... (Old value: %08X)\n", dsp_control);
461
462 //extern int blit_start_log;
463 //if (blit_start_log)
464 /*{
465         if (offset == 0x0674DE)
466                 WriteLog( "[JWW16] Bad write starting @ 0674DE! [%04X]\n", data);
467 }//*/
468 //TEMP--Mirror of F03000?
469 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
470 //WriteLog( "[JWW16] --> Possible GPU RAM mirror access! [%08X]", offset);
471 //if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
472 //      WriteLog("JagWW: Writing %04X at %08X\n", data, offset);
473         offset &= 0xFFFFFF;
474         
475         if (offset <= 0x3FFFFE)
476         {
477 //              jaguar_mainRam[(offset+0) & 0x3FFFFF] = data & 0xFF;
478 //              jaguar_mainRam[(offset+1) & 0x3FFFFF] = (data>>8) & 0xFF;
479                 jaguar_mainRam[(offset+0) & 0x3FFFFF] = (data>>8) & 0xFF;
480                 jaguar_mainRam[(offset+1) & 0x3FFFFF] = data & 0xFF;
481                 return;
482         }
483         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
484         {
485                 cdrom_word_write(offset, data);
486                 return;
487         }
488         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
489         {
490                 tom_word_write(offset, data);
491                 return;
492         }
493         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
494         {
495                 jerry_word_write(offset, data);
496                 return;
497         }
498     
499         jaguar_unknown_writeword(offset, data);
500 }
501
502 unsigned jaguar_long_read(unsigned int offset)
503 {
504 /*      uint32 data = jaguar_word_read(offset);
505         data = (data<<16) | jaguar_word_read(offset+2);
506         return data;*/
507         return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
508 }
509
510 void jaguar_long_write(unsigned offset, unsigned data)
511 {
512 extern int dsp_pc;//, dsp_control;
513 if (offset == 0xF1A114 && (data & 0x01))
514         WriteLog("JagLW: DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
515 //else
516 //      WriteLog("JagLW: DSP halted... (Old value: %08X)\n", dsp_control);
517
518 //extern int effect_start;
519 // $10, $0C, $0A, $09 too much, $08 too little...
520 //if (effect_start && offset == 0xF03000) data = (data & 0xFFFF0000) | (((data & 0xFFFF) + 0x0008) & 0xFFFF);
521 //Doesn't work--offsets horizontally if (effect_start && offset == 0xF03004) data -= (0x300 * 8); // one line is $300
522 //if (effect_start && offset == 0xF03000) data = 0x00000000;    // Let's try making the top/bottom *always* 0!
523 //Interesting: it seems to pin half of the screen down (but too low)...
524 //Definitely the fine scroll offsets (for left side of screen)...
525
526 //if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
527 //      WriteLog("JagLW: Writing %08X at %08X\n", data, offset);
528         jaguar_word_write(offset, data >> 16);
529         jaguar_word_write(offset+2, data & 0xFFFF);
530 }
531
532 //
533 // Jaguar initialization
534 //
535
536 //void jaguar_init(const char * filename)
537 void jaguar_init(void)
538 {
539 //      uint32 romsize;
540
541         jaguar_screen_scanlines = 525;                  // PAL screen size
542         m68k_cycles_per_scanline = 13300000 / (jaguar_screen_scanlines * 60);
543         gpu_cycles_per_scanline = (26591000 / 4) / (jaguar_screen_scanlines * 60);
544         dsp_cycles_per_scanline = (26591000 / 4) / (jaguar_screen_scanlines * 60);
545
546         memory_malloc_secure((void **)&jaguar_mainRam, 0x400000, "Jaguar 68K CPU RAM");
547         memory_malloc_secure((void **)&jaguar_bootRom, 0x040000, "Jaguar 68K CPU BIOS ROM");
548         memory_malloc_secure((void **)&jaguar_mainRom, 0x600000, "Jaguar 68K CPU ROM");
549         memset(jaguar_mainRam, 0x00, 0x400000);
550 //      memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
551         memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
552
553 //      jaguar_rom_load_to(jaguar_bootRom, jaguar_bootRom_path, &romsize);
554 //      memcpy(jaguar_mainRam, jaguar_bootRom, 8);
555 //      SET32(jaguar_mainRam, 0, 0x00200000);
556
557 #ifdef JAGUAR_WIP_RELEASE
558 //      strcpy(romLoadDialog_filePath, filename);
559 //      jaguar_load_cart(romLoadDialog_filePath, jaguar_mainRom, 0x0000, 0x00802000, 0);
560
561         if ((jaguar_mainRom_crc32 == 0x3966698f) || (jaguar_mainRom_crc32 == 0x5e705756)
562                 || (jaguar_mainRom_crc32 == 0x2630cbc4) || (jaguar_mainRom_crc32 == 0xd46437e8)
563                 || (jaguar_mainRom_crc32 == 0x2630cbc4))
564                 dsp_enabled = true;
565
566         if ((jaguar_mainRom_crc32 == 0x6e90989f) || (jaguar_mainRom_crc32 == 0xfc8f0dcd)
567                 || (jaguar_mainRom_crc32 == 0x2a512a83) || (jaguar_mainRom_crc32 == 0x41307601)
568                 || (jaguar_mainRom_crc32 == 0x3c7bfda8) || (jaguar_mainRom_crc32 == 0x5e705756))
569                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
570
571         if (jaguar_mainRom_crc32 == 0x7ae20823)
572         {
573                 dsp_enabled = true;
574                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
575                 dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
576         }
577         if (jaguar_mainRom_crc32 == 0xe21d0e2f)
578         {
579                 dsp_enabled = true;
580                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
581                 dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
582         }
583         if (jaguar_mainRom_crc32 == 0x66f8914c)
584         {
585                 gpu_cycles_per_scanline = (26591000 / 1) /(jaguar_screen_scanlines * 60);
586         }
587         if (jaguar_mainRom_crc32 == 0x5a5b9c68)
588         {
589                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
590         }
591         if (jaguar_mainRom_crc32 == 0xdcb0197a)
592         {
593                 dsp_enabled = false; // dsp not needed
594                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
595                 //dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
596         }
597         if ((jaguar_mainRom_crc32 == 0x3966698f) || (jaguar_mainRom_crc32 == 0xe21d0e2f))
598                 dsp_enabled = true;
599         if (jaguar_mainRom_crc32 == 0x5e705756)
600         {
601                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
602                 dsp_enabled = true;
603         }
604         if (jaguar_mainRom_crc32 == 0x2630cbc4)
605         {
606                 // ultra vortek
607                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
608                 dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
609                 dsp_enabled = true;
610         }
611         if ((jaguar_mainRom_crc32 == 0xd46437e8) || (jaguar_mainRom_crc32 == 0xba74c3ed))
612         {
613                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
614                 dsp_enabled = true;
615         }
616         if (jaguar_mainRom_crc32 == 0x6e90989f)
617                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
618
619         if (jaguar_mainRom_crc32 == 0x41307601)
620         {
621                 gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
622         }
623
624         if (jaguar_mainRom_crc32 == 0x8483392b)
625         {
626                 dsp_enabled = true;
627         }
628
629 #else   // #ifdef JAGUAR_WIP_RELEASE
630 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/flashback.jag",jaguar_mainRom,0x0000, 0x20000080,0);
631 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Pinball Fantasies.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
632 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/alien vs predator (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
633 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/cannon fodder (1995) (computer west).jag",jaguar_mainRom,0x0000, 0x20000080,0);
634 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/double dragon v (1995) (williams).jag",jaguar_mainRom,0x0000, 0x20000080,0);
635 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Dragon - The Bruce Lee Story.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
636 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Syndicate.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
637 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Theme Park.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
638 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Brutal Sports Football.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
639 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/International Sensible Soccer.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
640 //  jaguar_load_cart("C:/ftp/jaguar/roms/roms/Defender 2000.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
641 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Fever Pitch Soccer.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
642 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Rayman.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
643 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Tempest 2000.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
644 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/zool 2 (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
645 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Bubsy - Fractured Furry Tails.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
646 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Raiden.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
647 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Dino Olympics.jag",jaguar_mainRom,0x0000, 0x20000080,0);
648 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/I-War.jag",jaguar_mainRom,0x0000, 0x20000080,0);
649 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Attack of the Mutant Penguins.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
650 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Cybermorph.jag",jaguar_mainRom,0x0000, 0x20000080,0);
651 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Troy Aikman NFL Football (1995) (Williams).jag",jaguar_mainRom,0x0000, 0x20000080,0);
652 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Power Drive Rally (1995) (TWI).jag",jaguar_mainRom,0x0000, 0x20000080,0);
653 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Zoop! (1996).jag",jaguar_mainRom,0x0000, 0x20000080,0);
654 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Missile Command 3D.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
655 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Hover Strike.jag",jaguar_mainRom,0x0000, 0x20000080,0);
656 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/worms.bin",jaguar_mainRom,0x0000, 0x20000080,0);
657 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Atari Kart.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
658 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/native.bin",jaguar_mainRam,0x5000, 0x50000000,0x00);
659
660         if (jaguar_mainRom_crc32==0xe21d0e2f)
661         {
662                 dsp_enabled=true;
663                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
664                 dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
665         }
666         if (jaguar_mainRom_crc32==0x66f8914c)
667         {
668                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
669         }
670         if (jaguar_mainRom_crc32==0x5a5b9c68)
671         {
672                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
673         }
674 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Super Cross 3D.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
675         if (jaguar_mainRom_crc32==0xdcb0197a)
676         {
677                 dsp_enabled=true; // dsp not needed
678                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
679                 //dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
680         }
681 //  jaguar_load_cart("C:/ftp/jaguar/roms/roms/wolfenstein 3d (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
682         if ((jaguar_mainRom_crc32==0x3966698f)||(jaguar_mainRom_crc32==0xe21d0e2f))
683                 dsp_enabled=true;
684 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/NBA JAM.jag",jaguar_mainRom,0x0000, 0x20000080,0);
685 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Doom - Evil Unleashed.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
686         if (jaguar_mainRom_crc32==0x5e705756)
687         {
688                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
689                 dsp_enabled=true;
690         }
691 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Ultra Vortek.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
692         if (jaguar_mainRom_crc32==0x2630cbc4)
693         {
694                 // ultra vortek
695                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
696                 dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
697                 dsp_enabled=true; 
698         }
699 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/fflbeta.rom",jaguar_mainRom,0x0000, 0x20000080,0);
700 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Fight for Your Life.jag",jaguar_mainRom,0x0000, 0x20000080,0);
701         if ((jaguar_mainRom_crc32==0xd46437e8)||(jaguar_mainRom_crc32==0xba74c3ed))
702         {
703                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
704 //              dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
705                 dsp_enabled=true;
706         }
707 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Pitfall - The Mayan Adventure.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
708         if (jaguar_mainRom_crc32==0x6e90989f)
709                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
710
711 // missing some sprites
712 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Crescent Galaxy.jag",jaguar_mainRom,0x0000, 0x20000080,0);
713         if (jaguar_mainRom_crc32==0x41307601)
714         {
715                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
716         }
717
718 // missing vertical bar shades  
719 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Phase Zero (2000) (PD).rom",jaguar_mainRom,0x0000, 0x20000080,0);
720         if (jaguar_mainRom_crc32==0x8483392b)
721         {
722                 dsp_enabled=true;
723         }
724 // cpu/dsp/gpu synchronization problems
725
726
727 // locks up during the game
728 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Club Drive.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
729
730 // no parallax floor, locks up at the start of the game 
731 // jaguar_load_cart("C:/ftp/jaguar/roms/roms/Kasumi Ninja.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
732
733 // displaying the sound control dialog. no way to exit from it  
734 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Checkered Flag.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
735
736 // no 3d        
737 //  jaguar_load_cart("C:/ftp/jaguar/roms/roms/Iron Soldier.jag",jaguar_mainRom,0x0000, 0x20000080,0);
738
739 // locks up at the start of the game
740 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Super Burnout.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
741         if (jaguar_mainRom_crc32==0x20ae75f4)
742         {
743                 dsp_enabled=true;
744                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
745                 dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
746         }
747 // locks up at the start of the game    
748 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Val D'Isere Skiing & Snowboarding (1994).jag",jaguar_mainRom,0x0000, 0x20000080,0);
749         if (jaguar_mainRom_crc32==0x4664ebd1)
750         {
751                 dsp_enabled=true;
752         }
753
754 // fonctionne avec le gpu et le dsp activés et gpu à frequence nominale, et dsp à 1/4 de la frequence nominale
755 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/white men can't jump (1995).jag",jaguar_mainRom,0x0000, 0x20000080,0);
756         if (jaguar_mainRom_crc32==0x7ae20823)
757         {
758                 dsp_enabled=true;
759                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
760         }
761 // not working at all
762 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/Flip Out.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
763         if (jaguar_mainRom_crc32==0x6f57dcd2)
764         {
765                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
766                 dsp_enabled=false;
767
768         }
769
770         jaguar_load_cart("C:/ftp/jaguar/roms/roms/Ruiner.JAG",jaguar_mainRom,0x0000, 0x20000080,0);
771         if (jaguar_mainRom_crc32==0x6a7c7430)
772         {
773                 dsp_enabled=true;
774         }
775
776         if (jaguar_mainRom_crc32==0x2f032271)
777         {
778                 dsp_enabled=true;
779                 dsp_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
780                 gpu_cycles_per_scanline=(26591000/1) /((jaguar_screen_scanlines)*60);
781         }
782 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/tetris.bin",jaguar_mainRam,0x4fe4, 0x50000000,0x00);
783 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/painter.bin",jaguar_mainRam,0xffe4, 0x00000001,0x00);
784 //      jaguar_load_cart("./roms/jagcd.rom",jaguar_mainRom,0x0000, 0x20000080,0);
785
786 //      jaguar_load_cart("cart.jag",jaguar_mainRom,0x0000, 0x20000080,0);
787
788         
789 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\Brain Dead 13.cdi");
790 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\baldies.cdi");
791 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\mystdemo.cdi");
792 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\battlemorph.cdi");
793 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\primalrage.cdi");
794 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\Dragons Lair.cdi");
795
796 //      jaguar_load_cart("C:/ftp/jaguar/roms/roms/raw.jag",jaguar_mainRam,0x4000, 0x40000000,0x00);
797 #endif  // #ifdef JAGUAR_WIP_RELEASE
798
799 #ifdef JAGUAR_REAL_SPEED
800         gpu_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
801         dsp_cycles_per_scanline = (26591000 / 1) / (jaguar_screen_scanlines * 60);
802 #endif
803 #ifdef SOUND_OUTPUT
804         ws_audio_init();
805 #endif
806
807         m68k_set_cpu_type(M68K_CPU_TYPE_68000);
808         gpu_init();
809         dsp_init();
810         tom_init();
811         jerry_init();
812         cdrom_init();
813 }
814
815 void jaguar_done(void)
816 {
817 //#ifdef CPU_DEBUG
818 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
819 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
820         uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
821         WriteLog("M68K: Top of stack: %08X. Stack trace:\n", jaguar_long_read(topOfStack));
822         for(int i=0; i<10; i++)
823                 WriteLog("%06X: %08X\n", topOfStack - (i * 4), jaguar_long_read(topOfStack - (i * 4)));
824 //      WriteLog("Jaguar: CD BIOS version %04X\n", jaguar_word_read(0x3004));
825         WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
826         M68K_show_context();
827 //#endif
828 #ifdef SOUND_OUTPUT
829         ws_audio_done();
830 #endif
831         cd_bios_done();
832         cdrom_done();
833         tom_done();
834         jerry_done();
835         memory_free(jaguar_mainRom);
836         memory_free(jaguar_bootRom);
837         memory_free(jaguar_mainRam);
838 }
839
840 void jaguar_reset(void)
841 {
842         if (jaguar_use_bios)
843                 memcpy(jaguar_mainRam, jaguar_bootRom, 8);
844         else
845         {
846                 SET32(jaguar_mainRam, 4, 0x00802000);
847                 // Handle PD stuff...
848                 // This should definitely go elsewhere (like in the cart load section)!
849                 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
850                 {
851                         uint32 runAddress = GET32(jaguar_mainRom, 0x2A);
852                         uint32 progLength = GET32(jaguar_mainRom, 0x02);
853                         WriteLog("Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
854                         memcpy(jaguar_mainRam + runAddress, jaguar_mainRom + 0x2E, progLength);
855                         SET32(jaguar_mainRam, 4, runAddress);
856                 }
857         }
858
859 //      WriteLog("jaguar_reset():\n");
860 #ifdef SOUND_OUTPUT
861         ws_audio_reset();
862 #endif
863         cd_bios_reset();
864         tom_reset();
865         jerry_reset();
866         gpu_reset();
867         dsp_reset();
868         cdrom_reset();
869     m68k_pulse_reset();                         // Reset the 68000
870         WriteLog( "\t68K PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
871 }
872
873 void jaguar_reset_handler(void)
874 {
875 }
876
877 void jaguar_exec(int16 * backbuffer, bool render)
878
879         uint32 i, vblank_duration = tom_get_vdb();
880
881         // vblank
882         if ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64)))
883         {
884                 if (jaguar_word_read(0xF0004E) != 0xFFFF)
885                 {
886                         tom_set_pending_video_int();
887 //                      s68000interrupt(7, IRQ_VBLANK+64);
888 //                      s68000flushInterrupts();
889                         m68k_set_irq(7);                                        // IRQ_VBLANK+64??? Not autovectored??? No.
890 // Could set a global variable here, to signal that this is a VBLANK interrupt...
891 // Then again, since IRQ_VBLANK is set to zero, this would not be necessary in this case.
892                 }
893         }
894
895         for(i=0; i<vblank_duration; i++)
896         {
897 /*              uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
898                 if (invalid_instruction_address != 0x80000000)
899                         cd_bios_process(invalid_instruction_address);*/
900                 m68k_execute(m68k_cycles_per_scanline);
901                 // No CD handling... !!! FIX !!!
902
903                 cd_bios_exec(i);
904                 tom_pit_exec(m68k_cycles_per_scanline);
905                 tom_exec_scanline(backbuffer, i, false);
906                 jerry_pit_exec(m68k_cycles_per_scanline);
907                 jerry_i2s_exec(m68k_cycles_per_scanline);
908                 gpu_exec(gpu_cycles_per_scanline);
909                 if (dsp_enabled)
910                         dsp_exec(dsp_cycles_per_scanline);
911         }
912         
913         for (; i<jaguar_screen_scanlines; i++)
914         {
915 /*              uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
916                 if (invalid_instruction_address != 0x80000000)
917                         cd_bios_process(invalid_instruction_address);*/
918                 m68k_execute(m68k_cycles_per_scanline);
919                 // No CD handling... !!! FIX !!!
920                 cd_bios_exec(i);
921                 tom_pit_exec(m68k_cycles_per_scanline);
922                 jerry_pit_exec(m68k_cycles_per_scanline);
923                 jerry_i2s_exec(m68k_cycles_per_scanline);
924                 tom_exec_scanline(backbuffer, i, render);
925                 gpu_exec(gpu_cycles_per_scanline);
926                 if (dsp_enabled)
927                         dsp_exec(dsp_cycles_per_scanline);
928                 backbuffer += tom_width;
929         }
930 #ifdef SOUND_OUTPUT
931         system_sound_update();
932 #endif
933 }
934
935 // Temp debugging stuff
936
937 void DumpMainMemory(void)
938 {
939         FILE * fp = fopen("./memdump.bin", "wb");
940
941         if (fp == NULL)
942                 return;
943
944         fwrite(jaguar_mainRam, 1, 0x400000, fp);
945         fclose(fp);
946 }
947
948 uint8 * GetRamPtr(void)
949 {
950         return jaguar_mainRam;
951 }