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