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) */
33 bool skipFrame = false; /* skip frame (according to frame skip) */
34 bool alt_fps = false; /* Alternative FPS algorithm */
35 bool show_fps = false; /* Show FPS statistics */
37 bool isPAL = false; /* PAL video timing */
38 bool progressInterlace_flag = false; /* Progressive interlace flag */
39 bool progressInterlace = false; /* Progressive interlace option*/
40 bool frameLimit = false; /* frames to wait */
42 bool light = true; /* lighting */
43 bool blend = true; /* blending */
44 bool FrameToRead = false; /* load image in progress */
45 bool FrameToWrite = false; /* store image in progress */
46 bool fb_dirty = false;
48 bool enableAbbeyHack = false; /* Abe's Odyssey hack */
57 ///////////////////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////////////////
61 ///////////////////////////////////////////////////////////////////////////////
71 ///////////////////////////////////////////////////////////////////////////////
75 ///////////////////////////////////////////////////////////////////////////////
77 u32 TextureWindow [4];
79 u32 DrawingOffset [2];
81 ///////////////////////////////////////////////////////////////////////////////
87 ///////////////////////////////////////////////////////////////////////////////
97 GPUPacket PacketBuffer;
98 // FRAME_BUFFER_SIZE is defined in bytes; 512K is guard memory for out of range reads
99 u16 GPU_FrameBuffer[(FRAME_BUFFER_SIZE+512*1024)/2] __attribute__((aligned(16)));
102 ///////////////////////////////////////////////////////////////////////////////
103 // Inner loop driver instanciation file
104 #include "gpu_inner.h"
106 ///////////////////////////////////////////////////////////////////////////////
108 #define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
110 #define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<20)>>20)
111 //#define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<21)>>21)
112 #define GPU_EXPANDSIGN_SPRT(x) (((s32)(x)<<21)>>21)
114 //#define GPU_TESTRANGE(x) { if((u32)(x+1024) > 2047) return; }
115 #define GPU_TESTRANGE(x) { if ((x<-1023) || (x>1023)) return; }
117 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
119 ///////////////////////////////////////////////////////////////////////////////
120 // GPU internal image drawing functions
121 #include "gpu_raster_image.h"
123 ///////////////////////////////////////////////////////////////////////////////
124 // GPU internal line drawing functions
125 #include "gpu_raster_line.h"
127 ///////////////////////////////////////////////////////////////////////////////
128 // GPU internal polygon drawing functions
129 #include "gpu_raster_polygon.h"
131 ///////////////////////////////////////////////////////////////////////////////
132 // GPU internal sprite drawing functions
133 #include "gpu_raster_sprite.h"
135 ///////////////////////////////////////////////////////////////////////////////
136 // GPU command buffer execution/store
137 #include "gpu_command.h"
139 ///////////////////////////////////////////////////////////////////////////////
140 INLINE void gpuReset(void)
142 GPU_GP1 = 0x14802000;
143 TextureWindow[0] = 0;
144 TextureWindow[1] = 0;
145 TextureWindow[2] = 255;
146 TextureWindow[3] = 255;
147 DrawingArea[2] = 256;
148 DrawingArea[3] = 240;
149 DisplayArea[2] = 256;
150 DisplayArea[3] = 240;
151 DisplayArea[5] = 240;
154 ///////////////////////////////////////////////////////////////////////////////
160 for(int i=1;i<=(1<<TABLE_BITS);++i)
162 double v = 1.0 / double(i);
163 #ifdef GPU_TABLE_10_BITS
164 v *= double(0xffffffff>>1);
166 v *= double(0x80000000);
168 s_invTable[i-1]=s32(v);
173 ///////////////////////////////////////////////////////////////////////////////
174 void GPU_shutdown(void)
178 ///////////////////////////////////////////////////////////////////////////////
179 long GPU_freeze(unsigned int bWrite, GPUFreeze_t* p2)
182 if (p2->Version != 1) return (0);
186 p2->GPU_gp1 = GPU_GP1;
187 memset(p2->Control, 0, sizeof(p2->Control));
188 // save resolution and registers for P.E.Op.S. compatibility
189 p2->Control[3] = (3 << 24) | ((GPU_GP1 >> 23) & 1);
190 p2->Control[4] = (4 << 24) | ((GPU_GP1 >> 29) & 3);
191 p2->Control[5] = (5 << 24) | (DisplayArea[0] | (DisplayArea[1] << 10));
192 p2->Control[6] = (6 << 24) | (2560 << 12);
193 p2->Control[7] = (7 << 24) | (DisplayArea[4] | (DisplayArea[5] << 10));
194 p2->Control[8] = (8 << 24) | ((GPU_GP1 >> 17) & 0x3f) | ((GPU_GP1 >> 10) & 0x40);
195 memcpy(p2->FrameBuffer, (u16*)GPU_FrameBuffer, FRAME_BUFFER_SIZE);
200 GPU_GP1 = p2->GPU_gp1;
201 memcpy((u16*)GPU_FrameBuffer, p2->FrameBuffer, FRAME_BUFFER_SIZE);
202 GPU_writeStatus((5 << 24) | p2->Control[5]);
203 GPU_writeStatus((7 << 24) | p2->Control[7]);
204 GPU_writeStatus((8 << 24) | p2->Control[8]);
205 gpuSetTexture(GPU_GP1);
211 ///////////////////////////////////////////////////////////////////////////////
212 // GPU DMA comunication
214 ///////////////////////////////////////////////////////////////////////////////
217 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
219 3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 32-47
220 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11, // 48-63
221 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // 64-79
222 3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, // 80-95
223 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, // 96-111
224 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, // 112-127
225 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-
226 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
227 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
229 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //
235 ///////////////////////////////////////////////////////////////////////////////
236 INLINE void gpuSendPacket()
238 #ifdef DEBUG_ANALYSIS
239 dbg_anacnt_GPU_sendPacket++;
241 gpuSendPacketFunction(PacketBuffer.U4[0]>>24);
244 ///////////////////////////////////////////////////////////////////////////////
245 INLINE void gpuCheckPacket(u32 uData)
249 PacketBuffer.U4[PacketIndex++] = uData;
254 PacketBuffer.U4[0] = uData;
255 PacketCount = PacketSize[uData >> 24];
258 if (!PacketCount) gpuSendPacket();
261 ///////////////////////////////////////////////////////////////////////////////
262 void GPU_writeDataMem(u32* dmaAddress, s32 dmaCount)
264 #ifdef DEBUG_ANALYSIS
265 dbg_anacnt_GPU_writeDataMem++;
267 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
268 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
270 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
271 GPU_GP1 &= ~0x14000000;
279 data = *dmaAddress++;
280 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
288 FrameToWrite = false;
289 GPU_GP1 &= ~0x08000000;
293 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
294 pvram[px] = data>>16;
301 FrameToWrite = false;
302 GPU_GP1 &= ~0x08000000;
310 data = *dmaAddress++;
312 gpuCheckPacket(data);
316 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
318 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
319 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
323 INLINE int CheckForEndlessLoop(u32 *laddr)
325 if(laddr==lUsedAddr[1]) return 1;
326 if(laddr==lUsedAddr[2]) return 1;
328 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
329 else lUsedAddr[2]=laddr;
334 ///////////////////////////////////////////////////////////////////////////////
335 long GPU_dmaChain(u32* baseAddr, u32 dmaVAddr)
337 #ifdef DEBUG_ANALYSIS
338 dbg_anacnt_GPU_dmaChain++;
340 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
341 u32 data, *address, count, offset;
342 unsigned int DMACommandCounter = 0;
345 GPU_GP1 &= ~0x14000000;
346 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=(u32*)0x1fffff;
347 dmaVAddr &= 0x001FFFFF;
348 while (dmaVAddr != 0x1FFFFF)
350 address = (baseAddr + (dmaVAddr >> 2));
351 if(DMACommandCounter++ > 2000000) break;
352 if(CheckForEndlessLoop(address)) break;
354 count = (data >> 24);
355 offset = data & 0x001FFFFF;
356 if (dmaVAddr != offset) dmaVAddr = offset;
357 else dmaVAddr = 0x1FFFFF;
359 if(count>0) GPU_writeDataMem(address,count);
360 dma_words += 1 + count;
362 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
363 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
368 ///////////////////////////////////////////////////////////////////////////////
369 void GPU_writeData(u32 data)
371 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
372 #ifdef DEBUG_ANALYSIS
373 dbg_anacnt_GPU_writeData++;
375 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
376 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
377 GPU_GP1 &= ~0x14000000;
381 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
389 FrameToWrite = false;
390 GPU_GP1 &= ~0x08000000;
395 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
403 FrameToWrite = false;
404 GPU_GP1 &= ~0x08000000;
411 gpuCheckPacket(data);
413 GPU_GP1 |= 0x14000000;
415 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
416 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
421 ///////////////////////////////////////////////////////////////////////////////
422 void GPU_readDataMem(u32* dmaAddress, s32 dmaCount)
424 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
425 #ifdef DEBUG_ANALYSIS
426 dbg_anacnt_GPU_readDataMem++;
428 if(!FrameToRead) return;
430 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
431 GPU_GP1 &= ~0x14000000;
434 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
436 u32 data = (unsigned long)pvram[px];
444 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
445 // higher 16 bit (always, even if it's an odd width)
446 data |= (unsigned long)(pvram[px])<<16;
448 *dmaAddress++ = data;
457 GPU_GP1 &= ~0x08000000;
461 } while (--dmaCount);
463 GPU_GP1 = (GPU_GP1 | 0x14000000) & ~0x60000000;
464 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
469 ///////////////////////////////////////////////////////////////////////////////
470 u32 GPU_readData(void)
472 const u16 *VIDEO_END=(GPU_FrameBuffer+(FRAME_BUFFER_SIZE/2)-1);
473 #ifdef DEBUG_ANALYSIS
474 dbg_anacnt_GPU_readData++;
476 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
477 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ);
478 GPU_GP1 &= ~0x14000000;
481 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
490 GPU_GP1 &= ~0x08000000;
493 if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024;
494 GP0 |= pvram[px]<<16;
502 GPU_GP1 &= ~0x08000000;
507 GPU_GP1 |= 0x14000000;
509 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_READ);
510 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
514 ///////////////////////////////////////////////////////////////////////////////
515 u32 GPU_readStatus(void)
517 #ifdef DEBUG_ANALYSIS
518 dbg_anacnt_GPU_readStatus++;
523 ///////////////////////////////////////////////////////////////////////////////
524 void GPU_writeStatus(u32 data)
526 #ifdef DEBUG_ANALYSIS
527 dbg_anacnt_GPU_writeStatus++;
529 pcsx4all_prof_pause(PCSX4ALL_PROF_CPU);
530 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
531 switch (data >> 24) {
536 GPU_GP1 &= ~0x08000000;
537 PacketCount = 0; FrameToRead = FrameToWrite = false;
540 GPU_GP1 &= ~0x08000000;
541 PacketCount = 0; FrameToRead = FrameToWrite = false;
544 GPU_GP1 = (GPU_GP1 & ~0x00800000) | ((data & 1) << 23);
547 if (data == 0x04000000)
549 GPU_GP1 = (GPU_GP1 & ~0x60000000) | ((data & 3) << 29);
552 DisplayArea[0] = (data & 0x000003FF); //(short)(data & 0x3ff);
553 DisplayArea[1] = ((data & 0x0007FC00)>>10); //(data & 0x000FFC00) >> 10; //(short)((data>>10)&0x1ff);
562 DisplayArea[4] = data & 0x000003FF; //(short)(data & 0x3ff);
563 DisplayArea[5] = (data & 0x000FFC00) >> 10; //(short)((data>>10) & 0x3ff);
568 GPU_GP1 = (GPU_GP1 & ~0x007F0000) | ((data & 0x3F) << 17) | ((data & 0x40) << 10);
569 static u32 HorizontalResolution[8] = { 256, 368, 320, 384, 512, 512, 640, 640 };
570 DisplayArea[2] = HorizontalResolution[(GPU_GP1 >> 16) & 7];
571 static u32 VerticalResolution[4] = { 240, 480, 256, 480 };
572 DisplayArea[3] = VerticalResolution[(GPU_GP1 >> 19) & 3];
573 isPAL = (data & 0x08) ? true : false; // if 1 - PAL mode, else NTSC
578 switch (data & 0xffff) {
582 GP0 = (DrawingArea[1] << 10) | DrawingArea[0];
585 GP0 = ((DrawingArea[3]-1) << 10) | (DrawingArea[2]-1);
589 GP0 = (DrawingOffset[1] << 11) | DrawingOffset[0];
599 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_HW_WRITE);
600 pcsx4all_prof_resume(PCSX4ALL_PROF_CPU);
605 // Blitting functions
606 #include "gpu_blit.h"
608 INLINE void gpuVideoOutput(void)
610 static s16 old_res_horz, old_res_vert, old_rgb24;
611 s16 h0, x0, y0, w0, h1;
617 h0 = DisplayArea[3]; // video mode
619 h1 = DisplayArea[5] - DisplayArea[4]; // display needed
620 if (h0 == 480) h1 = Min2(h1*2,480);
622 u16* dest_screen16 = SCREEN;
623 u16* src_screen16 = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(x0,y0)];
624 u32 isRGB24 = (GPU_GP1 & 0x00200000 ? 32 : 0);
626 /* Clear the screen if resolution changed to prevent interlacing and clipping to clash */
627 if( (w0 != old_res_horz || h1 != old_res_vert || (s16)isRGB24 != old_rgb24) )
629 // Update old resolution
632 old_rgb24 = (s16)isRGB24;
633 // Finally, clear the screen for this special case
639 if(h0==256) h0 = 240; else if(h0==480) sizeShift = 2;
640 if(h1>h0) { src_screen16 += ((h1-h0)>>sizeShift)*1024; h1 = h0; }
641 else if(h1<h0) dest_screen16 += ((h0-h1)>>sizeShift)*VIDEO_WIDTH;
644 int incY = (h0==480) ? 2 : 1;
645 h0=(h0==480 ? 2048 : 1024);
648 const int li=linesInterlace;
649 bool pi=progressInterlace;
650 bool pif=progressInterlace_flag;
654 for(int y1=y0+h1; y0<y1; y0+=incY)
656 if(( 0 == (y0&li) ) && ((!pi) || (pif=!pif))) GPU_BlitWWDWW( 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) ) && ((!pi) || (pif=!pif))) GPU_BlitWWWWWWWWS( src_screen16, dest_screen16, isRGB24, 4);
665 dest_screen16 += VIDEO_WIDTH;
670 for(int y1=y0+h1; y0<y1; y0+=incY)
672 if(( 0 == (y0&li) ) && ((!pi) || (pif=!pif))) GPU_BlitWW( src_screen16, dest_screen16, isRGB24);
673 dest_screen16 += VIDEO_WIDTH;
678 for(int y1=y0+h1; y0<y1; y0+=incY)
680 if(( 0 == (y0&li) ) && ((!pi) || (pif=!pif))) GPU_BlitWWWWWS( src_screen16, dest_screen16, isRGB24);
681 dest_screen16 += VIDEO_WIDTH;
686 for(int y1=y0+h1; y0<y1; y0+=incY)
688 if(( 0 == (y0&li) ) && ((!pi) || (pif=!pif))) GPU_BlitWWSWWSWS( 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) ) && ((!pi) || (pif=!pif))) GPU_BlitWS( src_screen16, dest_screen16, isRGB24);
697 dest_screen16 += VIDEO_WIDTH;
702 progressInterlace_flag=!progressInterlace_flag;
707 ///////////////////////////////////////////////////////////////////////////////
708 void GPU_updateLace(void)
710 #ifdef ENABLE_GPU_LOG_SUPPORT
711 fprintf(stdout,"GPU_updateLace()\n");
713 #ifdef DEBUG_ANALYSIS
714 dbg_anacnt_GPU_updateLace++;
716 pcsx4all_prof_start_with_pause(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_COUNTERS);
717 #ifdef PROFILER_PCSX4ALL
718 pcsx4all_prof_frames++;
724 if (!passed) dbg_enable();
725 else pcsx4all_exit();
731 static const unsigned char skipTable[12][12] =
733 { 0,0,0,0,0,0,0,0,0,0,0,0 },
734 { 0,0,0,0,0,0,0,0,0,0,0,1 },
735 { 0,0,0,0,0,1,0,0,0,0,0,1 },
736 { 0,0,0,1,0,0,0,1,0,0,0,1 },
737 { 0,0,1,0,0,1,0,0,1,0,0,1 },
738 { 0,1,0,0,1,0,1,0,0,1,0,1 },
739 { 0,1,0,1,0,1,0,1,0,1,0,1 },
740 { 0,1,0,1,1,0,1,0,1,1,0,1 },
741 { 0,1,1,0,1,1,0,1,1,0,1,1 },
742 { 0,1,1,1,0,1,1,1,0,1,1,1 },
743 { 0,1,1,1,1,1,0,1,1,1,1,1 },
744 { 0,1,1,1,1,1,1,1,1,1,1,1 }
747 // Interlace bit toggle
748 GPU_GP1 ^= 0x80000000;
751 if ((!skipFrame) && (!isSkip) && (fb_dirty) && (!(((GPU_GP1&0x08000000))||((GPU_GP1&0x00800000)))))
753 gpuVideoOutput(); // Display updated
755 if (DisplayArea[3] == 480)
757 if (linesInterlace_user) linesInterlace = 3; // 1/4 of lines
758 else linesInterlace = 1; // if 480 we only need half of lines
760 else if (linesInterlace != linesInterlace_user)
762 linesInterlace = linesInterlace_user; // resolution changed from 480 to lower one
770 static unsigned next=get_ticks();
773 unsigned now=get_ticks();
774 if (now<next) wait_ticks(next-now);
776 next+=(isPAL?(1000000/50):((unsigned)(1000000.0/59.94)));
779 // Show FPS statistics
782 static u32 real_fps=0;
783 static u32 prev=get_ticks();
784 static char msg[32]="FPS=000/00 SPD=000%";
787 if ((now-prev)>=1000000)
789 u32 expected_fps=(isPAL?50:60);
790 sprintf(msg,"FPS=%3d/%2d SPD=%3d%%",((real_fps*(12-skipCount))/12),((expected_fps*(12-skipCount))/12),((real_fps*100)/expected_fps));
794 port_printf(5,5,msg);
801 skipFrame=skipTable[skipCount][skCount];
802 skCount--; if (skCount<0) skCount=11;
810 skipFrame=skipTable[skipCount][skCount];
811 skCount--; if (skCount<0) skCount=11;
817 pcsx4all_prof_end_with_resume(PCSX4ALL_PROF_GPU,PCSX4ALL_PROF_COUNTERS);
822 #include "../../frontend/plugin_lib.h"
823 #include "../../frontend/arm_utils.h"
827 static const struct rearmed_cbs *cbs;
828 static void *screen_buf;
830 static void blit(void)
832 static s16 old_res_horz, old_res_vert, old_rgb24;
833 s16 isRGB24 = (GPU_GP1 & 0x00200000) ? 1 : 0;
834 s16 h0, x0, y0, w0, h1;
838 x0 = DisplayArea[0] & ~1; // alignment needed by blitter
840 srcs = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(x0,y0)];
843 h0 = DisplayArea[3]; // video mode
845 h1 = DisplayArea[5] - DisplayArea[4]; // display needed
846 if (h0 == 480) h1 = Min2(h1*2,480);
851 if (w0 != old_res_horz || h1 != old_res_vert || isRGB24 != old_rgb24)
855 old_rgb24 = (s16)isRGB24;
856 screen_buf = cbs->pl_vout_set_mode(w0, h1, isRGB24 ? 24 : 16);
858 dest = (u8 *)screen_buf;
863 for (; h1-- > 0; dest += w0 * 3, srcs += 1024)
865 bgr888_to_rgb888(dest, srcs, w0 * 3);
868 for (; h1-- > 0; dest += w0 * 2, srcs += 1024)
870 bgr888_to_rgb565(dest, srcs, w0 * 3);
876 for (; h1-- > 0; dest += w0 * 2, srcs += 1024)
878 bgr555_to_rgb565(dest, srcs, w0 * 2);
882 screen_buf = cbs->pl_vout_flip();
885 void GPU_updateLace(void)
887 // Interlace bit toggle
888 GPU_GP1 ^= 0x80000000;
890 if (!fb_dirty || (GPU_GP1&0x08800000))
901 wasSkip = isSkip = 0;
904 skipFrame = cbs->fskip_advice;
907 long GPUopen(unsigned long *, char *, char *)
910 screen_buf = cbs->pl_vout_flip();
916 cbs->pl_vout_close();
920 long GPUfreeze(unsigned int ulGetFreezeData, GPUFreeze_t* p2)
922 if (ulGetFreezeData > 1)
925 return GPU_freeze(ulGetFreezeData, p2);
928 void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_)
930 enableAbbeyHack = cbs_->gpu_unai.abe_hack;
931 light = !cbs_->gpu_unai.no_light;
932 blend = !cbs_->gpu_unai.no_blend;