/[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 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 10 months ago) by william
File size: 12521 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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     __aligned16 u8 g_RealGSMem[0x2000];
29    
30     void gsOnModeChanged( Fixed100 framerate, u32 newTickrate )
31     {
32     GetMTGS().SendSimplePacket( GS_RINGTYPE_MODECHANGE, framerate.Raw, newTickrate, 0 );
33     }
34    
35     static bool gsIsInterlaced = false;
36     GS_RegionMode gsRegionMode = Region_NTSC;
37    
38    
39     void gsSetRegionMode( GS_RegionMode region )
40     {
41     if( gsRegionMode == region ) return;
42    
43     gsRegionMode = region;
44     UpdateVSyncRate();
45     }
46    
47    
48     // Make sure framelimiter options are in sync with the plugin's capabilities.
49     void gsInit()
50     {
51     memzero(g_RealGSMem);
52     }
53    
54 william 62 extern bool SIGNAL_IMR_Pending;
55     extern u32 SIGNAL_Data_Pending[2];
56    
57     void gsGIFReset()
58     {
59     gifRegs.stat.reset();
60     gifRegs.ctrl.reset();
61     gifRegs.mode.reset();
62     }
63    
64 william 31 void gsReset()
65     {
66     GetMTGS().ResetGS();
67    
68     UpdateVSyncRate();
69 william 62 GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE;
70 william 31 memzero(g_RealGSMem);
71    
72 william 62 SIGNAL_IMR_Pending = false;
73    
74     CSRreg.Reset();
75 william 31 GSIMR = 0x7f00;
76    
77 william 62 // FIXME: This really doesn't belong here, and I seriously doubt it's needed.
78     // If it is needed it should be in the GIF portion of hwReset(). --air
79     gsGIFReset();
80 william 31 }
81    
82 william 62 static __fi void gsCSRwrite( const tGS_CSR& csr )
83 william 31 {
84 william 62 if (csr.RESET) {
85 william 31
86     // perform a soft reset -- which is a clearing of all GIFpaths -- and fall back to doing
87     // a full reset if the plugin doesn't support soft resets.
88    
89     if( GSgifSoftReset != NULL )
90     {
91     GIFPath_Clear( GIF_PATH_1 );
92     GIFPath_Clear( GIF_PATH_2 );
93     GIFPath_Clear( GIF_PATH_3 );
94     }
95     else
96     {
97     GetMTGS().SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
98     }
99    
100 william 62 SIGNAL_IMR_Pending = false;
101     CSRreg.Reset();
102     GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
103 william 31 }
104 william 62
105     if(csr.FLUSH)
106 william 31 {
107     // Our emulated GS has no FIFO, but if it did, it would flush it here...
108     //Console.WriteLn("GS_CSR FLUSH GS fifo: %x (CSRr=%x)", value, GSCSRr);
109     }
110 william 62
111     if(csr.SIGNAL)
112 william 31 {
113 william 62 // SIGNAL : What's not known here is whether or not the SIGID register should be updated
114     // here or when the IMR is cleared (below).
115    
116     if(SIGNAL_IMR_Pending == true)
117     {
118     //DevCon.Warning("Firing pending signal");
119     GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x",SIGNAL_Data_Pending[0], SIGNAL_Data_Pending[1], GSIMR, GSCSRr);
120     GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~SIGNAL_Data_Pending[1])|(SIGNAL_Data_Pending[0]&SIGNAL_Data_Pending[1]);
121    
122     if (!(GSIMR&0x100))
123     gsIrq();
124    
125     CSRreg.SIGNAL = true; //Just to be sure :P
126     }
127     else CSRreg.SIGNAL = false;
128    
129     SIGNAL_IMR_Pending = false;
130    
131     if(gifRegs.stat.P1Q && gifRegs.stat.APATH <= GIF_APATH1) gsPath1Interrupt();
132 william 31 }
133 william 62
134     if(csr.FINISH) CSRreg.FINISH = false;
135     if(csr.HSINT) CSRreg.HSINT = false;
136     if(csr.VSINT) CSRreg.VSINT = false;
137     if(csr.EDWINT) CSRreg.EDWINT = false;
138 william 31 }
139    
140 william 62 static __fi void IMRwrite(u32 value)
141 william 31 {
142     GSIMR = (value & 0x1f00)|0x6000;
143    
144 william 62 if(CSRreg.GetInterruptMask() & (~(GSIMR >> 8) & 0x1f))
145     gsIrq();
146    
147     if( SIGNAL_IMR_Pending && !(GSIMR & 0x100))
148 william 31 {
149 william 62 // Note: PS2 apps are expected to write a successive 1 and 0 to the IMR in order to
150     // trigger the gsInt and clear the second pending SIGNAL interrupt -- if they fail
151     // to do so, the GS will freeze again upon the very next SIGNAL).
152     //
153     // What's not known here is whether or not the SIGID register should be updated
154     // here or when the GS is resumed during CSR write (above).
155    
156     //GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x\n",CSR_SIGNAL_Data[0], CSR_SIGNAL_Data[1], GSIMR, GSCSRr);
157     //GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~CSR_SIGNAL_Data[1])|(CSR_SIGNAL_Data[0]&CSR_SIGNAL_Data[1]);
158    
159     CSRreg.SIGNAL = true;
160 william 31 gsIrq();
161     }
162     }
163    
164 william 62 __fi void gsWrite8(u32 mem, u8 value)
165 william 31 {
166     switch (mem)
167     {
168 william 62 // CSR 8-bit write handlers.
169     // I'm quite sure these whould just write the CSR portion with the other
170     // bits set to 0 (no action). The previous implementation masked the 8-bit
171     // write value against the previous CSR write value, but that really doesn't
172     // make any sense, given that the real hardware's CSR circuit probably has no
173     // real "memory" where it saves anything. (for example, you can't write to
174     // and change the GS revision or ID portions -- they're all hard wired.) --air
175    
176 william 31 case GS_CSR: // GS_CSR
177 william 62 gsCSRwrite( tGS_CSR((u32)value) ); break;
178 william 31 case GS_CSR + 1: // GS_CSR
179 william 62 gsCSRwrite( tGS_CSR(((u32)value) << 8) ); break;
180 william 31 case GS_CSR + 2: // GS_CSR
181 william 62 gsCSRwrite( tGS_CSR(((u32)value) << 16) ); break;
182 william 31 case GS_CSR + 3: // GS_CSR
183 william 62 gsCSRwrite( tGS_CSR(((u32)value) << 24) ); break;
184    
185 william 31 default:
186     *PS2GS_BASE(mem) = value;
187 william 62 break;
188 william 31 }
189     GIF_LOG("GS write 8 at %8.8lx with data %8.8lx", mem, value);
190     }
191    
192 william 62 static __fi void _gsSMODEwrite( u32 mem, u32 value )
193 william 31 {
194     switch (mem)
195     {
196     case GS_SMODE1:
197     gsSetRegionMode( ((value & 0x6000) == 0x6000) ? Region_PAL : Region_NTSC );
198     break;
199    
200     case GS_SMODE2:
201     gsIsInterlaced = (value & 0x1);
202     break;
203     }
204     }
205    
206     //////////////////////////////////////////////////////////////////////////
207     // GS Write 16 bit
208    
209 william 62 __fi void gsWrite16(u32 mem, u16 value)
210 william 31 {
211     GIF_LOG("GS write 16 at %8.8lx with data %8.8lx", mem, value);
212    
213     _gsSMODEwrite( mem, value );
214    
215     switch (mem)
216     {
217 william 62 // See note above about CSR 8 bit writes, and handling them as zero'd bits
218     // for all but the written parts.
219    
220 william 31 case GS_CSR:
221 william 62 gsCSRwrite( tGS_CSR((u32)value) );
222 william 31 return; // do not write to MTGS memory
223    
224     case GS_CSR+2:
225 william 62 gsCSRwrite( tGS_CSR(((u32)value) << 16) );
226 william 31 return; // do not write to MTGS memory
227    
228     case GS_IMR:
229     IMRwrite(value);
230     return; // do not write to MTGS memory
231     }
232    
233     *(u16*)PS2GS_BASE(mem) = value;
234     }
235    
236     //////////////////////////////////////////////////////////////////////////
237     // GS Write 32 bit
238    
239 william 62 __fi void gsWrite32(u32 mem, u32 value)
240 william 31 {
241 william 62 pxAssume( (mem & 3) == 0 );
242 william 31 GIF_LOG("GS write 32 at %8.8lx with data %8.8lx", mem, value);
243    
244     _gsSMODEwrite( mem, value );
245    
246     switch (mem)
247     {
248     case GS_CSR:
249 william 62 gsCSRwrite(tGS_CSR(value));
250 william 31 return;
251    
252     case GS_IMR:
253     IMRwrite(value);
254     return;
255     }
256    
257     *(u32*)PS2GS_BASE(mem) = value;
258     }
259    
260     //////////////////////////////////////////////////////////////////////////
261     // GS Write 64 bit
262    
263 william 62 void __fastcall gsWrite64_generic( u32 mem, const mem64_t* value )
264     {
265     const u32* const srcval32 = (u32*)value;
266     GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x", mem, srcval32[1], srcval32[0]);
267    
268     *(u64*)PS2GS_BASE(mem) = *value;
269     }
270    
271 william 31 void __fastcall gsWrite64_page_00( u32 mem, const mem64_t* value )
272     {
273     gsWrite64_generic( mem, value );
274     _gsSMODEwrite( mem, (u32)value[0] );
275     }
276    
277     void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
278     {
279     GIF_LOG("GS Write64 at %8.8lx with data %8.8x_%8.8x", mem, (u32*)value[1], (u32*)value[0]);
280    
281     switch( mem )
282     {
283 william 62 case 0x12001040: //busdir
284    
285     //This is probably a complete hack, however writing to BUSDIR "should" start a transfer
286     //Only problem is it kills killzone :(.
287     // (yes it *is* a complete hack; both lines here in fact --air)
288     //=========================================================================
289     //gifRegs.stat.OPH = true; // Bleach wants it, Killzone hates it.
290    
291     gifRegs.stat.DIR = (u32)value[0];
292     //=========================================================================
293     // BUSDIR INSANITY !! MTGS FLUSH NEEDED
294     //
295     // Yup folks. BUSDIR is evil. The only safe way to handle it is to flush the whole MTGS
296     // and ensure complete MTGS and EEcore thread synchronization This is very slow, no doubt,
297     // but on the birght side BUSDIR is used quite rately, indeed.
298    
299     // Important: writeback to gsRegs area *prior* to flushing the MTGS. The flush will sync
300     // the GS and MTGS register states, and upload our screwy busdir register in the process. :)
301     gsWrite64_generic( mem, value );
302     GetMTGS().WaitGS();
303     return;
304    
305 william 31 case GS_CSR:
306 william 62 gsCSRwrite(tGS_CSR(*value));
307 william 31 return;
308    
309     case GS_IMR:
310     IMRwrite((u32)value[0]);
311     return;
312     }
313    
314     gsWrite64_generic( mem, value );
315     }
316    
317     //////////////////////////////////////////////////////////////////////////
318     // GS Write 128 bit
319    
320     void __fastcall gsWrite128_page_00( u32 mem, const mem128_t* value )
321     {
322     gsWrite128_generic( mem, value );
323     _gsSMODEwrite( mem, (u32)value[0] );
324     }
325    
326     void __fastcall gsWrite128_page_01( u32 mem, const mem128_t* value )
327     {
328     switch( mem )
329     {
330     case GS_CSR:
331     gsCSRwrite((u32)value[0]);
332     return;
333    
334     case GS_IMR:
335     IMRwrite((u32)value[0]);
336     return;
337     }
338    
339     gsWrite128_generic( mem, value );
340     }
341    
342     void __fastcall gsWrite128_generic( u32 mem, const mem128_t* value )
343     {
344     const u32* const srcval32 = (u32*)value;
345    
346     GIF_LOG("GS Write128 at %8.8lx with data %8.8x_%8.8x_%8.8x_%8.8x", mem,
347     srcval32[3], srcval32[2], srcval32[1], srcval32[0]);
348    
349 william 62 CopyQWC(PS2GS_BASE(mem), value);
350 william 31 }
351    
352 william 62 __fi u8 gsRead8(u32 mem)
353 william 31 {
354     GIF_LOG("GS read 8 from %8.8lx value: %8.8lx", mem, *(u8*)PS2GS_BASE(mem));
355     return *(u8*)PS2GS_BASE(mem);
356     }
357    
358 william 62 __fi u16 gsRead16(u32 mem)
359 william 31 {
360     GIF_LOG("GS read 16 from %8.8lx value: %8.8lx", mem, *(u16*)PS2GS_BASE(mem));
361     return *(u16*)PS2GS_BASE(mem);
362     }
363    
364 william 62 __fi u32 gsRead32(u32 mem)
365 william 31 {
366     GIF_LOG("GS read 32 from %8.8lx value: %8.8lx", mem, *(u32*)PS2GS_BASE(mem));
367     return *(u32*)PS2GS_BASE(mem);
368     }
369    
370 william 62 __fi u64 gsRead64(u32 mem)
371 william 31 {
372     // fixme - PS2GS_BASE(mem+4) = (g_RealGSMem+(mem + 4 & 0x13ff))
373     GIF_LOG("GS read 64 from %8.8lx value: %8.8lx_%8.8lx", mem, *(u32*)PS2GS_BASE(mem+4), *(u32*)PS2GS_BASE(mem) );
374     return *(u64*)PS2GS_BASE(mem);
375     }
376    
377     void gsIrq() {
378     hwIntcIrq(INTC_GS);
379     }
380    
381     // --------------------------------------------------------------------------------------
382     // gsFrameSkip
383     // --------------------------------------------------------------------------------------
384     // This function regulates the frameskipping status of the GS. Our new frameskipper for
385     // 0.9.7 is a very simple logic pattern compared to the old mess. The goal now is to provide
386     // the most compatible and efficient frameskip, instead of doing the adaptive logic of
387     // 0.9.6. This is almost a necessity because of how many games treat the GS: they upload
388     // great amounts of data while rendering 2 frames at a time (using double buffering), and
389     // then use a simple pageswap to display the contents of the second frame for that vsync.
390     // (this approach is mostly seen on interlace games; progressive games less so)
391     // The result is that any skip pattern besides a fully consistent 2on,2off would reuslt in
392     // tons of missing geometry, rendering frameskip useless.
393     //
394     // So instead we use a simple "always skipping" or "never skipping" logic.
395     //
396     // EE vs MTGS:
397     // This function does not regulate frame limiting, meaning it does no stalling. Stalling
398     // functions are performed by the EE, which itself uses thread sleep logic to avoid spin
399     // waiting as much as possible (maximizes CPU resource availability for the GS).
400    
401 william 62 __fi void gsFrameSkip()
402 william 31 {
403     static int consec_skipped = 0;
404     static int consec_drawn = 0;
405     static bool isSkipping = false;
406    
407 william 62 if( !EmuConfig.GS.FrameSkipEnable )
408     {
409     if( isSkipping )
410     {
411     // Frameskipping disabled on-the-fly .. make sure the GS is restored to non-skip
412     // behavior.
413     GSsetFrameSkip( false );
414     isSkipping = false;
415     }
416     return;
417     }
418    
419 william 31 GSsetFrameSkip( isSkipping );
420    
421     if( isSkipping )
422     {
423     ++consec_skipped;
424     if( consec_skipped >= EmuConfig.GS.FramesToSkip )
425     {
426     consec_skipped = 0;
427     isSkipping = false;
428     }
429     }
430     else
431     {
432     ++consec_drawn;
433     if( consec_drawn >= EmuConfig.GS.FramesToDraw )
434     {
435     consec_drawn = 0;
436     isSkipping = true;
437     }
438     }
439     }
440    
441     void gsPostVsyncEnd()
442     {
443 william 62 CSRreg.SwapField();
444 william 31 GetMTGS().PostVsyncEnd();
445     }
446    
447     void _gs_ResetFrameskip()
448     {
449     GSsetFrameSkip( 0 );
450     }
451    
452     // Disables the GS Frameskip at runtime without any racy mess...
453     void gsResetFrameSkip()
454     {
455     GetMTGS().SendSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
456     }
457    
458     void SaveStateBase::gsFreeze()
459     {
460     FreezeMem(PS2MEM_GS, 0x2000);
461 william 62 Freeze(SIGNAL_IMR_Pending);
462     Freeze(gsRegionMode);
463    
464 william 31 gifPathFreeze();
465     }

  ViewVC Help
Powered by ViewVC 1.1.22