/[pcsx2_0.9.7]/trunk/pcsx2/GS.cpp
ViewVC logotype

Contents of /trunk/pcsx2/GS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 5 months ago) by william
File size: 10324 byte(s)
exported r3113 from ./upstream/trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "Common.h"
18
19 #include <list>
20
21 #include "GS.h"
22 #include "Gif.h"
23 #include "Counters.h"
24
25 using namespace Threading;
26 using namespace R5900;
27
28 u32 CSRw;
29
30 __aligned16 u8 g_RealGSMem[0x2000];
31 extern int m_nCounters[];
32
33 void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
34 {
35 GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate.Raw, newTickrate, 0 );
36 }
37
38 static bool gsIsInterlaced = false;
39 GS_RegionMode gsRegionMode = Region_NTSC;
40
41
42 void gsSetRegionMode( GS_RegionMode region )
43 {
44 if( gsRegionMode == region ) return;
45
46 gsRegionMode = region;
47 UpdateVSyncRate();
48 }
49
50
51 // Make sure framelimiter options are in sync with the plugin's capabilities.
52 void gsInit()
53 {
54 memzero(g_RealGSMem);
55 }
56
57 void gsReset()
58 {
59 GetMTGS().ResetGS();
60
61 UpdateVSyncRate();
62 GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE;
63 memzero(g_RealGSMem);
64
65 GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now
66 GSIMR = 0x7f00;
67 gifRegs->stat.reset();
68 gifRegs->ctrl.reset();
69 gifRegs->mode.reset();
70 }
71
72 void gsGIFReset()
73 {
74 gifRegs->stat.reset();
75 gifRegs->ctrl.reset();
76 gifRegs->mode.reset();
77 }
78
79 void gsCSRwrite(u32 value)
80 {
81 if (value & 0x200) { // resetGS
82
83 // perform a soft reset -- which is a clearing of all GIFpaths -- and fall back to doing
84 // a full reset if the plugin doesn't support soft resets.
85
86 if( GSgifSoftReset != NULL )
87 {
88 GIFPath_Clear( GIF_PATH_1 );
89 GIFPath_Clear( GIF_PATH_2 );
90 GIFPath_Clear( GIF_PATH_3 );
91 }
92 else
93 {
94 GetMTGS().SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
95 }
96
97 CSRw |= 0x1f;
98 GSCSRr = 0x551B4000; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib)
99 GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
100 }
101 else if( value & 0x100 ) // FLUSH
102 {
103 // Our emulated GS has no FIFO, but if it did, it would flush it here...
104 //Console.WriteLn("GS_CSR FLUSH GS fifo: %x (CSRr=%x)", value, GSCSRr);
105 }
106 else
107 {
108 CSRw |= value & 0x1f;
109 GetMTGS().SendSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 );
110 GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
111 }
112
113 }
114
115 static void IMRwrite(u32 value)
116 {
117 GSIMR = (value & 0x1f00)|0x6000;
118
119 if((GSCSRr & 0x1f) & (~(GSIMR >> 8) & 0x1f))
120 {
121 gsIrq();
122 }
123 // don't update mtgs mem
124 }
125
126 __forceinline void gsWrite8(u32 mem, u8 value)
127 {
128 switch (mem)
129 {
130 case GS_CSR: // GS_CSR
131 gsCSRwrite((CSRw & ~0x000000ff) | value); break;
132 case GS_CSR + 1: // GS_CSR
133 gsCSRwrite((CSRw & ~0x0000ff00) | (value << 8)); break;
134 case GS_CSR + 2: // GS_CSR
135 gsCSRwrite((CSRw & ~0x00ff0000) | (value << 16)); break;
136 case GS_CSR + 3: // GS_CSR
137 gsCSRwrite((CSRw & ~0xff000000) | (value << 24)); break;
138 default:
139 *PS2GS_BASE(mem) = value;
140 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE8, mem&0x13ff, value, 0);
141 }
142 GIF_LOG("GS write 8 at %8.8lx with data %8.8lx", mem, value);
143 }
144
145 __forceinline void _gsSMODEwrite( u32 mem, u32 value )
146 {
147 switch (mem)
148 {
149 case GS_SMODE1:
150 gsSetRegionMode( ((value & 0x6000) == 0x6000) ? Region_PAL : Region_NTSC );
151 break;
152
153 case GS_SMODE2:
154 gsIsInterlaced = (value & 0x1);
155 break;
156 }
157 }
158
159 //////////////////////////////////////////////////////////////////////////
160 // GS Write 16 bit
161
162 __forceinline void gsWrite16(u32 mem, u16 value)
163 {
164 GIF_LOG("GS write 16 at %8.8lx with data %8.8lx", mem, value);
165
166 _gsSMODEwrite( mem, value );
167
168 switch (mem)
169 {
170 case GS_CSR:
171 gsCSRwrite( (CSRw&0xffff0000) | value);
172 return; // do not write to MTGS memory
173
174 case GS_CSR+2:
175 gsCSRwrite( (CSRw&0xffff) | ((u32)value<<16));
176 return; // do not write to MTGS memory
177
178 case GS_IMR:
179 IMRwrite(value);
180 return; // do not write to MTGS memory
181 }
182
183 *(u16*)PS2GS_BASE(mem) = value;
184 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0);
185 }
186
187 //////////////////////////////////////////////////////////////////////////
188 // GS Write 32 bit
189
190 __forceinline void gsWrite32(u32 mem, u32 value)
191 {
192 jASSUME( (mem & 3) == 0 );
193 GIF_LOG("GS write 32 at %8.8lx with data %8.8lx", mem, value);
194
195 _gsSMODEwrite( mem, value );
196
197 switch (mem)
198 {
199 case GS_CSR:
200 gsCSRwrite(value);
201 return;
202
203 case GS_IMR:
204 IMRwrite(value);
205 return;
206 }
207
208 *(u32*)PS2GS_BASE(mem) = value;
209 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0);
210 }
211
212 //////////////////////////////////////////////////////////////////////////
213 // GS Write 64 bit
214
215 void __fastcall gsWrite64_page_00( u32 mem, const mem64_t* value )
216 {
217 gsWrite64_generic( mem, value );
218 _gsSMODEwrite( mem, (u32)value[0] );
219 }
220
221 void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
222 {
223 GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x", mem, (u32*)value[1], (u32*)value[0]);
224
225 switch( mem )
226 {
227 case GS_CSR:
228 gsCSRwrite((u32)value[0]);
229 return;
230
231 case GS_IMR:
232 IMRwrite((u32)value[0]);
233 return;
234 }
235
236 gsWrite64_generic( mem, value );
237 }
238
239 void __fastcall gsWrite64_generic( u32 mem, const mem64_t* value )
240 {
241 const u32* const srcval32 = (u32*)value;
242 GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x", mem, srcval32[1], srcval32[0]);
243
244 *(u64*)PS2GS_BASE(mem) = *value;
245 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, srcval32[0], srcval32[1]);
246 }
247
248 //////////////////////////////////////////////////////////////////////////
249 // GS Write 128 bit
250
251 void __fastcall gsWrite128_page_00( u32 mem, const mem128_t* value )
252 {
253 gsWrite128_generic( mem, value );
254 _gsSMODEwrite( mem, (u32)value[0] );
255 }
256
257 void __fastcall gsWrite128_page_01( u32 mem, const mem128_t* value )
258 {
259 switch( mem )
260 {
261 case GS_CSR:
262 gsCSRwrite((u32)value[0]);
263 return;
264
265 case GS_IMR:
266 IMRwrite((u32)value[0]);
267 return;
268 }
269
270 gsWrite128_generic( mem, value );
271 }
272
273 void __fastcall gsWrite128_generic( u32 mem, const mem128_t* value )
274 {
275 const u32* const srcval32 = (u32*)value;
276
277 GIF_LOG("GS Write128 at %8.8lx with data %8.8x_%8.8x_%8.8x_%8.8x", mem,
278 srcval32[3], srcval32[2], srcval32[1], srcval32[0]);
279
280 const uint masked_mem = mem & 0x13ff;
281 u64* writeTo = (u64*)(&g_RealGSMem[masked_mem]);
282
283 writeTo[0] = value[0];
284 writeTo[1] = value[1];
285
286 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE64, masked_mem, srcval32[0], srcval32[1]);
287 GetMTGS().SendSimplePacket(GS_RINGTYPE_MEMWRITE64, masked_mem+8, srcval32[2], srcval32[3]);
288 }
289
290 __forceinline u8 gsRead8(u32 mem)
291 {
292 GIF_LOG("GS read 8 from %8.8lx value: %8.8lx", mem, *(u8*)PS2GS_BASE(mem));
293 return *(u8*)PS2GS_BASE(mem);
294 }
295
296 __forceinline u16 gsRead16(u32 mem)
297 {
298 GIF_LOG("GS read 16 from %8.8lx value: %8.8lx", mem, *(u16*)PS2GS_BASE(mem));
299 return *(u16*)PS2GS_BASE(mem);
300 }
301
302 __forceinline u32 gsRead32(u32 mem)
303 {
304 GIF_LOG("GS read 32 from %8.8lx value: %8.8lx", mem, *(u32*)PS2GS_BASE(mem));
305 return *(u32*)PS2GS_BASE(mem);
306 }
307
308 __forceinline u64 gsRead64(u32 mem)
309 {
310 // fixme - PS2GS_BASE(mem+4) = (g_RealGSMem+(mem + 4 & 0x13ff))
311 GIF_LOG("GS read 64 from %8.8lx value: %8.8lx_%8.8lx", mem, *(u32*)PS2GS_BASE(mem+4), *(u32*)PS2GS_BASE(mem) );
312 return *(u64*)PS2GS_BASE(mem);
313 }
314
315 void gsIrq() {
316 hwIntcIrq(INTC_GS);
317 }
318
319 // --------------------------------------------------------------------------------------
320 // gsFrameSkip
321 // --------------------------------------------------------------------------------------
322 // This function regulates the frameskipping status of the GS. Our new frameskipper for
323 // 0.9.7 is a very simple logic pattern compared to the old mess. The goal now is to provide
324 // the most compatible and efficient frameskip, instead of doing the adaptive logic of
325 // 0.9.6. This is almost a necessity because of how many games treat the GS: they upload
326 // great amounts of data while rendering 2 frames at a time (using double buffering), and
327 // then use a simple pageswap to display the contents of the second frame for that vsync.
328 // (this approach is mostly seen on interlace games; progressive games less so)
329 // The result is that any skip pattern besides a fully consistent 2on,2off would reuslt in
330 // tons of missing geometry, rendering frameskip useless.
331 //
332 // So instead we use a simple "always skipping" or "never skipping" logic.
333 //
334 // EE vs MTGS:
335 // This function does not regulate frame limiting, meaning it does no stalling. Stalling
336 // functions are performed by the EE, which itself uses thread sleep logic to avoid spin
337 // waiting as much as possible (maximizes CPU resource availability for the GS).
338
339 __forceinline void gsFrameSkip()
340 {
341
342 if( !EmuConfig.GS.FrameSkipEnable ) return;
343
344 static int consec_skipped = 0;
345 static int consec_drawn = 0;
346 static bool isSkipping = false;
347
348 GSsetFrameSkip( isSkipping );
349
350 if( isSkipping )
351 {
352 ++consec_skipped;
353 if( consec_skipped >= EmuConfig.GS.FramesToSkip )
354 {
355 consec_skipped = 0;
356 isSkipping = false;
357 }
358 }
359 else
360 {
361 ++consec_drawn;
362 if( consec_drawn >= EmuConfig.GS.FramesToDraw )
363 {
364 consec_drawn = 0;
365 isSkipping = true;
366 }
367 }
368 }
369
370 void gsPostVsyncEnd()
371 {
372 *(u32*)(PS2MEM_GS+0x1000) ^= 0x2000; // swap the vsync field
373 GetMTGS().PostVsyncEnd();
374 }
375
376 void _gs_ResetFrameskip()
377 {
378 GSsetFrameSkip( 0 );
379 }
380
381 // Disables the GS Frameskip at runtime without any racy mess...
382 void gsResetFrameSkip()
383 {
384 GetMTGS().SendSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
385 }
386
387 void SaveStateBase::gsFreeze()
388 {
389 FreezeMem(PS2MEM_GS, 0x2000);
390 Freeze(CSRw);
391 gifPathFreeze();
392 }

  ViewVC Help
Powered by ViewVC 1.1.22