]> Shamusworld >> Repos - virtualjaguar/blob - src/mmu.cpp
Fixed controller profile system.
[virtualjaguar] / 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 Addresses to be handled:
26
27 SYSTEM SETUP REGISTERS
28
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
65
66 GPU REGISTERS
67
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
77
78 BLITTER REGISTERS
79
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
84                                                                                                 F02204          RO
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
94                                                                                                 F0222C          RO
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
111 B_Z3            Z 3                                                                     F0228C          WO
112 B_Z2            Z 2                                                                     F02290          WO
113 B_Z1            Z 1                                                                     F02294          WO
114 B_Z0            Z 0                                                                     F02298          WO
115
116 JERRY REGISTERS
117
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
139
140 JOYSTICK REGISTERS
141
142 JOYSTICK        Joystick Register                                       F14000          RW
143 JOYBUTS         Button Register                                         F14002          RW
144
145 DSP REGISTERS
146
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
157 */
158
159 /*
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
162 something like this:
163
164         { 0xF14000, 0xF14001, MM_IO, JoystickReadHandler, JoystickWriteHandler },
165
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...
168 */
169
170 enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
171
172 /*
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:
175
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
182
183 There may be a need to have readFunc do both read & write functions (makes sense? perhaps)
184
185 Should we have a read mask as well, for the purposes of reading?
186 */
187
188 struct MemDesc {
189         uint32_t startAddr;
190         uint32_t endAddr;
191         MemType type;
192 //      (void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
193         void * readFunc;                                        // This is read & write with MM_IO
194         void * writeFunc;
195         uint32_t mask;
196 };
197
198
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 },
205
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
217
218         { 0xE00000, 0xE1FFFF, MM_ROM,  jaguarBootROM },
219
220         // TOM REGISTERS
221
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...)
263
264         // GPU REGISTERS
265
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 },
276
277         // BLITTER REGISTERS
278
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
283 //                                                                                              F02204          RO
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
293 //                                                                                              F0222C          RO
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
314
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
326
327         // JERRY REGISTERS
328
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
345
346         { 0xF14000, 0xF14001, MM_IO,   &joystick }, // JOYSTICK Joystick Register                                       F14000          RW
347         { 0xF14002, 0xF14003, MM_IO,   &joybuts }, // JOYBUTS           Button Register                                         F14002          RW
348
349         // DSP REGISTERS
350
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
361
362
363         { 0xF1A148, 0xF1A149, MM_IO,   &lrxd, &ltxd }, // 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
372
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
377 };
378
379 #if 0
380
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
398
399         { 0xE00000, 0xE3FFFF, MM_ROM, jaguarBootROM },
400
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
410
411         { 0xF10000, 0xF1FFFF, MM_IO,  JERRY_REGS_RW },
412
413 /*
414         EEPROM:
415         { 0xF14001, 0xF14001, MM_IO_RO, eepromFOO }
416         { 0xF14801, 0xF14801, MM_IO_WO, eepromBAR }
417         { 0xF15001, 0xF15001, MM_IO_RW, eepromBAZ }
418
419         JOYSTICK:
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
423         2 = unused, RO
424         3 = NTSC/PAL, certain button states, RO
425
426 JOYSTICK    $F14000               Read/Write
427             15.....8  7......0
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
432                                   x      don't care
433                                   m      Audio mute
434                                          0 = Audio muted (reset state)
435                                          1 = Audio enabled
436                                   7-4    J7-J4 outputs (port 2)
437                                   3-0    J3-J0 outputs (port 1)
438 JOYBUTS     $F14002               Read Only
439             15.....8  7......0
440 Read        xxxxxxxx  rrdv3210    x      don't care
441                                   r      Reserved
442                                   d      Reserved
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)
447
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
450  0  0  0  0
451  0  0  0  1
452  0  0  1  0
453  0  0  1  1
454  0  1  0  0
455  0  1  0  1
456  0  1  1  0
457  0  1  1  1  Row 3     C3   Option  #     9     6     3
458  1  0  0  0
459  1  0  0  1
460  1  0  1  0
461  1  0  1  1  Row 2     C2      C    0     8     5     2
462  1  1  0  0
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
465  1  1  1  1
466
467 0 bit read in any position means that button is pressed.
468 C3 = C2 = 1 means std. Jag. cntrlr. or nothing attached.
469 */
470 };
471 #endif
472
473 void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
474 {
475 }
476
477 void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
478 {
479 }
480
481 void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
482 {
483 }
484
485 void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
486 {
487 }
488
489 uint8_t MMURead8(uint32_t address, uint32_t who/*= UNKNOWN*/)
490 {
491         // Search for address in the memory map
492         // NOTE: This assumes that all entries are linear and sorted in ascending order!
493
494         MemDesc memory;
495         uint8_t byte = 0xFE;
496
497         uint32_t i = 0;
498         while (true)
499         {
500                 if (address <= memoryMap[i].endAddr)
501                 {
502                         if (address >= memoryMap[i].startAddr)
503                         {
504                                 memory = memoryMap[i];
505                                 break;
506                         }
507                         else
508                                 return 0xFF;    // Wasn't found...
509                 }
510
511                 i++;
512
513                 if (memoryMap[i].startAddr == 0xFFFFFF)
514                         return 0xFF;            // Exhausted the list, so bail!
515         }
516
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 };
520
521         if (memory.type == MM_RAM || memory.type == MM_ROM)
522         {
523                 byte = ((uint8_t *)memory.readFunc)[offset];
524         }
525         else if (memory.type == MM_IO_R || memory.type == MM_IO)
526         {
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.
531 /*
532 We can do like so:
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;
536
537 Let's see, will this work depending on the endianess?
538 uint32_t dword
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!
544
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
548
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);
551
552 We have something like this already in jaguar.h, since we treat I/O spaces like
553 contiguous memory anyway... For reference:
554
555 // Some handy macros to help converting native endian to big endian (jaguar native)
556 // & vice versa
557
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])
571 */
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;
585         }
586         else if (memory.type == MM_IO_W)
587         {
588                 byte = 0xFF;            // Write only, what do we return? A fixed value?
589         }
590
591         return byte;
592 }
593
594 uint16_t MMURead16(uint32_t address, uint32_t who/*= UNKNOWN*/)
595 {
596         return 0;
597 }
598
599 uint32_t MMURead32(uint32_t address, uint32_t who/*= UNKNOWN*/)
600 {
601         return 0;
602 }
603
604 uint64_t MMURead64(uint32_t address, uint32_t who/*= UNKNOWN*/)
605 {
606         return 0;
607 }
608