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