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