]> Shamusworld >> Repos - virtualjaguar/blob - src/jaguar.cpp
Changes mainly to support the removal of SDLptc.h
[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
14 //#define LOG_UNMAPPED_MEMORY_ACCESSES
15 //#define SOUND_OUTPUT
16 #define CPU_DEBUG
17 #define JAGUAR_WIP_RELEASE
18 //Do this in makefile??? Yes! Could, but it's easier to define here...
19 //#define LOG_UNMAPPED_MEMORY_ACCESSES
20
21 // Private function prototypes
22
23 unsigned jaguar_unknown_readbyte(unsigned address);
24 unsigned jaguar_unknown_readword(unsigned address);
25 void jaguar_unknown_writebyte(unsigned address, unsigned data);
26 void jaguar_unknown_writeword(unsigned address, unsigned data);
27 void M68K_show_context(void);
28
29 // External variables
30
31 extern bool hardwareTypeNTSC;                           // Set to false for PAL
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 void M68KInstructionHook(void)
55 {
56         uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
57
58 /*      static char buffer[2048];
59         m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
60         WriteLog("%08X: %s \t\tD0=%08X, A0=%08X\n", m68kPC, buffer, m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_A0));//*/
61
62 /*      if (m68kPC == 0x803F16)
63         {
64                 WriteLog("M68K: Registers found at $803F16:\n");
65                 WriteLog( "\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
66                 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
67                         WriteLog( "\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
68                 WriteLog( "\n");
69                 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
70                         WriteLog( "\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
71         }*/
72
73         if (!m68k_is_valid_instruction(jaguar_word_read(m68kPC), M68K_CPU_TYPE_68000))
74         {
75                 WriteLog("\nEncountered illegal instruction at %08X!!!\n\nAborting!\n", m68kPC);
76                 uint32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
77                 WriteLog("M68K: Top of stack: %08X. Stack trace:\n", jaguar_long_read(topOfStack));
78                 for(int i=0; i<10; i++)
79                         WriteLog("%06X: %08X\n", topOfStack - (i * 4), jaguar_long_read(topOfStack - (i * 4)));
80                 WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
81                 M68K_show_context();
82                 log_done();
83                 exit(0);
84         }
85 }
86
87 //
88 // Musashi 68000 read/write/IRQ functions
89 //
90
91 int irq_ack_handler(int level)
92 {
93         int vector = M68K_INT_ACK_AUTOVECTOR;
94
95         // The GPU/DSP/etc are probably *not* issuing an NMI, but it seems to work OK...
96
97         if (level == 7)
98         {
99                 m68k_set_irq(0);                                                // Clear the IRQ...
100                 vector = 64;                                                    // Set user interrupt #0
101         }
102
103         return vector;
104 }
105
106 unsigned int m68k_read_memory_8(unsigned int address)
107 {
108 //WriteLog( "[RM8] Addr: %08X\n", address);
109         unsigned int retVal = 0;
110
111         if ((address >= 0x000000) && (address <= 0x3FFFFF))
112                 retVal = jaguar_mainRam[address];
113         else if ((address >= 0x800000) && (address <= 0xDFFFFF))
114                 retVal = jaguar_mainRom[address - 0x800000];
115         else if ((address >= 0xE00000) && (address <= 0xE3FFFF))
116                 retVal = jaguar_bootRom[address - 0xE00000];
117         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
118                 retVal = cdrom_byte_read(address);
119         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
120                 retVal = tom_byte_read(address);
121         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
122                 retVal = jerry_byte_read(address);
123         else
124                 retVal = jaguar_unknown_readbyte(address);
125
126     return retVal;
127 }
128
129 void gpu_dump_disassembly(void);
130 void gpu_dump_registers(void);
131
132 unsigned int m68k_read_memory_16(unsigned int address)
133 {
134 //WriteLog( "[RM16] Addr: %08X\n", address);
135 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
136 //      for(int i=0; i<10000; i++)
137         WriteLog("[M68K] In routine #6!\n");//*/
138 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
139 //if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C)    // GPU Program #2
140 /*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8)    // GPU Program #3
141 {
142         WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, tom_word_read(address));
143         gpu_dump_registers();
144         gpu_dump_disassembly();
145 //      for(int i=0; i<10000; i++)
146 //              WriteLog( "[M68K] About to run GPU!\n");
147 }//*/
148 //WriteLog( "[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
149 /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
150 {
151         if (address == 0x000066A0)
152         {
153                 gpu_dump_registers();
154                 gpu_dump_disassembly();
155         }
156         for(int i=0; i<10000; i++)
157                 WriteLog( "[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, tom_word_read(address));
158 }//*/
159     unsigned int retVal = 0;
160
161         if ((address >= 0x000000) && (address <= 0x3FFFFE))
162                 retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
163         else if ((address >= 0x800000) && (address <= 0xDFFFFE))
164                 retVal = (jaguar_mainRom[address - 0x800000] << 8) | jaguar_mainRom[address - 0x800000 + 1];
165         else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
166                 retVal = (jaguar_bootRom[address - 0xE00000] << 8) | jaguar_bootRom[address - 0xE00000 + 1];
167         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
168                 retVal = cdrom_word_read(address);
169         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
170                 retVal = tom_word_read(address);
171         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
172                 retVal = jerry_word_read(address);
173         else
174 //{
175 //WriteLog( "[RM16] Unknown address: %08X\n", address);
176                 retVal = jaguar_unknown_readword(address);
177 //}
178
179     return retVal;
180 }
181
182 unsigned int m68k_read_memory_32(unsigned int address)
183 {
184 //WriteLog( "--> [RM32]\n");
185     return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
186 }
187
188 void m68k_write_memory_8(unsigned int address, unsigned int value)
189 {
190 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
191 //      WriteLog("M68K: Writing %02X at %08X\n", value, address);
192 //WriteLog( "[WM8  PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
193         if ((address >= 0x000000) && (address <= 0x3FFFFF))
194                 jaguar_mainRam[address] = value;
195         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
196                 cdrom_byte_write(address, value);
197         else if ((address >= 0xF00000) && (address <= 0xF0FFFF))
198                 tom_byte_write(address, value);
199         else if ((address >= 0xF10000) && (address <= 0xF1FFFF))
200                 jerry_byte_write(address, value);
201         else
202                 jaguar_unknown_writebyte(address, value);
203 }
204
205 void m68k_write_memory_16(unsigned int address, unsigned int value)
206 {
207 extern int dsp_pc;//, dsp_control;
208 if (address == 0xF1A116 && (value & 0x01))
209 {
210         WriteLog("  M68K(16): DSP is GO! (DSP_PC: %08X)\n\n", dsp_pc);
211
212 /*      static char buffer[512];
213         uint32 j = 0xF1B000;
214         while (j <= 0xF1BFFF)
215         {
216                 uint32 oldj = j;
217                 j += dasmjag(JAGUAR_DSP, buffer, j);
218                 WriteLog( "\t%08X: %s\n", oldj, buffer);
219         }
220         WriteLog( "\n");//*/
221 }
222 //else
223 //      WriteLog("M68K(16): DSP halted... (Old value: %08X)\n", dsp_control);
224
225 //if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
226 //      WriteLog("M68K: Writing %04X at %08X\n", value, address);
227 //WriteLog( "[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
228 //if (address >= 0xF02200 && address <= 0xF0229F)
229 //      WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
230 //if (address >= 0x0E75D0 && address <= 0x0E75E7)
231 //      WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
232 /*extern uint32 totalFrames;
233 extern bool suppressOutput;
234 if (totalFrames >= 59)
235         suppressOutput = false;//*/
236 /*if (address == 0xF02114)
237         WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
238 if (address == 0xF02110)
239         WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
240 //if (address >= 0xF03B00 && address <= 0xF03DFF)
241 //      WriteLog("M68K: Writing %04X to %08X...\n", value, address);
242
243         if ((address >= 0x000000) && (address <= 0x3FFFFE))
244         {
245                 jaguar_mainRam[address] = value >> 8;
246                 jaguar_mainRam[address + 1] = value & 0xFF;
247         }
248         else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
249                 cdrom_word_write(address, value);
250         else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
251                 tom_word_write(address, value);
252         else if ((address >= 0xF10000) && (address <= 0xF1FFFE))
253                 jerry_word_write(address, value);
254         else
255                 jaguar_unknown_writeword(address, value);
256 }
257
258 void m68k_write_memory_32(unsigned int address, unsigned int value)
259 {
260 extern int dsp_pc;//, dsp_control;
261 if (address == 0xF1A114 && (value & 0x01))
262         WriteLog("M68K(32): DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
263 //else
264 //      WriteLog("M68K(32): DSP halted... (Old value: %08X)\n", dsp_control);
265
266 //WriteLog( "--> [WM32]\n");
267         m68k_write_memory_16(address, value >> 16);
268         m68k_write_memory_16(address + 2, value & 0xFFFF);
269 }
270
271
272
273 uint32 jaguar_get_handler(uint32 i)
274 {
275 //      return (jaguar_word_read(i<<2) << 16) | jaguar_word_read((i<<2) + 2);
276 //      return (jaguar_word_read(i*4) << 16) | jaguar_word_read((i*4) + 2);
277         return jaguar_long_read(i * 4);
278 }
279
280 uint32 jaguar_interrupt_handler_is_valid(uint32 i)
281 {
282         uint32 handler = jaguar_get_handler(i);
283         if (handler && (handler != 0xFFFFFFFF))
284                 return 1;
285         else
286                 return 0;
287 }
288
289 void M68K_show_context(void)
290 {
291         WriteLog( "\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
292         for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
293                 WriteLog( "\tD%i = %08X\n", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
294         WriteLog( "\n");
295         for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
296                 WriteLog( "\tA%i = %08X\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
297
298         WriteLog( "68K disasm\n");
299 //      jaguar_dasm(s68000readPC()-0x1000,0x20000);
300         jaguar_dasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
301 //      jaguar_dasm(0x5000, 0x14414);
302
303         WriteLog( "..................\n");
304
305         if (tom_irq_enabled(IRQ_VBLANK))
306         {
307                 WriteLog( "vblank int: enabled\n");
308                 jaguar_dasm(jaguar_get_handler(64), 0x200);
309         }
310         else
311                 WriteLog( "vblank int: disabled\n");
312
313         WriteLog( "..................\n");
314
315         for(int i=0; i<256; i++)
316                 WriteLog( "handler %03i at $%08X\n", i, (unsigned int)jaguar_get_handler(i));
317 }
318
319 //
320 // Unknown read/write byte/word routines
321 //
322
323 void jaguar_unknown_writebyte(unsigned address, unsigned data)
324 {
325 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
326         WriteLog( "jaguar: unknown byte %02X write at %08X (PC=%06X)\n", data, address, m68k_get_reg(NULL, M68K_REG_PC));
327 #endif
328 }
329
330 void jaguar_unknown_writeword(unsigned address, unsigned data)
331 {
332 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
333         WriteLog( "jaguar: unknown word %04X write at %08X (PC=%06X)\n", data, address, m68k_get_reg(NULL, M68K_REG_PC));
334 #endif
335 }
336
337 unsigned jaguar_unknown_readbyte(unsigned address)
338 {
339 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
340         WriteLog( "jaguar: unknown byte read at %08X (PC=%06X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
341 #endif
342     return 0xFF;
343 }
344
345 unsigned jaguar_unknown_readword(unsigned address)
346 {
347 #ifdef LOG_UNMAPPED_MEMORY_ACCESSES
348         WriteLog( "Jaguar: Unknown word read at %08X (PC=%06X)\n", address, m68k_get_reg(NULL, M68K_REG_PC));
349 #endif
350     return 0xFFFF;
351 }
352
353 //
354 // Disassemble M68K instructions at the given offset
355 //
356
357 unsigned int m68k_read_disassembler_8(unsigned int address)
358 {
359         return m68k_read_memory_8(address);
360 }
361
362 unsigned int m68k_read_disassembler_16(unsigned int address)
363 {
364         return m68k_read_memory_16(address);
365 }
366
367 unsigned int m68k_read_disassembler_32(unsigned int address)
368 {
369         return m68k_read_memory_32(address);
370 }
371
372 void jaguar_dasm(uint32 offset, uint32 qt)
373 {
374 #ifdef CPU_DEBUG
375         static char buffer[2048];//, mem[64];
376         int pc = offset, oldpc;
377
378         for(uint32 i=0; i<qt; i++)
379         {
380 /*              oldpc = pc;
381                 for(int j=0; j<64; j++)
382                         mem[j^0x01] = jaguar_byte_read(pc + j);
383
384                 pc += Dasm68000((char *)mem, buffer, 0);
385                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
386                 oldpc = pc;
387                 pc += m68k_disassemble(buffer, pc, M68K_CPU_TYPE_68000);
388                 WriteLog("%08X: %s\n", oldpc, buffer);//*/
389         }
390 #endif
391 }
392
393 unsigned jaguar_byte_read(unsigned int offset)
394 {
395         uint8 data = 0x00;
396
397         offset &= 0xFFFFFF;
398         if (offset < 0x400000)
399 //              data = (jaguar_mainRam[(offset^0x01) & 0x3FFFFF]);
400                 data = jaguar_mainRam[offset & 0x3FFFFF];
401         else if ((offset >= 0x800000) && (offset < 0xC00000))
402 //              data = (jaguar_mainRom[(offset^0x01)-0x800000]);
403                 data = jaguar_mainRom[offset - 0x800000];
404 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
405         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
406                 data = cdrom_byte_read(offset);
407         else if ((offset >= 0xE00000) && (offset < 0xE40000))
408 //              data = (jaguar_bootRom[(offset^0x01) & 0x3FFFF]);
409                 data = jaguar_bootRom[offset & 0x3FFFF];
410         else if ((offset >= 0xF00000) && (offset < 0xF10000))
411                 data = tom_byte_read(offset);
412         else if ((offset >= 0xF10000) && (offset < 0xF20000))
413                 data = jerry_byte_read(offset);
414         else
415                 data = jaguar_unknown_readbyte(offset);
416
417         return data;
418 }
419
420 unsigned jaguar_word_read(unsigned int offset)
421 {
422 //TEMP--Mirror of F03000?
423 /*if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
424 WriteLog( "[JWR16] --> Possible GPU RAM mirror access! [%08X]\n", offset);//*/
425
426         offset &= 0xFFFFFF;
427         if (offset <= 0x3FFFFE)
428         {
429 //              return (jaguar_mainRam[(offset+1) & 0x3FFFFF] << 8) | jaguar_mainRam[(offset+0) & 0x3FFFFF];
430                 return (jaguar_mainRam[(offset+0) & 0x3FFFFF] << 8) | jaguar_mainRam[(offset+1) & 0x3FFFFF];
431         }
432         else if ((offset >= 0x800000) && (offset <= 0xBFFFFE))
433         {
434                 offset -= 0x800000;
435 //              return (jaguar_mainRom[offset+1] << 8) | jaguar_mainRom[offset+0];
436                 return (jaguar_mainRom[offset+0] << 8) | jaguar_mainRom[offset+1];
437         }
438 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
439         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
440                 return cdrom_word_read(offset);
441         else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
442 //              return *((uint16 *)&jaguar_bootRom[offset & 0x3FFFF]);
443                 return (jaguar_bootRom[(offset+0) & 0x3FFFF] << 8) | jaguar_bootRom[(offset+1) & 0x3FFFF];
444         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
445                 return tom_word_read(offset);
446         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
447 //{
448 //WriteLog("Reading from JERRY offset %08X...\n", offset);
449                 return jerry_word_read(offset);
450 //}
451
452         return jaguar_unknown_readword(offset);
453 }
454
455 void jaguar_byte_write(unsigned offset, unsigned data)
456 {
457         offset &= 0xFFFFFF;
458         if (offset < 0x400000)
459         {
460 //              jaguar_mainRam[(offset^0x01) & 0x3FFFFF] = data;
461                 jaguar_mainRam[offset & 0x3FFFFF] = data;
462                 return;
463         }
464 //      else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
465         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
466         {
467                 cdrom_byte_write(offset, data);
468                 return;
469         }
470         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
471         {
472                 tom_byte_write(offset, data);
473                 return;
474         }
475         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
476         {
477                 jerry_byte_write(offset, data);
478                 return;
479         }
480     
481         jaguar_unknown_writebyte(offset, data);
482 }
483
484 void jaguar_word_write(unsigned offset, unsigned data)
485 {
486 extern int dsp_pc;//, dsp_control;
487 if (offset == 0xF1A116 && (data & 0x01))
488         WriteLog("  JagWW: DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
489 //else
490 //      WriteLog("JagWW: DSP halted... (Old value: %08X)\n", dsp_control);
491
492 //extern int blit_start_log;
493 //if (blit_start_log)
494 /*{
495         if (offset == 0x0674DE)
496                 WriteLog( "[JWW16] Bad write starting @ 0674DE! [%04X]\n", data);
497 }//*/
498 //TEMP--Mirror of F03000?
499 //if (offset >= 0xF0B000 && offset <= 0xF0BFFF)
500 //WriteLog( "[JWW16] --> Possible GPU RAM mirror access! [%08X]", offset);
501 //if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
502 //      WriteLog("JagWW: Writing %04X at %08X\n", data, offset);
503         offset &= 0xFFFFFF;
504         
505         if (offset <= 0x3FFFFE)
506         {
507 //              jaguar_mainRam[(offset+0) & 0x3FFFFF] = data & 0xFF;
508 //              jaguar_mainRam[(offset+1) & 0x3FFFFF] = (data>>8) & 0xFF;
509                 jaguar_mainRam[(offset+0) & 0x3FFFFF] = (data>>8) & 0xFF;
510                 jaguar_mainRam[(offset+1) & 0x3FFFFF] = data & 0xFF;
511                 return;
512         }
513         else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
514         {
515                 cdrom_word_write(offset, data);
516                 return;
517         }
518         else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
519         {
520                 tom_word_write(offset, data);
521                 return;
522         }
523         else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
524         {
525                 jerry_word_write(offset, data);
526                 return;
527         }
528     
529         jaguar_unknown_writeword(offset, data);
530 }
531
532 unsigned jaguar_long_read(unsigned int offset)
533 {
534         return (jaguar_word_read(offset) << 16) | jaguar_word_read(offset+2);
535 }
536
537 void jaguar_long_write(unsigned offset, unsigned data)
538 {
539 extern int dsp_pc;//, dsp_control;
540 if (offset == 0xF1A114 && (data & 0x01))
541         WriteLog("JagLW: DSP is GO! (DSP_PC: %08X)\n", dsp_pc);
542 //else
543 //      WriteLog("JagLW: DSP halted... (Old value: %08X)\n", dsp_control);
544
545         jaguar_word_write(offset, data >> 16);
546         jaguar_word_write(offset+2, data & 0xFFFF);
547 }
548
549 //
550 // Jaguar console initialization
551 //
552 void jaguar_init(void)
553 {
554         memory_malloc_secure((void **)&jaguar_mainRam, 0x400000, "Jaguar 68K CPU RAM");
555         memory_malloc_secure((void **)&jaguar_bootRom, 0x040000, "Jaguar 68K CPU BIOS ROM");
556         memory_malloc_secure((void **)&jaguar_mainRom, 0x600000, "Jaguar 68K CPU ROM");
557         memset(jaguar_mainRam, 0x00, 0x400000);
558 //      memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
559         memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
560
561 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\Brain Dead 13.cdi");
562 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\baldies.cdi");
563 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\mystdemo.cdi");
564 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\battlemorph.cdi");
565 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\primalrage.cdi");
566 //      cd_bios_boot("C:\\ftp\\jaguar\\cd\\Dragons Lair.cdi");
567
568         // Should these be hardwired or read from VP?
569         jaguar_screen_scanlines = (hardwareTypeNTSC ? 524 : 624);
570 //Should the divisor be 50 for PAL??? Let's try it!
571         m68k_cycles_per_scanline = (hardwareTypeNTSC ? M68K_CLOCK_RATE_NTSC : M68K_CLOCK_RATE_PAL) / (jaguar_screen_scanlines * (hardwareTypeNTSC ? 60 : 50));
572         gpu_cycles_per_scanline = dsp_cycles_per_scanline
573                 = (hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL) / (jaguar_screen_scanlines * (hardwareTypeNTSC ? 60 : 50));
574
575 //#ifdef SOUND_OUTPUT
576 //      ws_audio_init();
577 //#endif
578
579         m68k_set_cpu_type(M68K_CPU_TYPE_68000);
580         gpu_init();
581         dsp_init();
582         tom_init();
583         jerry_init();
584         cdrom_init();
585 }
586
587 void jaguar_done(void)
588 {
589 //#ifdef CPU_DEBUG
590 //      for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
591 //              WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
592         int32 topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
593         WriteLog("M68K: Top of stack: %08X. Stack trace:\n", jaguar_long_read(topOfStack));
594         for(int i=-2; i<9; i++)
595                 WriteLog("%06X: %08X\n", topOfStack + (i * 4), jaguar_long_read(topOfStack + (i * 4)));
596
597 /*      WriteLog("\nM68000 disassembly at $802288...\n");
598         jaguar_dasm(0x802288, 3);
599         WriteLog("\nM68000 disassembly at $802200...\n");
600         jaguar_dasm(0x802200, 500);
601         WriteLog("\nM68000 disassembly at $802518...\n");
602         jaguar_dasm(0x802518, 100);//*/
603
604 /*      WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
605         jaguar_dasm(0x803F00, 500);
606         WriteLog("\n");//*/
607
608 /*      WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
609         jaguar_dasm(0x802B00, 500);
610         WriteLog("\n");//*/
611
612 //      WriteLog("Jaguar: CD BIOS version %04X\n", jaguar_word_read(0x3004));
613         WriteLog("Jaguar: Interrupt enable = %02X\n", tom_byte_read(0xF000E1) & 0x1F);
614         WriteLog("Jaguar: VBL interrupt is %s\n", ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64))) ? "enabled" : "disabled");
615         M68K_show_context();
616 //#endif
617 //#ifdef SOUND_OUTPUT
618 //      ws_audio_done();
619 //#endif
620         cd_bios_done();
621         cdrom_done();
622         tom_done();
623         jerry_done();
624         memory_free(jaguar_mainRom);
625         memory_free(jaguar_bootRom);
626         memory_free(jaguar_mainRam);
627 }
628
629 void jaguar_reset(void)
630 {
631         if (jaguar_use_bios)
632                 memcpy(jaguar_mainRam, jaguar_bootRom, 8);
633         else
634         {
635                 SET32(jaguar_mainRam, 4, 0x00802000);
636                 // Handle PD stuff...
637                 // This should definitely go elsewhere (like in the cart load section)!
638                 if (jaguar_mainRom[0] == 0x60 && jaguar_mainRom[1] == 0x1A)
639                 {
640                         uint32 runAddress = GET32(jaguar_mainRom, 0x2A);
641                         uint32 progLength = GET32(jaguar_mainRom, 0x02);
642                         WriteLog("Setting up PD ROM... Run address: %08X, length: %08X\n", runAddress, progLength);
643                         memcpy(jaguar_mainRam + runAddress, jaguar_mainRom + 0x2E, progLength);
644                         SET32(jaguar_mainRam, 4, runAddress);
645                 }
646         }
647
648 //      WriteLog("jaguar_reset():\n");
649 //#ifdef SOUND_OUTPUT
650 //      ws_audio_reset();
651 //#endif
652         cd_bios_reset();
653         tom_reset();
654         jerry_reset();
655         gpu_reset();
656         dsp_reset();
657         cdrom_reset();
658     m68k_pulse_reset();                         // Reset the 68000
659         WriteLog( "\t68K PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
660 }
661
662 void jaguar_reset_handler(void)
663 {
664 }
665
666 void jaguar_exec(int16 * backbuffer, bool render)
667
668         uint32 i, vblank_duration = tom_get_vdb();
669
670         // vblank
671         if ((tom_irq_enabled(IRQ_VBLANK)) && (jaguar_interrupt_handler_is_valid(64)))
672         {
673                 if (jaguar_word_read(0xF0004E) != 0x07FF)       // VI (11 bits wide!)
674                 {
675                         tom_set_pending_video_int();
676 //                      s68000interrupt(7, IRQ_VBLANK+64);
677 //                      s68000flushInterrupts();
678                         m68k_set_irq(7);                                        // IRQ_VBLANK+64??? Not autovectored??? No.
679 // Could set a global variable here, to signal that this is a VBLANK interrupt...
680 // Then again, since IRQ_VBLANK is set to zero, this would not be necessary in this case.
681                 }
682         }
683
684         for(i=0; i<vblank_duration; i++)
685         {
686 /*              uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
687                 if (invalid_instruction_address != 0x80000000)
688                         cd_bios_process(invalid_instruction_address);*/
689                 m68k_execute(m68k_cycles_per_scanline);
690                 // No CD handling... !!! FIX !!!
691
692                 cd_bios_exec(i);
693                 tom_pit_exec(m68k_cycles_per_scanline);
694                 tom_exec_scanline(backbuffer, i, false);
695                 jerry_pit_exec(m68k_cycles_per_scanline);
696                 jerry_i2s_exec(m68k_cycles_per_scanline);
697                 gpu_exec(gpu_cycles_per_scanline);
698                 if (dsp_enabled)
699                         dsp_exec(dsp_cycles_per_scanline);
700         }
701         
702         for (; i<jaguar_screen_scanlines; i++)
703         {
704 /*              uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
705                 if (invalid_instruction_address != 0x80000000)
706                         cd_bios_process(invalid_instruction_address);*/
707                 m68k_execute(m68k_cycles_per_scanline);
708                 // No CD handling... !!! FIX !!!
709                 cd_bios_exec(i);
710                 tom_pit_exec(m68k_cycles_per_scanline);
711                 jerry_pit_exec(m68k_cycles_per_scanline);
712                 jerry_i2s_exec(m68k_cycles_per_scanline);
713                 tom_exec_scanline(backbuffer, i, render);
714                 gpu_exec(gpu_cycles_per_scanline);
715                 if (dsp_enabled)
716                         dsp_exec(dsp_cycles_per_scanline);
717                 backbuffer += tom_width;
718         }
719 //#ifdef SOUND_OUTPUT
720 //      system_sound_update();
721 //#endif
722 }
723
724 //
725 // Main Jaguar execution loop (1 frame)
726 //
727 void JaguarExecute(int16 * backbuffer, bool render)
728 {
729         uint16 vp = tom_word_read(0xF0003E);//Hmm. This is a WO register. Will work? Looks like. But wrong behavior!
730         uint16 vi = tom_word_read(0xF0004E);//Another WO register...
731         uint16 vdb = tom_word_read(0xF00046);
732 //      uint16 endingLine = 
733 //Note: This is the *definite* end of the display, though VDE *might* be less than this...
734 //      uint16 vbb = tom_word_read(0xF00040);
735 //It seems that they mean it when they say that VDE is the end of object processing.
736 //However, we need to be able to tell the OP (or TOM) that we've reached the end of the
737 //buffer and not to write any more pixels...
738         uint16 vde = tom_word_read(0xF00048);
739
740 /*extern int effect_start;
741 if (effect_start)
742 {
743         WriteLog("JagExe: VP=%u, VI=%u, VDB=%u, VBB=%u CPU CPS=%u, GPU CPS=%u\n", vp, vi, vdb, vbb, m68k_cycles_per_scanline, gpu_cycles_per_scanline);
744 }//*/
745
746         for(uint16 i=0; i<vp; i++)
747         {
748                 // Increment the horizontal count (why? RNG?)
749                 tom_word_write(0xF00004, tom_word_read(0xF00004) + 1);
750
751                 tom_word_write(0xF00006, i);                            // Write the VC
752
753                 if (i == vi)                                                            // Time for Vertical Interrupt?
754                 {
755                         if (tom_irq_enabled(IRQ_VBLANK) && jaguar_interrupt_handler_is_valid(64))
756                         {
757                                 // We don't have to worry about autovectors & whatnot because the Jaguar
758                                 // tells you through registers who sent the interrupt...
759                                 tom_set_pending_video_int();
760                                 m68k_set_irq(7);
761                         }
762                 }
763                 
764 //              uint32 invalid_instruction_address = s68000exec(m68k_cycles_per_scanline);
765 //              if (invalid_instruction_address != 0x80000000)
766 //                      cd_bios_process(invalid_instruction_address);
767                 // These are divided by 2 because we're executing *half* lines...!
768                 m68k_execute(m68k_cycles_per_scanline / 2);
769                 // No CD handling... !!! FIX !!!
770                 cd_bios_exec(i);        // NOTE: Ignores parameter...
771                 tom_pit_exec(m68k_cycles_per_scanline / 2);
772                 jerry_pit_exec(m68k_cycles_per_scanline / 2);
773                 jerry_i2s_exec(m68k_cycles_per_scanline / 2);
774                 gpu_exec(gpu_cycles_per_scanline / 2);
775                 if (dsp_enabled)
776                         dsp_exec(dsp_cycles_per_scanline / 2);
777
778 //Interlacing is still not handled correctly here...
779                 if (i >= vdb && i < vde)//vbb)
780                 {
781                         if (!(i & 0x01))                                                // Execute OP only on even lines (non-interlaced only!)
782                         {
783                                 tom_exec_scanline(backbuffer, i/2, render);     // i/2 is a kludge...
784                                 backbuffer += TOMGetSDLScreenPitch() / 2;       // Convert bytes to words...
785                         }
786                 }
787         }
788
789 //#ifdef SOUND_OUTPUT
790 //      system_sound_update();
791 //#endif
792 }
793
794 // Temp debugging stuff
795
796 void DumpMainMemory(void)
797 {
798         FILE * fp = fopen("./memdump.bin", "wb");
799
800         if (fp == NULL)
801                 return;
802
803         fwrite(jaguar_mainRam, 1, 0x400000, fp);
804         fclose(fp);
805 }
806
807 uint8 * GetRamPtr(void)
808 {
809         return jaguar_mainRam;
810 }