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