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