Create cpudefs.c
[clinton/Virtual-Jaguar-Rx.git] / src / mmu.cpp
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 /*
28 Addresses to be handled:
29
30 SYSTEM SETUP REGISTERS
31
32 *MEMCON1 Memory Control Register 1 F00000 RW
33 *MEMCON2 Memory Control Register 2 F00002 RW
34 HC Horizontal Count F00004 RW
35 VC Vertical Count F00006 RW
36 LPH Light Pen Horizontal F00008 RO
37 LPV Light Pen Vertical F0000A RO
38 OB[0-3] Object Data Field F00010-16 RO
39 OLP Object List Pointer F00020-23 WO
40 OBF Object Flag F00026 WO
41 VMODE Video Mode F00028 WO
42 BORD1 Border Colour (Red & Green) F0002A WO
43 BORD2 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
49 HDB1 Horizontal Display Begin 1 F00038 WO
50 HDB2 Horizontal Display Begin 2 F0003A WO
51 HDE 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
56 VDB Vertical Display Begin F00046 WO
57 VDE Vertical Display End F00048 WO
58 *VEB Vertical Equalization Begin F0004A WO
59 *VEE Vertical Equalization End F0004C WO
60 VI Vertical Interrupt F0004E WO
61 PIT[0-1] Programmable Interrupt Timer F00050-52 WO
62 *HEQ Horizontal Equalization End F00054 WO
63 BG Background Colour F00058 WO
64 INT1 CPU Interrupt Control Register F000E0 RW
65 INT2 CPU Interrupt Resume Register F000E2 WO
66 CLUT Colour Look-Up Table F00400-7FE RW
67 LBUF Line Buffer F00800-1D9E RW
68
69 GPU REGISTERS
70
71 G_FLAGS GPU Flags Register F02100 RW
72 G_MTXC Matrix Control Register F02104 WO
73 G_MTXA Matrix Address Register F02108 WO
74 G_END Data Organization Register F0210C WO
75 G_PC GPU Program Counter F02110 RW
76 G_CTRL GPU Control/Status Register F02114 RW
77 G_HIDATA High Data Register F02118 RW
78 G_REMAIN Divide Unit Remainder F0211C RO
79 G_DIVCTRL Divide Unit Control F0211C WO
80
81 BLITTER REGISTERS
82
83 A1_BASE A1 Base Register F02200 WO
84 A1_FLAGS Flags Register F02204 WO
85 A1_CLIP A1 Clipping Size F02208 WO
86 A1_PIXEL A1 Pixel Pointer F0220C WO
87 F02204 RO
88 A1_STEP A1 Step Value F02210 WO
89 A1_FSTEP A1 Step Fraction Value F02214 WO
90 A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
91 A1_INC A1 Increment F0221C WO
92 A1_FINC A1 Increment Fraction F02220 WO
93 A2_BASE A2 Base Register F02224 WO
94 A2_FLAGS A2 Flags Register F02228 WO
95 A2_MASK A2 Window Mask F0222C WO
96 A2_PIXEL A2 Pixel Pointer F02230 WO
97 F0222C RO
98 A2_STEP A2 Step Value F02234 WO
99 B_CMD Command/Status Register F02238 RW
100 B_COUNT Counters Register F0223C WO
101 B_SRCD Source Data Register F02240 WO
102 B_DSTD Destination Data Register F02248 WO
103 B_DSTZ Destination Z Register F02250 WO
104 B_SRCZ1 Source Z Register 1 F02258 WO
105 B_SRCZ2 Source Z Register 2 F02260 WO
106 B_PATD Pattern Data Register F02268 WO
107 B_IINC Intensity Increment F02270 WO
108 B_ZINC Z Increment F02274 WO
109 B_STOP Collision Control F02278 WO
110 B_I3 Intensity 3 F0227C WO
111 B_I2 Intensity 2 F02280 WO
112 B_I1 Intensity 1 F02284 WO
113 B_I0 Intensity 0 F02288 WO
114 B_Z3 Z 3 F0228C WO
115 B_Z2 Z 2 F02290 WO
116 B_Z1 Z 1 F02294 WO
117 B_Z0 Z 0 F02298 WO
118
119 JERRY REGISTERS
120
121 *CLK1 Processor Clock Divider F10010 WO
122 *CLK2 Video Clock Divider F10012 WO
123 *CLK3 Chroma Clock Divider F10014 WO
124 JPIT1 Timer 1 Pre-scaler F10000 WO
125 JPIT3 Timer 2 Pre-scaler F10004 WO
126 JPIT2 Timer 1 Divider F10002 WO
127 JPIT4 Timer 2 Divider F10006 WO
128 J_INT Interrup Control Register F10020 RW
129 SCLK Serial Clock Frequency F1A150 WO
130 SMODE Serial Mode F1A154 WO
131 LTXD Left Transmit Data F1A148 WO
132 RTXD Right Transmit Data F1A14C WO
133 LRXD Left Receive Data F1A148 RO
134 RRXD Right Receive Data F1A14C RO
135 L_I2S Left I2S Serial Interface F1A148 RW
136 R_I2S Right I2S Serial Interface F1A14C RW
137 SSTAT Serial Status F1A150 RO
138 ASICLK Asynchronous Serial Interface Clock F10034 RW
139 ASICTRL Asynchronous Serial Control F10032 WO
140 ASISTAT Asynchronous Serial Status F10032 RO
141 ASIDATA Asynchronous Serial Data F10030 RW
142
143 JOYSTICK REGISTERS
144
145 JOYSTICK Joystick Register F14000 RW
146 JOYBUTS Button Register F14002 RW
147
148 DSP REGISTERS
149
150 D_FLAGS DSP Flags Register F1A100 RW
151 D_MTXC DSP Matrix Control Register F1A104 WO
152 D_MTXA DSP Matrix Address Register F1A108 WO
153 D_END DSP Data Organization Register F1A10C WO
154 D_PC DSP Program Counter F1A110 RW
155 D_CTRL DSP Control/Status Register F1A114 RW
156 D_MOD Modulo Instruction Mask F1A118 WO
157 D_REMAIN Divide Unit Remainder F1A11C RO
158 D_DIVCTRL Divide Unit Control F1A11C WO
159 D_MACHI MAC High Result Bits F1A120 RO
160 */
161
162 /*
163 The approach here is to have a list of addresses and who handles them. Could be
164 a one-to-one memory location up to a range for each function. Will look
165 something like this:
166
167 { 0xF14000, 0xF14001, MM_IO, JoystickReadHandler, JoystickWriteHandler },
168
169 Would be nice to have a way of either calling a handler function or reading/writing
170 directly to/from a variable or array...
171 */
172
173 enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
174
175 /*
176 Would be nice to have different structs tailored to different memory access types,
177 but if we don't do that, we can encode things as follows:
178
179 MM_NOP: readFunc = writeFunc = NULL
180 MM_RAM: readFunc = byte array pointer, writeFunc = NULL
181 MM_ROM: readFunc = byte array pointer, writeFunc = NULL
182 MM_IO_R: readFunc = function pointer to read function, writeFunc = NULL
183 MM_IO_W: readFunc = NULL, writeFunc = function pointer to write function
184 MM_IO: readFunc = function pointer to read function, writeFunc = function pointer to write function
185
186 There may be a need to have readFunc do both read & write functions (makes sense? perhaps)
187
188 Should we have a read mask as well, for the purposes of reading?
189 */
190
191 struct 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
202 MemDesc 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
385 uint32_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
429 JOYSTICK $F14000 Read/Write
430 15.....8 7......0
431 Read fedcba98 7654321q f-1 Signals J15 to J1
432 q Cartridge EEPROM output data
433 Write 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)
441 JOYBUTS $F14002 Read Only
442 15.....8 7......0
443 Read 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
451 J4 J5 J6 J7 Port 2 B2 B3 J12 J13 J14 J15
452 J3 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
470 0 bit read in any position means that button is pressed.
471 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
472 */
473 };
474 #endif
475
476 void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
477 {
478 }
479
480 void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
481 {
482 }
483
484 void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
485 {
486 }
487
488 void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
489 {
490 }
491
492 uint8_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 /*
535 We 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
540 Let's see, will this work depending on the endianess?
541 uint32_t dword
542 accessing it like so:
543 ((uint8_t *)dword &)[0] --> should give us high byte
544 but if we assign it directly...
545 dword = 0x12345678 --> becomes 78 56 34 12 in memory, ptr[0] will be 78 in LE!
546 dword = 0x12345678 --> becomes 12 34 56 78 in memory, ptr[0] will be 12 in BE!
547
548 So 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
552 Then, if we want to use a jaguar variable, we need to cast it like so:
553 uint16_t my_vbb = ENDIAN_SAFE_16(vbb);
554
555 We have something like this already in jaguar.h, since we treat I/O spaces like
556 contiguous 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
597 uint16_t MMURead16(uint32_t address, uint32_t who/*= UNKNOWN*/)
598 {
599 return 0;
600 }
601
602 uint32_t MMURead32(uint32_t address, uint32_t who/*= UNKNOWN*/)
603 {
604 return 0;
605 }
606
607 uint64_t MMURead64(uint32_t address, uint32_t who/*= UNKNOWN*/)
608 {
609 return 0;
610 }
611
612
613 #endif