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