1 #include <string.h>
2
3 #include "pgxp_mem.h"
4 #include "pgxp_cpu.h"
5 #include "pgxp_gte.h"
6 #include "pgxp_value.h"
7
8 PGXP_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3
9 const u32 UserMemOffset = 0;
10 const u32 ScratchOffset = 2048 * 1024 / 4;
11 const u32 RegisterOffset = 2 * 2048 * 1024 / 4;
12 const u32 InvalidAddress = 3 * 2048 * 1024 / 4;
13
PGXP_InitMem()14 void PGXP_InitMem()
15 {
16 memset(Mem, 0, sizeof(Mem));
17 }
18
PGXP_GetMem()19 char* PGXP_GetMem()
20 {
21 return (char*)(Mem); // Config.PGXP_GTE ? (char*)(Mem) : NULL;
22 }
23
24 /* Playstation Memory Map (from Playstation doc by Joshua Walker)
25 0x0000_0000-0x0000_ffff Kernel (64K)
26 0x0001_0000-0x001f_ffff User Memory (1.9 Meg)
27
28 0x1f00_0000-0x1f00_ffff Parallel Port (64K)
29
30 0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes)
31
32 0x1f80_1000-0x1f80_2fff Hardware Registers (8K)
33
34 0x1fc0_0000-0x1fc7_ffff BIOS (512K)
35
36 0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached
37 0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached
38
39 0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached
40 0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached
41 */
ValidateAddress(u32 addr)42 void ValidateAddress(u32 addr)
43 {
44 int* pi = NULL;
45
46 if ((addr >= 0x00000000) && (addr <= 0x007fffff)) {} // Kernel + User Memory x 8
47 else if ((addr >= 0x1f000000) && (addr <= 0x1f00ffff)) {} // Parallel Port
48 else if ((addr >= 0x1f800000) && (addr <= 0x1f8003ff)) {} // Scratch Pad
49 else if ((addr >= 0x1f801000) && (addr <= 0x1f802fff)) {} // Hardware Registers
50 else if ((addr >= 0x1fc00000) && (addr <= 0x1fc7ffff)) {} // Bios
51 else if ((addr >= 0x80000000) && (addr <= 0x807fffff)) {} // Kernel + User Memory x 8 Cached mirror
52 else if ((addr >= 0x9fc00000) && (addr <= 0x9fc7ffff)) {} // Bios Cached Mirror
53 else if ((addr >= 0xa0000000) && (addr <= 0xa07fffff)) {} // Kernel + User Memory x 8 Uncached mirror
54 else if ((addr >= 0xbfc00000) && (addr <= 0xbfc7ffff)) {} // Bios Uncached Mirror
55 else if (addr == 0xfffe0130) {} // Used for cache flushing
56 else
57 {
58 // *pi = 5;
59 }
60
61 }
62
PGXP_ConvertAddress(u32 addr)63 u32 PGXP_ConvertAddress(u32 addr)
64 {
65 u32 memOffs = 0;
66 u32 paddr = addr;
67
68 // ValidateAddress(addr);
69
70 switch (paddr >> 24)
71 {
72 case 0x80:
73 case 0xa0:
74 case 0x00:
75 // RAM further mirrored over 8MB
76 paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2;
77 paddr = UserMemOffset + paddr;
78 break;
79 default:
80 if ((paddr >> 20) == 0x1f8)
81 {
82 if (paddr >= 0x1f801000)
83 {
84 // paddr = ((paddr & 0xFFFF) - 0x1000);
85 // paddr = (paddr % 0x2000) >> 2;
86 paddr = ((paddr & 0xFFFF) - 0x1000) >> 2;
87 paddr = RegisterOffset + paddr;
88 break;
89 }
90 else
91 {
92 //paddr = ((paddr & 0xFFF) % 0x400) >> 2;
93 paddr = (paddr & 0x3FF) >> 2;
94 paddr = ScratchOffset + paddr;
95 break;
96 }
97 }
98
99 paddr = InvalidAddress;
100 break;
101 }
102
103 #ifdef GTE_LOG
104 //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr);
105 #endif
106
107 return paddr;
108 }
109
GetPtr(u32 addr)110 PGXP_value* GetPtr(u32 addr)
111 {
112 addr = PGXP_ConvertAddress(addr);
113
114 if (addr != InvalidAddress)
115 return &Mem[addr];
116 return NULL;
117 }
118
ReadMem(u32 addr)119 PGXP_value* ReadMem(u32 addr)
120 {
121 return GetPtr(addr);
122 }
123
ValidateAndCopyMem(PGXP_value * dest,u32 addr,u32 value)124 void ValidateAndCopyMem(PGXP_value* dest, u32 addr, u32 value)
125 {
126 PGXP_value* pMem = GetPtr(addr);
127 if (pMem != NULL)
128 {
129 Validate(pMem, value);
130 *dest = *pMem;
131 return;
132 }
133
134 *dest = PGXP_value_invalid_address;
135 }
136
ValidateAndCopyMem16(PGXP_value * dest,u32 addr,u32 value,int sign)137 void ValidateAndCopyMem16(PGXP_value* dest, u32 addr, u32 value, int sign)
138 {
139 u32 validMask = 0;
140 psx_value val, mask;
141 PGXP_value* pMem = GetPtr(addr);
142 if (pMem != NULL)
143 {
144 mask.d = val.d = 0;
145 // determine if high or low word
146 if ((addr % 4) == 2)
147 {
148 val.w.h = value;
149 mask.w.h = 0xFFFF;
150 validMask = VALID_1;
151 }
152 else
153 {
154 val.w.l = value;
155 mask.w.l = 0xFFFF;
156 validMask = VALID_0;
157 }
158
159 // validate and copy whole value
160 MaskValidate(pMem, val.d, mask.d, validMask);
161 *dest = *pMem;
162
163 // if high word then shift
164 if ((addr % 4) == 2)
165 {
166 dest->x = dest->y;
167 dest->lFlags = dest->hFlags;
168 dest->compFlags[0] = dest->compFlags[1];
169 }
170
171 // truncate value
172 dest->y = (dest->x < 0) ? -1.f * sign : 0.f;// 0.f;
173 dest->hFlags = 0;
174 dest->value = value;
175 dest->compFlags[1] = VALID; // iCB: High word is valid, just 0
176 return;
177 }
178
179 *dest = PGXP_value_invalid_address;
180 }
181
WriteMem(PGXP_value * value,u32 addr)182 void WriteMem(PGXP_value* value, u32 addr)
183 {
184 PGXP_value* pMem = GetPtr(addr);
185
186 if (pMem)
187 *pMem = *value;
188 }
189
WriteMem16(PGXP_value * src,u32 addr)190 void WriteMem16(PGXP_value* src, u32 addr)
191 {
192 PGXP_value* dest = GetPtr(addr);
193 psx_value* pVal = NULL;
194
195 if (dest)
196 {
197 pVal = (psx_value*)&dest->value;
198 // determine if high or low word
199 if ((addr % 4) == 2)
200 {
201 dest->y = src->x;
202 dest->hFlags = src->lFlags;
203 dest->compFlags[1] = src->compFlags[0];
204 pVal->w.h = (u16)src->value;
205 }
206 else
207 {
208 dest->x = src->x;
209 dest->lFlags = src->lFlags;
210 dest->compFlags[0] = src->compFlags[0];
211 pVal->w.l = (u16)src->value;
212 }
213
214 // overwrite z/w if valid
215 if (src->compFlags[2] == VALID)
216 {
217 dest->z = src->z;
218 dest->compFlags[2] = src->compFlags[2];
219 }
220
221
222 //dest->valid = dest->valid && src->valid;
223 dest->gFlags |= src->gFlags; // inherit flags from both values (?)
224 }
225 }
226
227 u32 lastDMAAddr = 0;
228
PGXP_SetLastDMA(u32 addr)229 void PGXP_SetLastDMA(u32 addr)
230 {
231 lastDMAAddr = PGXP_ConvertAddress(addr);
232 }
233
PGXP_GetLastDMA()234 u32 PGXP_GetLastDMA()
235 {
236 return lastDMAAddr;
237 }
238