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

Annotation of /trunk/pcsx2/GS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 5 months ago) by william
File size: 9932 byte(s)
committing r3113 initial commit again...
1 william 31 /* 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