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