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