Debugger sources code clean-up
[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
a8c13b4d 1044//
cf76e892
JPM
1045unsigned int m68k_read_memory_8(unsigned int address)
1046{
1047#ifdef ALPINE_FUNCTIONS
1048 // Check if breakpoint on memory is active, and deal with it
1049 if (bpmActive && address == bpmAddress1)
a8c13b4d 1050 {
cf76e892 1051 M68KDebugHalt();
a8c13b4d 1052 }
cf76e892
JPM
1053#endif
1054
1055 // Musashi does this automagically for you, UAE core does not :-P
1056 address &= 0x00FFFFFF;
1057#ifdef CPU_DEBUG_MEMORY
1058 // Note that the Jaguar only has 2M of RAM, not 4!
1059 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1060 {
1061 if (startMemLog)
1062 readMem[address] = 1;
1063 }
1064#endif
1065//WriteLog("[RM8] Addr: %08X\n", address);
1066//; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1067/* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1068 || address == 0x1AF05E)
1069 WriteLog("[RM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, jaguar_mainRam[address]);//*/
1070#ifndef USE_NEW_MMU
1071 unsigned int retVal = 0;
1072
1073 // Note that the Jaguar only has 2M of RAM, not 4!
1074 if ((address >= 0x000000) && (address <= (vjs.DRAM_size - 1)))
a8c13b4d 1075 {
cf76e892 1076 retVal = jaguarMainRAM[address];
a8c13b4d 1077 }
cf76e892 1078// else if ((address >= 0x800000) && (address <= 0xDFFFFF))
cf76e892 1079 else
a8c13b4d
JPM
1080 {
1081 if ((address >= 0x800000) && (address <= 0xDFFEFF))
1082 {
1083 retVal = jaguarMainROM[address - 0x800000];
1084 }
1085 else
1086 {
1087 if ((address >= 0xE00000) && (address <= 0xE3FFFF))
1088 {
1089 // retVal = jaguarBootROM[address - 0xE00000];
1090 // retVal = jaguarDevBootROM1[address - 0xE00000];
1091 retVal = jagMemSpace[address];
1092 }
1093 else
1094 {
1095 if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1096 {
1097 retVal = CDROMReadByte(address);
1098 }
1099 else
1100 {
1101 if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1102 {
1103 retVal = TOMReadByte(address, M68K);
1104 }
1105 else
1106 {
1107 if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1108 {
1109 retVal = JERRYReadByte(address, M68K);
1110 }
1111 else
1112 {
1113 retVal = jaguar_unknown_readbyte(address, M68K);
1114 }
1115 }
1116 }
1117 }
1118 }
1119 }
cf76e892
JPM
1120
1121//if (address >= 0x2800 && address <= 0x281F)
1122// WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1123//if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1124// WriteLog("M68K: Read byte $%02X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1125 return retVal;
1126#else
1127 return MMURead8(address, M68K);
1128#endif
1129}
1130
1131
1132/*
1133void gpu_dump_disassembly(void);
1134void gpu_dump_registers(void);
1135*/
1136
1137unsigned int m68k_read_memory_16(unsigned int address)
1138{
1139#ifdef ALPINE_FUNCTIONS
1140 // Check if breakpoint on memory is active, and deal with it
1141 if (bpmActive && (address == bpmAddress1))
1142 {
1143 M68KDebugHalt();
1144 }
1145#endif
1146
1147 // Musashi does this automagically for you, UAE core does not :-P
1148 address &= 0x00FFFFFF;
1149#ifdef CPU_DEBUG_MEMORY
1150/* if ((address >= 0x000000) && (address <= 0x3FFFFE))
1151 {
1152 if (startMemLog)
1153 readMem[address] = 1, readMem[address + 1] = 1;
1154 }//*/
1155/* if (effect_start && (address >= 0x8064FC && address <= 0x806501))
1156 {
1157 return 0x4E71; // NOP
1158 }
1159 if (effect_start2 && (address >= 0x806502 && address <= 0x806507))
1160 {
1161 return 0x4E71; // NOP
1162 }
1163 if (effect_start3 && (address >= 0x806512 && address <= 0x806517))
1164 {
1165 return 0x4E71; // NOP
1166 }
1167 if (effect_start4 && (address >= 0x806524 && address <= 0x806527))
1168 {
1169 return 0x4E71; // NOP
1170 }
1171 if (effect_start5 && (address >= 0x80653E && address <= 0x806543)) //Collision detection!
1172 {
1173 return 0x4E71; // NOP
1174 }
1175 if (effect_start6 && (address >= 0x806544 && address <= 0x806547))
1176 {
1177 return 0x4E71; // NOP
1178 }//*/
1179#endif
1180//WriteLog("[RM16] Addr: %08X\n", address);
1181/*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005FBA)
1182// for(int i=0; i<10000; i++)
1183 WriteLog("[M68K] In routine #6!\n");//*/
1184//if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00006696) // GPU Program #4
1185//if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005B3C) // GPU Program #2
1186/*if (m68k_get_reg(NULL, M68K_REG_PC) == 0x00005BA8) // GPU Program #3
1187{
1188 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1189 gpu_dump_registers();
1190 gpu_dump_disassembly();
1191// for(int i=0; i<10000; i++)
1192// WriteLog("[M68K] About to run GPU!\n");
1193}//*/
1194//WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1195/*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x00006696 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x000066A8)
1196{
1197 if (address == 0x000066A0)
1198 {
1199 gpu_dump_registers();
1200 gpu_dump_disassembly();
1201 }
1202 for(int i=0; i<10000; i++)
1203 WriteLog("[M68K] About to run GPU! (Addr:%08X, data:%04X)\n", address, TOMReadWord(address));
1204}//*/
1205//; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1206/* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1207 || address == 0x1AF05E)
1208 WriteLog("[RM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, GET16(jaguar_mainRam, address));//*/
1209#ifndef USE_NEW_MMU
1210 unsigned int retVal = 0;
1211
1212 // Note that the Jaguar only has 2M of RAM, not 4!
1213 if ((address >= 0x000000) && (address <= (vjs.DRAM_size - 2)))
a8c13b4d
JPM
1214 {
1215 // retVal = (jaguar_mainRam[address] << 8) | jaguar_mainRam[address+1];
cf76e892 1216 retVal = GET16(jaguarMainRAM, address);
a8c13b4d 1217 }
cf76e892 1218// else if ((address >= 0x800000) && (address <= 0xDFFFFE))
a8c13b4d 1219 else
cf76e892 1220 {
a8c13b4d 1221 if ((address >= 0x800000) && (address <= 0xDFFEFE))
cf76e892 1222 {
a8c13b4d
JPM
1223 // Memory Track reading...
1224 if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
1225 {
1226 retVal = MTReadWord(address);
1227 }
1228 else
1229 {
1230 retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
1231 }
cf76e892
JPM
1232 }
1233 else
a8c13b4d
JPM
1234 {
1235 if ((address >= 0xE00000) && (address <= 0xE3FFFE))
1236 {
1237 // retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
1238 // retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
1239 retVal = (jagMemSpace[address] << 8) | jagMemSpace[address + 1];
1240 }
1241 else
1242 {
1243 if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1244 {
1245 retVal = CDROMReadWord(address, M68K);
1246 }
1247 else
1248 {
1249 if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1250 {
1251 retVal = TOMReadWord(address, M68K);
1252 }
1253 else
1254 {
1255 if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1256 {
1257 retVal = JERRYReadWord(address, M68K);
1258 }
1259 else
1260 {
1261 retVal = jaguar_unknown_readword(address, M68K);
1262 }
1263 }
1264 }
1265 }
1266 }
cf76e892 1267 }
cf76e892
JPM
1268
1269//if (address >= 0xF1B000 && address <= 0xF1CFFF)
1270// WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1271//if (address >= 0x2800 && address <= 0x281F)
1272// WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1273//$8B3AE -> Transferred from $F1C010
1274//$8B5E4 -> Only +1 read at $808AA
1275//if (address >= 0x8B5E4 && address <= 0x8B5E4 + 16)
1276// WriteLog("M68K: Read word $%04X at $%08X [PC=%08X]\n", retVal, address, m68k_get_reg(NULL, M68K_REG_PC));
1277 return retVal;
1278#else
1279 return MMURead16(address, M68K);
1280#endif
1281}
1282
1283
1284unsigned int m68k_read_memory_32(unsigned int address)
1285{
1286#ifdef ALPINE_FUNCTIONS
1287 // Check if breakpoint on memory is active, and deal with it
1288 if (bpmActive && address == bpmAddress1)
a8c13b4d 1289 {
cf76e892 1290 M68KDebugHalt();
a8c13b4d 1291 }
cf76e892
JPM
1292#endif
1293
1294 // Musashi does this automagically for you, UAE core does not :-P
1295 address &= 0x00FFFFFF;
1296//; So, it seems that it stores the returned DWORD at $51136 and $FB074.
1297/* if (address == 0x51136 || address == 0xFB074 || address == 0x1AF05E)
1298 WriteLog("[RM32 PC=%08X] Addr: %08X, val: %08X\n", m68k_get_reg(NULL, M68K_REG_PC), address, (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2));//*/
1299
1300//WriteLog("--> [RM32]\n");
1301#ifndef USE_NEW_MMU
1302 uint32_t retVal = 0;
1303
1304 if ((address >= 0x800000) && (address <= 0xDFFEFE))
1305 {
1306 // Memory Track reading...
1307 if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
a8c13b4d 1308 {
cf76e892 1309 retVal = MTReadLong(address);
a8c13b4d 1310 }
cf76e892 1311 else
a8c13b4d 1312 {
cf76e892 1313 retVal = GET32(jaguarMainROM, address - 0x800000);
a8c13b4d 1314 }
cf76e892
JPM
1315
1316 return retVal;
1317 }
1318
1319 return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
1320#else
1321 return MMURead32(address, M68K);
1322#endif
1323}
1324
1325
a8c13b4d
JPM
1326//
1327bool m68k_write_unknown_alert(unsigned int address, char *bits, unsigned int value)
1328{
1329 QString msg;
1330 QMessageBox msgBox;
1331
1332 msg.sprintf("$%06x: Writing at this unknown memory location $%06x with a (%s bits) value of $%0x", pcQueue[pcQPtr ? (pcQPtr - 1) : 0x3FF], address, bits, value);
1333 msgBox.setText(msg);
1334 msgBox.setStandardButtons(QMessageBox::Cancel);
1335 msgBox.setDefaultButton(QMessageBox::Cancel);
1336 msgBox.exec();
1337 return M68KDebugHalt();
1338}
1339
1340
eb20f274 1341//
a8c13b4d 1342bool m68k_write_cartridge_alert(unsigned int address, char *bits, unsigned int value)
eb20f274
JPM
1343{
1344 QString msg;
eb20f274 1345 QMessageBox msgBox;
a8c13b4d
JPM
1346
1347 msg.sprintf("$%06x: Writing at this ROM cartridge location $%06x with a (%s bits) value of $%0x", pcQueue[pcQPtr ? (pcQPtr - 1) : 0x3FF], address, bits, value);
1348#if 1
eb20f274
JPM
1349 msgBox.setText(msg);
1350
1351 if (!M68KDebugHaltStatus() && !strstr(bits, "32"))
1352 {
1353 msgBox.setInformativeText("Do you want to continue?");
1354 msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1355 msgBox.setDefaultButton(QMessageBox::Cancel);
1356 }
1357 else
1358 {
1359 msgBox.setStandardButtons(QMessageBox::Cancel);
1360 msgBox.setDefaultButton(QMessageBox::Cancel);
1361 }
1362
1363 int retVal = msgBox.exec();
1364#endif
1365#if 0
1366 QMessageBox::StandardButton retVal = QMessageBox::question(this, tr("Remove Mapping"), msg, QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
1367#endif
1368
1369 if (retVal == QMessageBox::Ok)
1370 {
a8c13b4d 1371 return false;
eb20f274
JPM
1372 }
1373 else
1374 {
a8c13b4d 1375 return M68KDebugHalt();
eb20f274
JPM
1376 }
1377}
1378
1379
a8c13b4d
JPM
1380//
1381bool m68k_write_memory_check(unsigned int address, char *bits, unsigned int value)
1382{
1383#ifdef ALPINE_FUNCTIONS
1384 // Check if breakpoint on memory is active, and deal with it
1385 if (bpmActive && (address == bpmAddress1))
1386 {
1387 return M68KDebugHalt();
1388 }
1389 else
1390#endif
1391 {
1392 // Rom writing authorisation detection
1393 if (!vjs.allowWritesToROM && ((address >= 0x800000) && (address < 0xDFFF00)))
1394 {
1395 return m68k_write_cartridge_alert(address, bits, value);
1396 }
1397 else
1398 {
1399 //if ((address & 0xFF000000))
1400 //{
1401 // return m68k_write_unknown_alert(address, bits, value);
1402 //}
1403 //else
1404 //{
1405 return false;
1406 //}
1407 }
1408 }
1409}
1410
1411
1412//
cf76e892
JPM
1413void m68k_write_memory_8(unsigned int address, unsigned int value)
1414{
a8c13b4d
JPM
1415#if 1
1416 m68k_write_memory_check(address, "8", value);
1417#else
cf76e892
JPM
1418#ifdef ALPINE_FUNCTIONS
1419 // Check if breakpoint on memory is active, and deal with it
eb20f274
JPM
1420 if (bpmActive && (address == bpmAddress1))
1421 {
cf76e892 1422 M68KDebugHalt();
eb20f274
JPM
1423 }
1424 else
a8c13b4d 1425#endif
eb20f274
JPM
1426 {
1427 // Rom writing authorisation detection
1428 if (!vjs.allowWritesToROM && ((address >= 0x800000) && (address < 0xe00000)))
1429 {
a8c13b4d 1430 m68k_write_cartridge_alert(address, "8", value);
eb20f274
JPM
1431 }
1432 }
cf76e892
JPM
1433#endif
1434
1435 // Musashi does this automagically for you, UAE core does not :-P
a8c13b4d 1436 //address &= 0x00FFFFFF;
cf76e892
JPM
1437#ifdef CPU_DEBUG_MEMORY
1438 // Note that the Jaguar only has 2M of RAM, not 4!
1439 if ((address >= 0x000000) && (address <= 0x1FFFFF))
1440 {
1441 if (startMemLog)
1442 {
1443 if (value > writeMemMax[address])
1444 writeMemMax[address] = value;
1445 if (value < writeMemMin[address])
1446 writeMemMin[address] = value;
1447 }
1448 }
1449#endif
1450/*if (address == 0x4E00)
1451 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1452//if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1453// WriteLog("M68K: Writing %02X at %08X\n", value, address);
1454//WriteLog("[WM8 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1455/*if (effect_start)
1456 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1457 WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
1458//$53D0
1459/*if (address >= 0x53D0 && address <= 0x53FF)
1460 printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1461//Testing AvP on UAE core...
1462//000075A0: FFFFF80E B6320220 (BITMAP)
1463/*if (address == 0x75A0 && value == 0xFF)
1464 printf("M68K: (8) Tripwire hit...\n");//*/
1465
1466#ifndef USE_NEW_MMU
1467 // Note that the Jaguar only has 2M of RAM, not 4!
1468 if ((address >= 0x000000) && (address <= (vjs.DRAM_size - 1)))
a8c13b4d 1469 {
cf76e892 1470 jaguarMainRAM[address] = value;
a8c13b4d 1471 }
cf76e892 1472 else
a8c13b4d
JPM
1473 {
1474 if ((address >= 0xDFFF00) && (address <= 0xDFFFFF))
1475 {
1476 CDROMWriteByte(address, value, M68K);
1477 }
1478 else
1479 {
1480 if ((address >= 0xF00000) && (address <= 0xF0FFFF))
1481 {
1482 TOMWriteByte(address, value, M68K);
1483 }
1484 else
1485 {
1486 if ((address >= 0xF10000) && (address <= 0xF1FFFF))
1487 {
1488 JERRYWriteByte(address, value, M68K);
1489 }
1490 else
1491 {
1492 jaguar_unknown_writebyte(address, value, M68K);
1493 }
1494 }
1495 }
1496 }
cf76e892
JPM
1497#else
1498 MMUWrite8(address, value, M68K);
1499#endif
1500}
1501
1502
a8c13b4d 1503//
cf76e892
JPM
1504void m68k_write_memory_16(unsigned int address, unsigned int value)
1505{
a8c13b4d
JPM
1506#if 1
1507 if (!M68KDebugHaltStatus())
1508 {
1509 m68k_write_memory_check(address, "16", value);
1510 }
1511#else
cf76e892
JPM
1512#ifdef ALPINE_FUNCTIONS
1513 // Check if breakpoint on memory is active, and deal with it
1514 if (bpmActive && address == bpmAddress1)
eb20f274 1515 {
cf76e892 1516 M68KDebugHalt();
eb20f274
JPM
1517 }
1518 else
a8c13b4d 1519#endif
eb20f274
JPM
1520 {
1521 // Rom writing authorisation detection
1522 if (!vjs.allowWritesToROM && ((address >= 0x800000) && (address < 0xe00000)))
1523 {
1524 if (!M68KDebugHaltStatus())
1525 {
a8c13b4d 1526 m68k_write_cartridge_alert(address, "16", value);
eb20f274
JPM
1527 }
1528 }
1529 }
cf76e892
JPM
1530#endif
1531
1532 // Musashi does this automagically for you, UAE core does not :-P
a8c13b4d 1533 //address &= 0x00FFFFFF;
cf76e892
JPM
1534#ifdef CPU_DEBUG_MEMORY
1535 // Note that the Jaguar only has 2M of RAM, not 4!
1536 if ((address >= 0x000000) && (address <= 0x1FFFFE))
1537 {
1538 if (startMemLog)
1539 {
1540 uint8_t hi = value >> 8, lo = value & 0xFF;
1541
1542 if (hi > writeMemMax[address])
1543 writeMemMax[address] = hi;
1544 if (hi < writeMemMin[address])
1545 writeMemMin[address] = hi;
1546
1547 if (lo > writeMemMax[address+1])
1548 writeMemMax[address+1] = lo;
1549 if (lo < writeMemMin[address+1])
1550 writeMemMin[address+1] = lo;
1551 }
1552 }
1553#endif
1554/*if (address == 0x4E00)
1555 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1556//if ((address >= 0x1FF020 && address <= 0x1FF03F) || (address >= 0x1FF820 && address <= 0x1FF83F))
1557// WriteLog("M68K: Writing %04X at %08X\n", value, address);
1558//WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);
1559//if (address >= 0xF02200 && address <= 0xF0229F)
1560// WriteLog("M68K: Writing to blitter --> %04X at %08X\n", value, address);
1561//if (address >= 0x0E75D0 && address <= 0x0E75E7)
1562// WriteLog("M68K: Writing %04X at %08X, M68K PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));
1563/*extern uint32_t totalFrames;
1564if (address == 0xF02114)
1565 WriteLog("M68K: Writing to GPU_CTRL (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));
1566if (address == 0xF02110)
1567 WriteLog("M68K: Writing to GPU_PC (frame:%u)... [M68K PC:%08X]\n", totalFrames, m68k_get_reg(NULL, M68K_REG_PC));//*/
1568//if (address >= 0xF03B00 && address <= 0xF03DFF)
1569// WriteLog("M68K: Writing %04X to %08X...\n", value, address);
1570
1571/*if (address == 0x0100)//64*4)
1572 WriteLog("M68K: Wrote word to VI vector value %04X...\n", value);//*/
1573/*if (effect_start)
1574 if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
1575 WriteLog("M68K: Word %04X written at %08X by 68K\n", value, address);//*/
1576/* if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
1577 || address == 0x1AF05E)
1578 WriteLog("[WM16 PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1579//$53D0
1580/*if (address >= 0x53D0 && address <= 0x53FF)
1581 printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1582//Testing AvP on UAE core...
1583//000075A0: FFFFF80E B6320220 (BITMAP)
1584/*if (address == 0x75A0 && value == 0xFFFF)
1585{
1586 printf("\nM68K: (16) Tripwire hit...\n");
1587 ShowM68KContext();
1588}//*/
1589
1590#ifndef USE_NEW_MMU
1591 // Note that the Jaguar only has 2M of RAM, not 4!
1592 if ((address >= 0x000000) && (address <= (vjs.DRAM_size - 2)))
1593 {
1594/* jaguar_mainRam[address] = value >> 8;
1595 jaguar_mainRam[address + 1] = value & 0xFF;*/
1596 SET16(jaguarMainRAM, address, value);
1597 }
1598 // Memory Track device writes....
cf76e892
JPM
1599 else
1600 {
a8c13b4d
JPM
1601 if ((address >= 0x800000) && (address <= 0x87FFFE))
1602 {
1603 if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
1604 {
1605 MTWriteWord(address, value);
1606 }
1607 }
1608 else
1609 {
1610 if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
1611 {
1612 CDROMWriteWord(address, value, M68K);
1613 }
1614 else
1615 {
1616 if ((address >= 0xF00000) && (address <= 0xF0FFFE))
1617 {
1618 TOMWriteWord(address, value, M68K);
1619 }
1620 else
1621 {
1622 if ((address >= 0xF10000) && (address <= 0xF1FFFE))
1623 {
1624 JERRYWriteWord(address, value, M68K);
1625 }
1626 else
1627 {
1628 jaguar_unknown_writeword(address, value, M68K);
cf76e892 1629#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
a8c13b4d
JPM
1630 WriteLog("\tA0=%08X, A1=%08X, D0=%08X, D1=%08X\n",
1631 m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1),
1632 m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1));
cf76e892 1633#endif
a8c13b4d
JPM
1634 }
1635 }
1636 }
1637 }
cf76e892
JPM
1638 }
1639#else
1640 MMUWrite16(address, value, M68K);
1641#endif
1642}
1643
1644
a8c13b4d 1645//
cf76e892
JPM
1646void m68k_write_memory_32(unsigned int address, unsigned int value)
1647{
a8c13b4d
JPM
1648#if 1
1649 m68k_write_memory_check(address, "32", value);
1650#else
cf76e892
JPM
1651#ifdef ALPINE_FUNCTIONS
1652 // Check if breakpoint on memory is active, and deal with it
1653 if (bpmActive && address == bpmAddress1)
eb20f274 1654 {
cf76e892 1655 M68KDebugHalt();
eb20f274
JPM
1656 }
1657 else
a8c13b4d 1658#endif
eb20f274
JPM
1659 {
1660 // Rom writing authorisation detection
1661 if (!vjs.allowWritesToROM && ((address >= 0x800000) && (address < 0xe00000)))
1662 {
a8c13b4d 1663 m68k_write_cartridge_alert(address, "32", value);
eb20f274
JPM
1664 }
1665 }
cf76e892
JPM
1666#endif
1667
1668 // Musashi does this automagically for you, UAE core does not :-P
a8c13b4d 1669 //address &= 0x00FFFFFF;
cf76e892
JPM
1670/*if (address == 0x4E00)
1671 WriteLog("M68K: Writing %02X at %08X, PC=%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
1672//WriteLog("--> [WM32]\n");
1673/*if (address == 0x0100)//64*4)
1674 WriteLog("M68K: Wrote dword to VI vector value %08X...\n", value);//*/
1675/*if (address >= 0xF03214 && address < 0xF0321F)
1676 WriteLog("M68K: Writing DWORD (%08X) to GPU RAM (%08X)...\n", value, address);//*/
1677//M68K: Writing DWORD (88E30047) to GPU RAM (00F03214)...
1678/*extern bool doGPUDis;
1679if (address == 0xF03214 && value == 0x88E30047)
1680// start = true;
1681 doGPUDis = true;//*/
1682/* if (address == 0x51136 || address == 0xFB074)
1683 WriteLog("[WM32 PC=%08X] Addr: %08X, val: %02X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
1684//Testing AvP on UAE core...
1685//000075A0: FFFFF80E B6320220 (BITMAP)
1686/*if (address == 0x75A0 && (value & 0xFFFF0000) == 0xFFFF0000)
1687{
1688 printf("\nM68K: (32) Tripwire hit...\n");
1689 ShowM68KContext();
1690}//*/
1691
1692#ifndef USE_NEW_MMU
1693 m68k_write_memory_16(address, value >> 16);
1694 m68k_write_memory_16(address + 2, value & 0xFFFF);
1695#else
1696 MMUWrite32(address, value, M68K);
1697#endif
1698}
1699
1700
1701uint32_t JaguarGetHandler(uint32_t i)
1702{
1703 return JaguarReadLong(i * 4);
1704}
1705
1706
1707bool JaguarInterruptHandlerIsValid(uint32_t i) // Debug use only...
1708{
1709 uint32_t handler = JaguarGetHandler(i);
1710 return (handler && (handler != 0xFFFFFFFF) ? true : false);
1711}
1712
1713
1714void M68K_show_context(void)
1715{
1716 WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC));
1717
1718 for(int i=M68K_REG_D0; i<=M68K_REG_D7; i++)
1719 {
1720 WriteLog("D%i = %08X ", i-M68K_REG_D0, m68k_get_reg(NULL, (m68k_register_t)i));
1721
1722 if (i == M68K_REG_D3 || i == M68K_REG_D7)
1723 WriteLog("\n");
1724 }
1725
1726 for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
1727 {
1728 WriteLog("A%i = %08X ", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
1729
1730 if (i == M68K_REG_A3 || i == M68K_REG_A7)
1731 WriteLog("\n");
1732 }
1733
1734 WriteLog("68K disasm\n");
1735// jaguar_dasm(s68000readPC()-0x1000,0x20000);
1736 JaguarDasm(m68k_get_reg(NULL, M68K_REG_PC) - 0x80, 0x200);
1737// jaguar_dasm(0x5000, 0x14414);
1738
1739// WriteLog("\n.......[Cart start]...........\n\n");
1740// jaguar_dasm(0x192000, 0x1000);//0x200);
1741
1742 WriteLog("..................\n");
1743
1744 if (TOMIRQEnabled(IRQ_VIDEO))
1745 {
1746 WriteLog("video int: enabled\n");
1747 JaguarDasm(JaguarGetHandler(64), 0x200);
1748 }
1749 else
1750 WriteLog("video int: disabled\n");
1751
1752 WriteLog("..................\n");
1753
1754 for(int i=0; i<256; i++)
1755 {
1756 WriteLog("handler %03i at ", i);//$%08X\n", i, (unsigned int)JaguarGetHandler(i));
1757 uint32_t address = (uint32_t)JaguarGetHandler(i);
1758
1759 if (address == 0)
1760 WriteLog(".........\n");
1761 else
1762 WriteLog("$%08X\n", address);
1763 }
1764}
1765
1766
1767//
1768// Unknown read/write byte/word routines
1769//
1770
1771// It's hard to believe that developers would be sloppy with their memory
1772// writes, yet in some cases the developers screwed up royal. E.g., Club Drive
1773// has the following code:
1774//
1775// 807EC4: movea.l #$f1b000, A1
1776// 807ECA: movea.l #$8129e0, A0
1777// 807ED0: move.l A0, D0
1778// 807ED2: move.l #$f1bb94, D1
1779// 807ED8: sub.l D0, D1
1780// 807EDA: lsr.l #2, D1
1781// 807EDC: move.l (A0)+, (A1)+
1782// 807EDE: dbra D1, 807edc
1783//
1784// The problem is at $807ED0--instead of putting A0 into D0, they really meant
1785// to put A1 in. This mistake causes it to try and overwrite approximately
1786// $700000 worth of address space! (That is, unless the 68K causes a bus
1787// error...)
1788
1789void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1790{
a8c13b4d 1791 m68k_write_unknown_alert(address, "8", data);
cf76e892
JPM
1792#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1793 WriteLog("Jaguar: Unknown byte %02X written at %08X by %s (M68K PC=%06X)\n", data, address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1794#endif
1795#ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1796// extern bool finished;
1797 finished = true;
1798// extern bool doDSPDis;
1799 if (who == DSP)
1800 doDSPDis = true;
1801#endif
1802}
1803
1804
1805void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/)
1806{
a8c13b4d 1807 m68k_write_unknown_alert(address, "16", data);
cf76e892
JPM
1808#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1809 WriteLog("Jaguar: Unknown word %04X written at %08X by %s (M68K PC=%06X)\n", data, address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1810#endif
1811#ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1812// extern bool finished;
1813 finished = true;
1814// extern bool doDSPDis;
1815 if (who == DSP)
1816 doDSPDis = true;
1817#endif
1818}
1819
1820
1821unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who/*=UNKNOWN*/)
1822{
1823#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1824 WriteLog("Jaguar: Unknown byte read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1825#endif
1826#ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1827// extern bool finished;
1828 finished = true;
1829// extern bool doDSPDis;
1830 if (who == DSP)
1831 doDSPDis = true;
1832#endif
1833 return 0xFF;
1834}
1835
1836
1837unsigned jaguar_unknown_readword(unsigned address, uint32_t who/*=UNKNOWN*/)
1838{
1839#ifdef LOG_UNMAPPED_MEMORY_ACCESSES
1840 WriteLog("Jaguar: Unknown word read at %08X by %s (M68K PC=%06X)\n", address, whoName[who], m68k_get_reg(NULL, M68K_REG_PC));
1841#endif
1842#ifdef ABORT_ON_UNMAPPED_MEMORY_ACCESS
1843// extern bool finished;
1844 finished = true;
1845// extern bool doDSPDis;
1846 if (who == DSP)
1847 doDSPDis = true;
1848#endif
1849 return 0xFFFF;
1850}
1851
1852
1853//
1854// Disassemble M68K instructions at the given offset
1855//
1856
1857unsigned int m68k_read_disassembler_8(unsigned int address)
1858{
1859 return m68k_read_memory_8(address);
1860}
1861
1862
1863unsigned int m68k_read_disassembler_16(unsigned int address)
1864{
1865 return m68k_read_memory_16(address);
1866}
1867
1868
1869unsigned int m68k_read_disassembler_32(unsigned int address)
1870{
1871 return m68k_read_memory_32(address);
1872}
1873
1874
1875void JaguarDasm(uint32_t offset, uint32_t qt)
1876{
1877#ifdef CPU_DEBUG
1878 static char buffer[2048];//, mem[64];
1879 int pc = offset, oldpc;
1880
1881 for(uint32_t i=0; i<qt; i++)
1882 {
1883/* oldpc = pc;
1884 for(int j=0; j<64; j++)
1885 mem[j^0x01] = jaguar_byte_read(pc + j);
1886
1887 pc += Dasm68000((char *)mem, buffer, 0);
1888 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1889 oldpc = pc;
1890 pc += m68k_disassemble(buffer, pc, 0, 1);//M68K_CPU_TYPE_68000);
1891 WriteLog("%08X: %s\n", oldpc, buffer);//*/
1892 }
1893#endif
1894}
1895
1896
1897uint8_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1898{
1899 uint8_t data = 0x00;
1900 offset &= 0xFFFFFF;
1901
1902 // First 2M is mirrored in the $0 - $7FFFFF range
1903 if (offset < 0x800000)
1904 data = jaguarMainRAM[offset & (vjs.DRAM_size - 1)];
1905 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1906 data = jaguarMainROM[offset - 0x800000];
1907 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1908 data = CDROMReadByte(offset, who);
1909 else if ((offset >= 0xE00000) && (offset < 0xE40000))
1910// data = jaguarBootROM[offset & 0x3FFFF];
1911// data = jaguarDevBootROM1[offset & 0x3FFFF];
1912 data = jagMemSpace[offset];
1913 else if ((offset >= 0xF00000) && (offset < 0xF10000))
1914 data = TOMReadByte(offset, who);
1915 else if ((offset >= 0xF10000) && (offset < 0xF20000))
1916 data = JERRYReadByte(offset, who);
1917 else
1918 data = jaguar_unknown_readbyte(offset, who);
1919
1920 return data;
1921}
1922
1923
1924uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1925{
1926 offset &= 0xFFFFFF;
1927
1928 // First 2M is mirrored in the $0 - $7FFFFF range
1929 if (offset < 0x800000)
1930 {
1931 return (jaguarMainRAM[(offset+0) & (vjs.DRAM_size - 1)] << 8) | jaguarMainRAM[(offset+1) & (vjs.DRAM_size - 1)];
1932 }
1933 else if ((offset >= 0x800000) && (offset < 0xDFFF00))
1934 {
1935 offset -= 0x800000;
1936 return (jaguarMainROM[offset+0] << 8) | jaguarMainROM[offset+1];
1937 }
1938// else if ((offset >= 0xDFFF00) && (offset < 0xDFFF00))
1939 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFE))
1940 return CDROMReadWord(offset, who);
1941 else if ((offset >= 0xE00000) && (offset <= 0xE3FFFE))
1942// return (jaguarBootROM[(offset+0) & 0x3FFFF] << 8) | jaguarBootROM[(offset+1) & 0x3FFFF];
1943// return (jaguarDevBootROM1[(offset+0) & 0x3FFFF] << 8) | jaguarDevBootROM1[(offset+1) & 0x3FFFF];
1944 return (jagMemSpace[offset + 0] << 8) | jagMemSpace[offset + 1];
1945 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFE))
1946 return TOMReadWord(offset, who);
1947 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFE))
1948 return JERRYReadWord(offset, who);
1949
1950 return jaguar_unknown_readword(offset, who);
1951}
1952
1953
1954void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1955{
1956/* if ((offset & 0x1FFFFF) >= 0xE00 && (offset & 0x1FFFFF) < 0xE18)
1957 {
1958 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);
1959 }//*/
1960/* if (offset >= 0x4E00 && offset < 0x4E04)
1961 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1962//Need to check for writes in the range of $18FA70 + 8000...
1963/*if (effect_start)
1964 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
1965 WriteLog("JWB: Byte %02X written at %08X by %s\n", data, offset, whoName[who]);//*/
1966
1967 offset &= 0xFFFFFF;
1968
1969 // First 2M is mirrored in the $0 - $7FFFFF range
1970 if (offset < 0x800000)
1971 {
1972 jaguarMainRAM[offset & (vjs.DRAM_size - 1)] = data;
1973 return;
1974 }
1975 else if ((offset >= 0xDFFF00) && (offset <= 0xDFFFFF))
1976 {
1977 CDROMWriteByte(offset, data, who);
1978 return;
1979 }
1980 else if ((offset >= 0xF00000) && (offset <= 0xF0FFFF))
1981 {
1982 TOMWriteByte(offset, data, who);
1983 return;
1984 }
1985 else if ((offset >= 0xF10000) && (offset <= 0xF1FFFF))
1986 {
1987 JERRYWriteByte(offset, data, who);
1988 return;
1989 }
1990
1991 jaguar_unknown_writebyte(offset, data, who);
1992}
1993
1994
1995uint32_t starCount;
1996void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1997{
1998/* if ((offset & 0x1FFFFF) >= 0xE00 && (offset & 0x1FFFFF) < 0xE18)
1999 {
2000 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);
2001 WriteLog(" GPU PC = $%06X\n", GPUReadLong(0xF02110, DEBUG));
2002 }//*/
2003/* if (offset >= 0x4E00 && offset < 0x4E04)
2004 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
2005/*if (offset == 0x0100)//64*4)
2006 WriteLog("M68K: %s wrote word to VI vector value %04X...\n", whoName[who], data);
2007if (offset == 0x0102)//64*4)
2008 WriteLog("M68K: %s wrote word to VI vector+2 value %04X...\n", whoName[who], data);//*/
2009//TEMP--Mirror of F03000? Yes, but only 32-bit CPUs can do it (i.e., NOT the 68K!)
2010// PLUS, you would handle this in the GPU/DSP WriteLong code! Not here!
2011//Need to check for writes in the range of $18FA70 + 8000...
2012/*if (effect_start)
2013 if (offset >= 0x18FA70 && offset < (0x18FA70 + 8000))
2014 WriteLog("JWW: Word %04X written at %08X by %s\n", data, offset, whoName[who]);//*/
2015/*if (offset >= 0x2C00 && offset <= 0x2CFF)
2016 WriteLog("Jaguar: Word %04X written to TOC+%02X by %s\n", data, offset-0x2C00, whoName[who]);//*/
2017
2018 offset &= 0xFFFFFF;
2019
2020 // First 2M is mirrored in the $0 - $7FFFFF range
2021 if (offset <= 0x7FFFFE)
2022 {
2023/*
2024GPU Table (CD BIOS)
2025
20261A 69 F0 ($0000) -> Starfield
20271A 73 C8 ($0001) -> Final clearing blit & bitmap blit?
20281A 79 F0 ($0002)
20291A 88 C0 ($0003)
20301A 8F E8 ($0004) -> "Jaguar" small color logo?
20311A 95 20 ($0005)
20321A 9F 08 ($0006)
20331A A1 38 ($0007)
20341A AB 38 ($0008)
20351A B3 C8 ($0009)
20361A B9 C0 ($000A)
2037*/
2038
2039//This MUST be done by the 68K!
2040/*if (offset == 0x670C)
2041 WriteLog("Jaguar: %s writing to location $670C...\n", whoName[who]);*/
2042
2043/*extern bool doGPUDis;
2044//if ((offset == 0x100000 + 75522) && who == GPU) // 76,226 -> 75522
2045if ((offset == 0x100000 + 128470) && who == GPU) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
2046//if ((offset >= 0x100000 && offset <= 0x12C087) && who == GPU)
2047 doGPUDis = true;//*/
2048/*if (offset == 0x100000 + 128470) // 107,167 -> 128470 (384 x 250 screen size 16BPP)
2049 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);
2050if ((data & 0xFF00) != 0x7700)
2051 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
2052/*if ((offset >= 0x100000 && offset <= 0x147FFF) && who == GPU)
2053 return;//*/
2054/*if ((data & 0xFF00) != 0x7700 && who == GPU)
2055 WriteLog("JWW: Writing value %04X at %08X by %s...\n", data, offset, whoName[who]);//*/
2056/*if ((offset >= 0x100000 + 0x48000 && offset <= 0x12C087 + 0x48000) && who == GPU)
2057 return;//*/
2058/*extern bool doGPUDis;
2059if (offset == 0x120216 && who == GPU)
2060 doGPUDis = true;//*/
2061/*extern uint32_t gpu_pc;
2062if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
2063{
2064 uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
2065 uint32_t y = base / 0x300;
2066 uint32_t x = (base - (y * 0x300)) / 2;
2067 WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
2068}//*/
2069/*
2070JWW: Writing starfield star 775E at 0011F650 (555984/1447)
2071*/
2072//if (offset == (0x001E17F8 + 0x34))
2073/*if (who == GPU && offset == (0x001E17F8 + 0x34))
2074 data = 0xFE3C;//*/
2075// WriteLog("JWW: Write at %08X written to by %s.\n", 0x001E17F8 + 0x34, whoName[who]);//*/
2076/*extern uint32_t gpu_pc;
2077if (who == GPU && (gpu_pc == 0xF03604 || gpu_pc == 0xF03638))
2078{
2079 extern int objectPtr;
2080// if (offset > 0x148000)
2081// return;
2082 starCount++;
2083 if (starCount > objectPtr)
2084 return;
2085
2086// if (starCount == 1)
2087// WriteLog("--> Drawing 1st star...\n");
2088//
2089// uint32_t base = offset - (offset > 0x148000 ? 0x148000 : 0x100000);
2090// uint32_t y = base / 0x300;
2091// uint32_t x = (base - (y * 0x300)) / 2;
2092// WriteLog("JWW: Writing starfield star %04X at %08X (%u/%u) [%s]\n", data, offset, x, y, (gpu_pc == 0xF03604 ? "s" : "L"));
2093
2094//A star of interest...
2095//-->JWW: Writing starfield star 77C9 at 0011D31A (269/155) [s]
2096//1st trail +3(x), -1(y) -> 272, 154 -> 0011D020
2097//JWW: Blitter writing echo 77B3 at 0011D022...
2098}//*/
2099//extern bool doGPUDis;
2100/*if (offset == 0x11D022 + 0x48000 || offset == 0x11D022)// && who == GPU)
2101{
2102// doGPUDis = true;
2103 WriteLog("JWW: %s writing echo %04X at %08X...\n", whoName[who], data, offset);
2104// LogBlit();
2105}
2106if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A)
2107 WriteLog("JWW: %s writing star %04X at %08X...\n", whoName[who], data, offset);//*/
2108
2109 jaguarMainRAM[(offset+0) & (vjs.DRAM_size - 1)] = data >> 8;
2110 jaguarMainRAM[(offset+1) & (vjs.DRAM_size - 1)] = data & 0xFF;
2111 return;
2112 }
2113 else if (offset >= 0xDFFF00 && offset <= 0xDFFFFE)
2114 {
2115 CDROMWriteWord(offset, data, who);
2116 return;
2117 }
2118 else if (offset >= 0xF00000 && offset <= 0xF0FFFE)
2119 {
2120 TOMWriteWord(offset, data, who);
2121 return;
2122 }
2123 else if (offset >= 0xF10000 && offset <= 0xF1FFFE)
2124 {
2125 JERRYWriteWord(offset, data, who);
2126 return;
2127 }
2128 // Don't bomb on attempts to write to ROM
2129 else if (offset >= 0x800000 && offset <= 0xEFFFFF)
2130 return;
2131
2132 jaguar_unknown_writeword(offset, data, who);
2133}
2134
2135
2136// We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
2137uint32_t JaguarReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
2138{
2139 return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who);
2140}
2141
2142
2143// We really should re-do this so that it does *real* 32-bit access... !!! FIX !!!
2144void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
2145{
2146/* extern bool doDSPDis;
2147 if (offset < 0x400 && !doDSPDis)
2148 {
2149 WriteLog("JLW: Write to %08X by %s... Starting DSP log!\n\n", offset, whoName[who]);
2150 doDSPDis = true;
2151 }//*/
2152/*if (offset == 0x0100)//64*4)
2153 WriteLog("M68K: %s wrote dword to VI vector value %08X...\n", whoName[who], data);//*/
2154
2155 JaguarWriteWord(offset, data >> 16, who);
2156 JaguarWriteWord(offset+2, data & 0xFFFF, who);
2157}
2158
2159
2160void JaguarSetScreenBuffer(uint32_t * buffer)
2161{
2162 // This is in TOM, but we set it here...
2163 screenBuffer = buffer;
2164}
2165
2166
2167void JaguarSetScreenPitch(uint32_t pitch)
2168{
2169 // This is in TOM, but we set it here...
2170 screenPitch = pitch;
2171}
2172
2173
2174//
2175// Jaguar console initialization
2176//
2177void JaguarInit(void)
2178{
2179 // For randomizing RAM
2180 srand((unsigned int)time(NULL));
2181
2182 // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
2183 for(uint32_t i=0; i<vjs.DRAM_size; i+=4)
2184 *((uint32_t *)(&jaguarMainRAM[i])) = rand();
2185
2186#ifdef CPU_DEBUG_MEMORY
2187 memset(readMem, 0x00, 0x400000);
2188 memset(writeMemMin, 0xFF, 0x400000);
2189 memset(writeMemMax, 0x00, 0x400000);
2190#endif
2191// memset(jaguarMainRAM, 0x00, 0x200000);
2192// memset(jaguar_mainRom, 0xFF, 0x200000); // & set it to all Fs...
2193// memset(jaguar_mainRom, 0x00, 0x200000); // & set it to all 0s...
2194//NOTE: This *doesn't* fix FlipOut...
2195//Or does it? Hmm...
2196//Seems to want $01010101... Dunno why. Investigate!
2197// memset(jaguarMainROM, 0x01, 0x600000); // & set it to all 01s...
2198// memset(jaguar_mainRom, 0xFF, 0x600000); // & set it to all Fs...
2199 lowerField = false; // Reset the lower field flag
2200//temp, for crappy crap that sux
2201memset(jaguarMainRAM + 0x804, 0xFF, 4);
2202
2203 m68k_pulse_reset(); // Need to do this so UAE disasm doesn't segfault on exit
2204 GPUInit();
2205 DSPInit();
2206 TOMInit();
2207 JERRYInit();
2208 CDROMInit();
2209}
2210
2211
2212//New timer based code stuffola...
2213void HalflineCallback(void);
2214void RenderCallback(void);
2215void JaguarReset(void)
2216{
2217 // Only problem with this approach: It wipes out RAM loaded files...!
2218 // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
2219 for(uint32_t i=8; i<vjs.DRAM_size; i+=4)
2220 *((uint32_t *)(&jaguarMainRAM[i])) = rand();
2221
2222 // New timer base code stuffola...
2223 InitializeEventList();
2224//Need to change this so it uses the single RAM space and load the BIOS
2225//into it somewhere...
2226//Also, have to change this here and in JaguarReadXX() currently
2227 // Only use the system BIOS if it's available...! (it's always available now!)
2228 // AND only if a jaguar cartridge has been inserted.
2229 if (vjs.useJaguarBIOS && jaguarCartInserted && !vjs.hardwareTypeAlpine && !vjs.softTypeDebugger)
2230 memcpy(jaguarMainRAM, jagMemSpace + 0xE00000, 8);
2231 else
2232 SET32(jaguarMainRAM, 4, jaguarRunAddress);
2233
2234// WriteLog("jaguar_reset():\n");
2235 TOMReset();
2236 JERRYReset();
2237 GPUReset();
2238 DSPReset();
2239 CDROMReset();
2240 m68k_pulse_reset(); // Reset the 68000
2241 WriteLog("Jaguar: 68K reset. PC=%06X SP=%08X\n", m68k_get_reg(NULL, M68K_REG_PC), m68k_get_reg(NULL, M68K_REG_A7));
2242
2243 lowerField = false; // Reset the lower field flag
2244// SetCallbackTime(ScanlineCallback, 63.5555);
2245// SetCallbackTime(ScanlineCallback, 31.77775);
2246 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2247}
2248
2249
2250void JaguarDone(void)
2251{
2252#ifdef CPU_DEBUG_MEMORY
2253/* WriteLog("\nJaguar: Memory Usage Stats (return addresses)\n\n");
2254
2255 for(uint32_t i=0; i<=raPtr; i++)
2256 {
2257 WriteLog("\t%08X\n", returnAddr[i]);
2258 WriteLog("M68000 disassembly at $%08X...\n", returnAddr[i] - 16);
2259 jaguar_dasm(returnAddr[i] - 16, 16);
2260 WriteLog("\n");
2261 }
2262 WriteLog("\n");//*/
2263
2264/* int start = 0, end = 0;
2265 bool endTriggered = false, startTriggered = false;
2266 for(int i=0; i<0x400000; i++)
2267 {
2268 if (readMem[i] && writeMemMin[i] != 0xFF && writeMemMax != 0x00)
2269 {
2270 if (!startTriggered)
2271 startTriggered = true, endTriggered = false, start = i;
2272
2273 WriteLog("\t\tMin/Max @ %06X: %u/%u\n", i, writeMemMin[i], writeMemMax[i]);
2274 }
2275 else
2276 {
2277 if (!endTriggered)
2278 {
2279 end = i - 1, endTriggered = true, startTriggered = false;
2280 WriteLog("\tMemory range accessed: %06X - %06X\n", start, end);
2281 }
2282 }
2283 }
2284 WriteLog("\n");//*/
2285#endif
2286//#ifdef CPU_DEBUG
2287// for(int i=M68K_REG_A0; i<=M68K_REG_A7; i++)
2288// WriteLog("\tA%i = 0x%.8x\n", i-M68K_REG_A0, m68k_get_reg(NULL, (m68k_register_t)i));
2289 int32_t topOfStack = m68k_get_reg(NULL, M68K_REG_A7);
2290 WriteLog("M68K: Top of stack: %08X -> (%08X). Stack trace:\n", topOfStack, JaguarReadLong(topOfStack));
2291#if 0
2292 for(int i=-2; i<9; i++)
2293 WriteLog("%06X: %08X\n", topOfStack + (i * 4), JaguarReadLong(topOfStack + (i * 4)));
2294#else
2295 uint32_t address = topOfStack - (4 * 4 * 3);
2296
2297 for(int i=0; i<10; i++)
2298 {
2299 WriteLog("%06X:", address);
2300
2301 for(int j=0; j<4; j++)
2302 {
2303 WriteLog(" %08X", JaguarReadLong(address));
2304 address += 4;
2305 }
2306
2307 WriteLog("\n");
2308 }
2309#endif
2310
2311/* WriteLog("\nM68000 disassembly at $802288...\n");
2312 jaguar_dasm(0x802288, 3);
2313 WriteLog("\nM68000 disassembly at $802200...\n");
2314 jaguar_dasm(0x802200, 500);
2315 WriteLog("\nM68000 disassembly at $802518...\n");
2316 jaguar_dasm(0x802518, 100);//*/
2317
2318/* WriteLog("\n\nM68000 disassembly at $803F00 (look @ $803F2A)...\n");
2319 jaguar_dasm(0x803F00, 500);
2320 WriteLog("\n");//*/
2321
2322/* WriteLog("\n\nM68000 disassembly at $802B00 (look @ $802B5E)...\n");
2323 jaguar_dasm(0x802B00, 500);
2324 WriteLog("\n");//*/
2325
2326/* WriteLog("\n\nM68000 disassembly at $809900 (look @ $8099F8)...\n");
2327 jaguar_dasm(0x809900, 500);
2328 WriteLog("\n");//*/
2329//8099F8
2330/* WriteLog("\n\nDump of $8093C8:\n\n");
2331 for(int i=0x8093C8; i<0x809900; i+=4)
2332 WriteLog("%06X: %08X\n", i, JaguarReadLong(i));//*/
2333/* WriteLog("\n\nM68000 disassembly at $90006C...\n");
2334 jaguar_dasm(0x90006C, 500);
2335 WriteLog("\n");//*/
2336/* WriteLog("\n\nM68000 disassembly at $1AC000...\n");
2337 jaguar_dasm(0x1AC000, 6000);
2338 WriteLog("\n");//*/
2339
2340// WriteLog("Jaguar: CD BIOS version %04X\n", JaguarReadWord(0x3004));
2341 WriteLog("Jaguar: Interrupt enable = $%02X\n", TOMReadByte(0xF000E1, JAGUAR) & 0x1F);
2342 WriteLog("Jaguar: Video interrupt is %s (line=%u)\n", ((TOMIRQEnabled(IRQ_VIDEO))
2343 && (JaguarInterruptHandlerIsValid(64))) ? "enabled" : "disabled", TOMReadWord(0xF0004E, JAGUAR));
2344 M68K_show_context();
2345//#endif
2346
2347 CDROMDone();
2348 GPUDone();
2349 DSPDone();
2350 TOMDone();
2351 JERRYDone();
2352
2353 // temp, until debugger is in place
2354//00802016: jsr $836F1A.l
2355//0080201C: jsr $836B30.l
2356//00802022: jsr $836B18.l
2357//00802028: jsr $8135F0.l
2358//00813C1E: jsr $813F76.l
2359//00802038: jsr $836D00.l
2360//00802098: jsr $8373A4.l
2361//008020A2: jsr $83E24A.l
2362//008020BA: jsr $83E156.l
2363//008020C6: jsr $83E19C.l
2364//008020E6: jsr $8445E8.l
2365//008020EC: jsr $838C20.l
2366//0080211A: jsr $838ED6.l
2367//00802124: jsr $89CA56.l
2368//0080212A: jsr $802B48.l
2369#if 0
2370 WriteLog("-------------------------------------------\n");
2371 JaguarDasm(0x8445E8, 0x200);
2372 WriteLog("-------------------------------------------\n");
2373 JaguarDasm(0x838C20, 0x200);
2374 WriteLog("-------------------------------------------\n");
2375 JaguarDasm(0x838ED6, 0x200);
2376 WriteLog("-------------------------------------------\n");
2377 JaguarDasm(0x89CA56, 0x200);
2378 WriteLog("-------------------------------------------\n");
2379 JaguarDasm(0x802B48, 0x200);
2380 WriteLog("\n\nM68000 disassembly at $802000...\n");
2381 JaguarDasm(0x802000, 6000);
2382 WriteLog("\n");//*/
2383#endif
2384/* WriteLog("\n\nM68000 disassembly at $6004...\n");
2385 JaguarDasm(0x6004, 10000);
2386 WriteLog("\n");//*/
2387// WriteLog("\n\nM68000 disassembly at $802000...\n");
2388// JaguarDasm(0x802000, 0x1000);
2389// WriteLog("\n\nM68000 disassembly at $4100...\n");
2390// JaguarDasm(0x4100, 200);
2391// WriteLog("\n\nM68000 disassembly at $800800...\n");
2392// JaguarDasm(0x800800, 0x1000);
2393}
2394
2395
2396// Temp debugging stuff
2397
2398void DumpMainMemory(void)
2399{
2400 FILE * fp = fopen("./memdump.bin", "wb");
2401
2402 if (fp == NULL)
2403 return;
2404
2405 fwrite(jaguarMainRAM, 1, vjs.DRAM_size, fp);
2406 fclose(fp);
2407}
2408
2409
2410uint8_t * GetRamPtr(void)
2411{
2412 return jaguarMainRAM;
2413}
2414
2415
2416//
2417// New Jaguar execution stack
2418// This executes 1 frame's worth of code.
2419//
2420bool frameDone;
2421void JaguarExecuteNew(void)
2422{
2423 frameDone = false;
2424
2425 do
2426 {
2427 double timeToNextEvent = GetTimeToNextEvent();
2428//WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent));
2429
2430 m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2431
2432 if (vjs.GPUEnabled)
2433 GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
2434
2435 HandleNextEvent();
2436 }
2437 while (!frameDone);
2438}
2439
2440
2441// Step over function
2442void JaguarStepOver(int depth)
2443{
2444 bool exit;
2445 //bool case55 = false;
2446 //uint32_t m68kSR;
2447
2448 if (!depth)
2449 {
2450 exit = true;
2451 }
2452 else
2453 {
2454 exit = false;
2455 }
2456
2457 do
2458 {
2459 JaguarStepInto();
2460
2461 switch (M68KGetCurrentOpcodeFamily())
2462 {
2463 // rts
2464 case 49:
2465 //if (depth)
2466 {
2467 //if (!--depth)
2468 {
2469 exit = true;
2470 }
2471 //exit = false;
2472 }
2473 break;
2474
2475#if 0
2476 // bcc
2477 case 55:
2478 if (!depth)
2479 {
2480 //m68kSR = m68k_get_reg(NULL, M68K_REG_SR);
2481 if (m68k_get_reg(NULL, M68K_REG_SR) & 0x4)
2482 {
2483 exit = true;
2484 }
2485 else
2486 {
2487 exit = false;
2488 }
2489 }
2490 break;
2491#endif
2492
2493 // bsr & jsr
2494 case 54:
2495 case 52:
2496 JaguarStepOver(depth+1);
2497 //if (depth)
2498 //{
2499 // exit = false;
2500 //}
2501 break;
2502
2503 default:
2504 //if (case55)
2505 //{
2506 // exit = true;
2507 //}
2508 break;
2509 }
2510 }
2511 while (!exit);
2512
2513#ifdef _MSC_VER
2514#pragma message("Warning: !!! Need to verify the Jaguar Step Over function !!!")
2515#else
2516 #warning "!!! Need to verify the Jaguar Step Over function !!!"
2517#endif // _MSC_VER
2518}
2519
2520
2521// Step into function
2522void JaguarStepInto(void)
2523{
2524 // double timeToNextEvent = GetTimeToNextEvent();
2525
2526 m68k_execute(USEC_TO_M68K_CYCLES(0));
2527// m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent));
2528
2529 if (vjs.GPUEnabled)
2530 GPUExec(USEC_TO_RISC_CYCLES(0));
2531
2532// HandleNextEvent();
2533#ifdef _MSC_VER
2534#pragma message("Warning: !!! Need to verify the Jaguar Step Into function !!!")
2535#else
2536#warning "!!! Need to verify the Jaguar Step Into function !!!"
2537#endif // _MSC_VER
2538}
2539
2540
2541//
2542// The thing to keep in mind is that the VC is advanced every HALF line,
2543// regardless of whether the display is interlaced or not. The only difference
2544// with an interlaced display is that the high bit of VC will be set when the
2545// lower field is being rendered. (NB: The high bit of VC is ALWAYS set on the
2546// lower field, regardless of whether it's in interlace mode or not.
2547// NB2: Seems it doesn't always, not sure what the constraint is...)
2548//
2549// Normally, TVs will render a full frame in 1/30s (NTSC) or 1/25s (PAL) by
2550// rendering two fields that are slighty vertically offset from each other.
2551// Each field is created in 1/60s (NTSC) or 1/50s (PAL), and every other line
2552// is rendered in this mode so that each field, when overlaid on each other,
2553// will yield the final picture at the full resolution for the full frame.
2554//
2555// We execute a half frame in each timeslice (1/60s NTSC, 1/50s PAL).
2556// Since the number of lines in a FULL frame is 525 for NTSC, 625 for PAL,
2557// it will be half this number for a half frame. BUT, since we're counting
2558// HALF lines, we double this number and we're back at 525 for NTSC, 625 for
2559// PAL.
2560//
2561// Scanline times are 63.5555... μs in NTSC and 64 μs in PAL
2562// Half line times are, naturally, half of this. :-P
2563//
2564void HalflineCallback(void)
2565{
2566 uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
2567 uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
2568 uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);
2569// uint16_t vbb = TOMReadWord(0xF00040, JAGUAR);
2570 vc++;
2571
2572 // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL).
2573 // So we cut the number of half-lines in a frame in half. :-P
2574 uint16_t numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2;
2575
2576 if ((vc & 0x7FF) >= numHalfLines)
2577 {
2578 lowerField = !lowerField;
2579 // If we're rendering the lower field, set the high bit (#11, counting
2580 // from 0) of VC
2581 vc = (lowerField ? 0x0800 : 0x0000);
2582 }
2583
2584//WriteLog("HLC: Currently on line %u (VP=%u)...\n", vc, vp);
2585 TOMWriteWord(0xF00006, vc, JAGUAR);
2586
2587 // Time for Vertical Interrupt?
2588 if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0 && TOMIRQEnabled(IRQ_VIDEO))
2589 {
2590 // We don't have to worry about autovectors & whatnot because the Jaguar
2591 // tells you through its HW registers who sent the interrupt...
2592 TOMSetPendingVideoInt();
2593 m68k_set_irq(2);
2594 }
2595
2596 TOMExecHalfline(vc, true);
2597
2598//Change this to VBB???
2599//Doesn't seem to matter (at least for Flip Out & I-War)
2600 if ((vc & 0x7FF) == 0)
2601// if (vc == vbb)
2602 {
2603 JoystickExec();
2604 frameDone = true;
2605 }//*/
2606
2607 SetCallbackTime(HalflineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0));
2608}
2609