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 <stdlib.h>								// For NULL definition
16 
17 #include <boolean.h>
18 
19 #include "mmu.h"
20 
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 enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
160 
161 struct MemDesc {
162    uint32_t startAddr;
163    uint32_t endAddr;
164    enum MemType type;
165    //	(void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
166    void * readFunc;					// This is read & write with MM_IO
167    void * writeFunc;
168    uint32_t mask;
169 };
170 
171 
172 struct MemDesc memoryMap[] = {
173    { 0x000000, 0x3FFFFF, MM_RAM,  &jaguarMainRAM },
174    { 0x800000, 0xDFFEFF, MM_ROM,  &jaguarMainROM },
175 
176    { 0xDFFF00, 0xDFFF03, MM_IO,   &butch }, // base of Butch == interrupt control register, R/W
177    { 0xDFFF04, 0xDFFF07, MM_IO,   &dscntrl }, // DSA control register, R/W
178    { 0xDFFF0A, 0xDFFF0B, MM_IO,   &ds_data }, // DSA TX/RX data, R/W
179    { 0xDFFF10, 0xDFFF13, MM_IO,   &i2cntrl }, // i2s bus control register, R/W
180    { 0xDFFF14, 0xDFFF17, MM_IO,   &sbcntrl }, // CD subcode control register, R/W
181    { 0xDFFF18, 0xDFFF1B, MM_IO,   &subdata }, // Subcode data register A
182    { 0xDFFF1C, 0xDFFF1F, MM_IO,   &subdatb }, // Subcode data register B
183    { 0xDFFF20, 0xDFFF23, MM_IO,   &sb_time }, // Subcode time and compare enable (D24)
184    { 0xDFFF24, 0xDFFF27, MM_IO,   &fifo_data }, // i2s FIFO data
185    { 0xDFFF28, 0xDFFF2B, MM_IO,   &i2sdat2 }, // i2s FIFO data (old)
186    { 0xDFFF2C, 0xDFFF2F, MM_IO,   &unknown }, // Seems to be some sort of I2S interface
187 
188    { 0xE00000, 0xE1FFFF, MM_ROM,  jaguarBootROM },
189 
190    // TOM REGISTERS
191 
192    { 0xF00000, 0xF00001, MM_IO,   &memcon1 }, // *MEMCON1	Memory Control Register 1			F00000		RW
193    { 0xF00002, 0xF00003, MM_IO,   &memcon2 }, // *MEMCON2	Memory Control Register 2			F00002		RW
194    { 0xF00004, 0xF00005, MM_IO,   &hc }, // HC			Horizontal Count					F00004		RW
195    { 0xF00006, 0xF00007, MM_IO,   &vc }, // VC			Vertical Count						F00006		RW
196    { 0xF00008, 0xF00009, MM_IO_R, &lph }, // LPH			Light Pen Horizontal				F00008		RO
197    { 0xF0000A, 0xF0000B, MM_IO_R, &lpv }, // LPV			Light Pen Vertical					F0000A		RO
198    { 0xF00010, 0xF00017, MM_IO_R, &obData }, // OB[0-3]		Object Data Field					F00010-16	RO
199    { 0xF00020, 0xF00023, MM_IO_W, &olp }, // OLP			Object List Pointer					F00020-23	WO
200    { 0xF00026, 0xF00027, MM_IO_W, &obf }, // OBF			Object Flag							F00026		WO
201    { 0xF00028, 0xF00029, MM_IO_W, &vmode }, // VMODE		Video Mode							F00028		WO
202    { 0xF0002A, 0xF0002B, MM_IO_W, &bord1 }, // BORD1		Border Colour (Red & Green)			F0002A		WO
203    { 0xF0002C, 0xF0002D, MM_IO_W, &bord2 }, // BORD2		Border Colour (Blue)				F0002C		WO
204    { 0xF0002E, 0xF0002F, MM_IO_W, &hp }, // *HP			Horizontal Period					F0002E		WO
205    { 0xF00030, 0xF00031, MM_IO_W, &hbb }, // *HBB		Horizontal Blank Begin				F00030		WO
206    { 0xF00032, 0xF00033, MM_IO_W, &hbe }, // *HBE		Horizontal Blank End				F00032		WO
207    { 0xF00034, 0xF00035, MM_IO_W, &hs }, // *HS			Horizontal Sync						F00034		WO
208    { 0xF00036, 0xF00037, MM_IO_W, &hvs }, // *HVS		Horizontal Vertical Sync			F00036		WO
209    { 0xF00038, 0xF00039, MM_IO_W, &hdb1 }, // HDB1		Horizontal Display Begin 1			F00038		WO
210    { 0xF0003A, 0xF0003B, MM_IO_W, &hdb2 }, // HDB2		Horizontal Display Begin 2			F0003A		WO
211    { 0xF0003C, 0xF0003D, MM_IO_W, &hde }, // HDE			Horizontal Display End				F0003C		WO
212    { 0xF0003E, 0xF0003F, MM_IO_W, &vp }, // *VP			Vertical Period						F0003E		WO
213    { 0xF00040, 0xF00041, MM_IO_W, &vbb }, // *VBB		Vertical Blank Begin				F00040		WO
214    { 0xF00042, 0xF00043, MM_IO_W, &vbe }, // *VBE		Vertical Blank End					F00042		WO
215    { 0xF00044, 0xF00045, MM_IO_W, &vs }, // *VS			Vertical Sync						F00044		WO
216    { 0xF00046, 0xF00047, MM_IO_W, &vdb }, // VDB			Vertical Display Begin				F00046		WO
217    { 0xF00048, 0xF00049, MM_IO_W, &vde }, // VDE			Vertical Display End				F00048		WO
218    { 0xF0004A, 0xF0004B, MM_IO_W, &veb }, // *VEB		Vertical Equalization Begin			F0004A		WO
219    { 0xF0004C, 0xF0004D, MM_IO_W, &vee }, // *VEE		Vertical Equalization End			F0004C		WO
220    { 0xF0004E, 0xF0004F, MM_IO_W, &vi }, // VI			Vertical Interrupt					F0004E		WO
221    { 0xF00050, 0xF00051, MM_IO_W, &pit0 }, // PIT[0-1]	Programmable Interrupt Timer		F00050-52	WO
222    { 0xF00052, 0xF00053, MM_IO_W, &pit1 },
223    { 0xF00054, 0xF00055, MM_IO_W, &heq }, // *HEQ		Horizontal Equalization End			F00054		WO
224    { 0xF00058, 0xF0005B, MM_IO_W, &bg }, // BG			Background Colour					F00058		WO
225    { 0xF000E0, 0xF000E1, MM_IO,   &int1 }, // INT1		CPU Interrupt Control Register		F000E0		RW
226    { 0xF000E2, 0xF000E3, MM_IO_W, &int2 }, // INT2		CPU Interrupt Resume Register		F000E2		WO
227    //Some of these RAM spaces may be 16- or 32-bit only... in which case, we need
228    //to cast appropriately (in memory.cpp, that is)...
229    { 0xF00400, 0xF005FF, MM_RAM,  &clut }, // CLUT		Colour Look-Up Table				F00400-7FE	RW
230    { 0xF00600, 0xF007FF, MM_RAM,  &clut },
231    { 0xF00800, 0xF01D9F, MM_RAM,  &lbuf }, // LBUF		Line Buffer							F00800-1D9E	RW
232    //Need high speed RAM interface for GPU & DSP (we have it now...)
233 
234    // GPU REGISTERS
235 
236    { 0xF02100, 0xF02103, MM_IO,   &g_flags }, // G_FLAGS		GPU Flags Register					F02100		RW
237    { 0xF02104, 0xF02107, MM_IO_W, &g_mtxc }, // G_MTXC		Matrix Control Register				F02104		WO
238    { 0xF02108, 0xF0210B, MM_IO_W, &g_mtxa }, // G_MTXA		Matrix Address Register				F02108		WO
239    { 0xF0210C, 0xF0210F, MM_IO_W, &g_end }, // G_END		Data Organization Register			F0210C		WO
240    { 0xF02110, 0xF02113, MM_IO,   &g_pc }, // G_PC		GPU Program Counter					F02110		RW
241    { 0xF02114, 0xF02117, MM_IO,   &g_ctrl }, // G_CTRL		GPU Control/Status Register			F02114		RW
242    { 0xF02118, 0xF0211B, MM_IO,   &g_hidata }, // G_HIDATA	High Data Register					F02118		RW
243    { 0xF0211C, 0xF0211F, MM_IO,   &g_remain, &g_divctrl }, // G_REMAIN	Divide Unit Remainder				F0211C		RO
244    // G_DIVCTRL	Divide Unit Control					F0211C		WO
245    { 0xF03000, 0xF03FFF, MM_RAM,  &gpuRAM },
246 
247    // BLITTER REGISTERS
248 
249    { 0xF02200, 0xF02203, MM_IO_W, &a1_base }, // A1_BASE		A1 Base Register					F02200		WO
250    { 0xF02204, 0xF02207, MM_IO,   &a1_pixel, &a1_flags }, // A1_FLAGS	Flags Register						F02204		WO
251    { 0xF02208, 0xF0220B, MM_IO_W, &a1_clip }, // A1_CLIP		A1 Clipping Size					F02208		WO
252    { 0xF0220C, 0xF0220F, MM_IO_W, &a1_pixel }, // A1_PIXEL	A1 Pixel Pointer					F0220C		WO
253    //												F02204		RO
254    { 0xF02210, 0xF02213, MM_IO_W, &a1_step }, // A1_STEP		A1 Step Value						F02210		WO
255    { 0xF02214, 0xF02217, MM_IO_W, &a1_fstep }, // A1_FSTEP	A1 Step Fraction Value				F02214		WO
256    { 0xF02218, 0xF0221B, MM_IO,   &a1_fpixel }, // A1_FPIXEL	A1 Pixel Pointer Fraction			F02218		RW
257    { 0xF0221C, 0xF0221F, MM_IO_W, &a1_inc }, // A1_INC		A1 Increment						F0221C		WO
258    { 0xF02220, 0xF02223, MM_IO_W, &a1_finc }, // A1_FINC		A1 Increment Fraction				F02220		WO
259    { 0xF02224, 0xF02227, MM_IO_W, &a2_base }, // A2_BASE		A2 Base Register					F02224		WO
260    { 0xF02228, 0xF0222B, MM_IO_W, &a2_flags }, // A2_FLAGS	A2 Flags Register					F02228		WO
261    { 0xF0222C, 0xF0222F, MM_IO,   &a2_pixel, &a2_mask }, // A2_MASK		A2 Window Mask						F0222C		WO
262    { 0xF02230, 0xF02233, MM_IO_W, &a2_pixel }, // A2_PIXEL	A2 Pixel Pointer					F02230		WO
263    //												F0222C		RO
264    { 0xF02234, 0xF02237, MM_IO_W, &a2_step }, // A2_STEP		A2 Step Value						F02234		WO
265    { 0xF02238, 0xF0223B, MM_IO,   &b_cmd }, // B_CMD		Command/Status Register				F02238		RW
266    { 0xF0223C, 0xF0223F, MM_IO_W, &b_count }, // B_COUNT		Counters Register					F0223C		WO
267    { 0xF02240, 0xF02247, MM_IO_W, &b_srcd }, // B_SRCD		Source Data Register				F02240		WO
268    { 0xF02248, 0xF0224F, MM_IO_W, &b_dstd }, // B_DSTD		Destination Data Register			F02248		WO
269    { 0xF02250, 0xF02258, MM_IO_W, &b_dstz }, // B_DSTZ		Destination Z Register				F02250		WO
270    { 0xF02258, 0xF0225F, MM_IO_W, &b_srcz1 }, // B_SRCZ1		Source Z Register 1					F02258		WO
271    { 0xF02260, 0xF02267, MM_IO_W, &b_srcz2 }, // B_SRCZ2		Source Z Register 2					F02260		WO
272    { 0xF02268, 0xF0226F, MM_IO_W, &b_patd }, // B_PATD		Pattern Data Register				F02268		WO
273    { 0xF02270, 0xF02273, MM_IO_W, &b_iinc }, // B_IINC		Intensity Increment					F02270		WO
274    { 0xF02274, 0xF02277, MM_IO_W, &b_zinc }, // B_ZINC		Z Increment							F02274		WO
275    { 0xF02278, 0xF0227B, MM_IO_W, &b_stop }, // B_STOP		Collision Control					F02278		WO
276    { 0xF0227C, 0xF0227F, MM_IO_W, &b_i3 }, // B_I3		Intensity 3							F0227C		WO
277    { 0xF02280, 0xF02283, MM_IO_W, &b_i2 }, // B_I2		Intensity 2							F02280		WO
278    { 0xF02284, 0xF02287, MM_IO_W, &b_i1 }, // B_I1		Intensity 1							F02284		WO
279    { 0xF02288, 0xF0228B, MM_IO_W, &b_i0 }, // B_I0		Intensity 0							F02288		WO
280    { 0xF0228C, 0xF0228F, MM_IO_W, &b_z3 }, // B_Z3		Z 3									F0228C		WO
281    { 0xF02290, 0xF02293, MM_IO_W, &b_z2 }, // B_Z2		Z 2									F02290		WO
282    { 0xF02294, 0xF02297, MM_IO_W, &b_z1 }, // B_Z1		Z 1									F02294		WO
283    { 0xF02298, 0xF0229B, MM_IO_W, &b_z0 }, // B_Z0		Z 0									F02298		WO
284 
285    // JTRM sez ALL GPU address space is accessible from $8000 offset as "fast" 32-bit WO access
286    // Dunno if anything actually USED it tho... :-P
287    { 0xF0A100, 0xF0A103, MM_IO_W, &g_flags }, // G_FLAGS		GPU Flags Register					F02100		RW
288    { 0xF0A104, 0xF0A107, MM_IO_W, &g_mtxc }, // G_MTXC		Matrix Control Register				F02104		WO
289    { 0xF0A108, 0xF0A10B, MM_IO_W, &g_mtxa }, // G_MTXA		Matrix Address Register				F02108		WO
290    { 0xF0A10C, 0xF0A10F, MM_IO_W, &g_end }, // G_END		Data Organization Register			F0210C		WO
291    { 0xF0A110, 0xF0A113, MM_IO_W, &g_pc }, // G_PC		GPU Program Counter					F02110		RW
292    { 0xF0A114, 0xF0A117, MM_IO_W, &g_ctrl }, // G_CTRL		GPU Control/Status Register			F02114		RW
293    { 0xF0A118, 0xF0A11B, MM_IO_W, &g_hidata }, // G_HIDATA	High Data Register					F02118		RW
294    { 0xF0A11C, 0xF0A11F, MM_IO_W, &g_divctrl }, // G_REMAIN	Divide Unit Remainder				F0211C		RO
295    { 0xF0B000, 0xF0BFFF, MM_IO_W, &gpuRAM }, // "Fast" interface to GPU RAM
296 
297    // JERRY REGISTERS
298 
299    { 0xF10000, 0xF10001, MM_IO_W, &jpit1 }, // JPIT1		Timer 1 Pre-scaler					F10000		WO
300    { 0xF10002, 0xF10003, MM_IO_W, &jpit2 }, // JPIT2		Timer 1 Divider						F10002		WO
301    { 0xF10004, 0xF10005, MM_IO_W, &jpit3 }, // JPIT3		Timer 2 Pre-scaler					F10004		WO
302    { 0xF10006, 0xF10007, MM_IO_W, &jpit4 }, // JPIT4		Timer 2 Divider						F10006		WO
303    { 0xF10010, 0xF10011, MM_IO_W, &clk1 }, // *CLK1		Processor Clock Divider				F10010		WO
304    { 0xF10012, 0xF10013, MM_IO_W, &clk2 }, // *CLK2		Video Clock Divider					F10012		WO
305    { 0xF10014, 0xF10015, MM_IO_W, &clk3 }, // *CLK3		Chroma Clock Divider				F10014		WO
306    { 0xF10020, 0xF10021, MM_IO,   &j_int }, // J_INT		Interrup Control Register			F10020		RW
307    { 0xF10030, 0xF10031, MM_IO,   &asidata }, // ASIDATA		Asynchronous Serial Data			F10030		RW
308    { 0xF10032, 0xF10033, MM_IO,   &asistat, &asictrl }, // ASICTRL		Asynchronous Serial Control			F10032		WO
309    // ASISTAT		Asynchronous Serial Status			F10032		RO
310    { 0xF10034, 0xF10035, MM_IO,   &asiclk }, // ASICLK		Asynchronous Serial Interface Clock	F10034		RW
311    { 0xF10036, 0xF10037, MM_IO_R, &jpit1 }, // JPIT1		Timer 1 Pre-scaler					F10036		RO
312    { 0xF10038, 0xF10039, MM_IO_R, &jpit2 }, // JPIT2		Timer 1 Divider						F10038		RO
313    { 0xF1003A, 0xF1003B, MM_IO_R, &jpit3 }, // JPIT3		Timer 2 Pre-scaler					F1003A		RO
314    { 0xF1003C, 0xF1003D, MM_IO_R, &jpit4 }, // JPIT4		Timer 2 Divider						F1003C		RO
315 
316    { 0xF14000, 0xF14001, MM_IO,   &joystick }, // JOYSTICK	Joystick Register					F14000		RW
317    { 0xF14002, 0xF14003, MM_IO,   &joybuts }, // JOYBUTS		Button Register						F14002		RW
318 
319    // DSP REGISTERS
320 
321    { 0xF1A100, 0xF1A103, MM_IO,   &d_flags }, // D_FLAGS		DSP Flags Register					F1A100		RW
322    { 0xF1A104, 0xF1A107, MM_IO_W, &d_mtxc }, // D_MTXC		DSP Matrix Control Register			F1A104		WO
323    { 0xF1A108, 0xF1A10B, MM_IO_W, &d_mtxa }, // D_MTXA		DSP Matrix Address Register			F1A108		WO
324    { 0xF1A10C, 0xF1A10F, MM_IO_W, &d_end }, // D_END		DSP Data Organization Register		F1A10C		WO
325    { 0xF1A110, 0xF1A113, MM_IO,   &d_pc }, // D_PC		DSP Program Counter					F1A110		RW
326    { 0xF1A114, 0xF1A117, MM_IO,   &d_ctrl }, // D_CTRL		DSP Control/Status Register			F1A114		RW
327    { 0xF1A118, 0xF1A11B, MM_IO_W, &d_mod }, // D_MOD		Modulo Instruction Mask				F1A118		WO
328    { 0xF1A11C, 0xF1A11F, MM_IO_W, &d_remain, &d_divctrl }, // D_REMAIN	Divide Unit Remainder				F1A11C		RO
329    // D_DIVCTRL	Divide Unit Control					F1A11C		WO
330    { 0xF1A120, 0xF1A123, MM_IO_R, &d_machi }, // D_MACHI		MAC High Result Bits				F1A120		RO
331 
332 
333    { 0xF1A148, 0xF1A149, MM_IO,   &lrxd, &ltxd }, // LTXD		Left Transmit Data					F1A148		WO
334    // LRXD		Left Receive Data					F1A148		RO
335    // L_I2S		Left I2S Serial Interface			F1A148		RW
336    { 0xF1A14C, 0xF1A14D, MM_IO,   &rrxd, &rtxd }, // RTXD		Right Transmit Data					F1A14C		WO
337    // RRXD		Right Receive Data					F1A14C		RO
338    // R_I2S		Right I2S Serial Interface			F1A14C		RW
339    { 0xF1A150, 0xF1A150, MM_IO,   &sstat, &sclk }, // SCLK		Serial Clock Frequency				F1A150		WO
340    // SSTAT		Serial Status						F1A150		RO
341    { 0xF1A154, 0xF1A157, MM_IO_W, &smode }, // SMODE		Serial Mode							F1A154		WO
342 
343    { 0xF1B000, 0xF1CFFF, MM_RAM,  &dspRAM }, // F1B000-F1CFFF   R/W   xxxxxxxx xxxxxxxx   Local DSP RAM
344    { 0xF1D000, 0xF1DFFF, MM_ROM,  waveTableROM },
345    // hi-speed interface for DSP??? Ain't no such thang...
346    { 0xFFFFFF, 0xFFFFFF, MM_NOP } // End of memory address sentinel
347 };
348 
MMUWrite8(uint32_t address,uint8_t data,uint32_t who)349 void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
350 {
351 }
352 
MMUWrite16(uint32_t address,uint16_t data,uint32_t who)353 void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
354 {
355 }
356 
MMUWrite32(uint32_t address,uint32_t data,uint32_t who)357 void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
358 {
359 }
360 
MMUWrite64(uint32_t address,uint64_t data,uint32_t who)361 void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
362 {
363 }
364 
365 #define FUNC_CAST(retVal, function, params) (*(retVal(*)(params))function)
366 
MMURead8(uint32_t address,uint32_t who)367 uint8_t MMURead8(uint32_t address, uint32_t who/*= UNKNOWN*/)
368 {
369    // Search for address in the memory map
370    // NOTE: This assumes that all entries are linear and sorted in ascending order!
371 
372    struct MemDesc memory;
373    uint32_t offset;
374    uint8_t byte = 0xFE;
375    uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
376    uint32_t i = 0;
377 
378    while (true)
379    {
380       if (address <= memoryMap[i].endAddr)
381       {
382          if (address >= memoryMap[i].startAddr)
383          {
384             memory = memoryMap[i];
385             break;
386          }
387          return 0xFF;	// Wasn't found...
388       }
389 
390       i++;
391 
392       if (memoryMap[i].startAddr == 0xFFFFFF)
393          return 0xFF;		// Exhausted the list, so bail!
394    }
395 
396    offset = address - memory.startAddr;
397 
398    if (memory.type == MM_RAM || memory.type == MM_ROM)
399       byte = ((uint8_t *)memory.readFunc)[offset];
400    else if (memory.type == MM_IO_R || memory.type == MM_IO)
401    {
402       uint64_t retVal = FUNC_CAST(uint64_t, memory.readFunc, uint32_t)(offset);
403       byte = (retVal >> byteShift[offset]) & 0xFF;
404    }
405    else if (memory.type == MM_IO_W)
406       byte = 0xFF;		// Write only, what do we return? A fixed value?
407 
408    return byte;
409 }
410 
MMURead16(uint32_t address,uint32_t who)411 uint16_t MMURead16(uint32_t address, uint32_t who)
412 {
413    return 0;
414 }
415 
MMURead32(uint32_t address,uint32_t who)416 uint32_t MMURead32(uint32_t address, uint32_t who)
417 {
418    return 0;
419 }
420 
MMURead64(uint32_t address,uint32_t who)421 uint64_t MMURead64(uint32_t address, uint32_t who)
422 {
423    return 0;
424 }
425 
426