1 /***************************************************************************
2 * Copyright (C) 2010 PCSX4ALL Team *
3 * Copyright (C) 2010 Unai *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
26 int skipCount = 2; /* frame skip (0,1,2,3...) */
27 int skCount=0; /* internal frame skip */
28 int linesInterlace = 0; /* internal lines interlace */
29 int linesInterlace_user = 0; /* Lines interlace */
31 bool isSkip=false; /* skip frame (info coming from GPU) */
32 bool skipFrame=false; /* skip frame (according to frame skip) */
33 bool alt_fps = false; /* Alternative FPS algorithm */
34 bool show_fps = false; /* Show FPS statistics */
36 bool isPAL=false; /* PAL video timing */
37 bool progressInterlace_flag = false; /* Progressive interlace flag */
38 bool progressInterlace = false; /* Progressive interlace option*/
39 bool frameLimit = false; /* frames to wait */
40 bool light = true; /* lighting */
41 bool blend = true; /* blending */
43 bool fb_dirty = false;
45 bool enableAbbeyHack = false; /* Abe's Odyssey hack */
53 ///////////////////////////////////////////////////////////////////////////////
55 ///////////////////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////////////////
70 ///////////////////////////////////////////////////////////////////////////////
74 ///////////////////////////////////////////////////////////////////////////////
76 u32 TextureWindow [4];
78 u32 DrawingOffset [2];
80 ///////////////////////////////////////////////////////////////////////////////
86 ///////////////////////////////////////////////////////////////////////////////
96 GPUPacket PacketBuffer;
97 u16 GPU_FrameBuffer[FRAME_BUFFER_SIZE/2] __attribute__((aligned(16))); // FRAME_BUFFER_SIZE is defined in bytes
100 ///////////////////////////////////////////////////////////////////////////////
101 // Inner loop driver instanciation file
102 #include "gpu_inner.h"
104 ///////////////////////////////////////////////////////////////////////////////
106 #define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
108 #define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<20)>>20)
109 //#define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<21)>>21)
110 #define GPU_EXPANDSIGN_SPRT(x) (((s32)(x)<<21)>>21)
112 //#define GPU_TESTRANGE(x) { if((u32)(x+1024) > 2047) return; }
113 #define GPU_TESTRANGE(x) { if ((x<-1023) || (x>1023)) return; }
115 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
117 ///////////////////////////////////////////////////////////////////////////////
118 // GPU internal image drawing functions
119 #include "gpu_raster_image.h"
121 ///////////////////////////////////////////////////////////////////////////////
122 // GPU internal line drawing functions
123 #include "gpu_raster_line.h"
125 ///////////////////////////////////////////////////////////////////////////////
126 // GPU internal polygon drawing functions
127 #include "gpu_raster_polygon.h"
129 ///////////////////////////////////////////////////////////////////////////////
130 // GPU internal sprite drawing functions
131 #include "gpu_raster_sprite.h"
133 ///////////////////////////////////////////////////////////////////////////////
134 // GPU command buffer execution/store
135 #include "gpu_command.h"
137 ///////////////////////////////////////////////////////////////////////////////
138 INLINE void gpuReset(void)
140 GPU_GP1 = 0x14802000;
141 TextureWindow[0] = 0;
142 TextureWindow[1] = 0;
143 TextureWindow[2] = 255;
144 TextureWindow[3] = 255;
145 DrawingArea[2] = 256;
146 DrawingArea[3] = 240;
147 DisplayArea[2] = 256;
148 DisplayArea[3] = 240;
149 DisplayArea[5] = 240;
152 ///////////////////////////////////////////////////////////////////////////////
158 for(int i=1;i<=(1<<TABLE_BITS);++i)
160 double v = 1.0 / double(i);
161 #ifdef GPU_TABLE_10_BITS
162 v *= double(0xffffffff>>1);
164 v *= double(0x80000000);
166 s_invTable[i-1]=s32(v);
171 ///////////////////////////////////////////////////////////////////////////////
172 void GPU_shutdown(void)
176 ///////////////////////////////////////////////////////////////////////////////
177 long GPU_freeze(unsigned int bWrite, GPUFreeze_t* p2)
180 if (p2->Version != 1) return (0);
184 p2->GPU_gp1 = GPU_GP1;
185 memcpy(p2->FrameBuffer, (u16*)GPU_FrameBuffer, FRAME_BUFFER_SIZE);
190 GPU_GP1 = p2->GPU_gp1;
191 memcpy((u16*)GPU_FrameBuffer, p2->FrameBuffer, FRAME_BUFFER_SIZE);
197 ///////////////////////////////////////////////////////////////////////////////
198 // GPU DMA comunication
200 ///////////////////////////////////////////////////////////////////////////////
203 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
205 3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 32-47
206 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11, // 48-63
207 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // 64-79
208 3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, // 80-95
209 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, // 96-111
210 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, // 112-127
211 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-
212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
213 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
215 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //
221 ///////////////////////////////////////////////////////////////////////////////
222 INLINE void gpuSendPacket()
224 #ifdef DEBUG_ANALYSIS
225 dbg_anacnt_GPU_sendPacket++;
227 gpuSendPacketFunction(PacketBuffer.U4[0]>>24);
230 ///////////////////////////////////////////////////////////////////////////////
231 INLINE void gpuCheckPacket(u32 uData)
235 PacketBuffer.U4[PacketIndex++] = uData;
240 PacketBuffer.U4[0] = uData;
241 PacketCount = PacketSize[uData >> 24];
244 if (!PacketCount) gpuSendPacket();
247 ///////////////////////////////////////////////////////////////////////////////
248 void GPU_writeDataMem(u32* dmaAddress, s32 dmaCount)
250 #ifdef DEBUG_ANALYSIS
251 dbg_anacnt_GPU_writeDataMem++;
253 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
254 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
256 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
257 GPU_GP1 &= ~0x14000000;
265 data = *dmaAddress++;
266 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
275 GPU_GP1 &= ~0x08000000;
279 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
280 pvram[px] = data>>16;
288 GPU_GP1 &= ~0x08000000;
296 data = *dmaAddress++;
298 gpuCheckPacket(data);
302 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
304 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
305 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
309 INLINE int CheckForEndlessLoop(u32 *laddr)
311 if(laddr==lUsedAddr[1]) return 1;
312 if(laddr==lUsedAddr[2]) return 1;
314 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
315 else lUsedAddr[2]=laddr;
320 ///////////////////////////////////////////////////////////////////////////////
321 void GPU_dmaChain(u32* baseAddr, u32 dmaVAddr)
323 #ifdef DEBUG_ANALYSIS
324 dbg_anacnt_GPU_dmaChain++;
326 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
327 u32 data, *address, count, offset;
328 unsigned int DMACommandCounter = 0;
330 GPU_GP1 &= ~0x14000000;
331 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=(u32*)0x1fffff;
332 dmaVAddr &= 0x001FFFFF;
333 while (dmaVAddr != 0x1FFFFF)
335 address = (baseAddr + (dmaVAddr >> 2));
336 if(DMACommandCounter++ > 2000000) break;
337 if(CheckForEndlessLoop(address)) break;
339 count = (data >> 24);
340 offset = data & 0x001FFFFF;
341 if (dmaVAddr != offset) dmaVAddr = offset;
342 else dmaVAddr = 0x1FFFFF;
344 if(count>0) GPU_writeDataMem(address,count);
346 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
347 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
350 ///////////////////////////////////////////////////////////////////////////////
351 void GPU_writeData(u32 data)
353 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
354 #ifdef DEBUG_ANALYSIS
355 dbg_anacnt_GPU_writeData++;
357 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
358 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
359 GPU_GP1 &= ~0x14000000;
363 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
372 GPU_GP1 &= ~0x08000000;
377 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
386 GPU_GP1 &= ~0x08000000;
393 gpuCheckPacket(data);
395 GPU_GP1 |= 0x14000000;
397 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
398 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
403 ///////////////////////////////////////////////////////////////////////////////
404 void GPU_readDataMem(u32* dmaAddress, s32 dmaCount)
406 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
407 #ifdef DEBUG_ANALYSIS
408 dbg_anacnt_GPU_readDataMem++;
410 if(!FrameToRead) return;
412 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
413 GPU_GP1 &= ~0x14000000;
416 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
418 u32 data = (unsigned long)pvram[px];
426 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
427 // higher 16 bit (always, even if it's an odd width)
428 data |= (unsigned long)(pvram[px])<<16;
430 *dmaAddress++ = data;
439 GPU_GP1 &= ~0x08000000;
443 } while (--dmaCount);
445 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
446 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
451 ///////////////////////////////////////////////////////////////////////////////
452 u32 GPU_readData(void)
454 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
455 #ifdef DEBUG_ANALYSIS
456 dbg_anacnt_GPU_readData++;
458 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
459 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ);
460 GPU_GP1 &= ~0x14000000;
463 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
472 GPU_GP1 &= ~0x08000000;
475 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
476 GP0 |= pvram[px]<<16;
484 GPU_GP1 &= ~0x08000000;
489 GPU_GP1 |= 0x14000000;
491 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ);
492 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
496 ///////////////////////////////////////////////////////////////////////////////
497 u32 GPU_readStatus(void)
499 #ifdef DEBUG_ANALYSIS
500 dbg_anacnt_GPU_readStatus++;
505 ///////////////////////////////////////////////////////////////////////////////
506 void GPU_writeStatus(u32 data)
508 #ifdef DEBUG_ANALYSIS
509 dbg_anacnt_GPU_writeStatus++;
511 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
512 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
513 switch (data >> 24) {
518 GPU_GP1 &= ~0x08000000;
519 PacketCount = FrameToRead = FrameToWrite = 0;
522 GPU_GP1 &= ~0x08000000;
523 PacketCount = FrameToRead = FrameToWrite = 0;
526 GPU_GP1 = (GPU_GP1 & ~0x00800000) | ((data & 1) << 23);
529 if (data == 0x04000000)
531 GPU_GP1 = (GPU_GP1 & ~0x60000000) | ((data & 3) << 29);
534 DisplayArea[0] = (data & 0x000003FF); //(short)(data & 0x3ff);
535 DisplayArea[1] = ((data & 0x0007FC00)>>10); //(data & 0x000FFC00) >> 10; //(short)((data>>10)&0x1ff);
539 DisplayArea[4] = data & 0x000003FF; //(short)(data & 0x3ff);
540 DisplayArea[5] = (data & 0x000FFC00) >> 10; //(short)((data>>10) & 0x3ff);
545 GPU_GP1 = (GPU_GP1 & ~0x007F0000) | ((data & 0x3F) << 17) | ((data & 0x40) << 10);
546 static u32 HorizontalResolution[8] = { 256, 368, 320, 384, 512, 512, 640, 640 };
547 DisplayArea[2] = HorizontalResolution[(GPU_GP1 >> 16) & 7];
548 static u32 VerticalResolution[4] = { 240, 480, 256, 480 };
549 DisplayArea[3] = VerticalResolution[(GPU_GP1 >> 19) & 3];
550 isPAL = (data & 0x08) ? true : false; // if 1 - PAL mode, else NTSC
555 switch (data & 0xffff) {
559 GP0 = (DrawingArea[1] << 10) | DrawingArea[0];
562 GP0 = ((DrawingArea[3]-1) << 10) | (DrawingArea[2]-1);
566 GP0 = (DrawingOffset[1] << 11) | DrawingOffset[0];
576 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
577 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
582 // Blitting functions
583 #include "gpu_blit.h"
585 INLINE void gpuVideoOutput(void)
587 static s16 old_res_horz, old_res_vert, old_rgb24;
588 s16 h0, x0, y0, w0, h1;
594 h0 = DisplayArea[3]; // video mode
596 h1 = DisplayArea[5] - DisplayArea[4]; // display needed
597 if (h0 == 480) h1 = Min2(h1*2,480);
599 u16* dest_screen16 = SCREEN;
600 u16* src_screen16 = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(x0,y0)];
601 u32 isRGB24 = (GPU_GP1 & 0x00200000 ? 32 : 0);
603 /* Clear the screen if resolution changed to prevent interlacing and clipping to clash */
604 if( (w0 != old_res_horz || h1 != old_res_vert || (s16)isRGB24 != old_rgb24) )
606 // Update old resolution
609 old_rgb24 = (s16)isRGB24;
610 // Finally, clear the screen for this special case
616 if(h0==256) h0 = 240; else if(h0==480) sizeShift = 2;
617 if(h1>h0) { src_screen16 += ((h1-h0)>>sizeShift)*1024; h1 = h0; }
618 else if(h1<h0) dest_screen16 += ((h0-h1)>>sizeShift)*VIDEO_WIDTH;
621 int incY = (h0==480) ? 2 : 1;
622 h0=(h0==480 ? 2048 : 1024);
624 if (!progressInterlace)
626 const int li=linesInterlace;
630 for(int y1=y0+h1; y0<y1; y0+=incY)
632 if( 0 == (y0&li) ) GPU_BlitWWDWW( src_screen16, dest_screen16, isRGB24);
633 dest_screen16 += VIDEO_WIDTH;
638 for(int y1=y0+h1; y0<y1; y0+=incY)
640 if( 0 == (y0&li) ) GPU_BlitWWWWWWWWS( src_screen16, dest_screen16, isRGB24, 4);
641 dest_screen16 += VIDEO_WIDTH;
646 for(int y1=y0+h1; y0<y1; y0+=incY)
648 if( 0 == (y0&li) ) GPU_BlitWW( src_screen16, dest_screen16, isRGB24);
649 dest_screen16 += VIDEO_WIDTH;
654 for(int y1=y0+h1; y0<y1; y0+=incY)
656 if( 0 == (y0&li) ) GPU_BlitWWWWWS( src_screen16, dest_screen16, isRGB24);
657 dest_screen16 += VIDEO_WIDTH;
662 for(int y1=y0+h1; y0<y1; y0+=incY)
664 if( 0 == (y0&li) ) GPU_BlitWWSWWSWS( src_screen16, dest_screen16, isRGB24);
665 dest_screen16 += VIDEO_WIDTH;
670 for(int y1=y0+h1; y0<y1; y0+=incY)
672 if( 0 == (y0&li) ) GPU_BlitWS( src_screen16, dest_screen16, isRGB24);
673 dest_screen16 += VIDEO_WIDTH;
681 const int li=linesInterlace;
682 bool flag=progressInterlace_flag; /* progressive interlace */
686 for(int y1=y0+h1; y0<y1; y0+=incY)
688 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWWDWW( src_screen16, dest_screen16, isRGB24);
689 dest_screen16 += VIDEO_WIDTH;
694 for(int y1=y0+h1; y0<y1; y0+=incY)
696 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWWWWWWWWS( src_screen16, dest_screen16, isRGB24, 4);
697 dest_screen16 += VIDEO_WIDTH;
702 for(int y1=y0+h1; y0<y1; y0+=incY)
704 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWW( src_screen16, dest_screen16, isRGB24);
705 dest_screen16 += VIDEO_WIDTH;
710 for(int y1=y0+h1; y0<y1; y0+=incY)
712 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWWWWWS( src_screen16, dest_screen16, isRGB24);
713 dest_screen16 += VIDEO_WIDTH;
718 for(int y1=y0+h1; y0<y1; y0+=incY)
720 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWWSWWSWS( src_screen16, dest_screen16, isRGB24);
721 dest_screen16 += VIDEO_WIDTH;
726 for(int y1=y0+h1; y0<y1; y0+=incY)
728 if(( 0 == (y0&li) ) && (flag=!flag)) GPU_BlitWS( src_screen16, dest_screen16, isRGB24);
729 dest_screen16 += VIDEO_WIDTH;
734 progressInterlace_flag=!flag;
739 ///////////////////////////////////////////////////////////////////////////////
740 void GPU_updateLace(void)
742 #ifdef ENABLE_GPU_LOG_SUPPORT
743 fprintf(stdout,"GPU_updateLace()\n");
745 #ifdef DEBUG_ANALYSIS
746 dbg_anacnt_GPU_updateLace++;
748 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_COUNTERS);
749 #ifdef PROFILER_PCSX4ALL
750 pcsx4all_prof_frames++;
756 if (!passed) dbg_enable();
757 else pcsx4all_exit();
763 static const unsigned char skipTable[12][12] =
765 { 0,0,0,0,0,0,0,0,0,0,0,0 },
766 { 0,0,0,0,0,0,0,0,0,0,0,1 },
767 { 0,0,0,0,0,1,0,0,0,0,0,1 },
768 { 0,0,0,1,0,0,0,1,0,0,0,1 },
769 { 0,0,1,0,0,1,0,0,1,0,0,1 },
770 { 0,1,0,0,1,0,1,0,0,1,0,1 },
771 { 0,1,0,1,0,1,0,1,0,1,0,1 },
772 { 0,1,0,1,1,0,1,0,1,1,0,1 },
773 { 0,1,1,0,1,1,0,1,1,0,1,1 },
774 { 0,1,1,1,0,1,1,1,0,1,1,1 },
775 { 0,1,1,1,1,1,0,1,1,1,1,1 },
776 { 0,1,1,1,1,1,1,1,1,1,1,1 }
779 // Interlace bit toggle
780 GPU_GP1 ^= 0x80000000;
783 if ((!skipFrame) && (!isSkip) && (!(((GPU_GP1&0x08000000))||((GPU_GP1&0x00800000)))))
785 gpuVideoOutput(); // Display updated
787 if (DisplayArea[3] == 480)
789 if (linesInterlace_user) linesInterlace = 3; // 1/4 of lines
790 else linesInterlace = 1; // if 480 we only need half of lines
792 else if (linesInterlace != linesInterlace_user)
794 linesInterlace = linesInterlace_user; // resolution changed from 480 to lower one
801 static unsigned next=get_ticks();
802 unsigned now=get_ticks();
805 if (now<next) wait_ticks(next-now);
807 next+=(isPAL?(1000000/50):((unsigned)(1000000.0/59.94)));
811 // Show FPS statistics
814 static u32 real_fps=0;
815 static u32 prev=get_ticks();
816 static char msg[24]="FPS=000/00 SPD=000%";
819 if ((now-prev)>=1000000)
821 u32 expected_fps=(isPAL?50:60);
822 sprintf(msg,"FPS=%3d/%2d SPD=%3d%%",((real_fps*(12-skipCount))/12),((expected_fps*(12-skipCount))/12),((real_fps*100)/expected_fps));
826 port_printf(5,5,msg);
833 skipFrame=skipTable[skipCount][skCount];
834 skCount--; if (skCount<0) skCount=11;
842 skipFrame=skipTable[skipCount][skCount];
843 skCount--; if (skCount<0) skCount=11;
848 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_COUNTERS);
853 #include "../../frontend/plugin_lib.h"
857 extern void bgr555_to_rgb565(void *dst, void *src, int bytes);
858 extern void bgr888_to_rgb888(void *dst, void *src, int bytes);
859 static const struct rearmed_cbs *cbs;
860 static void *screen_buf;
862 static void blit(void)
864 static s16 old_res_horz, old_res_vert, old_rgb24;
865 s16 isRGB24 = (GPU_GP1 & 0x00200000) ? 1 : 0;
866 s16 h0, x0, y0, w0, h1;
870 x0 = DisplayArea[0] & ~3; // alignment needed by blitter
872 srcs = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(x0,y0)];
875 h0 = DisplayArea[3]; // video mode
877 h1 = DisplayArea[5] - DisplayArea[4]; // display needed
878 if (h0 == 480) h1 = Min2(h1*2,480);
883 if (w0 != old_res_horz || h1 != old_res_vert || isRGB24 != old_rgb24)
887 old_rgb24 = (s16)isRGB24;
888 screen_buf = cbs->pl_fbdev_set_mode(w0, h1, isRGB24 ? 24 : 16);
890 dest = (u8 *)screen_buf;
894 for (; h1-- > 0; dest += w0 * 3, srcs += 1024)
896 bgr888_to_rgb888(dest, srcs, w0 * 3);
901 for (; h1-- > 0; dest += w0 * 2, srcs += 1024)
903 bgr555_to_rgb565(dest, srcs, w0 * 2);
907 screen_buf = cbs->pl_fbdev_flip();
910 void GPU_updateLace(void)
912 // Interlace bit toggle
913 GPU_GP1 ^= 0x80000000;
915 if (!fb_dirty || (GPU_GP1&0x08800000))
922 if (*cbs->fskip_option)
929 long GPUopen(unsigned long *, char *, char *)
931 cbs->pl_fbdev_open();
932 screen_buf = cbs->pl_fbdev_flip();
938 cbs->pl_fbdev_close();
942 long GPUfreeze(unsigned int ulGetFreezeData, GPUFreeze_t* p2)
944 if (ulGetFreezeData > 1)
947 return GPU_freeze(ulGetFreezeData, p2);
950 void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_)