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