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