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