1 /***************************************************************************
2                            gpu.c  -  description
3                              -------------------
4     begin                : Sun Mar 08 2009
5     copyright            : (C) 1999-2009 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version. See also the license.txt file for *
15  *   additional informations.                                              *
16  *                                                                         *
17  ***************************************************************************/
18 
19 // !!! enable this, if Linux XF86VidMode is not supported:
20 //#define NOVMODE
21 
22 #include "stdafx.h"
23 
24 #if defined (_MACGL)
25 #include "drawgl.h"
26 #elif !defined(_MACGL) && !defined(_WINDOWS)
27 
28 #include "config.h"
29 
30 #ifndef NOVMODE
31 #include <X11/extensions/xf86vmode.h>
32 static XF86VidModeModeInfo **modes=0;
33 static int iOldMode=0;
34 #endif
35 
36 #endif
37 
38 #if defined(__linux__)
39 #include <sys/wait.h>
40 #endif
41 
42 #define _IN_GPU
43 
44 #include "externals.h"
45 #include "gpu.h"
46 #include "draw.h"
47 #include "cfg.h"
48 #include "prim.h"
49 #include "psemu_plugin_defs.h"
50 #include "texture.h"
51 #include "menu.h"
52 #include "fps.h"
53 #include "key.h"
54 #include "gte_accuracy.h"
55 #ifdef _WINDOWS
56 #include "resource.h"
57 #include "ssave.h"
58 #endif
59 #ifdef ENABLE_NLS
60 #include <libintl.h>
61 #include <locale.h>
62 #define _(x)  gettext(x)
63 #define N_(x) (x)
64 #elif defined(_MACOSX)
65 #ifdef PCSXRCORE
66 __private_extern char* Pcsxr_locale_text(char* toloc);
67 #define _(String) Pcsxr_locale_text(String)
68 #define N_(String) String
69 #else
70 #ifndef PCSXRPLUG
71 #warning please define the plug being built to use Mac OS X localization!
72 #define _(msgid) msgid
73 #define N_(msgid) msgid
74 #else
75 //Kludge to get the preprocessor to accept PCSXRPLUG as a variable.
76 #define PLUGLOC_x(x,y) x ## y
77 #define PLUGLOC_y(x,y) PLUGLOC_x(x,y)
78 #define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text)
79 __private_extern char* PLUGLOC(char* toloc);
80 #define _(String) PLUGLOC(String)
81 #define N_(String) String
82 #endif
83 #endif
84 #else
85 #define _(x)  (x)
86 #define N_(x) (x)
87 #endif
88 
89 #ifdef _MACGL
90 #include "drawgl.h"
91 #endif
92 
93 ////////////////////////////////////////////////////////////////////////
94 // PPDK developer must change libraryName field and can change revision and build
95 ////////////////////////////////////////////////////////////////////////
96 
97 const  unsigned char version  = 1;    // do not touch - library for PSEmu 1.x
98 const  unsigned char revision = 1;
99 const  unsigned char build    = 78;
100 
101 static char *libraryName     = N_("OpenGL Driver");
102 
103 static char *PluginAuthor    = N_("Pete Bernert");
104 static char *libraryInfo     = N_("Based on P.E.Op.S. MesaGL Driver V1.78\nCoded by Pete Bernert\n");
105 
106 ////////////////////////////////////////////////////////////////////////
107 // memory image of the PSX vram
108 ////////////////////////////////////////////////////////////////////////
109 
110 unsigned char  *psxVSecure;
111 unsigned char  *psxVub;
112 signed   char  *psxVsb;
113 unsigned short *psxVuw;
114 unsigned short *psxVuw_eom;
115 signed   short *psxVsw;
116 uint32_t       *psxVul;
117 signed   int   *psxVsl;
118 
119 // macro for easy access to packet information
120 #define GPUCOMMAND(x) ((x>>24) & 0xff)
121 
122 GLfloat         gl_z=0.0f;
123 BOOL            bNeedInterlaceUpdate=FALSE;
124 BOOL            bNeedRGB24Update=FALSE;
125 BOOL            bChangeWinMode=FALSE;
126 
127 #ifdef _WINDOWS
128 extern HGLRC    GLCONTEXT;
129 #endif
130 
131 uint32_t        ulStatusControl[256];
132 
133 ////////////////////////////////////////////////////////////////////////
134 // global GPU vars
135 ////////////////////////////////////////////////////////////////////////
136 
137 static int      GPUdataRet;
138 int             lGPUstatusRet;
139 char            szDispBuf[64];
140 
141 uint32_t        dwGPUVersion = 0;
142 int             iGPUHeight = 512;
143 int             iGPUHeightMask = 511;
144 int             GlobalTextIL = 0;
145 int             iTileCheat = 0;
146 
147 static uint32_t      gpuDataM[256];
148 static unsigned char gpuCommand = 0;
149 static int           gpuDataC = 0;
150 static int           gpuDataP = 0;
151 
152 VRAMLoad_t      VRAMWrite;
153 VRAMLoad_t      VRAMRead;
154 int             iDataWriteMode;
155 int             iDataReadMode;
156 
157 int             lClearOnSwap;
158 int             lClearOnSwapColor;
159 BOOL            bSkipNextFrame = FALSE;
160 int             iColDepth;
161 BOOL            bChangeRes;
162 BOOL            bWindowMode;
163 int             iWinSize;
164 
165 // possible psx display widths
166 short dispWidths[8] = {256,320,512,640,368,384,512,640};
167 
168 PSXDisplay_t    PSXDisplay;
169 PSXDisplay_t    PreviousPSXDisplay;
170 TWin_t          TWin;
171 short           imageX0,imageX1;
172 short           imageY0,imageY1;
173 BOOL            bDisplayNotSet = TRUE;
174 GLuint          uiScanLine=0;
175 int             iUseScanLines=0;
176 float           iScanlineColor[] = {0,0,0, 0.3f}; // easy on the eyes.
177 int             lSelectedSlot=0;
178 unsigned char * pGfxCardScreen=0;
179 int             iBlurBuffer=0;
180 int             iScanBlend=0;
181 int             iRenderFVR=0;
182 int             iNoScreenSaver=0;
183 uint32_t        ulGPUInfoVals[16];
184 int             iFakePrimBusy = 0;
185 int             iRumbleVal    = 0;
186 int             iRumbleTime   = 0;
187 uint32_t        vBlank=0;
188 BOOL			oddLines;
189 
190 ////////////////////////////////////////////////////////////////////////
191 // stuff to make this a true PDK module
192 ////////////////////////////////////////////////////////////////////////
193 
PSEgetLibName(void)194 char * CALLBACK PSEgetLibName(void)
195 {
196  return _(libraryName);
197 }
198 
PSEgetLibType(void)199 unsigned long CALLBACK PSEgetLibType(void)
200 {
201  return  PSE_LT_GPU;
202 }
203 
PSEgetLibVersion(void)204 unsigned long CALLBACK PSEgetLibVersion(void)
205 {
206  return version<<16|revision<<8|build;
207 }
208 
GPUgetLibInfos(void)209 char * GPUgetLibInfos(void)
210 {
211  return _(libraryInfo);
212 }
213 
214 ////////////////////////////////////////////////////////////////////////
215 // snapshot funcs (saves screen to bitmap / text infos into file)
216 ////////////////////////////////////////////////////////////////////////
217 
218 #ifdef _WINDOWS
GetConfigInfos(HWND hW)219 char * GetConfigInfos(HWND hW)
220 #else
221 char * GetConfigInfos(int hW)
222 #endif
223 {
224 #ifdef _WINDOWS
225  HDC hdc;HGLRC hglrc;
226 #endif
227  char szO[2][4]={"off","on "};
228  char szTxt[256];
229  char * pB=(char *)malloc(32767);
230 
231  if(!pB) return NULL;
232  *pB=0;
233  //----------------------------------------------------//
234  sprintf(szTxt,"Plugin: %s %d.%d.%d (mod)\r\n",libraryName,version,revision,build);
235  strcat(pB,szTxt);
236  sprintf(szTxt,"Author: %s\r\n",PluginAuthor);
237  strcat(pB,szTxt);
238 
239 #ifdef _WINDOWS
240  if(hW)
241   {
242    hdc = GetDC(hW);
243    bSetupPixelFormat(hdc);
244    hglrc = wglCreateContext(hdc);
245    wglMakeCurrent(hdc, hglrc);
246   }
247 #endif
248 
249  sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));
250  strcat(pB,szTxt);
251  sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));
252  strcat(pB,szTxt);
253  sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));
254  strcat(pB,szTxt);
255  //strcat(pB,(char *)glGetString(GL_EXTENSIONS));
256  //strcat(pB,"\r\n\r\n");
257 
258 #ifdef _WINDOWS
259  if(hW)
260   {
261    wglMakeCurrent(NULL, NULL);
262    wglDeleteContext(hglrc);
263    ReleaseDC(hW,hdc);
264   }
265  //----------------------------------------------------//
266 #endif
267 
268  if(hW && bWindowMode)
269   sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));
270  else
271   sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);
272  strcat(pB,szTxt);
273  if(bWindowMode) sprintf(szTxt,"Window mode\r\n");
274  else
275   {
276    sprintf(szTxt,"Fullscreen ");
277    strcat(pB,szTxt);
278    if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);
279    else           sprintf(szTxt,"- NO desktop changing\r\n");
280   }
281  strcat(pB,szTxt);
282 
283  if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]);
284  else               strcpy(szTxt,"- V-Sync: Driver\r\n");
285  strcat(pB,szTxt);
286  sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);
287  strcat(pB,szTxt);
288  //----------------------------------------------------//
289  strcpy(szTxt,"Textures:\r\n- ");
290  if(iTexQuality==0)      strcat(szTxt,"Default");
291  else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4");
292  else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1");
293  else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8");
294  else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8");
295  if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n");
296  else              strcat(szTxt,"\r\n");
297  strcat(pB,szTxt);
298  if(!hW)
299   {
300    sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType);
301    if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n");
302    else                             strcat(szTxt,"NOT supported\r\n");
303   }
304  else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);
305  strcat(pB,szTxt);
306  sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);
307  strcat(pB,szTxt);
308  if(!hW)
309   {
310    sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);
311    strcat(pB,szTxt);
312   }
313  sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);
314  if(!hW)
315       sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);
316  else strcat(szTxt,"\r\n\r\n");
317  strcat(pB,szTxt);
318  //----------------------------------------------------//
319  sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);
320  strcat(pB,szTxt);
321  sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);
322  strcat(pB,szTxt);
323  if(iFrameLimit==2)
324       strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");
325  else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);
326  strcat(pB,szTxt);
327  //----------------------------------------------------//
328  sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);
329  strcat(pB,szTxt);
330  sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);
331  if(!hW && iFrameTexType==2)
332   {
333    if(gTexFrameName) strcat(szTxt," - texture created\r\n");
334    else              strcat(szTxt," - not used yet\r\n");
335   }
336  else strcat(szTxt,"\r\n");
337  strcat(pB,szTxt);
338  sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);
339  strcat(pB,szTxt);
340  sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);
341  strcat(pB,szTxt);
342  sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);
343  strcat(pB,szTxt);
344  sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);
345  if(!hW && bAdvancedBlend)
346   {
347    if(bGLBlend) strcat(szTxt," (hardware)\r\n");
348    else         strcat(szTxt," (software)\r\n");
349   }
350  else strcat(szTxt,"\r\n");
351  strcat(pB,szTxt);
352 
353  if(!hW)
354   {
355    strcpy(szTxt,"- Subtractive blending: ");
356    if(glBlendEquationEXTEx)
357     {
358      if(bUseMultiPass) strcat(szTxt,"supported, but not used!");
359      else              strcat(szTxt,"activated");
360     }
361    else strcat(szTxt," NOT supported!");
362    strcat(szTxt,"\r\n\r\n");
363   }
364  else strcpy(szTxt,"\r\n");
365 
366  strcat(pB,szTxt);
367  //----------------------------------------------------//
368  sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);
369  strcat(pB,szTxt);
370  if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);
371  else strcpy(szTxt,"\r\n");
372  strcat(pB,szTxt);
373  sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);
374  strcat(pB,szTxt);
375 // sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]);
376 // fwrite(szTxt,lstrlen(szTxt),1,txtfile);
377  sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]);
378  strcat(pB,szTxt);
379  sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);
380  strcat(pB,szTxt);
381  sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);
382  strcat(pB,szTxt);
383  sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);
384  strcat(pB,szTxt);
385  if(!hW && iBlurBuffer)
386   {
387    if(gTexBlurName) strcat(pB," - supported\r\n");
388    else             strcat(pB," - not supported\r\n");
389   }
390  else strcat(pB,"\r\n");
391  sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[bUseFixes],dwCfgFixes);
392  strcat(pB,szTxt);
393  //----------------------------------------------------//
394  return pB;
395 }
396 
397 ////////////////////////////////////////////////////////////////////////
398 // save text infos to file
399 ////////////////////////////////////////////////////////////////////////
400 
DoTextSnapShot(int iNum)401 void DoTextSnapShot(int iNum)
402 {
403  FILE *txtfile;char szTxt[256];char * pB;
404 
405 #ifdef _WINDOWS
406  sprintf(szTxt,"snap\\pcsxr%04d.txt",iNum);
407 #else
408  sprintf(szTxt,"%s/pcsxr%04d.txt",getenv("HOME"),iNum);
409 #endif
410 
411  if((txtfile=fopen(szTxt,"wb"))==NULL)
412   return;
413 
414  pB=GetConfigInfos(0);
415  if(pB)
416   {
417    fwrite(pB,strlen(pB),1,txtfile);
418    free(pB);
419   }
420  fclose(txtfile);
421 }
422 
423 ////////////////////////////////////////////////////////////////////////
424 // saves screen bitmap to file
425 ////////////////////////////////////////////////////////////////////////
426 
DoSnapShot(void)427 void DoSnapShot(void)
428 {
429  unsigned char * snapshotdumpmem=NULL,* p,c;
430  FILE *bmpfile;char filename[256];
431  unsigned char header[0x36];int size;
432  unsigned char empty[2]={0,0};int i;
433  unsigned int snapshotnr = 0;
434  short SnapWidth;
435  short SnapHeigth;
436 
437  bSnapShot=FALSE;
438 
439  SnapWidth  = iResX;
440  SnapHeigth = iResY;
441 
442  size=SnapWidth * SnapHeigth * 3 + 0x38;
443 
444  if((snapshotdumpmem=(unsigned char *)
445    malloc(SnapWidth*SnapHeigth*3))==NULL)
446   return;
447 
448   // fill in proper values for BMP
449  for(i=0;i<0x36;i++) header[i]=0;
450  header[0]='B';
451  header[1]='M';
452  header[2]=(unsigned char)(size&0xff);
453  header[3]=(unsigned char)((size>>8)&0xff);
454  header[4]=(unsigned char)((size>>16)&0xff);
455  header[5]=(unsigned char)((size>>24)&0xff);
456  header[0x0a]=0x36;
457  header[0x0e]=0x28;
458  header[0x12]=(unsigned char)(SnapWidth%256);
459  header[0x13]=(unsigned char)(SnapWidth/256);
460  header[0x16]=(unsigned char)(SnapHeigth%256);
461  header[0x17]=(unsigned char)(SnapHeigth/256);
462  header[0x1a]=0x01;
463  header[0x1c]=0x18;
464  header[0x26]=0x12;
465  header[0x27]=0x0B;
466  header[0x2A]=0x12;
467  header[0x2B]=0x0B;
468 
469  // increment snapshot value
470  // get filename
471  do
472   {
473    snapshotnr++;
474 #ifdef _WINDOWS
475    sprintf(filename,"snap/pcsxr%04d.bmp",snapshotnr);
476 #else
477    sprintf(filename,"%s/pcsxr%04d.bmp",getenv("HOME"),snapshotnr);
478 #endif
479    bmpfile=fopen(filename,"rb");
480    if(bmpfile==NULL)break;
481    fclose(bmpfile);
482    if(snapshotnr==9999) break;
483   }
484  while(TRUE);
485 
486  // try opening new snapshot file
487  if((bmpfile=fopen(filename,"wb"))==NULL)
488   {free(snapshotdumpmem);return;}
489 
490  fwrite(header,0x36,1,bmpfile);
491 
492  glReadPixels(0,0,SnapWidth,SnapHeigth,GL_RGB,
493                GL_UNSIGNED_BYTE,snapshotdumpmem);
494  p=snapshotdumpmem;
495  size=SnapWidth * SnapHeigth;
496 
497  for(i=0;i<size;i++,p+=3)
498   {c=*p;*p=*(p+2);*(p+2)=c;}
499 
500  fwrite(snapshotdumpmem,size*3,1,bmpfile);
501  fwrite(empty,0x2,1,bmpfile);
502  fclose(bmpfile);
503  free(snapshotdumpmem);
504 
505  DoTextSnapShot(snapshotnr);
506 #ifdef _WINDOWS
507  MessageBeep((UINT)-1);
508 #endif
509 }
510 
GPUmakeSnapshot(void)511 void CALLBACK GPUmakeSnapshot(void)
512 {
513  bSnapShot = TRUE;
514 }
515 
516 ////////////////////////////////////////////////////////////////////////
517 // GPU INIT... here starts it all (first func called by emu)
518 ////////////////////////////////////////////////////////////////////////
519 
GPUinit()520 long CALLBACK GPUinit()
521 {
522  memset(ulStatusControl,0,256*sizeof(uint32_t));
523 
524  // different ways of accessing PSX VRAM
525 
526  psxVSecure=(unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
527  if(!psxVSecure) return -1;
528 
529  psxVub=psxVSecure+512*1024;                           // security offset into double sized psx vram!
530  psxVsb=(signed char *)psxVub;
531  psxVsw=(signed short *)psxVub;
532  psxVsl=(signed int *)psxVub;
533  psxVuw=(unsigned short *)psxVub;
534  psxVul=(uint32_t *)psxVub;
535 
536  psxVuw_eom=psxVuw+1024*iGPUHeight;                    // pre-calc of end of vram
537 
538  memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
539  memset(ulGPUInfoVals,0x00,16*sizeof(uint32_t));
540 
541  InitFrameCap();                                       // init frame rate stuff
542 
543  PSXDisplay.RGB24        = 0;                          // init vars
544  PreviousPSXDisplay.RGB24= 0;
545  PSXDisplay.Interlaced   = 0;
546  PSXDisplay.InterlacedTest=0;
547  PSXDisplay.DrawOffset.x = 0;
548  PSXDisplay.DrawOffset.y = 0;
549  PSXDisplay.DrawArea.x0  = 0;
550  PSXDisplay.DrawArea.y0  = 0;
551  PSXDisplay.DrawArea.x1  = 320;
552  PSXDisplay.DrawArea.y1  = 240;
553  PSXDisplay.DisplayMode.x= 320;
554  PSXDisplay.DisplayMode.y= 240;
555  PSXDisplay.Disabled     = FALSE;
556  PreviousPSXDisplay.Range.x0 =0;
557  PreviousPSXDisplay.Range.x1 =0;
558  PreviousPSXDisplay.Range.y0 =0;
559  PreviousPSXDisplay.Range.y1 =0;
560  PSXDisplay.Range.x0=0;
561  PSXDisplay.Range.x1=0;
562  PSXDisplay.Range.y0=0;
563  PSXDisplay.Range.y1=0;
564  PreviousPSXDisplay.DisplayPosition.x = 1;
565  PreviousPSXDisplay.DisplayPosition.y = 1;
566  PSXDisplay.DisplayPosition.x = 1;
567  PSXDisplay.DisplayPosition.y = 1;
568  PreviousPSXDisplay.DisplayModeNew.y=0;
569  PSXDisplay.Double=1;
570  GPUdataRet=0x400;
571 
572  PSXDisplay.DisplayModeNew.x=0;
573  PSXDisplay.DisplayModeNew.y=0;
574 
575  //PreviousPSXDisplay.Height = PSXDisplay.Height = 239;
576 
577  iDataWriteMode = DR_NORMAL;
578 
579  // Reset transfer values, to prevent mis-transfer of data
580  memset(&VRAMWrite,0,sizeof(VRAMLoad_t));
581  memset(&VRAMRead,0,sizeof(VRAMLoad_t));
582 
583  // device initialised already !
584  //lGPUstatusRet = 0x74000000;
585  vBlank = 0;
586  oddLines = FALSE;
587 
588  STATUSREG = 0x14802000;
589  GPUIsIdle;
590  GPUIsReadyForCommands;
591 
592  return 0;
593 }
594 
595 ////////////////////////////////////////////////////////////////////////
596 // GPU OPEN: funcs to open up the gpu display (Windows)
597 ////////////////////////////////////////////////////////////////////////
598 
599 #ifdef _WINDOWS
600 
ChangeDesktop()601 void ChangeDesktop()                                   // change destop resolution
602 {
603  DEVMODE dv;long lRes,iTry=0;
604 
605  while(iTry<10)                                        // keep on hammering...
606   {
607    memset(&dv,0,sizeof(DEVMODE));
608    dv.dmSize=sizeof(DEVMODE);
609    dv.dmBitsPerPel=iColDepth;
610    dv.dmPelsWidth=iResX;
611    dv.dmPelsHeight=iResY;
612 
613    dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
614 
615    lRes=ChangeDisplaySettings(&dv,0);                  // ...hammering the anvil
616 
617    if(lRes==DISP_CHANGE_SUCCESSFUL) return;
618    iTry++;Sleep(10);
619   }
620 }
621 
622 ////////////////////////////////////////////////////////////////////////
623 // OPEN interface func: attention!
624 // some emus are calling this func in their main Window thread,
625 // but all other interface funcs (to draw stuff) in a different thread!
626 // that's a problem, since OGL is thread safe! Therefore we cannot
627 // initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE"
628 // flag, to initialize OGL on the first real draw call.
629 // btw, we also call this open func ourselfes, each time when the user
630 // is changing between fullscreen/window mode (ENTER key)
631 // btw part 2: in windows the plugin gets the window handle from the
632 // main emu, and doesn't create it's own window (if it would do it,
633 // some PAD or SPU plugins would not work anymore)
634 ////////////////////////////////////////////////////////////////////////
635 
636 HMENU hPSEMenu=NULL;
637 
GPUopen(HWND hwndGPU)638 long CALLBACK GPUopen(HWND hwndGPU)
639 {
640  HDC hdc;RECT r;DEVMODE dv;
641 
642  hWWindow = hwndGPU;                                   // store hwnd globally
643 
644  InitKeyHandler();                                     // init key handler (subclass window)
645 
646  if(bChangeWinMode)                                    // user wants to change fullscreen/window mode?
647   {
648    ReadWinSizeConfig();                                // -> get sizes again
649   }
650  else                                                  // first real startup
651   {
652    ReadConfig();                                       // -> read config from registry
653 
654    SetFrameRateConfig();                               // -> setup frame rate stuff
655   }
656 
657  if(iNoScreenSaver) EnableScreenSaver(FALSE);          // at least we can try
658 
659 
660  memset(&dv,0,sizeof(DEVMODE));
661  dv.dmSize=sizeof(DEVMODE);
662  EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv);
663 
664  bIsFirstFrame = TRUE;                                 // flag: we have to init OGL later in windows!
665 
666  if(bWindowMode)                                       // win mode?
667   {
668    DWORD dw=GetWindowLong(hWWindow, GWL_STYLE);        // -> adjust wnd style (owndc needed by some stupid ogl drivers)
669    dw&=~WS_THICKFRAME;
670    dw|=WS_BORDER|WS_CAPTION|CS_OWNDC;
671    SetWindowLong(hWWindow, GWL_STYLE, dw);
672 
673    hPSEMenu=GetMenu(hWWindow);                         // -> hide emu menu (if any)
674    if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
675 
676    iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize);
677    ShowWindow(hWWindow,SW_SHOWNORMAL);
678 
679    MoveWindow(hWWindow,                                // -> center wnd
680       GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2,
681       GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2,
682       iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3,
683       iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3,
684       TRUE);
685    UpdateWindow(hWWindow);                             // -> let windows do some update
686 
687    if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32)      // -> overwrite user color info with desktop color info
688     iColDepth=dv.dmBitsPerPel;
689   }
690  else                                                  // fullscreen mode:
691   {
692    if(dv.dmBitsPerPel!=(unsigned int)iColDepth ||      // -> check, if we have to change resolution
693       dv.dmPelsWidth !=(unsigned int)iResX ||
694       dv.dmPelsHeight!=(unsigned int)iResY)
695     bChangeRes=TRUE; else bChangeRes=FALSE;
696 
697    if(bChangeRes) ChangeDesktop();                     // -> change the res (had to do an own func because of some MS 'optimizations')
698 
699    SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC);       // -> adjust wnd style as well (to be sure)
700 
701    hPSEMenu=GetMenu(hWWindow);                         // -> hide menu
702    if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
703    ShowWindow(hWWindow,SW_SHOWMAXIMIZED);              // -> max mode
704   }
705 
706  rRatioRect.left   = rRatioRect.top=0;
707  rRatioRect.right  = iResX;
708  rRatioRect.bottom = iResY;
709 
710  r.left=r.top=0;r.right=iResX;r.bottom=iResY;          // hack for getting a clean black window until OGL gets initialized
711  hdc = GetDC(hWWindow);
712  FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));
713  bSetupPixelFormat(hdc);
714  ReleaseDC(hWWindow,hdc);
715 
716  bDisplayNotSet = TRUE;
717  bSetClip=TRUE;
718 
719  SetFixes();                                           // setup game fixes
720 
721  InitializeTextureStore();                             // init texture mem
722 
723  resetGteVertices();
724 
725 // lGPUstatusRet = 0x74000000;
726 
727 // with some emus, we could do the OGL init right here... oh my
728 // if(bIsFirstFrame) GLinitialize();
729 
730  return 0;
731 }
732 
733 #elif !defined (_MACGL)
734 
735 ////////////////////////////////////////////////////////////////////////
736 // LINUX GPU OPEN: func to open up the gpu display (X stuff)
737 // please note: in linux we are creating our own display, and we return
738 // the display ID to the main emu... that's cleaner
739 ////////////////////////////////////////////////////////////////////////
740 
741 char * pCaptionText=0;
742 int    bFullScreen=0;
743 Display              *display;
744 
745 static Cursor        cursor;
746 static XVisualInfo   *myvisual;
747 static Colormap      colormap;
748 static Window        window;
749 
750 static int bModeChanged=0;
751 
752 typedef struct
753 {
754 #define MWM_HINTS_DECORATIONS   2
755   long flags;
756   long functions;
757   long decorations;
758   long input_mode;
759 } MotifWmHints;
760 
761 static int dbdepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,GLX_DEPTH_SIZE,16,None};
762 static int dbnodepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,None};
763 static GLXContext cx;
764 
765 static int fx=0;
766 
767 ////////////////////////////////////////////////////////////////////////
768 
osd_close_display(void)769 void osd_close_display (void)                          // close display
770 {
771  if(display)                                           // display exists?
772   {
773    glXDestroyContext(display,cx);                      // -> kill context
774    XFreeColormap(display, colormap);                   // -> kill colormap
775    XSync(display,False);                               // -> sync events
776 
777 #ifndef NOVMODE
778    if(bModeChanged)                                    // -> repair screen mode
779     {
780      int myscreen=DefaultScreen(display);
781      XF86VidModeSwitchToMode(display,myscreen,         // --> switch mode back
782                              modes[iOldMode]);
783      XF86VidModeSetViewPort(display,myscreen,0,0);     // --> set viewport upperleft
784      free(modes);                                      // --> finally kill mode infos
785      bModeChanged=0;                                   // --> done
786     }
787 #endif
788 
789    XCloseDisplay(display);                             // -> close display
790   }
791 }
792 
793 ////////////////////////////////////////////////////////////////////////
794 
sysdep_create_display(void)795 void sysdep_create_display(void)                       // create display
796 {
797  XSetWindowAttributes winattr;float fxgamma=2;
798  int myscreen;char gammastr[14];
799  Screen * screen;XEvent event;
800  XSizeHints hints;XWMHints wm_hints;
801  MotifWmHints mwmhints;
802  Atom mwmatom;
803  Atom delwindow;
804  XClassHint* classHint;
805  char *glxfx;
806 
807  glxfx=getenv("MESA_GLX_FX");                          // 3dfx mesa fullscreen flag
808  if(glxfx)
809   {
810    if(glxfx[0]=='f')                                   // -> yup, fullscreen needed
811     {
812      fx=1;                                             // -> raise flag
813      putenv("FX_GLIDE_NO_SPLASH=");
814      sprintf(gammastr,"SST_GAMMA=%2.1f",fxgamma);      // -> set gamma
815      putenv(gammastr);
816     }
817   }
818 
819  display=XOpenDisplay(NULL);                           // open display
820  if(!display)                                          // no display?
821   {
822    fprintf (stderr,"Failed to open display!!!\n");
823    osd_close_display();
824    return;                                             // -> bye
825   }
826 
827  myscreen=DefaultScreen(display);                      // get screen id
828 
829 #ifdef NOVMODE
830  if(bFullScreen) {fx=1;bModeChanged=0;}
831 #else
832  if(bFullScreen)
833   {
834    XF86VidModeModeLine mode;
835    int nmodes,iC;
836    fx=1;                                               // raise flag
837    XF86VidModeGetModeLine(display,myscreen,&iC,&mode); // get actual mode info
838    if(mode.privsize) XFree(mode.private);              // no need for private stuff
839    bModeChanged=0;                                     // init mode change flag
840    if(iResX!=mode.hdisplay || iResY!=mode.vdisplay)    // wanted mode is different?
841     {
842      XF86VidModeGetAllModeLines(display,myscreen,      // -> enum all mode infos
843                                 &nmodes,&modes);
844      if(modes)                                         // -> infos got?
845       {
846        for(iC=0;iC<nmodes;++iC)                        // -> loop modes
847         {
848          if(mode.hdisplay==modes[iC]->hdisplay &&      // -> act mode found?
849             mode.vdisplay==modes[iC]->vdisplay)        //    if yes: store mode id
850           iOldMode=iC;
851 
852          if(iResX==modes[iC]->hdisplay &&              // -> wanted mode found?
853             iResY==modes[iC]->vdisplay)
854           {
855            XF86VidModeSwitchToMode(display,myscreen,   // --> switch to mode
856                                    modes[iC]);
857            XF86VidModeSetViewPort(display,myscreen,0,0);
858            bModeChanged=1;                             // --> raise flag for repairing mode on close
859           }
860         }
861 
862        if(bModeChanged==0)                             // -> no mode found?
863         {
864          free(modes);                                  // --> free infos
865          printf("%s", "No proper fullscreen mode found!\n"); // --> some info output
866         }
867       }
868     }
869   }
870 #endif
871 
872  screen=DefaultScreenOfDisplay(display);
873 
874  if(iZBufferDepth)                                      // visual (with or without zbuffer)
875       myvisual=glXChooseVisual(display,myscreen,dbdepat);
876  else myvisual=glXChooseVisual(display,myscreen,dbnodepat);
877 
878  if(!myvisual)                                         // no visual?
879   {
880    fprintf(stderr,"Failed to obtain visual!!!\n");     // -> bye
881    osd_close_display();
882    return;
883   }
884 
885  cx=glXCreateContext(display,myvisual,0,GL_TRUE);      // create rendering context
886 
887  if(!cx)                                               // no context?
888   {
889    fprintf(stderr,"Failed to create OpenGL context!!!\n");
890    osd_close_display();                                // -> bxe
891    return;
892   }
893 
894  // pffff... much work for a simple blank cursor... oh, well...
895  if(!bFullScreen) cursor=XCreateFontCursor(display,XC_left_ptr);
896  else
897   {
898    Pixmap p1,p2;XImage * img;
899    XColor b,w;unsigned char * idata;
900    XGCValues GCv;
901    GC        GCc;
902 
903    memset(&b,0,sizeof(XColor));
904    memset(&w,0,sizeof(XColor));
905    idata=(unsigned char *)malloc(8);
906    memset(idata,0,8);
907 
908    p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1);
909    p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1);
910 
911    img = XCreateImage(display,myvisual->visual,
912                       1,XYBitmap,0,idata,8,8,8,1);
913 
914    GCv.function   = GXcopy;
915    GCv.foreground = ~0;
916    GCv.background =  0;
917    GCv.plane_mask = AllPlanes;
918    GCc = XCreateGC(display,p1,
919                    (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv);
920 
921    XPutImage(display, p1,GCc,img,0,0,0,0,8,8);
922    XPutImage(display, p2,GCc,img,0,0,0,0,8,8);
923    XFreeGC(display, GCc);
924 
925    cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0);
926 
927    XFreePixmap(display,p1);
928    XFreePixmap(display,p2);
929    XDestroyImage(img);                                 // will free idata as well
930   }
931 
932  colormap=XCreateColormap(display,                     // create colormap
933                           RootWindow(display,myvisual->screen),
934                           myvisual->visual,AllocNone);
935 
936  winattr.background_pixel=0;
937  winattr.border_pixel=WhitePixelOfScreen(screen);
938  winattr.bit_gravity=ForgetGravity;
939  winattr.win_gravity=NorthWestGravity;
940  winattr.backing_store=NotUseful;
941  winattr.override_redirect=False;
942  winattr.save_under=False;
943  winattr.event_mask=ExposureMask |
944                     VisibilityChangeMask |
945                     FocusChangeMask |
946                     KeyPressMask | KeyReleaseMask |
947                     ButtonPressMask | ButtonReleaseMask |
948                     PointerMotionMask;
949  winattr.do_not_propagate_mask=0;
950  winattr.colormap=colormap;
951  winattr.cursor=None;
952 
953  window=XCreateWindow(display,                         // create own window
954              RootWindow(display,DefaultScreen(display)),
955              0,0,iResX,iResY,
956              0,myvisual->depth,
957              InputOutput,myvisual->visual,
958              CWBorderPixel | CWBackPixel |
959              CWEventMask | CWDontPropagate |
960              CWColormap | CWCursor | CWEventMask,
961              &winattr);
962 
963  if(!window)                                           // no window?
964   {
965    fprintf(stderr,"Failed in XCreateWindow()!!!\n");
966    osd_close_display();                                // -> bye
967    return;
968   }
969 
970  delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0);
971  XSetWMProtocols(display, window, &delwindow, 1);
972 
973  hints.flags=PMinSize|PMaxSize;                        // hints
974  if(fx) hints.flags|=USPosition|USSize;
975  else   hints.flags|=PSize;
976 
977  hints.min_width   = hints.max_width  = hints.base_width  = iResX;
978  hints.min_height  = hints.max_height = hints.base_height = iResY;
979 
980  wm_hints.input=1;
981  wm_hints.flags=InputHint;
982 
983  XSetWMHints(display,window,&wm_hints);
984  XSetWMNormalHints(display,window,&hints);
985 
986  if(!pCaptionText)
987      pCaptionText = "Pete MesaGL PSX Gpu";
988 
989  // set the WM_NAME and WM_CLASS of the window
990 
991  // set the titlebar name
992  XStoreName(display, window, pCaptionText);
993 
994  // set the name and class hints for the window manager to use
995  classHint = XAllocClassHint();
996  if(classHint)
997  {
998    classHint->res_name = pCaptionText;
999    classHint->res_class = pCaptionText;
1000  }
1001 
1002  XSetClassHint(display, window, classHint);
1003  XFree(classHint);
1004 
1005  XDefineCursor(display,window,cursor);                 // cursor
1006 
1007  if(fx)                                                // window title bar hack
1008   {
1009    mwmhints.flags=MWM_HINTS_DECORATIONS;
1010    mwmhints.decorations=0;
1011    mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
1012    XChangeProperty(display,window,mwmatom,mwmatom,32,
1013                    PropModeReplace,(unsigned char *)&mwmhints,4);
1014   }
1015 
1016  XMapRaised(display,window);
1017  XClearWindow(display,window);
1018  XWindowEvent(display,window,ExposureMask,&event);
1019  glXMakeCurrent(display,window,cx);
1020 
1021 /*
1022  printf("%s", glGetString(GL_VENDOR));
1023  printf("\n");
1024  printf("%s", glGetString(GL_RENDERER));
1025  printf("\n");
1026 */
1027 
1028  if (fx)                                               // after make current: fullscreen resize
1029   {
1030    XResizeWindow(display,window,screen->width,screen->height);
1031    hints.min_width   = hints.max_width = hints.base_width = screen->width;
1032    hints.min_height= hints.max_height = hints.base_height = screen->height;
1033    XSetWMNormalHints(display,window,&hints);
1034 
1035    // set the window layer for GNOME
1036    {
1037     XEvent xev;
1038 
1039     memset(&xev, 0, sizeof(xev));
1040     xev.xclient.type = ClientMessage;
1041     xev.xclient.serial = 0;
1042     xev.xclient.send_event = 1;
1043     xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
1044     xev.xclient.window = window;
1045     xev.xclient.format = 32;
1046     xev.xclient.data.l[0] = 1;
1047     xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
1048     xev.xclient.data.l[2] = 0;
1049     xev.xclient.data.l[3] = 0;
1050     xev.xclient.data.l[4] = 0;
1051 
1052     XSendEvent(display, RootWindow(display, DefaultScreen(display)), 0,
1053       SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1054    }
1055   }
1056 }
1057 
1058 #endif // !defined(_MACGL)
1059 
1060 #ifndef _WINDOWS
1061 
1062 #if defined(_MACGL)
1063 extern char * pCaptionText;
1064 #endif
1065 
1066 ////////////////////////////////////////////////////////////////////////
1067 
GPUopen(unsigned long * disp,char * CapText,char * CfgFile)1068 long GPUopen(unsigned long * disp,char * CapText,char * CfgFile)
1069 {
1070  pCaptionText=CapText;
1071 #if !defined (_MACGL)
1072  pConfigFile=CfgFile;
1073 #endif
1074 
1075  ReadConfig();                                         // read text file for config
1076 
1077  SetFrameRateConfig();                                 // setup frame rate stuff
1078 
1079  bIsFirstFrame = TRUE;                                 // we have to init later (well, no really... in Linux we do all in GPUopen)
1080 
1081 #if defined (_MACGL)
1082  unsigned long display = ulInitDisplay();
1083 #else
1084  sysdep_create_display();                              // create display
1085 #endif
1086 
1087  InitializeTextureStore();                             // init texture mem
1088 
1089  rRatioRect.left   = rRatioRect.top=0;
1090  rRatioRect.right  = iResX;
1091  rRatioRect.bottom = iResY;
1092 
1093  GLinitialize();                                       // init opengl
1094 
1095  if(disp)
1096    *disp = (unsigned long)display;                     // return display ID to main emu
1097 
1098  if(display) return 0;
1099  return -1;
1100 }
1101 
1102 #endif // ndef _WINDOWS
1103 
1104 
1105 
1106 ////////////////////////////////////////////////////////////////////////
1107 // close
1108 ////////////////////////////////////////////////////////////////////////
1109 
1110 #ifdef _WINDOWS
1111 
GPUclose()1112 long CALLBACK GPUclose()                               // WINDOWS CLOSE
1113 {
1114  ExitKeyHandler();
1115 
1116  GLcleanup();                                          // close OGL
1117 
1118  if(bChangeRes)                                        // change res back
1119   ChangeDisplaySettings(NULL,0);
1120 
1121  if(hPSEMenu)                                          // set menu again
1122   SetMenu(hWWindow,hPSEMenu);
1123 
1124  if(pGfxCardScreen) free(pGfxCardScreen);              // free helper memory
1125  pGfxCardScreen=0;
1126 
1127  if(iNoScreenSaver) EnableScreenSaver(TRUE);           // enable screen saver again
1128 
1129  return 0;
1130 }
1131 
1132 #else
1133 
GPUclose()1134 long GPUclose()                                        // LINUX CLOSE
1135 {
1136  GLcleanup();                                          // close OGL
1137 
1138  if(pGfxCardScreen) free(pGfxCardScreen);              // free helper memory
1139  pGfxCardScreen=0;
1140 #if defined (_MACGL)
1141  CloseDisplay();
1142 #else
1143  osd_close_display();                                  // destroy display
1144 #endif
1145  return 0;
1146 }
1147 
1148 #endif
1149 
1150 ////////////////////////////////////////////////////////////////////////
1151 // I shot the sheriff... last function called from emu
1152 ////////////////////////////////////////////////////////////////////////
1153 
GPUshutdown()1154 long CALLBACK GPUshutdown()
1155 {
1156  if(psxVSecure) free(psxVSecure);                      // kill emulated vram memory
1157  psxVSecure=0;
1158 
1159  return 0;
1160 }
1161 
1162 ////////////////////////////////////////////////////////////////////////
1163 // paint it black: simple func to clean up optical border garbage
1164 ////////////////////////////////////////////////////////////////////////
1165 
PaintBlackBorders(void)1166 void PaintBlackBorders(void)
1167 {
1168  short s;
1169 
1170  glDisable(GL_SCISSOR_TEST);
1171  if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}
1172  if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
1173  if(bBlendEnable)     {glDisable(GL_BLEND);bBlendEnable=FALSE;}
1174  glDisable(GL_ALPHA_TEST);
1175 
1176  glBegin(GL_QUADS);
1177 
1178  vertex[0].c.lcol=0xff000000;
1179  SETCOL(vertex[0]);
1180 
1181  if(PreviousPSXDisplay.Range.x0)
1182   {
1183    s=PreviousPSXDisplay.Range.x0+1;
1184    glVertex3f(0,0,0.99996f);
1185    glVertex3f(0,PSXDisplay.DisplayMode.y,0.99996f);
1186    glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f);
1187    glVertex3f(s,0,0.99996f);
1188 
1189    s+=PreviousPSXDisplay.Range.x1-2;
1190 
1191    glVertex3f(s,0,0.99996f);
1192    glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f);
1193    glVertex3f(PSXDisplay.DisplayMode.x,PSXDisplay.DisplayMode.y,0.99996f);
1194    glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f);
1195   }
1196 
1197  if(PreviousPSXDisplay.Range.y0)
1198   {
1199    s=PreviousPSXDisplay.Range.y0+1;
1200    glVertex3f(0,0,0.99996f);
1201    glVertex3f(0,s,0.99996f);
1202    glVertex3f(PSXDisplay.DisplayMode.x,s,0.99996f);
1203    glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f);
1204   }
1205 
1206  glEnd();
1207 
1208  glEnable(GL_ALPHA_TEST);
1209  glEnable(GL_SCISSOR_TEST);
1210 }
1211 
1212 ////////////////////////////////////////////////////////////////////////
1213 // helper to draw scanlines
1214 ////////////////////////////////////////////////////////////////////////
1215 
XPRIMdrawTexturedQuad(OGLVertex * vertex1,OGLVertex * vertex2,OGLVertex * vertex3,OGLVertex * vertex4)1216 static __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
1217                                     OGLVertex* vertex3, OGLVertex* vertex4)
1218 {
1219 
1220  glBegin(GL_QUAD_STRIP);
1221   glTexCoord2fv(&vertex1->sow);
1222   glVertex3fv(&vertex1->x);
1223 
1224   glTexCoord2fv(&vertex2->sow);
1225   glVertex3fv(&vertex2->x);
1226 
1227   glTexCoord2fv(&vertex4->sow);
1228   glVertex3fv(&vertex4->x);
1229 
1230   glTexCoord2fv(&vertex3->sow);
1231   glVertex3fv(&vertex3->x);
1232  glEnd();
1233 }
1234 
1235 ////////////////////////////////////////////////////////////////////////
1236 // scanlines
1237 ////////////////////////////////////////////////////////////////////////
1238 
SetScanLines(void)1239 void SetScanLines(void)
1240 {
1241  glLoadIdentity();
1242  glOrtho(0,iResX,iResY, 0, -1, 1);
1243 
1244  if(bKeepRatio)
1245   glViewport(0,0,iResX,iResY);
1246 
1247  glDisable(GL_SCISSOR_TEST);
1248  glDisable(GL_ALPHA_TEST);
1249  if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
1250 
1251  if(iScanBlend<0)                                      // special texture mask scanline mode
1252   {
1253    if(!bTexEnabled)    {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;}
1254    gTexName=gTexScanName;
1255    glBindTexture(GL_TEXTURE_2D, gTexName);
1256    if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1257    if(!bBlendEnable)   {glEnable(GL_BLEND);bBlendEnable=TRUE;}
1258    SetScanTexTrans();
1259 
1260    vertex[0].x=0;
1261    vertex[0].y=iResY;
1262    vertex[0].z=0.99996f;
1263 
1264    vertex[1].x=iResX;
1265    vertex[1].y=iResY;
1266    vertex[1].z=0.99996f;
1267 
1268    vertex[2].x=iResX;
1269    vertex[2].y=0;
1270    vertex[2].z=0.99996f;
1271 
1272    vertex[3].x=0;
1273    vertex[3].y=0;
1274    vertex[3].z=0.99996f;
1275 
1276    vertex[0].sow=0;
1277    vertex[0].tow=0;
1278    vertex[1].sow=(float)iResX/4.0f;
1279    vertex[1].tow=0;
1280    vertex[2].sow=vertex[1].sow;
1281    vertex[2].tow=(float)iResY/4.0f;
1282    vertex[3].sow=0;
1283    vertex[3].tow=vertex[2].tow;
1284 
1285    vertex[0].c.lcol=0xffffffff;
1286    SETCOL(vertex[0]);
1287 
1288    XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
1289 
1290    if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT);
1291   }
1292  else                                                  // typical line mode
1293   {
1294    if(bTexEnabled)     {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}
1295 
1296    if(iScanBlend==0)
1297     {
1298      if(bBlendEnable)    {glDisable(GL_BLEND);bBlendEnable=FALSE;}
1299      vertex[0].c.lcol=0xff000000;
1300     }
1301    else
1302     {
1303      if(!bBlendEnable)   {glEnable(GL_BLEND);bBlendEnable=TRUE;}
1304      SetScanTrans();
1305      vertex[0].c.lcol=iScanBlend<<24;
1306     }
1307 
1308    SETCOL(vertex[0]);
1309 
1310    glCallList(uiScanLine);
1311   }
1312 
1313  glLoadIdentity();
1314  glOrtho(0,PSXDisplay.DisplayMode.x,
1315          PSXDisplay.DisplayMode.y, 0, -1, 1);
1316 
1317  if(bKeepRatio)
1318   glViewport(rRatioRect.left,
1319              iResY-(rRatioRect.top+rRatioRect.bottom),
1320              rRatioRect.right,
1321              rRatioRect.bottom);                         // init viewport
1322 
1323  glEnable(GL_ALPHA_TEST);
1324  glEnable(GL_SCISSOR_TEST);
1325 }
1326 
1327 ////////////////////////////////////////////////////////////////////////
1328 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)
1329 ////////////////////////////////////////////////////////////////////////
1330 
BlurBackBuffer(void)1331 void BlurBackBuffer(void)
1332 {
1333  if(!gTexBlurName) return;
1334 
1335  if(bKeepRatio) glViewport(0,0,iResX,iResY);
1336 
1337  glDisable(GL_SCISSOR_TEST);
1338  glDisable(GL_ALPHA_TEST);
1339  if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
1340  if(bBlendEnable)     {glDisable(GL_BLEND);bBlendEnable=FALSE;}
1341  if(!bTexEnabled)     {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;}
1342  if(iZBufferDepth)    glDisable(GL_DEPTH_TEST);
1343  if(bDrawDither)      glDisable(GL_DITHER);
1344 
1345  gTexName=gTexBlurName;
1346  glBindTexture(GL_TEXTURE_2D, gTexName);
1347 
1348  glCopyTexSubImage2D( GL_TEXTURE_2D, 0,                // get back buffer in texture
1349                       0,
1350                       0,
1351                       0,
1352                       0,
1353                       iResX,iResY);
1354 
1355  vertex[0].x=0;
1356  vertex[0].y=PSXDisplay.DisplayMode.y;
1357  vertex[1].x=PSXDisplay.DisplayMode.x;
1358  vertex[1].y=PSXDisplay.DisplayMode.y;
1359  vertex[2].x=PSXDisplay.DisplayMode.x;
1360  vertex[2].y=0;
1361  vertex[3].x=0;
1362  vertex[3].y=0;
1363  vertex[0].sow=0;
1364  vertex[0].tow=0;
1365 
1366 #ifdef OWNSCALE
1367  vertex[1].sow=((GLfloat)iFTexA)/256.0f;
1368  vertex[2].tow=((GLfloat)iFTexB)/256.0f;
1369 #else
1370  vertex[1].sow=iFTexA;
1371  vertex[2].tow=iFTexB;
1372 #endif
1373  vertex[1].tow=0;
1374  vertex[2].sow=vertex[1].sow;
1375  vertex[3].sow=0;
1376  vertex[3].tow=vertex[2].tow;
1377 
1378  if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1379  vertex[0].c.lcol=0x7fffffff;
1380  SETCOL(vertex[0]);
1381 
1382  DrawMultiBlur();                                      // draw the backbuffer texture to create blur effect
1383 
1384  glEnable(GL_ALPHA_TEST);
1385  glEnable(GL_SCISSOR_TEST);
1386  if(iZBufferDepth)  glEnable(GL_DEPTH_TEST);
1387  if(bDrawDither)    glEnable(GL_DITHER);
1388  if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT);
1389 
1390  if(bKeepRatio)
1391   glViewport(rRatioRect.left,                            // re-init viewport
1392              iResY-(rRatioRect.top+rRatioRect.bottom),
1393              rRatioRect.right,
1394              rRatioRect.bottom);
1395 }
1396 
1397 ////////////////////////////////////////////////////////////////////////
1398 // "unblur" repairs the backbuffer after a blur
1399 
UnBlurBackBuffer(void)1400 void UnBlurBackBuffer(void)
1401 {
1402  if(!gTexBlurName) return;
1403 
1404  if(bKeepRatio) glViewport(0,0,iResX,iResY);
1405 
1406  glDisable(GL_SCISSOR_TEST);
1407  glDisable(GL_ALPHA_TEST);
1408  if(bBlendEnable)    {glDisable(GL_BLEND);bBlendEnable=FALSE;}
1409  if(!bTexEnabled)    {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;}
1410  if(iZBufferDepth)    glDisable(GL_DEPTH_TEST);
1411  if(bDrawDither)      glDisable(GL_DITHER);
1412 
1413  gTexName=gTexBlurName;
1414  glBindTexture(GL_TEXTURE_2D, gTexName);
1415 
1416  vertex[0].x=0;
1417  vertex[0].y=PSXDisplay.DisplayMode.y;
1418  vertex[1].x=PSXDisplay.DisplayMode.x;
1419  vertex[1].y=PSXDisplay.DisplayMode.y;
1420  vertex[2].x=PSXDisplay.DisplayMode.x;
1421  vertex[2].y=0;
1422  vertex[3].x=0;
1423  vertex[3].y=0;
1424  vertex[0].sow=0;
1425  vertex[0].tow=0;
1426 #ifdef OWNSCALE
1427  vertex[1].sow=((GLfloat)iFTexA)/256.0f;
1428  vertex[2].tow=((GLfloat)iFTexB)/256.0f;
1429 #else
1430  vertex[1].sow=iFTexA;
1431  vertex[2].tow=iFTexB;
1432 #endif
1433  vertex[1].tow=0;
1434  vertex[2].sow=vertex[1].sow;
1435  vertex[3].sow=0;
1436  vertex[3].tow=vertex[2].tow;
1437  if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1438  vertex[0].c.lcol=0xffffffff;
1439  SETCOL(vertex[0]);
1440 
1441  // simply draw the backbuffer texture (without blur)
1442  XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
1443 
1444  glEnable(GL_ALPHA_TEST);
1445  glEnable(GL_SCISSOR_TEST);
1446  if(iZBufferDepth)  glEnable(GL_DEPTH_TEST);
1447  if(bDrawDither)    glEnable(GL_DITHER);                  // dither mode
1448  if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT);
1449 
1450  if(bKeepRatio)
1451   glViewport(rRatioRect.left,
1452              iResY-(rRatioRect.top+rRatioRect.bottom),
1453              rRatioRect.right,
1454              rRatioRect.bottom);                         // init viewport
1455 }
1456 
1457 ////////////////////////////////////////////////////////////////////////
1458 // Update display (swap buffers)... called in interlaced mode on
1459 // every emulated vsync, otherwise whenever the displayed screen region
1460 // has been changed
1461 ////////////////////////////////////////////////////////////////////////
1462 
1463 int iLastRGB24=0;                                      // special vars for checking when to skip two display updates
1464 int iSkipTwo=0;
1465 
updateDisplay(void)1466 void updateDisplay(void)                               // UPDATE DISPLAY
1467 {
1468  BOOL bBlur=FALSE;
1469 
1470 #ifdef _WINDOWS
1471  HDC hdc=GetDC(hWWindow);                              // windows:
1472  wglMakeCurrent(hdc,GLCONTEXT);                        // -> make context current again
1473 #endif
1474 #if defined (_MACGL)
1475  BringContextForward();
1476 #endif
1477  bFakeFrontBuffer=FALSE;
1478  bRenderFrontBuffer=FALSE;
1479 
1480  if(iRenderFVR)                                        // frame buffer read fix mode still active?
1481   {
1482    iRenderFVR--;                                       // -> if some frames in a row without read access: turn off mode
1483    if(!iRenderFVR) bFullVRam=FALSE;
1484   }
1485 
1486  if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1)      // (mdec) garbage check
1487   {
1488    iSkipTwo=2;                                         // -> skip two frames to avoid garbage if color mode changes
1489   }
1490  iLastRGB24=0;
1491 
1492  if(PSXDisplay.RGB24)// && !bNeedUploadAfter)          // (mdec) upload wanted?
1493   {
1494    PrepareFullScreenUpload(-1);
1495    UploadScreen(PSXDisplay.Interlaced);                // -> upload whole screen from psx vram
1496    bNeedUploadTest=FALSE;
1497    bNeedInterlaceUpdate=FALSE;
1498    bNeedUploadAfter=FALSE;
1499    bNeedRGB24Update=FALSE;
1500   }
1501  else
1502  if(bNeedInterlaceUpdate)                              // smaller upload?
1503   {
1504    bNeedInterlaceUpdate=FALSE;
1505    xrUploadArea=xrUploadAreaIL;                        // -> upload this rect
1506    UploadScreen(TRUE);
1507   }
1508 
1509  if(dwActFixes&512) bCheckFF9G4(NULL);                 // special game fix for FF9
1510 
1511  if(PreviousPSXDisplay.Range.x0||                      // paint black borders around display area, if needed
1512     PreviousPSXDisplay.Range.y0)
1513   PaintBlackBorders();
1514 
1515  if(PSXDisplay.Disabled)                               // display disabled?
1516   {
1517    // moved here
1518    glDisable(GL_SCISSOR_TEST);
1519    glClearColor(0,0,0,128);                            // -> clear whole backbuffer
1520    glClear(uiBufferBits);
1521    glEnable(GL_SCISSOR_TEST);
1522    gl_z=0.0f;
1523    bDisplayNotSet = TRUE;
1524   }
1525 
1526  if(iSkipTwo)                                          // we are in skipping mood?
1527   {
1528    iSkipTwo--;
1529    iDrawnSomething=0;                                  // -> simply lie about something drawn
1530   }
1531 
1532  if(iBlurBuffer && !bSkipNextFrame)                    // "blur display" activated?
1533   {BlurBackBuffer();bBlur=TRUE;}                       // -> blur it
1534 
1535  if(iUseScanLines) SetScanLines();                     // "scan lines" activated? do it
1536 
1537  if(usCursorActive) ShowGunCursor();                   // "gun cursor" wanted? show 'em
1538 
1539  if(dwActFixes&128)                                    // special FPS limitation mode?
1540   {
1541    if(bUseFrameLimit) PCFrameCap();                    // -> ok, do it
1542    if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)
1543     PCcalcfps();
1544   }
1545 
1546  if(gTexPicName) DisplayPic();                         // some gpu info picture active? display it
1547 
1548  if(bSnapShot) DoSnapShot();                           // snapshot key pressed? cheeeese :)
1549 
1550  if(ulKeybits&KEY_SHOWFPS)                             // wanna see FPS?
1551   {
1552    sprintf(szDispBuf,"%06.1f",fps_cur);
1553    DisplayText();                                      // -> show it
1554   }
1555 
1556  //----------------------------------------------------//
1557  // main buffer swapping (well, or skip it)
1558 
1559  if(bUseFrameSkip)                                     // frame skipping active ?
1560   {
1561    if(!bSkipNextFrame)
1562     {
1563      if(iDrawnSomething)
1564 #ifdef _WINDOWS
1565       SwapBuffers(wglGetCurrentDC());                  // -> to skip or not to skip
1566 #elif defined(_MACGL)
1567      DoBufferSwap();
1568 #else
1569       glXSwapBuffers(display,window);
1570 #endif
1571     }
1572    if(dwActFixes&0x180)                                // -> special old frame skipping: skip max one in a row
1573     {
1574      if((fps_skip < fFrameRateHz) && !(bSkipNextFrame))
1575       {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
1576      else bSkipNextFrame = FALSE;
1577     }
1578    else FrameSkip();
1579   }
1580  else                                                  // no skip ?
1581   {
1582    if(iDrawnSomething)
1583 #ifdef _WINDOWS
1584     SwapBuffers(wglGetCurrentDC());                    // -> swap
1585 #elif defined(_MACGL)
1586    DoBufferSwap();
1587 #else
1588     glXSwapBuffers(display,window);
1589 #endif
1590   }
1591 
1592  iDrawnSomething=0;
1593 
1594  //----------------------------------------------------//
1595 
1596  if(lClearOnSwap)                                      // clear buffer after swap?
1597   {
1598    GLclampf g,b,r;
1599 
1600    if(bDisplayNotSet)                                  // -> set new vals
1601     SetOGLDisplaySettings(1);
1602 
1603    g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f;      // -> get col
1604    b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;
1605    r=((GLclampf)RED(lClearOnSwapColor))/255.0f;
1606 
1607    glDisable(GL_SCISSOR_TEST);
1608    glClearColor(r,g,b,128);                            // -> clear
1609    glClear(uiBufferBits);
1610    glEnable(GL_SCISSOR_TEST);
1611    lClearOnSwap=0;                                     // -> done
1612   }
1613  else
1614   {
1615    if(bBlur) UnBlurBackBuffer();                       // unblur buff, if blurred before
1616 
1617    if(iZBufferDepth)                                   // clear zbuffer as well (if activated)
1618     {
1619      glDisable(GL_SCISSOR_TEST);
1620      glClear(GL_DEPTH_BUFFER_BIT);
1621      glEnable(GL_SCISSOR_TEST);
1622     }
1623   }
1624  gl_z=0.0f;
1625 
1626  //----------------------------------------------------//
1627  // additional uploads immediatly after swapping
1628 
1629  if(bNeedUploadAfter)                                  // upload wanted?
1630   {
1631    bNeedUploadAfter=FALSE;
1632    bNeedUploadTest=FALSE;
1633    UploadScreen(-1);                                   // -> upload
1634   }
1635 
1636  if(bNeedUploadTest)
1637   {
1638    bNeedUploadTest=FALSE;
1639    if(PSXDisplay.InterlacedTest &&
1640       //iOffscreenDrawing>2 &&
1641       PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&
1642       PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&
1643       PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&
1644       PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)
1645     {
1646      PrepareFullScreenUpload(TRUE);
1647      UploadScreen(TRUE);
1648     }
1649   }
1650 
1651  //----------------------------------------------------//
1652  // rumbling (main emu pad effect)
1653 
1654  if(iRumbleTime)                                       // shake screen by modifying view port
1655   {
1656    int i1=0,i2=0,i3=0,i4=0;
1657 
1658    iRumbleTime--;
1659    if(iRumbleTime)
1660     {
1661      i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
1662      i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
1663      i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
1664      i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
1665     }
1666 
1667    glViewport(rRatioRect.left+i1,
1668               iResY-(rRatioRect.top+rRatioRect.bottom)+i2,
1669               rRatioRect.right+i3,
1670               rRatioRect.bottom+i4);
1671   }
1672 
1673 #ifdef _WINDOWS
1674  ReleaseDC(hWWindow,hdc);                              // ! important !
1675 #endif
1676 
1677  if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff();         // reset on gpu mode changes? do it before next frame is filled
1678 }
1679 
1680 ////////////////////////////////////////////////////////////////////////
1681 // update front display: smaller update func, if something has changed
1682 // in the frontbuffer... dirty, but hey... real men know no pain
1683 ////////////////////////////////////////////////////////////////////////
1684 
updateFrontDisplay(void)1685 void updateFrontDisplay(void)
1686 {
1687  if(PreviousPSXDisplay.Range.x0||
1688     PreviousPSXDisplay.Range.y0)
1689   PaintBlackBorders();
1690 
1691  if(iBlurBuffer) BlurBackBuffer();
1692 
1693  if(iUseScanLines) SetScanLines();
1694 
1695  if(usCursorActive) ShowGunCursor();
1696 
1697  bFakeFrontBuffer=FALSE;
1698  bRenderFrontBuffer=FALSE;
1699 
1700  if(gTexPicName) DisplayPic();
1701  if(ulKeybits&KEY_SHOWFPS) DisplayText();
1702 
1703 #ifdef _WINDOWS
1704   {                                                    // windows:
1705    HDC hdc=GetDC(hWWindow);
1706    wglMakeCurrent(hdc,GLCONTEXT);                      // -> make current again
1707    if(iDrawnSomething)
1708     SwapBuffers(wglGetCurrentDC());                    // -> swap
1709    ReleaseDC(hWWindow,hdc);                            // -> ! important !
1710   }
1711 #elif defined (_MACGL)
1712  if (iDrawnSomething){
1713   DoBufferSwap();
1714  }
1715 #else
1716  if(iDrawnSomething)                                   // linux:
1717   glXSwapBuffers(display,window);
1718 #endif
1719 
1720  if(iBlurBuffer) UnBlurBackBuffer();
1721 }
1722 
1723 ////////////////////////////////////////////////////////////////////////
1724 // check if update needed
1725 ////////////////////////////////////////////////////////////////////////
1726 
ChangeDispOffsetsX(void)1727 void ChangeDispOffsetsX(void)                          // CENTER X
1728 {
1729  int lx,l;short sO;
1730 
1731  if(!PSXDisplay.Range.x1) return;                      // some range given?
1732 
1733  l=PSXDisplay.DisplayMode.x;
1734 
1735  l*=(int)PSXDisplay.Range.x1;                          // some funky calculation
1736  l/=2560;lx=l;l&=0xfffffff8;
1737 
1738  if(l==PreviousPSXDisplay.Range.x1) return;            // some change?
1739 
1740  sO=PreviousPSXDisplay.Range.x0;                       // store old
1741 
1742  if(lx>=PSXDisplay.DisplayMode.x)                      // range bigger?
1743   {
1744    PreviousPSXDisplay.Range.x1=                        // -> take display width
1745     PSXDisplay.DisplayMode.x;
1746    PreviousPSXDisplay.Range.x0=0;                      // -> start pos is 0
1747   }
1748  else                                                  // range smaller? center it
1749   {
1750    PreviousPSXDisplay.Range.x1=l;                      // -> store width (8 pixel aligned)
1751     PreviousPSXDisplay.Range.x0=                       // -> calc start pos
1752     (PSXDisplay.Range.x0-500)/8;
1753    if(PreviousPSXDisplay.Range.x0<0)                   // -> we don't support neg. values yet
1754     PreviousPSXDisplay.Range.x0=0;
1755 
1756    if((PreviousPSXDisplay.Range.x0+lx)>                // -> uhuu... that's too much
1757       PSXDisplay.DisplayMode.x)
1758     {
1759      PreviousPSXDisplay.Range.x0=                      // -> adjust start
1760       PSXDisplay.DisplayMode.x-lx;
1761      PreviousPSXDisplay.Range.x1+=lx-l;                // -> adjust width
1762     }
1763   }
1764 
1765  if(sO!=PreviousPSXDisplay.Range.x0)                   // something changed?
1766   {
1767    bDisplayNotSet=TRUE;                                // -> recalc display stuff
1768   }
1769 }
1770 
1771 ////////////////////////////////////////////////////////////////////////
1772 
ChangeDispOffsetsY(void)1773 void ChangeDispOffsetsY(void)                          // CENTER Y
1774 {
1775  int iT;short sO;                                      // store previous y size
1776 
1777  if(PSXDisplay.PAL) iT=48; else iT=28;                 // different offsets on PAL/NTSC
1778 
1779  if(PSXDisplay.Range.y0>=iT)                           // crossed the security line? :)
1780   {
1781    PreviousPSXDisplay.Range.y1=                        // -> store width
1782     PSXDisplay.DisplayModeNew.y;
1783 
1784    sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double;    // -> calc offset
1785    if(sO<0) sO=0;
1786 
1787    PSXDisplay.DisplayModeNew.y+=sO;                    // -> add offset to y size, too
1788   }
1789  else sO=0;                                            // else no offset
1790 
1791  if(sO!=PreviousPSXDisplay.Range.y0)                   // something changed?
1792   {
1793    PreviousPSXDisplay.Range.y0=sO;
1794    bDisplayNotSet=TRUE;                                // -> recalc display stuff
1795   }
1796 }
1797 
1798 ////////////////////////////////////////////////////////////////////////
1799 // Aspect ratio of ogl screen: simply adjusting ogl view port
1800 ////////////////////////////////////////////////////////////////////////
1801 
SetAspectRatio(void)1802 void SetAspectRatio(void)
1803 {
1804  float xs,ys,s,resx,resy;RECT r;
1805 
1806  if(!PSXDisplay.DisplayModeNew.x) return;
1807  if(!PSXDisplay.DisplayModeNew.y) return;
1808 
1809  resx = bForceRatio43 ? 640.0f : (float)PSXDisplay.DisplayModeNew.x;
1810  resy = bForceRatio43 ? 480.0f : (float)PSXDisplay.DisplayModeNew.y;
1811 
1812  xs=(float)iResX/resx;
1813  ys=(float)iResY/resy;
1814 
1815  s=min(xs,ys);
1816  r.right =(int)(resx*s);
1817  r.bottom=(int)(resy*s);
1818  if(r.right  > iResX) r.right  = iResX;
1819  if(r.bottom > iResY) r.bottom = iResY;
1820  if(r.right  < 1)     r.right  = 1;
1821  if(r.bottom < 1)     r.bottom = 1;
1822 
1823  r.left = (iResX-r.right)/2;
1824  r.top  = (iResY-r.bottom)/2;
1825 
1826  if(r.bottom<rRatioRect.bottom ||
1827     r.right <rRatioRect.right)
1828   {
1829    RECT rC;
1830    glClearColor(0,0,0,128);
1831 
1832    if(r.right <rRatioRect.right)
1833     {
1834      rC.left=0;
1835      rC.top=0;
1836      rC.right=r.left;
1837      rC.bottom=iResY;
1838      glScissor(rC.left,rC.top,rC.right,rC.bottom);
1839      glClear(uiBufferBits);
1840      rC.left=iResX-rC.right;
1841      glScissor(rC.left,rC.top,rC.right,rC.bottom);
1842      glClear(uiBufferBits);
1843     }
1844 
1845    if(r.bottom <rRatioRect.bottom)
1846     {
1847      rC.left=0;
1848      rC.top=0;
1849      rC.right=iResX;
1850      rC.bottom=r.top;
1851      glScissor(rC.left,rC.top,rC.right,rC.bottom);
1852      glClear(uiBufferBits);
1853      rC.top=iResY-rC.bottom;
1854      glScissor(rC.left,rC.top,rC.right,rC.bottom);
1855      glClear(uiBufferBits);
1856     }
1857 
1858    bSetClip=TRUE;
1859    bDisplayNotSet=TRUE;
1860   }
1861 
1862  rRatioRect=r;
1863 
1864 
1865  glViewport(rRatioRect.left,
1866             iResY-(rRatioRect.top+rRatioRect.bottom),
1867             rRatioRect.right,
1868             rRatioRect.bottom);                         // init viewport
1869 }
1870 
1871 ////////////////////////////////////////////////////////////////////////
1872 // big ass check, if an ogl swap buffer is needed
1873 ////////////////////////////////////////////////////////////////////////
1874 
updateDisplayIfChanged(void)1875 void updateDisplayIfChanged(void)
1876 {
1877  BOOL bUp;
1878 
1879  if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
1880      (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
1881   {
1882    if((PSXDisplay.RGB24      == PSXDisplay.RGB24New) &&
1883       (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew))
1884       return;                                          // nothing has changed? fine, no swap buffer needed
1885   }
1886  else                                                  // some res change?
1887   {
1888    glLoadIdentity();
1889    glOrtho(0,PSXDisplay.DisplayModeNew.x,              // -> new psx resolution
1890              PSXDisplay.DisplayModeNew.y, 0, -1, 1);
1891    if(bKeepRatio) SetAspectRatio();
1892   }
1893 
1894  bDisplayNotSet = TRUE;                                // re-calc offsets/display area
1895 
1896  bUp=FALSE;
1897  if(PSXDisplay.RGB24!=PSXDisplay.RGB24New)             // clean up textures, if rgb mode change (usually mdec on/off)
1898   {
1899    PreviousPSXDisplay.RGB24=0;                         // no full 24 frame uploaded yet
1900    ResetTextureArea(FALSE);
1901    bUp=TRUE;
1902   }
1903 
1904  PSXDisplay.RGB24         = PSXDisplay.RGB24New;       // get new infos
1905  PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
1906  PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
1907  PSXDisplay.Interlaced    = PSXDisplay.InterlacedNew;
1908 
1909  PSXDisplay.DisplayEnd.x=                              // calc new ends
1910   PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
1911  PSXDisplay.DisplayEnd.y=
1912   PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
1913  PreviousPSXDisplay.DisplayEnd.x=
1914   PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
1915  PreviousPSXDisplay.DisplayEnd.y=
1916   PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
1917 
1918  ChangeDispOffsetsX();
1919 
1920  if(iFrameLimit==2) SetAutoFrameCap();                 // set new fps limit vals (depends on interlace)
1921 
1922  if(bUp) updateDisplay();                              // yeah, real update (swap buffer)
1923 }
1924 
1925 ////////////////////////////////////////////////////////////////////////
1926 // window mode <-> fullscreen mode (windows)
1927 ////////////////////////////////////////////////////////////////////////
1928 
1929 #ifdef _WINDOWS
ChangeWindowMode(void)1930 void ChangeWindowMode(void)
1931  {
1932   GPUclose();
1933   bWindowMode=!bWindowMode;
1934   GPUopen(hWWindow);
1935   bChangeWinMode=FALSE;
1936  }
1937 #endif
1938 
1939 ////////////////////////////////////////////////////////////////////////
1940 // swap update check (called by psx vsync function)
1941 ////////////////////////////////////////////////////////////////////////
1942 
bSwapCheck(void)1943 BOOL bSwapCheck(void)
1944 {
1945  static int iPosCheck=0;
1946  static PSXPoint_t pO;
1947  static PSXPoint_t pD;
1948  static int iDoAgain=0;
1949 
1950  if(PSXDisplay.DisplayPosition.x==pO.x &&
1951     PSXDisplay.DisplayPosition.y==pO.y &&
1952     PSXDisplay.DisplayEnd.x==pD.x &&
1953     PSXDisplay.DisplayEnd.y==pD.y)
1954       iPosCheck++;
1955  else iPosCheck=0;
1956 
1957  pO=PSXDisplay.DisplayPosition;
1958  pD=PSXDisplay.DisplayEnd;
1959 
1960  if(iPosCheck<=4) return FALSE;
1961 
1962  iPosCheck=4;
1963 
1964  if(PSXDisplay.Interlaced) return FALSE;
1965 
1966  if (bNeedInterlaceUpdate||
1967      bNeedRGB24Update ||
1968      bNeedUploadAfter||
1969      bNeedUploadTest ||
1970      iDoAgain
1971     )
1972   {
1973    iDoAgain=0;
1974    if(bNeedUploadAfter)
1975     iDoAgain=1;
1976    if(bNeedUploadTest && PSXDisplay.InterlacedTest)
1977     iDoAgain=1;
1978 
1979    bDisplayNotSet = TRUE;
1980    updateDisplay();
1981 
1982    PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;
1983    PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;
1984    PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;
1985    PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;
1986    pO=PSXDisplay.DisplayPosition;
1987    pD=PSXDisplay.DisplayEnd;
1988 
1989    return TRUE;
1990   }
1991 
1992  return FALSE;
1993 }
1994 
1995 ////////////////////////////////////////////////////////////////////////
1996 // gun cursor func: player=0-7, x=0-511, y=0-255
1997 ////////////////////////////////////////////////////////////////////////
1998 
GPUcursor(int iPlayer,int x,int y)1999 void CALLBACK GPUcursor(int iPlayer,int x,int y)
2000 {
2001  if(iPlayer<0) return;
2002  if(iPlayer>7) return;
2003 
2004  usCursorActive|=(1<<iPlayer);
2005 
2006  if(x<0)              x=0;
2007  if(x>iGPUHeightMask) x=iGPUHeightMask;
2008  if(y<0)              y=0;
2009  if(y>255)            y=255;
2010 
2011  ptCursorPoint[iPlayer].x=x;
2012  ptCursorPoint[iPlayer].y=y;
2013 }
2014 
2015 ////////////////////////////////////////////////////////////////////////
2016 // update lace is called every VSync. Basically we limit frame rate
2017 // here, and in interlaced mode we swap ogl display buffers.
2018 ////////////////////////////////////////////////////////////////////////
2019 
2020 static unsigned short usFirstPos=2;
2021 
GPUupdateLace(void)2022 void CALLBACK GPUupdateLace(void)
2023 {
2024  if(!(dwActFixes&0x1000))
2025   STATUSREG^=0x80000000;                               // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
2026 
2027  if(!(dwActFixes&128))                                 // normal frame limit func
2028   CheckFrameRate();
2029 
2030  if(iOffscreenDrawing==4)                              // special check if high offscreen drawing is on
2031   {
2032    if(bSwapCheck()) return;
2033   }
2034 
2035  if(PSXDisplay.Interlaced)                             // interlaced mode?
2036   {
2037    //STATUSREG^=0x80000000;
2038    if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
2039     {
2040      updateDisplay();                                  // -> swap buffers (new frame)
2041     }
2042   }
2043  else if(bRenderFrontBuffer)                           // no interlace mode? and some stuff in front has changed?
2044   {
2045    updateFrontDisplay();                               // -> update front buffer
2046   }
2047  else if(usFirstPos==1)                                // initial updates (after startup)
2048   {
2049    updateDisplay();
2050   }
2051 
2052 #if defined(_WINDOWS) || defined(_MACGL)
2053  if(bChangeWinMode) ChangeWindowMode();
2054 #endif
2055 }
2056 
2057 ////////////////////////////////////////////////////////////////////////
2058 // process read request from GPU status register
2059 ////////////////////////////////////////////////////////////////////////
2060 
GPUreadStatus(void)2061 uint32_t CALLBACK GPUreadStatus(void)
2062 {
2063  if (vBlank || oddLines == FALSE)
2064   { // vblank or even lines
2065    STATUSREG &= ~(0x80000000);
2066   }
2067  else
2068   { // Oddlines and not vblank
2069    STATUSREG |= 0x80000000;
2070   }
2071 
2072  if(dwActFixes&0x1000)                                 // CC game fix
2073   {
2074    static int iNumRead=0;
2075    if((iNumRead++)==2)
2076     {
2077      iNumRead=0;
2078      STATUSREG^=0x80000000;                            // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
2079     }
2080   }
2081 
2082  if(iFakePrimBusy)                                     // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread...
2083   {
2084    iFakePrimBusy--;
2085 
2086    if(iFakePrimBusy&1)                                 // we do a busy-idle-busy-idle sequence after/while drawing prims
2087     {
2088      GPUIsBusy;
2089      GPUIsNotReadyForCommands;
2090     }
2091    else
2092     {
2093      GPUIsIdle;
2094      GPUIsReadyForCommands;
2095     }
2096   }
2097 
2098  return STATUSREG;
2099 }
2100 
2101 ////////////////////////////////////////////////////////////////////////
2102 // processes data send to GPU status register
2103 // these are always single packet commands.
2104 ////////////////////////////////////////////////////////////////////////
2105 
GPUwriteStatus(uint32_t gdata)2106 void CALLBACK GPUwriteStatus(uint32_t gdata)
2107 {
2108  uint32_t lCommand=(gdata>>24)&0xff;
2109 
2110 #ifdef _WINDOWS
2111  if(bIsFirstFrame) GLinitialize();                     // real ogl startup (needed by some emus)
2112 #endif
2113 
2114  ulStatusControl[lCommand]=gdata;
2115 
2116  switch(lCommand)
2117   {
2118    //--------------------------------------------------//
2119    // reset gpu
2120    case 0x00:
2121     memset(ulGPUInfoVals, 0x00, 16 * sizeof(uint32_t));
2122     lGPUstatusRet = 0x14802000;
2123     PSXDisplay.Disabled=1;
2124     iDataWriteMode=iDataReadMode=DR_NORMAL;
2125     PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
2126     drawX=drawY=0;drawW=drawH=0;
2127     sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;
2128     usMirror=0;
2129     GlobalTextAddrX=0;GlobalTextAddrY=0;
2130     GlobalTextTP=0;GlobalTextABR=0;
2131     PSXDisplay.RGB24=FALSE;
2132     PSXDisplay.Interlaced=FALSE;
2133     bUsingTWin = FALSE;
2134     return;
2135 
2136    // dis/enable display
2137    case 0x03:
2138     PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
2139     PSXDisplay.Disabled = (gdata & 1);
2140 
2141     if(PSXDisplay.Disabled)
2142          STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
2143     else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
2144 
2145     if (iOffscreenDrawing==4 &&
2146          PreviousPSXDisplay.Disabled &&
2147         !(PSXDisplay.Disabled))
2148      {
2149 
2150       if(!PSXDisplay.RGB24)
2151        {
2152         PrepareFullScreenUpload(TRUE);
2153         UploadScreen(TRUE);
2154         updateDisplay();
2155        }
2156      }
2157 
2158     return;
2159 
2160    // setting transfer mode
2161    case 0x04:
2162     gdata &= 0x03;                                     // only want the lower two bits
2163 
2164     iDataWriteMode=iDataReadMode=DR_NORMAL;
2165     if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
2166     if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
2167 
2168     STATUSREG&=~GPUSTATUS_DMABITS;                     // clear the current settings of the DMA bits
2169     STATUSREG|=(gdata << 29);                          // set the DMA bits according to the received data
2170 
2171     return;
2172 
2173    // setting display position
2174    case 0x05:
2175     {
2176      short sx=(short)(gdata & 0x3ff);
2177      short sy;
2178 
2179      if(iGPUHeight==1024)
2180       {
2181        if(dwGPUVersion==2)
2182             sy = (short)((gdata>>12)&0x3ff);
2183        else sy = (short)((gdata>>10)&0x3ff);
2184       }
2185      else sy = (short)((gdata>>10)&0x3ff);             // really: 0x1ff, but we adjust it later
2186 
2187      if (sy & 0x200)
2188       {
2189        sy|=0xfc00;
2190        PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
2191        sy=0;
2192       }
2193      else PreviousPSXDisplay.DisplayModeNew.y=0;
2194 
2195      if(sx>1000) sx=0;
2196 
2197      if(usFirstPos)
2198       {
2199        usFirstPos--;
2200        if(usFirstPos)
2201         {
2202          PreviousPSXDisplay.DisplayPosition.x = sx;
2203          PreviousPSXDisplay.DisplayPosition.y = sy;
2204          PSXDisplay.DisplayPosition.x = sx;
2205          PSXDisplay.DisplayPosition.y = sy;
2206         }
2207       }
2208 
2209      if(dwActFixes&8)
2210       {
2211        if((!PSXDisplay.Interlaced) &&
2212           PreviousPSXDisplay.DisplayPosition.x == sx  &&
2213           PreviousPSXDisplay.DisplayPosition.y == sy)
2214         return;
2215 
2216        PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;
2217        PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;
2218        PreviousPSXDisplay.DisplayPosition.x = sx;
2219        PreviousPSXDisplay.DisplayPosition.y = sy;
2220       }
2221      else
2222       {
2223        if((!PSXDisplay.Interlaced) &&
2224           PSXDisplay.DisplayPosition.x == sx  &&
2225           PSXDisplay.DisplayPosition.y == sy)
2226         return;
2227        PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
2228        PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
2229        PSXDisplay.DisplayPosition.x = sx;
2230        PSXDisplay.DisplayPosition.y = sy;
2231       }
2232 
2233      PSXDisplay.DisplayEnd.x=
2234       PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
2235      PSXDisplay.DisplayEnd.y=
2236       PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
2237 
2238      PreviousPSXDisplay.DisplayEnd.x=
2239       PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
2240      PreviousPSXDisplay.DisplayEnd.y=
2241       PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
2242 
2243      bDisplayNotSet = TRUE;
2244 
2245      if (!(PSXDisplay.Interlaced))
2246       {
2247        updateDisplay();
2248       }
2249      else
2250      if(PSXDisplay.InterlacedTest &&
2251         ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||
2252          (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))
2253       PSXDisplay.InterlacedTest--;
2254 
2255      return;
2256     }
2257 
2258    // setting width
2259    case 0x06:
2260 
2261     PSXDisplay.Range.x0=gdata & 0x7ff;      //0x3ff;
2262     PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
2263 
2264     PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
2265 
2266     ChangeDispOffsetsX();
2267 
2268     return;
2269 
2270    // setting height
2271    case 0x07:
2272 
2273     PreviousPSXDisplay.Height = PSXDisplay.Height;
2274 
2275     PSXDisplay.Range.y0=gdata & 0x3ff;
2276     PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
2277 
2278     PSXDisplay.Height = PSXDisplay.Range.y1 -
2279                         PSXDisplay.Range.y0 +
2280                         PreviousPSXDisplay.DisplayModeNew.y;
2281 
2282     if (PreviousPSXDisplay.Height != PSXDisplay.Height)
2283      {
2284       PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
2285       ChangeDispOffsetsY();
2286       updateDisplayIfChanged();
2287      }
2288     return;
2289 
2290    // setting display infos
2291    case 0x08:
2292 
2293     PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
2294 
2295     if (gdata&0x04) PSXDisplay.Double=2;
2296     else            PSXDisplay.Double=1;
2297     PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
2298 
2299     ChangeDispOffsetsY();
2300 
2301     PSXDisplay.PAL           = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
2302     PSXDisplay.RGB24New      = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
2303     PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
2304 
2305     STATUSREG&=~GPUSTATUS_WIDTHBITS;                   // clear the width bits
2306 
2307     STATUSREG|=
2308                (((gdata & 0x03) << 17) |
2309                ((gdata & 0x40) << 10));                // set the width bits
2310 
2311     PreviousPSXDisplay.InterlacedNew=FALSE;
2312     if (PSXDisplay.InterlacedNew)
2313      {
2314       if(!PSXDisplay.Interlaced)
2315        {
2316         PSXDisplay.InterlacedTest=2;
2317         PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
2318         PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
2319         PreviousPSXDisplay.InterlacedNew=TRUE;
2320        }
2321 
2322       STATUSREG|=GPUSTATUS_INTERLACED;
2323      }
2324     else
2325      {
2326       PSXDisplay.InterlacedTest=0;
2327       STATUSREG&=~GPUSTATUS_INTERLACED;
2328      }
2329 
2330     if (PSXDisplay.PAL)
2331          STATUSREG|=GPUSTATUS_PAL;
2332     else STATUSREG&=~GPUSTATUS_PAL;
2333 
2334     if (PSXDisplay.Double==2)
2335          STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
2336     else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
2337 
2338     if (PSXDisplay.RGB24New)
2339          STATUSREG|=GPUSTATUS_RGB24;
2340     else STATUSREG&=~GPUSTATUS_RGB24;
2341 
2342     updateDisplayIfChanged();
2343 
2344     return;
2345 
2346    //--------------------------------------------------//
2347    // ask about GPU version and other stuff
2348    case 0x10:
2349 
2350     gdata&=0xff;
2351 
2352     switch(gdata)
2353      {
2354       case 0x02:
2355        GPUdataRet=ulGPUInfoVals[INFO_TW];              // tw infos
2356        return;
2357       case 0x03:
2358        GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART];       // draw start
2359        return;
2360       case 0x04:
2361        GPUdataRet=ulGPUInfoVals[INFO_DRAWEND];         // draw end
2362        return;
2363       case 0x05:
2364       case 0x06:
2365        GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF];         // draw offset
2366        return;
2367       case 0x07:
2368        if(dwGPUVersion==2)
2369             GPUdataRet=0x01;
2370        else GPUdataRet=0x02;                           // gpu type
2371        return;
2372       case 0x08:
2373       case 0x0F:                                       // some bios addr?
2374        GPUdataRet=0xBFC03720;
2375        return;
2376      }
2377     return;
2378    //--------------------------------------------------//
2379   }
2380 }
2381 
2382 ////////////////////////////////////////////////////////////////////////
2383 // vram read/write helpers
2384 ////////////////////////////////////////////////////////////////////////
2385 
2386 BOOL bNeedWriteUpload=FALSE;
2387 
FinishedVRAMWrite(void)2388 static __inline void FinishedVRAMWrite(void)
2389 {
2390  if(bNeedWriteUpload)
2391   {
2392    bNeedWriteUpload=FALSE;
2393    CheckWriteUpdate();
2394   }
2395 
2396  // set register to NORMAL operation
2397  iDataWriteMode = DR_NORMAL;
2398 
2399  // reset transfer values, to prevent mis-transfer of data
2400  VRAMWrite.ColsRemaining = 0;
2401  VRAMWrite.RowsRemaining = 0;
2402 }
2403 
FinishedVRAMRead(void)2404 static __inline void FinishedVRAMRead(void)
2405 {
2406  // set register to NORMAL operation
2407  iDataReadMode = DR_NORMAL;
2408  // reset transfer values, to prevent mis-transfer of data
2409  VRAMRead.x = 0;
2410  VRAMRead.y = 0;
2411  VRAMRead.Width = 0;
2412  VRAMRead.Height = 0;
2413  VRAMRead.ColsRemaining = 0;
2414  VRAMRead.RowsRemaining = 0;
2415 
2416  // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
2417  STATUSREG&=~GPUSTATUS_READYFORVRAM;
2418 }
2419 
2420 ////////////////////////////////////////////////////////////////////////
2421 // vram read check ex (reading from card's back/frontbuffer if needed...
2422 // slow!)
2423 ////////////////////////////////////////////////////////////////////////
2424 
CheckVRamReadEx(int x,int y,int dx,int dy)2425 void CheckVRamReadEx(int x, int y, int dx, int dy)
2426 {
2427  unsigned short sArea;
2428  int ux,uy,udx,udy,wx,wy;
2429  unsigned short * p1, *p2;
2430  float XS,YS;
2431  unsigned char * ps;
2432  unsigned char * px;
2433  unsigned short s,sx;
2434 
2435  if(STATUSREG&GPUSTATUS_RGB24) return;
2436 
2437  if(((dx  > PSXDisplay.DisplayPosition.x) &&
2438      (x   < PSXDisplay.DisplayEnd.x) &&
2439      (dy  > PSXDisplay.DisplayPosition.y) &&
2440      (y   < PSXDisplay.DisplayEnd.y)))
2441   sArea=0;
2442  else
2443  if((!(PSXDisplay.InterlacedTest) &&
2444      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&
2445      (x   < PreviousPSXDisplay.DisplayEnd.x) &&
2446      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&
2447      (y   < PreviousPSXDisplay.DisplayEnd.y)))
2448   sArea=1;
2449  else
2450   {
2451    return;
2452   }
2453 
2454  //////////////
2455 
2456  if(iRenderFVR)
2457   {
2458    bFullVRam=TRUE;iRenderFVR=2;return;
2459   }
2460  bFullVRam=TRUE;iRenderFVR=2;
2461 
2462  //////////////
2463 
2464  p2=0;
2465 
2466  if(sArea==0)
2467   {
2468    ux=PSXDisplay.DisplayPosition.x;
2469    uy=PSXDisplay.DisplayPosition.y;
2470    udx=PSXDisplay.DisplayEnd.x-ux;
2471    udy=PSXDisplay.DisplayEnd.y-uy;
2472    if((PreviousPSXDisplay.DisplayEnd.x-
2473        PreviousPSXDisplay.DisplayPosition.x)==udx &&
2474       (PreviousPSXDisplay.DisplayEnd.y-
2475        PreviousPSXDisplay.DisplayPosition.y)==udy)
2476     p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) +
2477         PreviousPSXDisplay.DisplayPosition.x);
2478   }
2479  else
2480   {
2481    ux=PreviousPSXDisplay.DisplayPosition.x;
2482    uy=PreviousPSXDisplay.DisplayPosition.y;
2483    udx=PreviousPSXDisplay.DisplayEnd.x-ux;
2484    udy=PreviousPSXDisplay.DisplayEnd.y-uy;
2485    if((PSXDisplay.DisplayEnd.x-
2486        PSXDisplay.DisplayPosition.x)==udx &&
2487       (PSXDisplay.DisplayEnd.y-
2488        PSXDisplay.DisplayPosition.y)==udy)
2489     p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) +
2490         PSXDisplay.DisplayPosition.x);
2491   }
2492 
2493  p1=(psxVuw + (1024*uy) + ux);
2494  if(p1==p2) p2=0;
2495 
2496  x=0;y=0;
2497  wx=dx=udx;wy=dy=udy;
2498 
2499  if(udx<=0) return;
2500  if(udy<=0) return;
2501  if(dx<=0)  return;
2502  if(dy<=0)  return;
2503  if(wx<=0)  return;
2504  if(wy<=0)  return;
2505 
2506  XS=(float)rRatioRect.right/(float)wx;
2507  YS=(float)rRatioRect.bottom/(float)wy;
2508 
2509  dx=(int)((float)(dx)*XS);
2510  dy=(int)((float)(dy)*YS);
2511 
2512  if(dx>iResX) dx=iResX;
2513  if(dy>iResY) dy=iResY;
2514 
2515  if(dx<=0) return;
2516  if(dy<=0) return;
2517 
2518  // ogl y adjust
2519  y=iResY-y-dy;
2520 
2521  x+=rRatioRect.left;
2522  y-=rRatioRect.top;
2523 
2524  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
2525 
2526  if(!pGfxCardScreen)
2527   {
2528    glPixelStorei(GL_PACK_ALIGNMENT,1);
2529    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
2530   }
2531 
2532  ps=pGfxCardScreen;
2533 
2534  if(!sArea) glReadBuffer(GL_FRONT);
2535 
2536  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
2537 
2538  if(!sArea) glReadBuffer(GL_BACK);
2539 
2540  s=0;
2541 
2542  XS=(float)dx/(float)(udx);
2543  YS=(float)dy/(float)(udy+1);
2544 
2545  for(y=udy;y>0;y--)
2546   {
2547    for(x=0;x<udx;x++)
2548     {
2549      if(p1>=psxVuw && p1<psxVuw_eom)
2550       {
2551        px=ps+(3*((int)((float)x * XS))+
2552              (3*dx)*((int)((float)y*YS)));
2553        sx=(*px)>>3;px++;
2554        s=sx;
2555        sx=(*px)>>3;px++;
2556        s|=sx<<5;
2557        sx=(*px)>>3;
2558        s|=sx<<10;
2559        s&=~0x8000;
2560        *p1=s;
2561       }
2562      if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
2563 
2564      p1++;
2565      if(p2) p2++;
2566     }
2567 
2568    p1 += 1024 - udx;
2569    if(p2) p2 += 1024 - udx;
2570   }
2571 }
2572 
2573 ////////////////////////////////////////////////////////////////////////
2574 // vram read check (reading from card's back/frontbuffer if needed...
2575 // slow!)
2576 ////////////////////////////////////////////////////////////////////////
2577 
CheckVRamRead(int x,int y,int dx,int dy,BOOL bFront)2578 void CheckVRamRead(int x, int y, int dx, int dy,BOOL bFront)
2579 {
2580  unsigned short sArea;unsigned short * p;
2581  int ux,uy,udx,udy,wx,wy;float XS,YS;
2582  unsigned char * ps, * px;
2583  unsigned short s=0,sx;
2584 
2585  if(STATUSREG&GPUSTATUS_RGB24) return;
2586 
2587  if(((dx  > PSXDisplay.DisplayPosition.x) &&
2588      (x   < PSXDisplay.DisplayEnd.x) &&
2589      (dy  > PSXDisplay.DisplayPosition.y) &&
2590      (y   < PSXDisplay.DisplayEnd.y)))
2591   sArea=0;
2592  else
2593  if((!(PSXDisplay.InterlacedTest) &&
2594      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&
2595      (x   < PreviousPSXDisplay.DisplayEnd.x) &&
2596      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&
2597      (y   < PreviousPSXDisplay.DisplayEnd.y)))
2598   sArea=1;
2599  else
2600   {
2601    return;
2602   }
2603 
2604  if(dwActFixes&0x40)
2605   {
2606    if(iRenderFVR)
2607     {
2608      bFullVRam=TRUE;iRenderFVR=2;return;
2609     }
2610    bFullVRam=TRUE;iRenderFVR=2;
2611   }
2612 
2613  ux=x;uy=y;udx=dx;udy=dy;
2614 
2615  if(sArea==0)
2616   {
2617    x -=PSXDisplay.DisplayPosition.x;
2618    dx-=PSXDisplay.DisplayPosition.x;
2619    y -=PSXDisplay.DisplayPosition.y;
2620    dy-=PSXDisplay.DisplayPosition.y;
2621    wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;
2622    wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;
2623   }
2624  else
2625   {
2626    x -=PreviousPSXDisplay.DisplayPosition.x;
2627    dx-=PreviousPSXDisplay.DisplayPosition.x;
2628    y -=PreviousPSXDisplay.DisplayPosition.y;
2629    dy-=PreviousPSXDisplay.DisplayPosition.y;
2630    wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;
2631    wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;
2632   }
2633  if(x<0) {ux-=x;x=0;}
2634  if(y<0) {uy-=y;y=0;}
2635  if(dx>wx) {udx-=(dx-wx);dx=wx;}
2636  if(dy>wy) {udy-=(dy-wy);dy=wy;}
2637  udx-=ux;
2638  udy-=uy;
2639 
2640  p=(psxVuw + (1024*uy) + ux);
2641 
2642  if(udx<=0) return;
2643  if(udy<=0) return;
2644  if(dx<=0)  return;
2645  if(dy<=0)  return;
2646  if(wx<=0)  return;
2647  if(wy<=0)  return;
2648 
2649  XS=(float)rRatioRect.right/(float)wx;
2650  YS=(float)rRatioRect.bottom/(float)wy;
2651 
2652  dx=(int)((float)(dx)*XS);
2653  dy=(int)((float)(dy)*YS);
2654  x=(int)((float)x*XS);
2655  y=(int)((float)y*YS);
2656 
2657  dx-=x;
2658  dy-=y;
2659 
2660  if(dx>iResX) dx=iResX;
2661  if(dy>iResY) dy=iResY;
2662 
2663  if(dx<=0) return;
2664  if(dy<=0) return;
2665 
2666  // ogl y adjust
2667  y=iResY-y-dy;
2668 
2669  x+=rRatioRect.left;
2670  y-=rRatioRect.top;
2671 
2672  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
2673 
2674  if(!pGfxCardScreen)
2675   {
2676    glPixelStorei(GL_PACK_ALIGNMENT,1);
2677    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
2678   }
2679 
2680  ps=pGfxCardScreen;
2681 
2682  if(bFront) glReadBuffer(GL_FRONT);
2683 
2684  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
2685 
2686  if(bFront) glReadBuffer(GL_BACK);
2687 
2688  XS=(float)dx/(float)(udx);
2689  YS=(float)dy/(float)(udy+1);
2690 
2691  for(y=udy;y>0;y--)
2692   {
2693    for(x=0;x<udx;x++)
2694     {
2695      if(p>=psxVuw && p<psxVuw_eom)
2696       {
2697        px=ps+(3*((int)((float)x * XS))+
2698              (3*dx)*((int)((float)y*YS)));
2699        sx=(*px)>>3;px++;
2700        s=sx;
2701        sx=(*px)>>3;px++;
2702        s|=sx<<5;
2703        sx=(*px)>>3;
2704        s|=sx<<10;
2705        s&=~0x8000;
2706        *p=s;
2707       }
2708      p++;
2709     }
2710    p += 1024 - udx;
2711   }
2712 }
2713 
2714 ////////////////////////////////////////////////////////////////////////
2715 // core read from vram
2716 ////////////////////////////////////////////////////////////////////////
2717 
GPUreadDataMem(uint32_t * pMem,int iSize)2718 void CALLBACK GPUreadDataMem(uint32_t *pMem, int iSize)
2719 {
2720  int i;
2721 
2722  if(iDataReadMode!=DR_VRAMTRANSFER) return;
2723 
2724  GPUIsBusy;
2725 
2726  // adjust read ptr, if necessary
2727  while(VRAMRead.ImagePtr>=psxVuw_eom)
2728   VRAMRead.ImagePtr-=iGPUHeight*1024;
2729  while(VRAMRead.ImagePtr<psxVuw)
2730   VRAMRead.ImagePtr+=iGPUHeight*1024;
2731 
2732  if((iFrameReadType&1 && iSize>1) &&
2733     !(iDrawnSomething==2 &&
2734       VRAMRead.x      == VRAMWrite.x     &&
2735       VRAMRead.y      == VRAMWrite.y     &&
2736       VRAMRead.Width  == VRAMWrite.Width &&
2737       VRAMRead.Height == VRAMWrite.Height))
2738   CheckVRamRead(VRAMRead.x,VRAMRead.y,
2739                 VRAMRead.x+VRAMRead.RowsRemaining,
2740                 VRAMRead.y+VRAMRead.ColsRemaining,
2741                 TRUE);
2742 
2743  for(i=0;i<iSize;i++)
2744   {
2745    // do 2 seperate 16bit reads for compatibility (wrap issues)
2746    if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
2747     {
2748      // lower 16 bit
2749      GPUdataRet=(uint32_t)*VRAMRead.ImagePtr;
2750 
2751      VRAMRead.ImagePtr++;
2752      if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
2753      VRAMRead.RowsRemaining --;
2754 
2755      if(VRAMRead.RowsRemaining<=0)
2756       {
2757        VRAMRead.RowsRemaining = VRAMRead.Width;
2758        VRAMRead.ColsRemaining--;
2759        VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
2760        if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
2761       }
2762 
2763      // higher 16 bit (always, even if it's an odd width)
2764      GPUdataRet|=(uint32_t)(*VRAMRead.ImagePtr)<<16;
2765      *pMem++=GPUdataRet;
2766 
2767      if(VRAMRead.ColsRemaining <= 0)
2768       {FinishedVRAMRead();goto ENDREAD;}
2769 
2770      VRAMRead.ImagePtr++;
2771      if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
2772      VRAMRead.RowsRemaining--;
2773      if(VRAMRead.RowsRemaining<=0)
2774       {
2775        VRAMRead.RowsRemaining = VRAMRead.Width;
2776        VRAMRead.ColsRemaining--;
2777        VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
2778        if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
2779       }
2780      if(VRAMRead.ColsRemaining <= 0)
2781       {FinishedVRAMRead();goto ENDREAD;}
2782     }
2783    else {FinishedVRAMRead();goto ENDREAD;}
2784   }
2785 
2786 ENDREAD:
2787  GPUIsIdle;
2788 }
2789 
GPUreadData(void)2790 uint32_t CALLBACK GPUreadData(void)
2791 {
2792  uint32_t l;
2793  GPUreadDataMem(&l,1);
2794  return GPUdataRet;
2795 }
2796 
2797 ////////////////////////////////////////////////////////////////////////
2798 // helper table to know how much data is used by drawing commands
2799 ////////////////////////////////////////////////////////////////////////
2800 
2801 const unsigned char primTableCX[256] =
2802 {
2803     // 00
2804     0,0,3,0,0,0,0,0,
2805     // 08
2806     0,0,0,0,0,0,0,0,
2807     // 10
2808     0,0,0,0,0,0,0,0,
2809     // 18
2810     0,0,0,0,0,0,0,0,
2811     // 20
2812     4,4,4,4,7,7,7,7,
2813     // 28
2814     5,5,5,5,9,9,9,9,
2815     // 30
2816     6,6,6,6,9,9,9,9,
2817     // 38
2818     8,8,8,8,12,12,12,12,
2819     // 40
2820     3,3,3,3,0,0,0,0,
2821     // 48
2822 //    5,5,5,5,6,6,6,6,      //FLINE
2823     254,254,254,254,254,254,254,254,
2824     // 50
2825     4,4,4,4,0,0,0,0,
2826     // 58
2827 //    7,7,7,7,9,9,9,9,    //    LINEG3    LINEG4
2828     255,255,255,255,255,255,255,255,
2829     // 60
2830     3,3,3,3,4,4,4,4,    //    TILE    SPRT
2831     // 68
2832     2,2,2,2,3,3,3,3,    //    TILE1
2833     // 70
2834     2,2,2,2,3,3,3,3,
2835     // 78
2836     2,2,2,2,3,3,3,3,
2837     // 80
2838     4,0,0,0,0,0,0,0,
2839     // 88
2840     0,0,0,0,0,0,0,0,
2841     // 90
2842     0,0,0,0,0,0,0,0,
2843     // 98
2844     0,0,0,0,0,0,0,0,
2845     // a0
2846     3,0,0,0,0,0,0,0,
2847     // a8
2848     0,0,0,0,0,0,0,0,
2849     // b0
2850     0,0,0,0,0,0,0,0,
2851     // b8
2852     0,0,0,0,0,0,0,0,
2853     // c0
2854     3,0,0,0,0,0,0,0,
2855     // c8
2856     0,0,0,0,0,0,0,0,
2857     // d0
2858     0,0,0,0,0,0,0,0,
2859     // d8
2860     0,0,0,0,0,0,0,0,
2861     // e0
2862     0,1,1,1,1,1,1,0,
2863     // e8
2864     0,0,0,0,0,0,0,0,
2865     // f0
2866     0,0,0,0,0,0,0,0,
2867     // f8
2868     0,0,0,0,0,0,0,0
2869 };
2870 
2871 ////////////////////////////////////////////////////////////////////////
2872 // processes data send to GPU data register
2873 ////////////////////////////////////////////////////////////////////////
2874 
GPUwriteDataMem(uint32_t * pMem,int iSize)2875 void CALLBACK GPUwriteDataMem(uint32_t *pMem, int iSize)
2876 {
2877  unsigned char command;
2878  uint32_t gdata=0;
2879  int i=0;
2880  GPUIsBusy;
2881  GPUIsNotReadyForCommands;
2882 
2883 STARTVRAM:
2884 
2885  if(iDataWriteMode==DR_VRAMTRANSFER)
2886   {
2887    // make sure we are in vram
2888    while(VRAMWrite.ImagePtr>=psxVuw_eom)
2889     VRAMWrite.ImagePtr-=iGPUHeight*1024;
2890    while(VRAMWrite.ImagePtr<psxVuw)
2891     VRAMWrite.ImagePtr+=iGPUHeight*1024;
2892 
2893    // now do the loop
2894    while(VRAMWrite.ColsRemaining>0)
2895     {
2896      while(VRAMWrite.RowsRemaining>0)
2897       {
2898        if(i>=iSize) {goto ENDVRAM;}
2899        i++;
2900 
2901        gdata=*pMem++;
2902 
2903        // Write odd pixel - Wrap from beginning to next index if going past GPU width
2904        if(VRAMWrite.Width+VRAMWrite.x-VRAMWrite.RowsRemaining >= 1024) {
2905          *((VRAMWrite.ImagePtr++)-1024) = (unsigned short)gdata;
2906        } else { *VRAMWrite.ImagePtr++ = (unsigned short)gdata;}
2907        if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;// Check if went past framebuffer
2908        VRAMWrite.RowsRemaining --;
2909 
2910        // Check if end at odd pixel drawn
2911        if(VRAMWrite.RowsRemaining <= 0)
2912         {
2913          VRAMWrite.ColsRemaining--;
2914          if (VRAMWrite.ColsRemaining <= 0)             // last pixel is odd width
2915           {
2916            gdata=(gdata&0xFFFF)|(((uint32_t)(*VRAMWrite.ImagePtr))<<16);
2917            FinishedVRAMWrite();
2918            goto ENDVRAM;
2919           }
2920          VRAMWrite.RowsRemaining = VRAMWrite.Width;
2921          VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
2922         }
2923 
2924        // Write even pixel - Wrap from beginning to next index if going past GPU width
2925        if(VRAMWrite.Width+VRAMWrite.x-VRAMWrite.RowsRemaining >= 1024) {
2926          *((VRAMWrite.ImagePtr++)-1024) = (unsigned short)(gdata>>16);
2927        } else *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
2928        if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;// Check if went past framebuffer
2929        VRAMWrite.RowsRemaining --;
2930       }
2931 
2932      VRAMWrite.RowsRemaining = VRAMWrite.Width;
2933      VRAMWrite.ColsRemaining--;
2934      VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
2935     }
2936 
2937    FinishedVRAMWrite();
2938   }
2939 
2940 ENDVRAM:
2941 
2942  if(iDataWriteMode==DR_NORMAL)
2943   {
2944    void (* *primFunc)(unsigned char *);
2945    if(bSkipNextFrame) primFunc=primTableSkip;
2946    else               primFunc=primTableJ;
2947 
2948    for(;i<iSize;)
2949     {
2950      if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
2951 
2952      gdata=*pMem++;i++;
2953 
2954      if(gpuDataC == 0)
2955       {
2956        command = (unsigned char)((gdata>>24) & 0xff);
2957 
2958        if(primTableCX[command])
2959         {
2960          gpuDataC = primTableCX[command];
2961          gpuCommand = command;
2962          gpuDataM[0] = gdata;
2963          gpuDataP = 1;
2964         }
2965        else continue;
2966       }
2967      else
2968       {
2969        gpuDataM[gpuDataP] = gdata;
2970        if(gpuDataC>128)
2971         {
2972          if((gpuDataC==254 && gpuDataP>=3) ||
2973             (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
2974           {
2975            if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
2976             gpuDataP=gpuDataC-1;
2977           }
2978         }
2979        gpuDataP++;
2980       }
2981 
2982      if(gpuDataP == gpuDataC)
2983       {
2984        gpuDataC=gpuDataP=0;
2985        primFunc[gpuCommand]((unsigned char *)gpuDataM);
2986 
2987        if(dwEmuFixes&0x0001 || dwActFixes&0x20000)     // hack for emulating "gpu busy" in some games
2988         iFakePrimBusy=4;
2989       }
2990     }
2991   }
2992 
2993  GPUdataRet=gdata;
2994 
2995  GPUIsReadyForCommands;
2996  GPUIsIdle;
2997 }
2998 
2999 ////////////////////////////////////////////////////////////////////////
3000 
GPUwriteData(uint32_t gdata)3001 void CALLBACK GPUwriteData(uint32_t gdata)
3002 {
3003  GPUwriteDataMem(&gdata,1);
3004 }
3005 
3006 ////////////////////////////////////////////////////////////////////////
3007 // call config dlg
3008 ////////////////////////////////////////////////////////////////////////
3009 
3010 #ifdef _WINDOWS
3011 
GPUconfigure(void)3012 long CALLBACK GPUconfigure(void)
3013 {
3014  HWND hWP=GetActiveWindow();
3015  DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),
3016            hWP,(DLGPROC)CfgDlgProc);
3017 
3018  return 0;
3019 }
3020 
3021 #elif defined(_MACGL)
GPUconfigure(void)3022 long CALLBACK GPUconfigure(void)
3023 {
3024 	DlgProc();
3025 	return 0;
3026 }
3027 #else
3028 
StartCfgTool(char * arg)3029 void StartCfgTool(char *arg) // linux: start external cfg tool
3030 {
3031 	char cfg[256];
3032 	struct stat buf;
3033 
3034 	strcpy(cfg, "./cfgpeopsxgl");
3035 	if (stat(cfg, &buf) != -1) {
3036 		int pid = fork();
3037 		if (pid == 0) {
3038 			if (fork() == 0) {
3039 				execl(cfg, "cfgpeopsxgl", arg, NULL);
3040 			}
3041 			exit(0);
3042 		} else {
3043 			waitpid(pid, NULL, 0);
3044 		}
3045 		return;
3046 	}
3047 
3048 	strcpy(cfg, "./cfg/cfgpeopsxgl");
3049 	if (stat(cfg, &buf) != -1) {
3050 		int pid = fork();
3051 		if (pid == 0) {
3052 			if (fork() == 0) {
3053 				execl(cfg, "cfgpeopsxgl", arg, NULL);
3054 			}
3055 			exit(0);
3056 		} else {
3057 			waitpid(pid, NULL, 0);
3058 		}
3059 		return;
3060 	}
3061 
3062 	sprintf(cfg, "%s/.pcsxr/plugins/cfg/cfgpeopsxgl", getenv("HOME"));
3063 	if (stat(cfg, &buf) != -1) {
3064 		int pid = fork();
3065 		if (pid == 0) {
3066 			if (fork() == 0) {
3067 				execl(cfg, "cfgpeopsxgl", arg, NULL);
3068 			}
3069 			exit(0);
3070 		} else {
3071 			waitpid(pid, NULL, 0);
3072 		}
3073 		return;
3074 	}
3075 
3076 	printf("ERROR: cfgpeopsxgl file not found!\n");
3077 }
3078 
GPUconfigure(void)3079 long CALLBACK GPUconfigure(void)
3080 {
3081  StartCfgTool("configure");
3082  return 0;
3083 }
3084 
3085 #endif // def _WINDOWS / _MACGL
3086 
3087 ////////////////////////////////////////////////////////////////////////
3088 // sets all kind of act fixes
3089 ////////////////////////////////////////////////////////////////////////
3090 
SetFixes(void)3091 void SetFixes(void)
3092 {
3093  ReInitFrameCap();
3094 
3095  if(dwActFixes & 0x2000)
3096       dispWidths[4]=384;
3097  else dispWidths[4]=368;
3098 }
3099 
3100 ////////////////////////////////////////////////////////////////////////
3101 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
3102 ////////////////////////////////////////////////////////////////////////
3103 
3104 uint32_t lUsedAddr[3];
3105 
CheckForEndlessLoop(uint32_t laddr)3106 static __inline BOOL CheckForEndlessLoop(uint32_t laddr)
3107 {
3108  if(laddr==lUsedAddr[1]) return TRUE;
3109  if(laddr==lUsedAddr[2]) return TRUE;
3110 
3111  if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
3112  else                   lUsedAddr[2]=laddr;
3113  lUsedAddr[0]=laddr;
3114  return FALSE;
3115 }
3116 
3117 ////////////////////////////////////////////////////////////////////////
3118 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
3119 ////////////////////////////////////////////////////////////////////////
3120 
GPUdmaChain(uint32_t * baseAddrL,uint32_t addr)3121 long CALLBACK GPUdmaChain(uint32_t *baseAddrL, uint32_t addr)
3122 {
3123  uint32_t dmaMem;
3124  unsigned char * baseAddrB;
3125  short count;unsigned int DMACommandCounter = 0;
3126 
3127  if(bIsFirstFrame) GLinitialize();
3128 
3129  GPUIsBusy;
3130 
3131  lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
3132 
3133  baseAddrB = (unsigned char*) baseAddrL;
3134 
3135  do
3136   {
3137    if(iGPUHeight==512) addr&=0x1FFFFC;
3138 
3139    if(DMACommandCounter++ > 2000000) break;
3140    if(CheckForEndlessLoop(addr)) break;
3141 
3142    count = baseAddrB[addr+3];
3143 
3144    dmaMem=addr+4;
3145 
3146    if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
3147 
3148    addr = baseAddrL[addr>>2]&0xffffff;
3149   }
3150  while (addr != 0xffffff);
3151 
3152  GPUIsIdle;
3153 
3154  return 0;
3155 }
3156 
3157 ////////////////////////////////////////////////////////////////////////
3158 // show about dlg
3159 ////////////////////////////////////////////////////////////////////////
3160 
GPUabout(void)3161 void CALLBACK GPUabout(void)
3162 {
3163 #ifdef _WINDOWS
3164 	HWND hWP=GetActiveWindow();                           // to be sure
3165 	DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWP,(DLGPROC)AboutDlgProc);
3166 #elif defined(_MACGL)
3167  AboutDlgProc();
3168 #else
3169 	StartCfgTool("about");
3170 #endif
3171 }
3172 
3173 ////////////////////////////////////////////////////////////////////////
3174 // We are ever fine ;)
3175 ////////////////////////////////////////////////////////////////////////
3176 
GPUtest(void)3177 long CALLBACK GPUtest(void)
3178 {
3179  // if test fails this function should return negative value for error (unable to continue)
3180  // and positive value for warning (can continue but output might be crappy)
3181 
3182  return 0;
3183 }
3184 
3185 ////////////////////////////////////////////////////////////////////////
3186 // save state funcs
3187 ////////////////////////////////////////////////////////////////////////
3188 
3189 typedef struct GPUFREEZETAG
3190 {
3191  uint32_t ulFreezeVersion;      // should be always 1 for now (set by main emu)
3192  uint32_t ulStatus;             // current gpu status
3193  uint32_t ulControl[256];       // latest control register values
3194  unsigned char psxVRam[1024*1024*2]; // current VRam image (full 2 MB for ZN)
3195 } GPUFreeze_t;
3196 
3197 ////////////////////////////////////////////////////////////////////////
3198 
GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF)3199 long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF)
3200 {
3201  if(ulGetFreezeData==2)
3202   {
3203    int lSlotNum=*((int *)pF);
3204    if(lSlotNum<0) return 0;
3205    if(lSlotNum>8) return 0;
3206    lSelectedSlot=lSlotNum+1;
3207    return 1;
3208   }
3209 
3210  if(!pF)                    return 0;
3211  if(pF->ulFreezeVersion!=1) return 0;
3212 
3213  if(ulGetFreezeData==1)
3214   {
3215    pF->ulStatus=STATUSREG;
3216    memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t));
3217    memcpy(pF->psxVRam,  psxVub,         1024*iGPUHeight*2);
3218 
3219    return 1;
3220   }
3221 
3222  if(ulGetFreezeData!=0) return 0;
3223 
3224  STATUSREG=pF->ulStatus;
3225  memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t));
3226  memcpy(psxVub,         pF->psxVRam,  1024*iGPUHeight*2);
3227 
3228  ResetTextureArea(TRUE);
3229 
3230  GPUwriteStatus(ulStatusControl[0]);
3231  GPUwriteStatus(ulStatusControl[1]);
3232  GPUwriteStatus(ulStatusControl[2]);
3233  GPUwriteStatus(ulStatusControl[3]);
3234  GPUwriteStatus(ulStatusControl[8]);
3235  GPUwriteStatus(ulStatusControl[6]);
3236  GPUwriteStatus(ulStatusControl[7]);
3237  GPUwriteStatus(ulStatusControl[5]);
3238  GPUwriteStatus(ulStatusControl[4]);
3239 
3240  return 1;
3241 }
3242 
3243 ////////////////////////////////////////////////////////////////////////
3244 // special "emu infos" / "emu effects" functions
3245 ////////////////////////////////////////////////////////////////////////
3246 
3247 //00 = black
3248 //01 = white
3249 //10 = red
3250 //11 = transparent
3251 
3252 unsigned char cFont[10][120]=
3253 {
3254 // 0
3255 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3256  0x80,0x00,0x00,0x00,0x00,0x00,
3257  0x80,0x00,0x00,0x00,0x00,0x00,
3258  0x80,0x00,0x00,0x00,0x00,0x00,
3259  0x80,0x00,0x00,0x00,0x00,0x00,
3260  0x80,0x00,0x05,0x54,0x00,0x00,
3261  0x80,0x00,0x14,0x05,0x00,0x00,
3262  0x80,0x00,0x14,0x05,0x00,0x00,
3263  0x80,0x00,0x14,0x05,0x00,0x00,
3264  0x80,0x00,0x14,0x05,0x00,0x00,
3265  0x80,0x00,0x14,0x05,0x00,0x00,
3266  0x80,0x00,0x14,0x05,0x00,0x00,
3267  0x80,0x00,0x14,0x05,0x00,0x00,
3268  0x80,0x00,0x14,0x05,0x00,0x00,
3269  0x80,0x00,0x05,0x54,0x00,0x00,
3270  0x80,0x00,0x00,0x00,0x00,0x00,
3271  0x80,0x00,0x00,0x00,0x00,0x00,
3272  0x80,0x00,0x00,0x00,0x00,0x00,
3273  0x80,0x00,0x00,0x00,0x00,0x00,
3274  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3275 },
3276 // 1
3277 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3278  0x80,0x00,0x00,0x00,0x00,0x00,
3279  0x80,0x00,0x00,0x00,0x00,0x00,
3280  0x80,0x00,0x00,0x00,0x00,0x00,
3281  0x80,0x00,0x00,0x00,0x00,0x00,
3282  0x80,0x00,0x00,0x50,0x00,0x00,
3283  0x80,0x00,0x05,0x50,0x00,0x00,
3284  0x80,0x00,0x00,0x50,0x00,0x00,
3285  0x80,0x00,0x00,0x50,0x00,0x00,
3286  0x80,0x00,0x00,0x50,0x00,0x00,
3287  0x80,0x00,0x00,0x50,0x00,0x00,
3288  0x80,0x00,0x00,0x50,0x00,0x00,
3289  0x80,0x00,0x00,0x50,0x00,0x00,
3290  0x80,0x00,0x00,0x50,0x00,0x00,
3291  0x80,0x00,0x05,0x55,0x00,0x00,
3292  0x80,0x00,0x00,0x00,0x00,0x00,
3293  0x80,0x00,0x00,0x00,0x00,0x00,
3294  0x80,0x00,0x00,0x00,0x00,0x00,
3295  0x80,0x00,0x00,0x00,0x00,0x00,
3296  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3297 },
3298 // 2
3299 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3300  0x80,0x00,0x00,0x00,0x00,0x00,
3301  0x80,0x00,0x00,0x00,0x00,0x00,
3302  0x80,0x00,0x00,0x00,0x00,0x00,
3303  0x80,0x00,0x00,0x00,0x00,0x00,
3304  0x80,0x00,0x05,0x54,0x00,0x00,
3305  0x80,0x00,0x14,0x05,0x00,0x00,
3306  0x80,0x00,0x00,0x05,0x00,0x00,
3307  0x80,0x00,0x00,0x05,0x00,0x00,
3308  0x80,0x00,0x00,0x14,0x00,0x00,
3309  0x80,0x00,0x00,0x50,0x00,0x00,
3310  0x80,0x00,0x01,0x40,0x00,0x00,
3311  0x80,0x00,0x05,0x00,0x00,0x00,
3312  0x80,0x00,0x14,0x00,0x00,0x00,
3313  0x80,0x00,0x15,0x55,0x00,0x00,
3314  0x80,0x00,0x00,0x00,0x00,0x00,
3315  0x80,0x00,0x00,0x00,0x00,0x00,
3316  0x80,0x00,0x00,0x00,0x00,0x00,
3317  0x80,0x00,0x00,0x00,0x00,0x00,
3318  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3319 },
3320 // 3
3321 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3322  0x80,0x00,0x00,0x00,0x00,0x00,
3323  0x80,0x00,0x00,0x00,0x00,0x00,
3324  0x80,0x00,0x00,0x00,0x00,0x00,
3325  0x80,0x00,0x00,0x00,0x00,0x00,
3326  0x80,0x00,0x05,0x54,0x00,0x00,
3327  0x80,0x00,0x14,0x05,0x00,0x00,
3328  0x80,0x00,0x00,0x05,0x00,0x00,
3329  0x80,0x00,0x00,0x05,0x00,0x00,
3330  0x80,0x00,0x01,0x54,0x00,0x00,
3331  0x80,0x00,0x00,0x05,0x00,0x00,
3332  0x80,0x00,0x00,0x05,0x00,0x00,
3333  0x80,0x00,0x00,0x05,0x00,0x00,
3334  0x80,0x00,0x14,0x05,0x00,0x00,
3335  0x80,0x00,0x05,0x54,0x00,0x00,
3336  0x80,0x00,0x00,0x00,0x00,0x00,
3337  0x80,0x00,0x00,0x00,0x00,0x00,
3338  0x80,0x00,0x00,0x00,0x00,0x00,
3339  0x80,0x00,0x00,0x00,0x00,0x00,
3340  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3341 },
3342 // 4
3343 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3344  0x80,0x00,0x00,0x00,0x00,0x00,
3345  0x80,0x00,0x00,0x00,0x00,0x00,
3346  0x80,0x00,0x00,0x00,0x00,0x00,
3347  0x80,0x00,0x00,0x00,0x00,0x00,
3348  0x80,0x00,0x00,0x14,0x00,0x00,
3349  0x80,0x00,0x00,0x54,0x00,0x00,
3350  0x80,0x00,0x01,0x54,0x00,0x00,
3351  0x80,0x00,0x01,0x54,0x00,0x00,
3352  0x80,0x00,0x05,0x14,0x00,0x00,
3353  0x80,0x00,0x14,0x14,0x00,0x00,
3354  0x80,0x00,0x15,0x55,0x00,0x00,
3355  0x80,0x00,0x00,0x14,0x00,0x00,
3356  0x80,0x00,0x00,0x14,0x00,0x00,
3357  0x80,0x00,0x00,0x55,0x00,0x00,
3358  0x80,0x00,0x00,0x00,0x00,0x00,
3359  0x80,0x00,0x00,0x00,0x00,0x00,
3360  0x80,0x00,0x00,0x00,0x00,0x00,
3361  0x80,0x00,0x00,0x00,0x00,0x00,
3362  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3363 },
3364 // 5
3365 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3366  0x80,0x00,0x00,0x00,0x00,0x00,
3367  0x80,0x00,0x00,0x00,0x00,0x00,
3368  0x80,0x00,0x00,0x00,0x00,0x00,
3369  0x80,0x00,0x00,0x00,0x00,0x00,
3370  0x80,0x00,0x15,0x55,0x00,0x00,
3371  0x80,0x00,0x14,0x00,0x00,0x00,
3372  0x80,0x00,0x14,0x00,0x00,0x00,
3373  0x80,0x00,0x14,0x00,0x00,0x00,
3374  0x80,0x00,0x15,0x54,0x00,0x00,
3375  0x80,0x00,0x00,0x05,0x00,0x00,
3376  0x80,0x00,0x00,0x05,0x00,0x00,
3377  0x80,0x00,0x00,0x05,0x00,0x00,
3378  0x80,0x00,0x14,0x05,0x00,0x00,
3379  0x80,0x00,0x05,0x54,0x00,0x00,
3380  0x80,0x00,0x00,0x00,0x00,0x00,
3381  0x80,0x00,0x00,0x00,0x00,0x00,
3382  0x80,0x00,0x00,0x00,0x00,0x00,
3383  0x80,0x00,0x00,0x00,0x00,0x00,
3384  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3385 },
3386 // 6
3387 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3388  0x80,0x00,0x00,0x00,0x00,0x00,
3389  0x80,0x00,0x00,0x00,0x00,0x00,
3390  0x80,0x00,0x00,0x00,0x00,0x00,
3391  0x80,0x00,0x00,0x00,0x00,0x00,
3392  0x80,0x00,0x01,0x54,0x00,0x00,
3393  0x80,0x00,0x05,0x00,0x00,0x00,
3394  0x80,0x00,0x14,0x00,0x00,0x00,
3395  0x80,0x00,0x14,0x00,0x00,0x00,
3396  0x80,0x00,0x15,0x54,0x00,0x00,
3397  0x80,0x00,0x15,0x05,0x00,0x00,
3398  0x80,0x00,0x14,0x05,0x00,0x00,
3399  0x80,0x00,0x14,0x05,0x00,0x00,
3400  0x80,0x00,0x14,0x05,0x00,0x00,
3401  0x80,0x00,0x05,0x54,0x00,0x00,
3402  0x80,0x00,0x00,0x00,0x00,0x00,
3403  0x80,0x00,0x00,0x00,0x00,0x00,
3404  0x80,0x00,0x00,0x00,0x00,0x00,
3405  0x80,0x00,0x00,0x00,0x00,0x00,
3406  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3407 },
3408 // 7
3409 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3410  0x80,0x00,0x00,0x00,0x00,0x00,
3411  0x80,0x00,0x00,0x00,0x00,0x00,
3412  0x80,0x00,0x00,0x00,0x00,0x00,
3413  0x80,0x00,0x00,0x00,0x00,0x00,
3414  0x80,0x00,0x15,0x55,0x00,0x00,
3415  0x80,0x00,0x14,0x05,0x00,0x00,
3416  0x80,0x00,0x00,0x14,0x00,0x00,
3417  0x80,0x00,0x00,0x14,0x00,0x00,
3418  0x80,0x00,0x00,0x50,0x00,0x00,
3419  0x80,0x00,0x00,0x50,0x00,0x00,
3420  0x80,0x00,0x01,0x40,0x00,0x00,
3421  0x80,0x00,0x01,0x40,0x00,0x00,
3422  0x80,0x00,0x05,0x00,0x00,0x00,
3423  0x80,0x00,0x05,0x00,0x00,0x00,
3424  0x80,0x00,0x00,0x00,0x00,0x00,
3425  0x80,0x00,0x00,0x00,0x00,0x00,
3426  0x80,0x00,0x00,0x00,0x00,0x00,
3427  0x80,0x00,0x00,0x00,0x00,0x00,
3428  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3429 },
3430 // 8
3431 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3432  0x80,0x00,0x00,0x00,0x00,0x00,
3433  0x80,0x00,0x00,0x00,0x00,0x00,
3434  0x80,0x00,0x00,0x00,0x00,0x00,
3435  0x80,0x00,0x00,0x00,0x00,0x00,
3436  0x80,0x00,0x05,0x54,0x00,0x00,
3437  0x80,0x00,0x14,0x05,0x00,0x00,
3438  0x80,0x00,0x14,0x05,0x00,0x00,
3439  0x80,0x00,0x14,0x05,0x00,0x00,
3440  0x80,0x00,0x05,0x54,0x00,0x00,
3441  0x80,0x00,0x14,0x05,0x00,0x00,
3442  0x80,0x00,0x14,0x05,0x00,0x00,
3443  0x80,0x00,0x14,0x05,0x00,0x00,
3444  0x80,0x00,0x14,0x05,0x00,0x00,
3445  0x80,0x00,0x05,0x54,0x00,0x00,
3446  0x80,0x00,0x00,0x00,0x00,0x00,
3447  0x80,0x00,0x00,0x00,0x00,0x00,
3448  0x80,0x00,0x00,0x00,0x00,0x00,
3449  0x80,0x00,0x00,0x00,0x00,0x00,
3450  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3451 },
3452 // 9
3453 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
3454  0x80,0x00,0x00,0x00,0x00,0x00,
3455  0x80,0x00,0x00,0x00,0x00,0x00,
3456  0x80,0x00,0x00,0x00,0x00,0x00,
3457  0x80,0x00,0x00,0x00,0x00,0x00,
3458  0x80,0x00,0x05,0x54,0x00,0x00,
3459  0x80,0x00,0x14,0x05,0x00,0x00,
3460  0x80,0x00,0x14,0x05,0x00,0x00,
3461  0x80,0x00,0x14,0x05,0x00,0x00,
3462  0x80,0x00,0x14,0x15,0x00,0x00,
3463  0x80,0x00,0x05,0x55,0x00,0x00,
3464  0x80,0x00,0x00,0x05,0x00,0x00,
3465  0x80,0x00,0x00,0x05,0x00,0x00,
3466  0x80,0x00,0x00,0x14,0x00,0x00,
3467  0x80,0x00,0x05,0x50,0x00,0x00,
3468  0x80,0x00,0x00,0x00,0x00,0x00,
3469  0x80,0x00,0x00,0x00,0x00,0x00,
3470  0x80,0x00,0x00,0x00,0x00,0x00,
3471  0x80,0x00,0x00,0x00,0x00,0x00,
3472  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
3473 }
3474 };
3475 
3476 ////////////////////////////////////////////////////////////////////////
3477 
PaintPicDot(unsigned char * p,unsigned char c)3478 void PaintPicDot(unsigned char * p,unsigned char c)
3479 {
3480  if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}
3481  if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}
3482  if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}
3483 }
3484 
3485 ////////////////////////////////////////////////////////////////////////
3486 
GPUgetScreenPic(unsigned char * pMem)3487 void CALLBACK GPUgetScreenPic(unsigned char * pMem)
3488 {
3489  float XS,YS;int x,y,v;
3490  unsigned char * ps, * px, * pf;
3491  unsigned char c;
3492 
3493  if(!pGfxCardScreen)
3494   {
3495    glPixelStorei(GL_PACK_ALIGNMENT,1);
3496    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
3497   }
3498 
3499  ps=pGfxCardScreen;
3500 
3501  glReadBuffer(GL_FRONT);
3502 
3503  glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
3504 
3505  glReadBuffer(GL_BACK);
3506 
3507  XS=(float)iResX/128;
3508  YS=(float)iResY/96;
3509  pf=pMem;
3510 
3511  for(y=96;y>0;y--)
3512   {
3513    for(x=0;x<128;x++)
3514     {
3515      px=ps+(3*((int)((float)x * XS))+
3516            (3*iResX)*((int)((float)y*YS)));
3517      *(pf+0)=*(px+2);
3518      *(pf+1)=*(px+1);
3519      *(pf+2)=*(px+0);
3520      pf+=3;
3521     }
3522   }
3523 
3524  /////////////////////////////////////////////////////////////////////
3525  // generic number/border painter
3526 
3527  pf=pMem+(103*3);
3528 
3529  for(y=0;y<20;y++)
3530   {
3531    for(x=0;x<6;x++)
3532     {
3533      c=cFont[lSelectedSlot][x+y*6];
3534      v=(c&0xc0)>>6;
3535      PaintPicDot(pf,(unsigned char)v);pf+=3;                // paint the dots into the rect
3536      v=(c&0x30)>>4;
3537      PaintPicDot(pf,(unsigned char)v);pf+=3;
3538      v=(c&0x0c)>>2;
3539      PaintPicDot(pf,(unsigned char)v);pf+=3;
3540      v=c&0x03;
3541      PaintPicDot(pf,(unsigned char)v);pf+=3;
3542     }
3543    pf+=104*3;
3544   }
3545 
3546  pf=pMem;
3547  for(x=0;x<128;x++)
3548   {
3549    *(pf+(95*128*3))=0x00;*pf++=0x00;
3550    *(pf+(95*128*3))=0x00;*pf++=0x00;
3551    *(pf+(95*128*3))=0xff;*pf++=0xff;
3552   }
3553  pf=pMem;
3554  for(y=0;y<96;y++)
3555   {
3556    *(pf+(127*3))=0x00;*pf++=0x00;
3557    *(pf+(127*3))=0x00;*pf++=0x00;
3558    *(pf+(127*3))=0xff;*pf++=0xff;
3559    pf+=127*3;
3560   }
3561 
3562 }
3563 
3564 ////////////////////////////////////////////////////////////////////////
3565 
GPUshowScreenPic(unsigned char * pMem)3566 void CALLBACK GPUshowScreenPic(unsigned char * pMem)
3567 {
3568  DestroyPic();
3569  if(pMem==0) return;
3570  CreatePic(pMem);
3571 }
3572 
3573 ////////////////////////////////////////////////////////////////////////
3574 
GPUsetfix(uint32_t dwFixBits)3575 void CALLBACK GPUsetfix(uint32_t dwFixBits)
3576 {
3577  dwEmuFixes=dwFixBits;
3578 }
3579 
3580 ////////////////////////////////////////////////////////////////////////
3581 
GPUvisualVibration(uint32_t iSmall,uint32_t iBig)3582 void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig)
3583 {
3584  int iVibVal;
3585 
3586  if(PSXDisplay.DisplayModeNew.x)                       // calc min "shake pixel" from screen width
3587       iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
3588  else iVibVal=1;
3589                                                        // big rumble: 4...15 sp ; small rumble 1...3 sp
3590  if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig  *iVibVal)/10));
3591  else     iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));
3592 
3593  srand(timeGetTime());                                 // init rand (will be used in BufferSwap)
3594 
3595  iRumbleTime=15;                                       // let the rumble last 16 buffer swaps
3596 }
3597 
3598 ////////////////////////////////////////////////////////////////////////
3599 // main emu can set display infos (A/M/G/D)
3600 ////////////////////////////////////////////////////////////////////////
3601 
GPUdisplayFlags(uint32_t dwFlags)3602 void CALLBACK GPUdisplayFlags(uint32_t dwFlags)
3603 {
3604  dwCoreFlags=dwFlags;
3605 }
3606 
GPUvBlank(int val)3607 void CALLBACK GPUvBlank( int val )
3608 {
3609  vBlank = val;
3610  oddLines = oddLines ? FALSE : TRUE; // bit changes per frame when not interlaced
3611  //printf("VB %x (%x)\n", oddLines, vBlank);
3612 }
3613 
GPUhSync(int val)3614 void CALLBACK GPUhSync( int val ) {
3615  // Interlaced mode - update bit every scanline
3616  if (PSXDisplay.Interlaced) {
3617    oddLines = (val%2 ? FALSE : TRUE);
3618  }
3619  //printf("HS %x (%x)\n", oddLines, vBlank);
3620 }
3621