Update the breakpoint feature
[clinton/Virtual-Jaguar-Rx.git] / src / mmu.cpp
CommitLineData
cf76e892
JPM
1//
2// mmu.cpp
3//
4// Jaguar Memory Manager Unit
5//
6// by James Hammons
7//
8// JLH = James Hammons <jlhamm@acm.org>
9//
10// WHO WHEN WHAT
11// --- ---------- -----------------------------------------------------------
12// JLH 11/25/2009 Created this file. :-)
13//
14
15#include "mmu.h"
16
17#include <stdlib.h> // For NULL definition
18#include "dac.h"
19//#include "jaguar.h"
20//#include "memory.h"
21#include "jagbios.h"
22#include "wavetable.h"
23
24
25#ifdef USE_NEW_MMU
26
27/*
28Addresses to be handled:
29
30SYSTEM SETUP REGISTERS
31
32*MEMCON1 Memory Control Register 1 F00000 RW
33*MEMCON2 Memory Control Register 2 F00002 RW
34HC Horizontal Count F00004 RW
35VC Vertical Count F00006 RW
36LPH Light Pen Horizontal F00008 RO
37LPV Light Pen Vertical F0000A RO
38OB[0-3] Object Data Field F00010-16 RO
39OLP Object List Pointer F00020-23 WO
40OBF Object Flag F00026 WO
41VMODE Video Mode F00028 WO
42BORD1 Border Colour (Red & Green) F0002A WO
43BORD2 Border Colour (Blue) F0002C WO
44*HP Horizontal Period F0002E WO
45*HBB Horizontal Blank Begin F00030 WO
46*HBE Horizontal Blank End F00032 WO
47*HS Horizontal Sync F00034 WO
48*HVS Horizontal Vertical Sync F00036 WO
49HDB1 Horizontal Display Begin 1 F00038 WO
50HDB2 Horizontal Display Begin 2 F0003A WO
51HDE Horizontal Display End F0003C WO
52*VP Vertical Period F0003E WO
53*VBB Vertical Blank Begin F00040 WO
54*VBE Vertical Blank End F00042 WO
55*VS Vertical Sync F00044 WO
56VDB Vertical Display Begin F00046 WO
57VDE Vertical Display End F00048 WO
58*VEB Vertical Equalization Begin F0004A WO
59*VEE Vertical Equalization End F0004C WO
60VI Vertical Interrupt F0004E WO
61PIT[0-1] Programmable Interrupt Timer F00050-52 WO
62*HEQ Horizontal Equalization End F00054 WO
63BG Background Colour F00058 WO
64INT1 CPU Interrupt Control Register F000E0 RW
65INT2 CPU Interrupt Resume Register F000E2 WO
66CLUT Colour Look-Up Table F00400-7FE RW
67LBUF Line Buffer F00800-1D9E RW
68
69GPU REGISTERS
70
71G_FLAGS GPU Flags Register F02100 RW
72G_MTXC Matrix Control Register F02104 WO
73G_MTXA Matrix Address Register F02108 WO
74G_END Data Organization Register F0210C WO
75G_PC GPU Program Counter F02110 RW
76G_CTRL GPU Control/Status Register F02114 RW
77G_HIDATA High Data Register F02118 RW
78G_REMAIN Divide Unit Remainder F0211C RO
79G_DIVCTRL Divide Unit Control F0211C WO
80
81BLITTER REGISTERS
82
83A1_BASE A1 Base Register F02200 WO
84A1_FLAGS Flags Register F02204 WO
85A1_CLIP A1 Clipping Size F02208 WO
86A1_PIXEL A1 Pixel Pointer F0220C WO
87 F02204 RO
88A1_STEP A1 Step Value F02210 WO
89A1_FSTEP A1 Step Fraction Value F02214 WO
90A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
91A1_INC A1 Increment F0221C WO
92A1_FINC A1 Increment Fraction F02220 WO
93A2_BASE A2 Base Register F02224 WO
94A2_FLAGS A2 Flags Register F02228 WO
95A2_MASK A2 Window Mask F0222C WO
96A2_PIXEL A2 Pixel Pointer F02230 WO
97 F0222C RO
98A2_STEP A2 Step Value F02234 WO
99B_CMD Command/Status Register F02238 RW
100B_COUNT Counters Register F0223C WO
101B_SRCD Source Data Register F02240 WO
102B_DSTD Destination Data Register F02248 WO
103B_DSTZ Destination Z Register F02250 WO
104B_SRCZ1 Source Z Register 1 F02258 WO
105B_SRCZ2 Source Z Register 2 F02260 WO
106B_PATD Pattern Data Register F02268 WO
107B_IINC Intensity Increment F02270 WO
108B_ZINC Z Increment F02274 WO
109B_STOP Collision Control F02278 WO
110B_I3 Intensity 3 F0227C WO
111B_I2 Intensity 2 F02280 WO
112B_I1 Intensity 1 F02284 WO
113B_I0 Intensity 0 F02288 WO
114B_Z3 Z 3 F0228C WO
115B_Z2 Z 2 F02290 WO
116B_Z1 Z 1 F02294 WO
117B_Z0 Z 0 F02298 WO
118
119JERRY REGISTERS
120
121*CLK1 Processor Clock Divider F10010 WO
122*CLK2 Video Clock Divider F10012 WO
123*CLK3 Chroma Clock Divider F10014 WO
124JPIT1 Timer 1 Pre-scaler F10000 WO
125JPIT3 Timer 2 Pre-scaler F10004 WO
126JPIT2 Timer 1 Divider F10002 WO
127JPIT4 Timer 2 Divider F10006 WO
128J_INT Interrup Control Register F10020 RW
129SCLK Serial Clock Frequency F1A150 WO
130SMODE Serial Mode F1A154 WO
131LTXD Left Transmit Data F1A148 WO
132RTXD Right Transmit Data F1A14C WO
133LRXD Left Receive Data F1A148 RO
134RRXD Right Receive Data F1A14C RO
135L_I2S Left I2S Serial Interface F1A148 RW
136R_I2S Right I2S Serial Interface F1A14C RW
137SSTAT Serial Status F1A150 RO
138ASICLK Asynchronous Serial Interface Clock F10034 RW
139ASICTRL Asynchronous Serial Control F10032 WO
140ASISTAT Asynchronous Serial Status F10032 RO
141ASIDATA Asynchronous Serial Data F10030 RW
142
143JOYSTICK REGISTERS
144
145JOYSTICK Joystick Register F14000 RW
146JOYBUTS Button Register F14002 RW
147
148DSP REGISTERS
149
150D_FLAGS DSP Flags Register F1A100 RW
151D_MTXC DSP Matrix Control Register F1A104 WO
152D_MTXA DSP Matrix Address Register F1A108 WO
153D_END DSP Data Organization Register F1A10C WO
154D_PC DSP Program Counter F1A110 RW
155D_CTRL DSP Control/Status Register F1A114 RW
156D_MOD Modulo Instruction Mask F1A118 WO
157D_REMAIN Divide Unit Remainder F1A11C RO
158D_DIVCTRL Divide Unit Control F1A11C WO
159D_MACHI MAC High Result Bits F1A120 RO
160*/
161
162/*
163The approach here is to have a list of addresses and who handles them. Could be
164a one-to-one memory location up to a range for each function. Will look
165something like this:
166
167 { 0xF14000, 0xF14001, MM_IO, JoystickReadHandler, JoystickWriteHandler },
168
169Would be nice to have a way of either calling a handler function or reading/writing
170directly to/from a variable or array...
171*/
172
173enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
174
175/*
176Would be nice to have different structs tailored to different memory access types,
177but if we don't do that, we can encode things as follows:
178
179MM_NOP: readFunc = writeFunc = NULL
180MM_RAM: readFunc = byte array pointer, writeFunc = NULL
181MM_ROM: readFunc = byte array pointer, writeFunc = NULL
182MM_IO_R: readFunc = function pointer to read function, writeFunc = NULL
183MM_IO_W: readFunc = NULL, writeFunc = function pointer to write function
184MM_IO: readFunc = function pointer to read function, writeFunc = function pointer to write function
185
186There may be a need to have readFunc do both read & write functions (makes sense? perhaps)
187
188Should we have a read mask as well, for the purposes of reading?
189*/
190
191struct MemDesc {
192 uint32_t startAddr;
193 uint32_t endAddr;
194 MemType type;
195// (void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
196 void * readFunc; // This is read & write with MM_IO
197 void * writeFunc;
198 uint32_t mask;
199};
200
201
202MemDesc memoryMap[] = {
203 { 0x000000, 0x1FFFFF, MM_RAM, jaguarMainRAM },
204 { 0x200000, 0x3FFFFF, MM_RAM, jaguarMainRAM }, // Mirror of 1st 2 megs or next 2nd 2 megs of ram
205 { 0x400000, 0x5FFFFF, MM_RAM, jaguarMainRAM }, // " " or next 3rd 2 megs of ram
206 { 0x600000, 0x7FFFFF, MM_RAM, jaguarMainRAM }, // " " or next 4th 2 megs of ram
207 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
208
209 { 0xDFFF00, 0xDFFF03, MM_IO, &butch }, // base of Butch == interrupt control register, R/W
210 { 0xDFFF04, 0xDFFF07, MM_IO, &dscntrl }, // DSA control register, R/W
211 { 0xDFFF0A, 0xDFFF0B, MM_IO, &ds_data }, // DSA TX/RX data, R/W
212 { 0xDFFF10, 0xDFFF13, MM_IO, &i2cntrl }, // i2s bus control register, R/W
213 { 0xDFFF14, 0xDFFF17, MM_IO, &sbcntrl }, // CD subcode control register, R/W
214 { 0xDFFF18, 0xDFFF1B, MM_IO, &subdata }, // Subcode data register A
215 { 0xDFFF1C, 0xDFFF1F, MM_IO, &subdatb }, // Subcode data register B
216 { 0xDFFF20, 0xDFFF23, MM_IO, &sb_time }, // Subcode time and compare enable (D24)
217 { 0xDFFF24, 0xDFFF27, MM_IO, &fifo_data }, // i2s FIFO data
218 { 0xDFFF28, 0xDFFF2B, MM_IO, &i2sdat2 }, // i2s FIFO data (old)
219 { 0xDFFF2C, 0xDFFF2F, MM_IO, &unknown }, // Seems to be some sort of I2S interface
220
221 { 0xE00000, 0xE1FFFF, MM_ROM, jaguarBootROM },
222
223 // TOM REGISTERS
224
225 { 0xF00000, 0xF00001, MM_IO, &memcon1 }, // *MEMCON1 Memory Control Register 1 F00000 RW
226 { 0xF00002, 0xF00003, MM_IO, &memcon2 }, // *MEMCON2 Memory Control Register 2 F00002 RW
227 { 0xF00004, 0xF00005, MM_IO, &hc }, // HC Horizontal Count F00004 RW
228 { 0xF00006, 0xF00007, MM_IO, &vc }, // VC Vertical Count F00006 RW
229 { 0xF00008, 0xF00009, MM_IO_R, &lph }, // LPH Light Pen Horizontal F00008 RO
230 { 0xF0000A, 0xF0000B, MM_IO_R, &lpv }, // LPV Light Pen Vertical F0000A RO
231 { 0xF00010, 0xF00017, MM_IO_R, &obData }, // OB[0-3] Object Data Field F00010-16 RO
232 { 0xF00020, 0xF00023, MM_IO_W, &olp }, // OLP Object List Pointer F00020-23 WO
233 { 0xF00026, 0xF00027, MM_IO_W, &obf }, // OBF Object Flag F00026 WO
234 { 0xF00028, 0xF00029, MM_IO_W, &vmode }, // VMODE Video Mode F00028 WO
235 { 0xF0002A, 0xF0002B, MM_IO_W, &bord1 }, // BORD1 Border Colour (Red & Green) F0002A WO
236 { 0xF0002C, 0xF0002D, MM_IO_W, &bord2 }, // BORD2 Border Colour (Blue) F0002C WO
237 { 0xF0002E, 0xF0002F, MM_IO_W, &hp }, // *HP Horizontal Period F0002E WO
238 { 0xF00030, 0xF00031, MM_IO_W, &hbb }, // *HBB Horizontal Blank Begin F00030 WO
239 { 0xF00032, 0xF00033, MM_IO_W, &hbe }, // *HBE Horizontal Blank End F00032 WO
240 { 0xF00034, 0xF00035, MM_IO_W, &hs }, // *HS Horizontal Sync F00034 WO
241 { 0xF00036, 0xF00037, MM_IO_W, &hvs }, // *HVS Horizontal Vertical Sync F00036 WO
242 { 0xF00038, 0xF00039, MM_IO_W, &hdb1 }, // HDB1 Horizontal Display Begin 1 F00038 WO
243 { 0xF0003A, 0xF0003B, MM_IO_W, &hdb2 }, // HDB2 Horizontal Display Begin 2 F0003A WO
244 { 0xF0003C, 0xF0003D, MM_IO_W, &hde }, // HDE Horizontal Display End F0003C WO
245 { 0xF0003E, 0xF0003F, MM_IO_W, &vp }, // *VP Vertical Period F0003E WO
246 { 0xF00040, 0xF00041, MM_IO_W, &vbb }, // *VBB Vertical Blank Begin F00040 WO
247 { 0xF00042, 0xF00043, MM_IO_W, &vbe }, // *VBE Vertical Blank End F00042 WO
248 { 0xF00044, 0xF00045, MM_IO_W, &vs }, // *VS Vertical Sync F00044 WO
249 { 0xF00046, 0xF00047, MM_IO_W, &vdb }, // VDB Vertical Display Begin F00046 WO
250 { 0xF00048, 0xF00049, MM_IO_W, &vde }, // VDE Vertical Display End F00048 WO
251 { 0xF0004A, 0xF0004B, MM_IO_W, &veb }, // *VEB Vertical Equalization Begin F0004A WO
252 { 0xF0004C, 0xF0004D, MM_IO_W, &vee }, // *VEE Vertical Equalization End F0004C WO
253 { 0xF0004E, 0xF0004F, MM_IO_W, &vi }, // VI Vertical Interrupt F0004E WO
254 { 0xF00050, 0xF00051, MM_IO_W, &pit0 }, // PIT[0-1] Programmable Interrupt Timer F00050-52 WO
255 { 0xF00052, 0xF00053, MM_IO_W, &pit1 },
256 { 0xF00054, 0xF00055, MM_IO_W, &heq }, // *HEQ Horizontal Equalization End F00054 WO
257 { 0xF00058, 0xF0005B, MM_IO_W, &bg }, // BG Background Colour F00058 WO
258 { 0xF000E0, 0xF000E1, MM_IO, &int1 }, // INT1 CPU Interrupt Control Register F000E0 RW
259 { 0xF000E2, 0xF000E3, MM_IO_W, &int2 }, // INT2 CPU Interrupt Resume Register F000E2 WO
260//Some of these RAM spaces may be 16- or 32-bit only... in which case, we need
261//to cast appropriately (in memory.cpp, that is)...
262 { 0xF00400, 0xF005FF, MM_RAM, clut }, // CLUT Colour Look-Up Table F00400-7FE RW
263 { 0xF00600, 0xF007FF, MM_RAM, clut },
264 { 0xF00800, 0xF01D9F, MM_RAM, lbuf }, // LBUF Line Buffer F00800-1D9E RW
265//Need high speed RAM interface for GPU & DSP (we have it now...)
266
267 // GPU REGISTERS
268
269 { 0xF02100, 0xF02103, MM_IO, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
270 { 0xF02104, 0xF02107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
271 { 0xF02108, 0xF0210B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
272 { 0xF0210C, 0xF0210F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
273 { 0xF02110, 0xF02113, MM_IO, &g_pc }, // G_PC GPU Program Counter F02110 RW
274 { 0xF02114, 0xF02117, MM_IO, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
275 { 0xF02118, 0xF0211B, MM_IO, &g_hidata }, // G_HIDATA High Data Register F02118 RW
276 { 0xF0211C, 0xF0211F, MM_IO, &g_remain, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
277 // G_DIVCTRL Divide Unit Control F0211C WO
278 { 0xF03000, 0xF03FFF, MM_RAM, gpuRAM },
279
280 // BLITTER REGISTERS
281
282 { 0xF02200, 0xF02203, MM_IO_W, &a1_base }, // A1_BASE A1 Base Register F02200 WO
283 { 0xF02204, 0xF02207, MM_IO, &a1_pixel, &a1_flags }, // A1_FLAGS Flags Register F02204 WO
284 { 0xF02208, 0xF0220B, MM_IO_W, &a1_clip }, // A1_CLIP A1 Clipping Size F02208 WO
285 { 0xF0220C, 0xF0220F, MM_IO_W, &a1_pixel }, // A1_PIXEL A1 Pixel Pointer F0220C WO
286// F02204 RO
287 { 0xF02210, 0xF02213, MM_IO_W, &a1_step }, // A1_STEP A1 Step Value F02210 WO
288 { 0xF02214, 0xF02217, MM_IO_W, &a1_fstep }, // A1_FSTEP A1 Step Fraction Value F02214 WO
289 { 0xF02218, 0xF0221B, MM_IO, &a1_fpixel }, // A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
290 { 0xF0221C, 0xF0221F, MM_IO_W, &a1_inc }, // A1_INC A1 Increment F0221C WO
291 { 0xF02220, 0xF02223, MM_IO_W, &a1_finc }, // A1_FINC A1 Increment Fraction F02220 WO
292 { 0xF02224, 0xF02227, MM_IO_W, &a2_base }, // A2_BASE A2 Base Register F02224 WO
293 { 0xF02228, 0xF0222B, MM_IO_W, &a2_flags }, // A2_FLAGS A2 Flags Register F02228 WO
294 { 0xF0222C, 0xF0222F, MM_IO, &a2_pixel, &a2_mask }, // A2_MASK A2 Window Mask F0222C WO
295 { 0xF02230, 0xF02233, MM_IO_W, &a2_pixel }, // A2_PIXEL A2 Pixel Pointer F02230 WO
296// F0222C RO
297 { 0xF02234, 0xF02237, MM_IO_W, &a2_step }, // A2_STEP A2 Step Value F02234 WO
298 { 0xF02238, 0xF0223B, MM_IO, &b_cmd }, // B_CMD Command/Status Register F02238 RW
299 { 0xF0223C, 0xF0223F, MM_IO_W, &b_count }, // B_COUNT Counters Register F0223C WO
300 { 0xF02240, 0xF02247, MM_IO_W, &b_srcd }, // B_SRCD Source Data Register F02240 WO
301 { 0xF02248, 0xF0224F, MM_IO_W, &b_dstd }, // B_DSTD Destination Data Register F02248 WO
302 { 0xF02250, 0xF02258, MM_IO_W, &b_dstz }, // B_DSTZ Destination Z Register F02250 WO
303 { 0xF02258, 0xF0225F, MM_IO_W, &b_srcz1 }, // B_SRCZ1 Source Z Register 1 F02258 WO
304 { 0xF02260, 0xF02267, MM_IO_W, &b_srcz2 }, // B_SRCZ2 Source Z Register 2 F02260 WO
305 { 0xF02268, 0xF0226F, MM_IO_W, &b_patd }, // B_PATD Pattern Data Register F02268 WO
306 { 0xF02270, 0xF02273, MM_IO_W, &b_iinc }, // B_IINC Intensity Increment F02270 WO
307 { 0xF02274, 0xF02277, MM_IO_W, &b_zinc }, // B_ZINC Z Increment F02274 WO
308 { 0xF02278, 0xF0227B, MM_IO_W, &b_stop }, // B_STOP Collision Control F02278 WO
309 { 0xF0227C, 0xF0227F, MM_IO_W, &b_i3 }, // B_I3 Intensity 3 F0227C WO
310 { 0xF02280, 0xF02283, MM_IO_W, &b_i2 }, // B_I2 Intensity 2 F02280 WO
311 { 0xF02284, 0xF02287, MM_IO_W, &b_i1 }, // B_I1 Intensity 1 F02284 WO
312 { 0xF02288, 0xF0228B, MM_IO_W, &b_i0 }, // B_I0 Intensity 0 F02288 WO
313 { 0xF0228C, 0xF0228F, MM_IO_W, &b_z3 }, // B_Z3 Z 3 F0228C WO
314 { 0xF02290, 0xF02293, MM_IO_W, &b_z2 }, // B_Z2 Z 2 F02290 WO
315 { 0xF02294, 0xF02297, MM_IO_W, &b_z1 }, // B_Z1 Z 1 F02294 WO
316 { 0xF02298, 0xF0229B, MM_IO_W, &b_z0 }, // B_Z0 Z 0 F02298 WO
317
318// JTRM sez ALL GPU address space is accessible from $8000 offset as "fast" 32-bit WO access
319// Dunno if anything actually USED it tho... :-P
320 { 0xF0A100, 0xF0A103, MM_IO_W, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
321 { 0xF0A104, 0xF0A107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
322 { 0xF0A108, 0xF0A10B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
323 { 0xF0A10C, 0xF0A10F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
324 { 0xF0A110, 0xF0A113, MM_IO_W, &g_pc }, // G_PC GPU Program Counter F02110 RW
325 { 0xF0A114, 0xF0A117, MM_IO_W, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
326 { 0xF0A118, 0xF0A11B, MM_IO_W, &g_hidata }, // G_HIDATA High Data Register F02118 RW
327 { 0xF0A11C, 0xF0A11F, MM_IO_W, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
328 { 0xF0B000, 0xF0BFFF, MM_IO_W, gpuRAM }, // "Fast" interface to GPU RAM
329
330 // JERRY REGISTERS
331
332 { 0xF10000, 0xF10001, MM_IO_W, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10000 WO
333 { 0xF10002, 0xF10003, MM_IO_W, &jpit2 }, // JPIT2 Timer 1 Divider F10002 WO
334 { 0xF10004, 0xF10005, MM_IO_W, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F10004 WO
335 { 0xF10006, 0xF10007, MM_IO_W, &jpit4 }, // JPIT4 Timer 2 Divider F10006 WO
336 { 0xF10010, 0xF10011, MM_IO_W, &clk1 }, // *CLK1 Processor Clock Divider F10010 WO
337 { 0xF10012, 0xF10013, MM_IO_W, &clk2 }, // *CLK2 Video Clock Divider F10012 WO
338 { 0xF10014, 0xF10015, MM_IO_W, &clk3 }, // *CLK3 Chroma Clock Divider F10014 WO
339 { 0xF10020, 0xF10021, MM_IO, &j_int }, // J_INT Interrup Control Register F10020 RW
340 { 0xF10030, 0xF10031, MM_IO, &asidata }, // ASIDATA Asynchronous Serial Data F10030 RW
341 { 0xF10032, 0xF10033, MM_IO, &asistat, &asictrl }, // ASICTRL Asynchronous Serial Control F10032 WO
342 // ASISTAT Asynchronous Serial Status F10032 RO
343 { 0xF10034, 0xF10035, MM_IO, &asiclk }, // ASICLK Asynchronous Serial Interface Clock F10034 RW
344 { 0xF10036, 0xF10037, MM_IO_R, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10036 RO
345 { 0xF10038, 0xF10039, MM_IO_R, &jpit2 }, // JPIT2 Timer 1 Divider F10038 RO
346 { 0xF1003A, 0xF1003B, MM_IO_R, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F1003A RO
347 { 0xF1003C, 0xF1003D, MM_IO_R, &jpit4 }, // JPIT4 Timer 2 Divider F1003C RO
348
349 { 0xF14000, 0xF14001, MM_IO, &joystick }, // JOYSTICK Joystick Register F14000 RW
350 { 0xF14002, 0xF14003, MM_IO, &joybuts }, // JOYBUTS Button Register F14002 RW
351
352 // DSP REGISTERS
353
354 { 0xF1A100, 0xF1A103, MM_IO, &d_flags }, // D_FLAGS DSP Flags Register F1A100 RW
355 { 0xF1A104, 0xF1A107, MM_IO_W, &d_mtxc }, // D_MTXC DSP Matrix Control Register F1A104 WO
356 { 0xF1A108, 0xF1A10B, MM_IO_W, &d_mtxa }, // D_MTXA DSP Matrix Address Register F1A108 WO
357 { 0xF1A10C, 0xF1A10F, MM_IO_W, &d_end }, // D_END DSP Data Organization Register F1A10C WO
358 { 0xF1A110, 0xF1A113, MM_IO, &d_pc }, // D_PC DSP Program Counter F1A110 RW
359 { 0xF1A114, 0xF1A117, MM_IO, &d_ctrl }, // D_CTRL DSP Control/Status Register F1A114 RW
360 { 0xF1A118, 0xF1A11B, MM_IO_W, &d_mod }, // D_MOD Modulo Instruction Mask F1A118 WO
361 { 0xF1A11C, 0xF1A11F, MM_IO_W, &d_remain, &d_divctrl }, // D_REMAIN Divide Unit Remainder F1A11C RO
362 // D_DIVCTRL Divide Unit Control F1A11C WO
363 { 0xF1A120, 0xF1A123, MM_IO_R, &d_machi }, // D_MACHI MAC High Result Bits F1A120 RO
364
365
366 { 0xF1A148, 0xF1A149, MM_IO, &lrxd, &ltxd }, // LTXD Left Transmit Data F1A148 WO
367 // LRXD Left Receive Data F1A148 RO
368 // L_I2S Left I2S Serial Interface F1A148 RW
369 { 0xF1A14C, 0xF1A14D, MM_IO, &rrxd, &rtxd }, // RTXD Right Transmit Data F1A14C WO
370 // RRXD Right Receive Data F1A14C RO
371 // R_I2S Right I2S Serial Interface F1A14C RW
372 { 0xF1A150, 0xF1A150, MM_IO, &sstat, &sclk }, // SCLK Serial Clock Frequency F1A150 WO
373 // SSTAT Serial Status F1A150 RO
374 { 0xF1A154, 0xF1A157, MM_IO_W, &smode }, // SMODE Serial Mode F1A154 WO
375
376 { 0xF1B000, 0xF1CFFF, MM_RAM, dspRAM }, // F1B000-F1CFFF R/W xxxxxxxx xxxxxxxx Local DSP RAM
377 { 0xF1D000, 0xF1DFFF, MM_ROM, waveTableROM },
378// hi-speed interface for DSP??? Ain't no such thang...
379 { 0xFFFFFF, 0xFFFFFF, MM_NOP } // End of memory address sentinel
380};
381
382#if 0
383
384// Jaguar Memory map/handlers
385uint32_t memoryMap[] = {
386 { 0x000000, 0x3FFFFF, MM_RAM, jaguarMainRAM },
387 { 0x800000, 0xDFFEFF, MM_ROM, jaguarMainROM },
388// Note that this is really memory mapped I/O region...
389// { 0xDFFF00, 0xDFFFFF, MM_RAM, cdRAM },
390 { 0xDFFF00, 0xDFFF03, MM_IO, cdBUTCH }, // base of Butch == interrupt control register, R/W
391 { 0xDFFF04, 0xDFFF07, MM_IO, cdDSCNTRL }, // DSA control register, R/W
392 { 0xDFFF0A, 0xDFFF0B, MM_IO, cdDS_DATA }, // DSA TX/RX data, R/W
393 { 0xDFFF10, 0xDFFF13, MM_IO, cdI2CNTRL }, // i2s bus control register, R/W
394 { 0xDFFF14, 0xDFFF17, MM_IO, cdSBCNTRL }, // CD subcode control register, R/W
395 { 0xDFFF18, 0xDFFF1B, MM_IO, cdSUBDATA }, // Subcode data register A
396 { 0xDFFF1C, 0xDFFF1F, MM_IO, cdSUBDATB }, // Subcode data register B
397 { 0xDFFF20, 0xDFFF23, MM_IO, cdSB_TIME }, // Subcode time and compare enable (D24)
398 { 0xDFFF24, 0xDFFF27, MM_IO, cdFIFO_DATA }, // i2s FIFO data
399 { 0xDFFF28, 0xDFFF2B, MM_IO, cdI2SDAT2 }, // i2s FIFO data (old)
400 { 0xDFFF2C, 0xDFFF2F, MM_IO, cdUNKNOWN }, // Seems to be some sort of I2S interface
401
402 { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
403
404// { 0xF00000, 0xF0FFFF, MM_IO, TOM_REGS_RW },
405 { 0xF00050, 0xF00051, MM_IO, tomTimerPrescaler },
406 { 0xF00052, 0xF00053, MM_IO, tomTimerDivider },
407 { 0xF00400, 0xF005FF, MM_RAM, tomRAM }, // CLUT A&B: How to link these? Write to one writes to the other...
408 { 0xF00600, 0xF007FF, MM_RAM, tomRAM }, // Actually, this is a good approach--just make the reads the same as well
409 //What about LBUF writes???
410 { 0xF02100, 0xF0211F, MM_IO, GPUWriteByte }, // GPU CONTROL
411 { 0xF02200, 0xF0229F, MM_IO, BlitterWriteByte }, // BLITTER
412 { 0xF03000, 0xF03FFF, MM_RAM, GPUWriteByte }, // GPU RAM
413
414 { 0xF10000, 0xF1FFFF, MM_IO, JERRY_REGS_RW },
415
416/*
417 EEPROM:
418 { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
419 { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
420 { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
421
422 JOYSTICK:
423 { 0xF14000, 0xF14003, MM_IO, joystickFoo }
424 0 = pad0/1 button values (4 bits each), RO(?)
425 1 = pad0/1 index value (4 bits each), WO
426 2 = unused, RO
427 3 = NTSC/PAL, certain button states, RO
428
429JOYSTICK $F14000 Read/Write
430 15.....8 7......0
431Read fedcba98 7654321q f-1 Signals J15 to J1
432 q Cartridge EEPROM output data
433Write exxxxxxm 76543210 e 1 = enable J7-J0 outputs
434 0 = disable J7-J0 outputs
435 x don't care
436 m Audio mute
437 0 = Audio muted (reset state)
438 1 = Audio enabled
439 7-4 J7-J4 outputs (port 2)
440 3-0 J3-J0 outputs (port 1)
441JOYBUTS $F14002 Read Only
442 15.....8 7......0
443Read xxxxxxxx rrdv3210 x don't care
444 r Reserved
445 d Reserved
446 v 1 = NTSC Video hardware
447 0 = PAL Video hardware
448 3-2 Button inputs B3 & B2 (port 2)
449 1-0 Button inputs B1 & B0 (port 1)
450
451J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
452J3 J2 J1 J0 Port 1 B0 B1 J8 J9 J10 J11
453 0 0 0 0
454 0 0 0 1
455 0 0 1 0
456 0 0 1 1
457 0 1 0 0
458 0 1 0 1
459 0 1 1 0
460 0 1 1 1 Row 3 C3 Option # 9 6 3
461 1 0 0 0
462 1 0 0 1
463 1 0 1 0
464 1 0 1 1 Row 2 C2 C 0 8 5 2
465 1 1 0 0
466 1 1 0 1 Row 1 C1 B * 7 4 1
467 1 1 1 0 Row 0 Pause A Up Down Left Right
468 1 1 1 1
469
4700 bit read in any position means that button is pressed.
471C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
472*/
473};
474#endif
475
476void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
477{
478}
479
480void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
481{
482}
483
484void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
485{
486}
487
488void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
489{
490}
491
492uint8_t MMURead8(uint32_t address, uint32_t who/*= UNKNOWN*/)
493{
494 // Search for address in the memory map
495 // NOTE: This assumes that all entries are linear and sorted in ascending order!
496
497 MemDesc memory;
498 uint8_t byte = 0xFE;
499
500 uint32_t i = 0;
501 while (true)
502 {
503 if (address <= memoryMap[i].endAddr)
504 {
505 if (address >= memoryMap[i].startAddr)
506 {
507 memory = memoryMap[i];
508 break;
509 }
510 else
511 return 0xFF; // Wasn't found...
512 }
513
514 i++;
515
516 if (memoryMap[i].startAddr == 0xFFFFFF)
517 return 0xFF; // Exhausted the list, so bail!
518 }
519
520 uint32_t offset = address - memory.startAddr;
521 //uint32_t size = memory.endAddr - memory.startAddr + 1;
522 uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
523
524 if (memory.type == MM_RAM || memory.type == MM_ROM)
525 {
526 byte = ((uint8_t *)memory.readFunc)[offset];
527 }
528 else if (memory.type == MM_IO_R || memory.type == MM_IO)
529 {
530 // Problem here: We don't know yet how wide the function is, so we don't know
531 // how to properly cast it. We COULD ignore the problem by passing in/receiving
532 // 64-bits of data and letting the function make heads or tails of it, but we
533 // still have the problem of, say, taking a byte from a 32-bit value.
534/*
535We can do like so:
536 uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
537 size = memory.endAddr - memory.startAddr + 1;
538 byte = (returnValFromFunc >> byteShift[offset]) & 0xFF;
539
540Let's see, will this work depending on the endianess?
541uint32_t dword
542accessing it like so:
543((uint8_t *)dword &)[0] --> should give us high byte
544but if we assign it directly...
545dword = 0x12345678 --> becomes 78 56 34 12 in memory, ptr[0] will be 78 in LE!
546dword = 0x12345678 --> becomes 12 34 56 78 in memory, ptr[0] will be 12 in BE!
547
548So we're in danger if we use the variables directly! We'd need something like
549#define ENDIAN_SAFE_16(x) swap lo & hi bytes on LE systems
550#define ENDIAN_SAFE_16(x) do nothing on BE systems
551
552Then, if we want to use a jaguar variable, we need to cast it like so:
553uint16_t my_vbb = ENDIAN_SAFE_16(vbb);
554
555We have something like this already in jaguar.h, since we treat I/O spaces like
556contiguous memory anyway... For reference:
557
558// Some handy macros to help converting native endian to big endian (jaguar native)
559// & vice versa
560
561#define SET64(r, a, v) r[(a)] = ((v) & 0xFF00000000000000) >> 56, r[(a)+1] = ((v) & 0x00FF000000000000) >> 48, \
562 r[(a)+2] = ((v) & 0x0000FF0000000000) >> 40, r[(a)+3] = ((v) & 0x000000FF00000000) >> 32, \
563 r[(a)+4] = ((v) & 0xFF000000) >> 24, r[(a)+5] = ((v) & 0x00FF0000) >> 16, \
564 r[(a)+6] = ((v) & 0x0000FF00) >> 8, r[(a)+7] = (v) & 0x000000FF
565#define GET64(r, a) (((uint64)r[(a)] << 56) | ((uint64)r[(a)+1] << 48) | \
566 ((uint64)r[(a)+2] << 40) | ((uint64)r[(a)+3] << 32) | \
567 ((uint64)r[(a)+4] << 24) | ((uint64)r[(a)+5] << 16) | \
568 ((uint64)r[(a)+6] << 8) | (uint64)r[(a)+7])
569#define SET32(r, a, v) r[(a)] = ((v) & 0xFF000000) >> 24, r[(a)+1] = ((v) & 0x00FF0000) >> 16, \
570 r[(a)+2] = ((v) & 0x0000FF00) >> 8, r[(a)+3] = (v) & 0x000000FF
571#define GET32(r, a) ((r[(a)] << 24) | (r[(a)+1] << 16) | (r[(a)+2] << 8) | r[(a)+3])
572#define SET16(r, a, v) r[(a)] = ((v) & 0xFF00) >> 8, r[(a)+1] = (v) & 0xFF
573#define GET16(r, a) ((r[(a)] << 8) | r[(a)+1])
574*/
575 // Confused? Let me enlighten... What we're doing here is casting
576 // data1 as a pointer to a function which returns a Window pointer and
577 // which takes no parameters (the "(Window *(*)(void))" part), then
578 // derefencing it (the "*" in front of that) in order to call the
579 // function that it points to. Clear as mud? Yeah, I hate function
580 // pointers too, but what else are you gonna do?
581// mainWindow = (*(Window *(*)(void))event.user.data1)();
582// uint32_t retVal = (*(uint32(*)(uint32))memory.readFunc)(offset);
583//#define FUNC_CAST(x) (*(uint32(*)(uint32))x)
584// uint32_t retVal = FUNC_CAST(memory.readFunc)(offset);
585#define FUNC_CAST(retVal, function, params) (*(retVal(*)(params))function)
586 uint64_t retVal = FUNC_CAST(uint64_t, memory.readFunc, uint32_t)(offset);
587 byte = (retVal >> byteShift[offset]) & 0xFF;
588 }
589 else if (memory.type == MM_IO_W)
590 {
591 byte = 0xFF; // Write only, what do we return? A fixed value?
592 }
593
594 return byte;
595}
596
597uint16_t MMURead16(uint32_t address, uint32_t who/*= UNKNOWN*/)
598{
599 return 0;
600}
601
602uint32_t MMURead32(uint32_t address, uint32_t who/*= UNKNOWN*/)
603{
604 return 0;
605}
606
607uint64_t MMURead64(uint32_t address, uint32_t who/*= UNKNOWN*/)
608{
609 return 0;
610}
611
612
613#endif