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