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