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