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