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