gpu-gles from psx4m
[pcsx_rearmed.git] / plugins / gpu-gles / gpuPlugin.c
... / ...
CommitLineData
1/***************************************************************************\r
2 gpu.c - description\r
3 -------------------\r
4 begin : Sun Mar 08 2009\r
5 copyright : (C) 1999-2009 by Pete Bernert\r
6 email : BlackDove@addcom.de\r
7 ***************************************************************************/\r
8\r
9/***************************************************************************\r
10 * *\r
11 * This program is free software; you can redistribute it and/or modify *\r
12 * it under the terms of the GNU General Public License as published by *\r
13 * the Free Software Foundation; either version 2 of the License, or *\r
14 * (at your option) any later version. See also the license.txt file for *\r
15 * additional informations. *\r
16 * *\r
17 ***************************************************************************/\r
18\r
19//*************************************************************************// \r
20// History of changes:\r
21//\r
22// 2009/03/08 - Pete \r
23// - generic cleanup for the Peops release\r
24//\r
25//*************************************************************************// \r
26\r
27//#include "gpuStdafx.h"\r
28\r
29//#include <mmsystem.h>\r
30\r
31#define _IN_GPU\r
32\r
33#ifdef _WINDOWS\r
34#include "stdafx.h"\r
35#include <stdlib.h>\r
36#include <stdio.h>\r
37#include <stdarg.h>\r
38#include <string.h>\r
39#include <mmsystem.h>\r
40\r
41#include "externals.h"\r
42#include "gpu.h"\r
43#include "draw.h"\r
44#include "prim.h"\r
45#include "texture.h"\r
46#include "fps.h"\r
47#include "resource.h"\r
48#else\r
49#include <stdlib.h>\r
50#include <stdio.h>\r
51#include <stdarg.h>\r
52#include <string.h>\r
53#include "gpuExternals.h"\r
54#include "gpuPlugin.h"\r
55#include "gpuDraw.h"\r
56#include "gpuTexture.h"\r
57#include "gpuFps.h"\r
58#include "gpuPrim.h"\r
59\r
60//#include "NoPic.h"\r
61\r
62#include "gpuStdafx.h"\r
63#endif\r
64\r
65extern void ProcessEvents();\r
66 \r
67short g_m1=255,g_m2=255,g_m3=255;\r
68short DrawSemiTrans=FALSE;\r
69short Ymin;\r
70short Ymax;\r
71\r
72short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords\r
73long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;\r
74long GlobalTextREST,GlobalTextABR,GlobalTextPAGE;\r
75\r
76unsigned long dwGPUVersion=0;\r
77int iGPUHeight=512;\r
78int iGPUHeightMask=511;\r
79int GlobalTextIL=0;\r
80int iTileCheat=0;\r
81\r
82////////////////////////////////////////////////////////////////////////\r
83// memory image of the PSX vram\r
84////////////////////////////////////////////////////////////////////////\r
85\r
86u8 *psxVSecure;\r
87u8 *psxVub;\r
88signed char *psxVsb;\r
89unsigned short *psxVuw;\r
90unsigned short *psxVuw_eom;\r
91signed short *psxVsw;\r
92unsigned long *psxVul;\r
93signed long *psxVsl;\r
94\r
95// macro for easy access to packet information\r
96#define GPUCOMMAND(x) ((x>>24) & 0xff)\r
97\r
98GLfloat gl_z=0.0f;\r
99BOOL bNeedInterlaceUpdate=FALSE;\r
100BOOL bNeedRGB24Update=FALSE;\r
101BOOL bChangeWinMode=FALSE;\r
102\r
103#ifdef _WINDOWS\r
104extern HGLRC GLCONTEXT;\r
105#endif\r
106\r
107unsigned long ulStatusControl[256];\r
108\r
109////////////////////////////////////////////////////////////////////////\r
110// global GPU vars\r
111////////////////////////////////////////////////////////////////////////\r
112\r
113static long GPUdataRet;\r
114long lGPUstatusRet;\r
115s8 szDispBuf[64];\r
116\r
117static unsigned long gpuDataM[256];\r
118static u8 gpuCommand = 0;\r
119static long gpuDataC = 0;\r
120static long gpuDataP = 0;\r
121\r
122VRAMLoad_t VRAMWrite;\r
123VRAMLoad_t VRAMRead;\r
124int iDataWriteMode;\r
125int iDataReadMode;\r
126\r
127long lClearOnSwap;\r
128long lClearOnSwapColor;\r
129BOOL bSkipNextFrame = FALSE;\r
130int iColDepth;\r
131BOOL bChangeRes;\r
132BOOL bWindowMode;\r
133int iWinSize;\r
134\r
135// possible psx display widths\r
136short dispWidths[8] = {256,320,512,640,368,384,512,640};\r
137\r
138PSXDisplay_t PSXDisplay;\r
139PSXDisplay_t PreviousPSXDisplay;\r
140TWin_t TWin;\r
141short imageX0,imageX1;\r
142short imageY0,imageY1;\r
143BOOL bDisplayNotSet = TRUE;\r
144GLuint uiScanLine=0;\r
145int iUseScanLines=0;\r
146long lSelectedSlot=0;\r
147u8 * pGfxCardScreen=0;\r
148int iBlurBuffer=0;\r
149int iScanBlend=0;\r
150int iRenderFVR=0;\r
151int iNoScreenSaver=0;\r
152unsigned long ulGPUInfoVals[16];\r
153int iFakePrimBusy = 0;\r
154int iRumbleVal = 0;\r
155int iRumbleTime = 0;\r
156\r
157////////////////////////////////////////////////////////////////////////\r
158// stuff to make this a true PDK module\r
159////////////////////////////////////////////////////////////////////////\r
160\r
161#ifdef _WINDOWS\r
162s8 * CALLBACK PSEgetLibName(void)\r
163{\r
164 return "name";\r
165}\r
166\r
167unsigned long CALLBACK PSEgetLibType(void)\r
168{\r
169 return 1;\r
170}\r
171\r
172unsigned long CALLBACK PSEgetLibVersion(void)\r
173{\r
174 return 1<<16|1<<8|1;\r
175}\r
176#endif\r
177\r
178////////////////////////////////////////////////////////////////////////\r
179// snapshot funcs (saves screen to bitmap / text infos into file)\r
180////////////////////////////////////////////////////////////////////////\r
181\r
182void ResizeWindow()\r
183{\r
184 rRatioRect.left = rRatioRect.top=0;\r
185 rRatioRect.right = iResX;\r
186 rRatioRect.bottom = iResY;\r
187 glViewport(rRatioRect.left, // init viewport by ratio rect\r
188 iResY-(rRatioRect.top+rRatioRect.bottom),\r
189 rRatioRect.right, \r
190 rRatioRect.bottom); \r
191 \r
192 glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)\r
193 glEnable(GL_SCISSOR_TEST); \r
194\r
195#ifndef OWNSCALE\r
196 glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"\r
197 glLoadIdentity();\r
198 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack\r
199#endif \r
200\r
201 glMatrixMode(GL_PROJECTION); // init projection with psx resolution\r
202 glLoadIdentity();\r
203 glOrtho(0,PSXDisplay.DisplayMode.x,\r
204 PSXDisplay.DisplayMode.y, 0, -1, 1);\r
205 if (bKeepRatio)\r
206 SetAspectRatio();\r
207}\r
208\r
209s8 * GetConfigInfos(int hW)\r
210{\r
211#ifdef _WINDOWS\r
212 HDC hdc;HGLRC hglrc;\r
213#endif\r
214 s8 szO[2][4]={"off","on "};\r
215 s8 szTxt[256];\r
216 s8 * pB=(s8 *)malloc(32767);\r
217/*\r
218 if(!pB) return NULL;\r
219 *pB=0;\r
220 //----------------------------------------------------//\r
221 strcat(pB,szTxt);\r
222 strcat(pB,szTxt);\r
223#ifdef _WINDOWS\r
224 if(hW)\r
225 {\r
226 hdc = GetDC(hW);\r
227 bSetupPixelFormat(hdc);\r
228 hglrc = wglCreateContext(hdc);\r
229 wglMakeCurrent(hdc, hglrc);\r
230 }\r
231#endif\r
232 sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));\r
233 strcat(pB,szTxt);\r
234 sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));\r
235 strcat(pB,szTxt);\r
236 sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));\r
237 strcat(pB,szTxt);\r
238 //strcat(pB,(s8 *)glGetString(GL_EXTENSIONS));\r
239 //strcat(pB,"\r\n\r\n");\r
240\r
241#ifdef _WINDOWS\r
242 if(hW)\r
243 {\r
244 wglMakeCurrent(NULL, NULL);\r
245 wglDeleteContext(hglrc);\r
246 ReleaseDC(hW,hdc);\r
247 }\r
248 //----------------------------------------------------//\r
249#endif\r
250 if(hW && bWindowMode)\r
251 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));\r
252 else\r
253 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);\r
254 strcat(pB,szTxt);\r
255 if(bWindowMode) sprintf(szTxt,"Window mode\r\n");\r
256 else\r
257 {\r
258 sprintf(szTxt,"Fullscreen ");\r
259 strcat(pB,szTxt);\r
260 if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);\r
261 else sprintf(szTxt,"- NO desktop changing\r\n");\r
262 } \r
263 strcat(pB,szTxt);\r
264\r
265// if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]);\r
266// else strcpy(szTxt,"- V-Sync: Driver\r\n");\r
267 strcat(pB,szTxt); \r
268 sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);\r
269 strcat(pB,szTxt);\r
270 //----------------------------------------------------//\r
271 strcpy(szTxt,"Textures:\r\n- ");\r
272/*! if(iTexQuality==0) strcat(szTxt,"Default");\r
273 else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4");\r
274 else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1");\r
275 else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8");\r
276 else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8");\r
277 if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n");\r
278 else strcat(szTxt,"\r\n");\r
279 strcat(pB,szTxt);\r
280 if(!hW)\r
281 {\r
282 sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType);\r
283 if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n");\r
284 else strcat(szTxt,"NOT supported\r\n");\r
285 }\r
286 else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);\r
287 strcat(pB,szTxt);\r
288 sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);\r
289 strcat(pB,szTxt); \r
290 if(!hW)\r
291 {\r
292 sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);\r
293 strcat(pB,szTxt); \r
294 }\r
295 !*/\r
296 /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);\r
297 if(!hW)\r
298 sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);\r
299 else strcat(szTxt,"\r\n\r\n");\r
300 strcat(pB,szTxt);\r
301 //----------------------------------------------------//\r
302 sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);\r
303 strcat(pB,szTxt);\r
304 sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);\r
305 strcat(pB,szTxt);\r
306 if(iFrameLimit==2)\r
307 strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");\r
308 else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);\r
309 strcat(pB,szTxt);\r
310 //----------------------------------------------------//\r
311 sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);\r
312 strcat(pB,szTxt);\r
313 sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);\r
314 if(!hW && iFrameTexType==2)\r
315 {\r
316 if(gTexFrameName) strcat(szTxt," - texture created\r\n");\r
317 else strcat(szTxt," - not used yet\r\n");\r
318 }\r
319 else strcat(szTxt,"\r\n");\r
320 strcat(pB,szTxt);\r
321 sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);\r
322 strcat(pB,szTxt);\r
323// sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);\r
324 strcat(pB,szTxt);\r
325 sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);\r
326 strcat(pB,szTxt);\r
327 //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);\r
328 //if(!hW && bAdvancedBlend)\r
329// {\r
330// if(bGLBlend) strcat(szTxt," (hardware)\r\n");\r
331// else strcat(szTxt," (software)\r\n");\r
332// }\r
333 strcat(szTxt,"\r\n");\r
334 strcat(pB,szTxt);\r
335\r
336 if(!hW)\r
337 {\r
338 strcpy(szTxt,"- Subtractive blending: ");\r
339// if(glBlendEquationEXTEx)\r
340// {\r
341// if(bUseMultiPass) strcat(szTxt,"supported, but not used!");\r
342// else strcat(szTxt,"activated");\r
343// }\r
344 strcat(szTxt," NOT supported!");\r
345 strcat(szTxt,"\r\n\r\n");\r
346 }\r
347 else strcpy(szTxt,"\r\n");\r
348 \r
349 strcat(pB,szTxt); \r
350 //----------------------------------------------------//\r
351 sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);\r
352 strcat(pB,szTxt);\r
353 if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);\r
354 else strcpy(szTxt,"\r\n");\r
355 strcat(pB,szTxt);\r
356// sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);\r
357 strcat(pB,szTxt);\r
358// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]);\r
359// fwrite(szTxt,lstrlen(szTxt),1,txtfile);\r
360 sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]);\r
361 strcat(pB,szTxt);\r
362 sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);\r
363 strcat(pB,szTxt);\r
364 sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);\r
365 strcat(pB,szTxt);\r
366 sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);\r
367 strcat(pB,szTxt);\r
368 if(!hW && iBlurBuffer) \r
369 {\r
370 if(gTexBlurName) strcat(pB," - supported\r\n");\r
371 else strcat(pB," - not supported\r\n");\r
372 }\r
373 else strcat(pB,"\r\n");\r
374 sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes);\r
375 strcat(pB,szTxt);\r
376 //----------------------------------------------------//\r
377*/ return pB;\r
378}\r
379\r
380////////////////////////////////////////////////////////////////////////\r
381// save text infos to file\r
382////////////////////////////////////////////////////////////////////////\r
383\r
384void DoTextSnapShot(int iNum)\r
385{\r
386}\r
387\r
388////////////////////////////////////////////////////////////////////////\r
389// saves screen bitmap to file\r
390////////////////////////////////////////////////////////////////////////\r
391\r
392void DoSnapShot(void)\r
393{\r
394} \r
395\r
396#ifdef _WINDOWS\r
397void CALLBACK GPUmakeSnapshot(void)\r
398#else\r
399void CALLBACK GPU_makeSnapshot(void)\r
400#endif\r
401{\r
402 //bSnapShot = TRUE;\r
403} \r
404\r
405////////////////////////////////////////////////////////////////////////\r
406// GPU INIT... here starts it all (first func called by emu)\r
407////////////////////////////////////////////////////////////////////////\r
408\r
409#ifdef _WINDOWS\r
410long CALLBACK GPUinit()\r
411#else\r
412long CALLBACK GPU_init()\r
413#endif\r
414{\r
415memset(ulStatusControl,0,256*sizeof(unsigned long));\r
416\r
417#ifdef _WINDOWS\r
418iResX=240;iResY=320;\r
419#endif\r
420bChangeRes=FALSE;\r
421#ifdef _WINDOWS\r
422bWindowMode=TRUE;\r
423#else\r
424bWindowMode=FALSE;\r
425#endif \r
426#ifdef _WINDOWS\r
427iWinSize=MAKELONG(iResX,iResY);\r
428#endif\r
429\r
430bKeepRatio = TRUE;\r
431// different ways of accessing PSX VRAM\r
432\r
433psxVSecure=(u8 *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security\r
434if(!psxVSecure) return -1;\r
435\r
436psxVub=psxVSecure+512*1024; // security offset into double sized psx vram!\r
437psxVsb=(signed char *)psxVub;\r
438psxVsw=(signed short *)psxVub;\r
439psxVsl=(signed long *)psxVub;\r
440psxVuw=(unsigned short *)psxVub;\r
441psxVul=(unsigned long *)psxVub;\r
442\r
443psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram\r
444\r
445memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));\r
446memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));\r
447\r
448InitFrameCap(); // init frame rate stuff\r
449\r
450PSXDisplay.RGB24 = 0; // init vars\r
451PreviousPSXDisplay.RGB24= 0;\r
452PSXDisplay.Interlaced = 0;\r
453PSXDisplay.InterlacedTest=0;\r
454PSXDisplay.DrawOffset.x = 0;\r
455PSXDisplay.DrawOffset.y = 0;\r
456PSXDisplay.DrawArea.x0 = 0;\r
457PSXDisplay.DrawArea.y0 = 0;\r
458PSXDisplay.DrawArea.x1 = 320;\r
459PSXDisplay.DrawArea.y1 = 240;\r
460PSXDisplay.DisplayMode.x= 320;\r
461PSXDisplay.DisplayMode.y= 240;\r
462PSXDisplay.Disabled = FALSE;\r
463PreviousPSXDisplay.Range.x0 =0;\r
464PreviousPSXDisplay.Range.x1 =0;\r
465PreviousPSXDisplay.Range.y0 =0;\r
466PreviousPSXDisplay.Range.y1 =0;\r
467PSXDisplay.Range.x0=0;\r
468PSXDisplay.Range.x1=0;\r
469PSXDisplay.Range.y0=0;\r
470PSXDisplay.Range.y1=0;\r
471PreviousPSXDisplay.DisplayPosition.x = 1;\r
472PreviousPSXDisplay.DisplayPosition.y = 1;\r
473PSXDisplay.DisplayPosition.x = 1;\r
474PSXDisplay.DisplayPosition.y = 1;\r
475PreviousPSXDisplay.DisplayModeNew.y=0;\r
476PSXDisplay.Double=1;\r
477GPUdataRet=0x400;\r
478\r
479PSXDisplay.DisplayModeNew.x=0;\r
480PSXDisplay.DisplayModeNew.y=0;\r
481\r
482//PreviousPSXDisplay.Height = PSXDisplay.Height = 239;\r
483\r
484iDataWriteMode = DR_NORMAL;\r
485\r
486// Reset transfer values, to prevent mis-transfer of data\r
487memset(&VRAMWrite,0,sizeof(VRAMLoad_t));\r
488memset(&VRAMRead,0,sizeof(VRAMLoad_t));\r
489\r
490// device initialised already !\r
491//lGPUstatusRet = 0x74000000;\r
492\r
493STATUSREG = 0x14802000;\r
494GPUIsIdle;\r
495GPUIsReadyForCommands;\r
496\r
497return 0;\r
498} \r
499\r
500\r
501////////////////////////////////////////////////////////////////////////\r
502// GPU OPEN: funcs to open up the gpu display (Windows)\r
503////////////////////////////////////////////////////////////////////////\r
504\r
505#ifdef _WINDOWS\r
506\r
507void ChangeDesktop() // change destop resolution\r
508{\r
509 DEVMODE dv;long lRes,iTry=0; \r
510\r
511 while(iTry<10) // keep on hammering...\r
512 {\r
513 memset(&dv,0,sizeof(DEVMODE));\r
514 dv.dmSize=sizeof(DEVMODE);\r
515 dv.dmBitsPerPel=iColDepth;\r
516 dv.dmPelsWidth=iResX;\r
517 dv.dmPelsHeight=iResY;\r
518\r
519 dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;\r
520\r
521 lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil\r
522\r
523 if(lRes==DISP_CHANGE_SUCCESSFUL) return;\r
524 iTry++;Sleep(10);\r
525 }\r
526}\r
527\r
528////////////////////////////////////////////////////////////////////////\r
529// OPEN interface func: attention! \r
530// some emus are calling this func in their main Window thread,\r
531// but all other interface funcs (to draw stuff) in a different thread!\r
532// that's a problem, since OGL is thread safe! Therefore we cannot \r
533// initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE"\r
534// flag, to initialize OGL on the first real draw call.\r
535// btw, we also call this open func ourselfes, each time when the user \r
536// is changing between fullscreen/window mode (ENTER key)\r
537// btw part 2: in windows the plugin gets the window handle from the\r
538// main emu, and doesn't create it's own window (if it would do it,\r
539// some PAD or SPU plugins would not work anymore)\r
540////////////////////////////////////////////////////////////////////////\r
541\r
542HMENU hPSEMenu=NULL;\r
543\r
544long CALLBACK GPUopen(HWND hwndGPU) \r
545#else\r
546long CALLBACK GPU_open(int hwndGPU) \r
547#endif\r
548{\r
549 #ifdef _WINDOWS\r
550 HDC hdc;RECT r;DEVMODE dv;\r
551\r
552 hWWindow = hwndGPU; // store hwnd globally\r
553 #endif\r
554 // InitKeyHandler(); // init key handler (subclass window)\r
555\r
556\r
557\r
558 \r
559 \r
560 #ifdef _WINDOWS\r
561 iResX=240;iResY=320;\r
562 #endif\r
563 iColDepth=32;\r
564 bChangeRes=FALSE;\r
565 #ifdef _WINDOWS\r
566 bWindowMode=TRUE;\r
567 #else\r
568 bWindowMode=FALSE;\r
569 #endif \r
570 bFullVRam=FALSE;\r
571 iFilterType=0;\r
572 // bAdvancedBlend=FALSE;\r
573 bDrawDither=FALSE;\r
574 // bUseLines=FALSE;\r
575 bUseFrameLimit=FALSE;\r
576 bUseFrameSkip=FALSE;\r
577 iFrameLimit=0;\r
578 fFrameRate=50.0f;\r
579 iOffscreenDrawing=0;\r
580 //bOpaquePass=FALSE;\r
581 //bUseAntiAlias=FALSE;\r
582 //iTexQuality=0;\r
583 #ifdef _WINDOWS\r
584 iWinSize=MAKELONG(iResX,iResY);\r
585 #endif\r
586 iUseMask=0;\r
587 iZBufferDepth=0;\r
588 bUseFastMdec=FALSE;\r
589 bUse15bitMdec=FALSE;\r
590 dwCfgFixes=0;\r
591 bUseFixes=FALSE;\r
592 // iUseScanLines=0;\r
593 iFrameTexType=0;\r
594 iFrameReadType=0;\r
595 //iShowFPS=0;\r
596 bKeepRatio=TRUE;\r
597 iScanBlend=0;\r
598 iVRamSize=0;\r
599 iTexGarbageCollection=0;\r
600 iBlurBuffer=0; \r
601 //iHiResTextures=0;\r
602 iNoScreenSaver=0;\r
603 //iForceVSync=0;\r
604\r
605\r
606\r
607#ifdef _WINDOWS\r
608 memset(&dv,0,sizeof(DEVMODE));\r
609 dv.dmSize=sizeof(DEVMODE);\r
610 EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv);\r
611#endif\r
612 bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows!\r
613\r
614#ifdef _WINDOWS\r
615 if(bWindowMode) // win mode?\r
616 {\r
617 DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers)\r
618 dw&=~WS_THICKFRAME;\r
619 dw|=WS_BORDER|WS_CAPTION|CS_OWNDC;\r
620 SetWindowLong(hWWindow, GWL_STYLE, dw);\r
621\r
622 hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any)\r
623 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);\r
624\r
625 iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize);\r
626 ShowWindow(hWWindow,SW_SHOWNORMAL);\r
627\r
628 MoveWindow(hWWindow, // -> center wnd\r
629 GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2,\r
630 GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2,\r
631 iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3,\r
632 iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3,\r
633 TRUE);\r
634 UpdateWindow(hWWindow); // -> let windows do some update\r
635\r
636 if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info\r
637 iColDepth=dv.dmBitsPerPel;\r
638 }\r
639 else // fullscreen mode:\r
640 {\r
641 if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution\r
642 dv.dmPelsWidth !=(unsigned int)iResX ||\r
643 dv.dmPelsHeight!=(unsigned int)iResY)\r
644 bChangeRes=TRUE; else bChangeRes=FALSE;\r
645\r
646 if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations')\r
647\r
648 SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure)\r
649 \r
650 hPSEMenu=GetMenu(hWWindow); // -> hide menu\r
651 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);\r
652 ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode\r
653 }\r
654#endif\r
655 rRatioRect.left = rRatioRect.top=0;\r
656 rRatioRect.right = iResX;\r
657 rRatioRect.bottom = iResY;\r
658\r
659#ifdef _WINDOWS\r
660 r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized\r
661 hdc = GetDC(hWWindow);\r
662 FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));\r
663 bSetupPixelFormat(hdc);\r
664 ReleaseDC(hWWindow,hdc);\r
665#endif\r
666 bDisplayNotSet = TRUE; \r
667 bSetClip=TRUE;\r
668\r
669 SetFixes(); // setup game fixes\r
670\r
671 InitializeTextureStore(); // init texture mem\r
672\r
673// lGPUstatusRet = 0x74000000;\r
674\r
675// with some emus, we could do the OGL init right here... oh my\r
676// if(bIsFirstFrame) GLinitialize();\r
677\r
678 return 0;\r
679}\r
680\r
681////////////////////////////////////////////////////////////////////////\r
682// close\r
683////////////////////////////////////////////////////////////////////////\r
684\r
685#ifdef _WINDOWS\r
686long CALLBACK GPUclose() // WINDOWS CLOSE\r
687{\r
688// ExitKeyHandler();\r
689\r
690 GLcleanup(); // close OGL\r
691\r
692 if(bChangeRes) // change res back\r
693 ChangeDisplaySettings(NULL,0);\r
694\r
695 if(hPSEMenu) // set menu again\r
696 SetMenu(hWWindow,hPSEMenu);\r
697\r
698 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory\r
699 pGfxCardScreen=0;\r
700\r
701// if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again\r
702\r
703 return 0;\r
704}\r
705\r
706#else\r
707\r
708long GPU_close() // LINUX CLOSE\r
709{\r
710 GLcleanup(); // close OGL\r
711\r
712 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory\r
713 pGfxCardScreen=0;\r
714\r
715// osd_close_display(); // destroy display\r
716\r
717 return 0;\r
718}\r
719#endif\r
720\r
721////////////////////////////////////////////////////////////////////////\r
722// I shot the sheriff... last function called from emu \r
723////////////////////////////////////////////////////////////////////////\r
724\r
725#ifdef _WINDOWS\r
726long CALLBACK GPUshutdown()\r
727#else\r
728long CALLBACK GPU_shutdown()\r
729#endif\r
730{\r
731 if(psxVSecure) free(psxVSecure); // kill emulated vram memory\r
732 psxVSecure=0;\r
733\r
734 return 0;\r
735}\r
736\r
737////////////////////////////////////////////////////////////////////////\r
738// paint it black: simple func to clean up optical border garbage\r
739////////////////////////////////////////////////////////////////////////\r
740\r
741void PaintBlackBorders(void)\r
742{\r
743 short s;\r
744\r
745 glDisable(GL_SCISSOR_TEST);\r
746 if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}\r
747 if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}\r
748 if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;}\r
749 glDisable(GL_ALPHA_TEST);\r
750\r
751 glEnable(GL_ALPHA_TEST);\r
752 glEnable(GL_SCISSOR_TEST);\r
753}\r
754\r
755////////////////////////////////////////////////////////////////////////\r
756// helper to draw scanlines\r
757////////////////////////////////////////////////////////////////////////\r
758\r
759__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, \r
760 OGLVertex* vertex3, OGLVertex* vertex4) \r
761{\r
762\r
763}\r
764\r
765////////////////////////////////////////////////////////////////////////\r
766// scanlines\r
767////////////////////////////////////////////////////////////////////////\r
768\r
769void SetScanLines(void)\r
770{\r
771}\r
772\r
773////////////////////////////////////////////////////////////////////////\r
774// blur, babe, blur (heavy performance hit for a so-so fullscreen effect)\r
775////////////////////////////////////////////////////////////////////////\r
776\r
777\r
778////////////////////////////////////////////////////////////////////////\r
779// Update display (swap buffers)... called in interlaced mode on \r
780// every emulated vsync, otherwise whenever the displayed screen region\r
781// has been changed\r
782////////////////////////////////////////////////////////////////////////\r
783\r
784int iLastRGB24=0; // special vars for checking when to skip two display updates\r
785int iSkipTwo=0;\r
786void GPU_vSinc(void){\r
787updateDisplay();\r
788}\r
789void updateDisplay(void) // UPDATE DISPLAY\r
790{\r
791BOOL bBlur=FALSE;\r
792\r
793#ifdef _WINDOWS\r
794HDC hdc=GetDC(hWWindow); // windows:\r
795wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again\r
796#endif\r
797\r
798bFakeFrontBuffer=FALSE;\r
799bRenderFrontBuffer=FALSE;\r
800\r
801if(iRenderFVR) // frame buffer read fix mode still active?\r
802 {\r
803 iRenderFVR--; // -> if some frames in a row without read access: turn off mode\r
804 if(!iRenderFVR) bFullVRam=FALSE;\r
805 }\r
806\r
807if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check\r
808 {\r
809 iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes\r
810 }\r
811iLastRGB24=0;\r
812\r
813if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted?\r
814 {\r
815 PrepareFullScreenUpload(-1);\r
816 UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram\r
817 bNeedUploadTest=FALSE;\r
818 bNeedInterlaceUpdate=FALSE;\r
819 bNeedUploadAfter=FALSE;\r
820 bNeedRGB24Update=FALSE;\r
821 }\r
822else\r
823if(bNeedInterlaceUpdate) // smaller upload?\r
824 {\r
825 bNeedInterlaceUpdate=FALSE;\r
826 xrUploadArea=xrUploadAreaIL; // -> upload this rect\r
827 UploadScreen(TRUE);\r
828 }\r
829\r
830if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 \r
831\r
832if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed\r
833 PreviousPSXDisplay.Range.y0)\r
834 PaintBlackBorders();\r
835\r
836if(PSXDisplay.Disabled) // display disabled?\r
837 {\r
838 // moved here\r
839 glDisable(GL_SCISSOR_TEST); \r
840 glClearColor(0,0,0,128); // -> clear whole backbuffer\r
841 glClear(uiBufferBits);\r
842 glEnable(GL_SCISSOR_TEST); \r
843 gl_z=0.0f;\r
844 bDisplayNotSet = TRUE;\r
845 }\r
846\r
847if(iSkipTwo) // we are in skipping mood?\r
848 {\r
849 iSkipTwo--;\r
850 iDrawnSomething=0; // -> simply lie about something drawn\r
851 }\r
852\r
853//if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated?\r
854// {BlurBackBuffer();bBlur=TRUE;} // -> blur it\r
855\r
856// if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it\r
857\r
858// if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em\r
859\r
860if(dwActFixes&128) // special FPS limitation mode?\r
861 {\r
862 if(bUseFrameLimit) PCFrameCap(); // -> ok, do it\r
863// if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) \r
864 PCcalcfps(); \r
865 }\r
866\r
867// if(gTexPicName) DisplayPic(); // some gpu info picture active? display it\r
868\r
869// if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :)\r
870\r
871// if(ulKeybits&KEY_SHOWFPS) // wanna see FPS?\r
872 {\r
873// sprintf(szDispBuf,"%06.1f",fps_cur);\r
874// DisplayText(); // -> show it\r
875 }\r
876\r
877//----------------------------------------------------//\r
878// main buffer swapping (well, or skip it)\r
879\r
880if(bUseFrameSkip) // frame skipping active ?\r
881 {\r
882 if(!bSkipNextFrame) \r
883 {\r
884 if(iDrawnSomething)\r
885#ifdef _WINDOWS\r
886 SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip\r
887#else\r
888 eglSwapBuffers(display,surface);\r
889#endif\r
890 }\r
891 if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row\r
892 {\r
893 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) \r
894 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}\r
895 else bSkipNextFrame = FALSE;\r
896 }\r
897 else FrameSkip();\r
898 }\r
899else // no skip ?\r
900 {\r
901 if(iDrawnSomething)\r
902#ifdef _WINDOWS\r
903 SwapBuffers(wglGetCurrentDC()); // -> swap\r
904#else\r
905 eglSwapBuffers(display,surface);\r
906#endif\r
907 }\r
908\r
909iDrawnSomething=0;\r
910\r
911//----------------------------------------------------//\r
912\r
913if(lClearOnSwap) // clear buffer after swap?\r
914 {\r
915 GLclampf g,b,r;\r
916\r
917 if(bDisplayNotSet) // -> set new vals\r
918 SetOGLDisplaySettings(1);\r
919\r
920 g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col\r
921 b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;\r
922 r=((GLclampf)RED(lClearOnSwapColor))/255.0f;\r
923 \r
924 glDisable(GL_SCISSOR_TEST); \r
925 glClearColor(r,g,b,128); // -> clear \r
926 glClear(uiBufferBits);\r
927 glEnable(GL_SCISSOR_TEST); \r
928 lClearOnSwap=0; // -> done\r
929 }\r
930else \r
931 {\r
932// if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before\r
933\r
934 if(iZBufferDepth) // clear zbuffer as well (if activated)\r
935 {\r
936 glDisable(GL_SCISSOR_TEST); \r
937 glClear(GL_DEPTH_BUFFER_BIT);\r
938 glEnable(GL_SCISSOR_TEST); \r
939 }\r
940 }\r
941gl_z=0.0f;\r
942\r
943//----------------------------------------------------//\r
944// additional uploads immediatly after swapping\r
945\r
946if(bNeedUploadAfter) // upload wanted?\r
947 {\r
948 bNeedUploadAfter=FALSE; \r
949 bNeedUploadTest=FALSE;\r
950 UploadScreen(-1); // -> upload\r
951 }\r
952\r
953if(bNeedUploadTest)\r
954 {\r
955 bNeedUploadTest=FALSE;\r
956 if(PSXDisplay.InterlacedTest &&\r
957 //iOffscreenDrawing>2 &&\r
958 PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&\r
959 PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&\r
960 PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&\r
961 PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)\r
962 {\r
963 PrepareFullScreenUpload(TRUE);\r
964 UploadScreen(TRUE);\r
965 }\r
966 }\r
967\r
968//----------------------------------------------------//\r
969// rumbling (main emu pad effect)\r
970\r
971if(iRumbleTime) // shake screen by modifying view port\r
972 {\r
973 int i1=0,i2=0,i3=0,i4=0;\r
974\r
975 iRumbleTime--;\r
976 if(iRumbleTime) \r
977 {\r
978 i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
979 i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
980 i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
981 i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
982 }\r
983\r
984 glViewport(rRatioRect.left+i1, \r
985 iResY-(rRatioRect.top+rRatioRect.bottom)+i2,\r
986 rRatioRect.right+i3, \r
987 rRatioRect.bottom+i4); \r
988 }\r
989\r
990//----------------------------------------------------//\r
991\r
992\r
993\r
994// if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled\r
995}\r
996\r
997////////////////////////////////////////////////////////////////////////\r
998// update front display: smaller update func, if something has changed \r
999// in the frontbuffer... dirty, but hey... real men know no pain\r
1000////////////////////////////////////////////////////////////////////////\r
1001\r
1002void updateFrontDisplay(void)\r
1003{\r
1004if(PreviousPSXDisplay.Range.x0||\r
1005 PreviousPSXDisplay.Range.y0)\r
1006 PaintBlackBorders();\r
1007\r
1008//if(iBlurBuffer) BlurBackBuffer();\r
1009\r
1010//if(iUseScanLines) SetScanLines();\r
1011\r
1012// if(usCursorActive) ShowGunCursor();\r
1013\r
1014bFakeFrontBuffer=FALSE;\r
1015bRenderFrontBuffer=FALSE;\r
1016\r
1017// if(gTexPicName) DisplayPic();\r
1018// if(ulKeybits&KEY_SHOWFPS) DisplayText();\r
1019\r
1020#ifdef _WINDOWS\r
1021 { // windows: \r
1022 HDC hdc=GetDC(hWWindow);\r
1023 wglMakeCurrent(hdc,GLCONTEXT); // -> make current again\r
1024 if(iDrawnSomething)\r
1025 SwapBuffers(wglGetCurrentDC()); // -> swap\r
1026 ReleaseDC(hWWindow,hdc); // -> ! important !\r
1027 }\r
1028#else\r
1029if(iDrawnSomething) // linux:\r
1030 eglSwapBuffers(display,surface);\r
1031#endif\r
1032\r
1033//if(iBlurBuffer) UnBlurBackBuffer();\r
1034}\r
1035 \r
1036////////////////////////////////////////////////////////////////////////\r
1037// check if update needed\r
1038////////////////////////////////////////////////////////////////////////\r
1039void ChangeDispOffsetsX(void) // CENTER X\r
1040{\r
1041long lx,l;short sO;\r
1042\r
1043if(!PSXDisplay.Range.x1) return; // some range given?\r
1044\r
1045l=PSXDisplay.DisplayMode.x;\r
1046\r
1047l*=(long)PSXDisplay.Range.x1; // some funky calculation\r
1048l/=2560;lx=l;l&=0xfffffff8;\r
1049\r
1050if(l==PreviousPSXDisplay.Range.x1) return; // some change?\r
1051\r
1052sO=PreviousPSXDisplay.Range.x0; // store old\r
1053\r
1054if(lx>=PSXDisplay.DisplayMode.x) // range bigger?\r
1055 {\r
1056 PreviousPSXDisplay.Range.x1= // -> take display width\r
1057 PSXDisplay.DisplayMode.x;\r
1058 PreviousPSXDisplay.Range.x0=0; // -> start pos is 0\r
1059 }\r
1060else // range smaller? center it\r
1061 {\r
1062 PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned)\r
1063 PreviousPSXDisplay.Range.x0= // -> calc start pos\r
1064 (PSXDisplay.Range.x0-500)/8;\r
1065 if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet\r
1066 PreviousPSXDisplay.Range.x0=0;\r
1067\r
1068 if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much\r
1069 PSXDisplay.DisplayMode.x)\r
1070 {\r
1071 PreviousPSXDisplay.Range.x0= // -> adjust start\r
1072 PSXDisplay.DisplayMode.x-lx;\r
1073 PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width\r
1074 } \r
1075 }\r
1076\r
1077if(sO!=PreviousPSXDisplay.Range.x0) // something changed?\r
1078 {\r
1079 bDisplayNotSet=TRUE; // -> recalc display stuff\r
1080 }\r
1081}\r
1082\r
1083////////////////////////////////////////////////////////////////////////\r
1084\r
1085void ChangeDispOffsetsY(void) // CENTER Y\r
1086{\r
1087int iT;short sO; // store previous y size\r
1088\r
1089if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC\r
1090\r
1091if(PSXDisplay.Range.y0>=iT) // crossed the security line? :)\r
1092 {\r
1093 PreviousPSXDisplay.Range.y1= // -> store width\r
1094 PSXDisplay.DisplayModeNew.y;\r
1095 \r
1096 sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset\r
1097 if(sO<0) sO=0;\r
1098\r
1099 PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too\r
1100 }\r
1101else sO=0; // else no offset\r
1102\r
1103if(sO!=PreviousPSXDisplay.Range.y0) // something changed?\r
1104 {\r
1105 PreviousPSXDisplay.Range.y0=sO;\r
1106 bDisplayNotSet=TRUE; // -> recalc display stuff\r
1107 }\r
1108}\r
1109\r
1110////////////////////////////////////////////////////////////////////////\r
1111// Aspect ratio of ogl screen: simply adjusting ogl view port\r
1112////////////////////////////////////////////////////////////////////////\r
1113\r
1114void SetAspectRatio(void)\r
1115{\r
1116float xs,ys,s;RECT r;\r
1117\r
1118if(!PSXDisplay.DisplayModeNew.x) return;\r
1119if(!PSXDisplay.DisplayModeNew.y) return;\r
1120\r
1121xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;\r
1122ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;\r
1123\r
1124s=min(xs,ys);\r
1125r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);\r
1126r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);\r
1127if(r.right > iResX) r.right = iResX;\r
1128if(r.bottom > iResY) r.bottom = iResY;\r
1129if(r.right < 1) r.right = 1;\r
1130if(r.bottom < 1) r.bottom = 1;\r
1131\r
1132r.left = (iResX-r.right)/2;\r
1133r.top = (iResY-r.bottom)/2;\r
1134\r
1135if(r.bottom<rRatioRect.bottom ||\r
1136 r.right <rRatioRect.right)\r
1137 {\r
1138 RECT rC;\r
1139 glClearColor(0,0,0,128); \r
1140\r
1141 if(r.right <rRatioRect.right)\r
1142 {\r
1143 rC.left=0;\r
1144 rC.top=0;\r
1145 rC.right=r.left;\r
1146 rC.bottom=iResY;\r
1147 glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
1148 glClear(uiBufferBits);\r
1149 rC.left=iResX-rC.right;\r
1150 glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
1151 glClear(uiBufferBits);\r
1152 }\r
1153\r
1154 if(r.bottom <rRatioRect.bottom)\r
1155 {\r
1156 rC.left=0;\r
1157 rC.top=0;\r
1158 rC.right=iResX;\r
1159 rC.bottom=r.top;\r
1160 glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
1161 glClear(uiBufferBits);\r
1162 rC.top=iResY-rC.bottom;\r
1163 glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
1164 glClear(uiBufferBits);\r
1165 }\r
1166 \r
1167 bSetClip=TRUE;\r
1168 bDisplayNotSet=TRUE;\r
1169 }\r
1170\r
1171rRatioRect=r;\r
1172\r
1173\r
1174glViewport(rRatioRect.left,\r
1175 iResY-(rRatioRect.top+rRatioRect.bottom),\r
1176 rRatioRect.right,\r
1177 rRatioRect.bottom); // init viewport\r
1178}\r
1179\r
1180////////////////////////////////////////////////////////////////////////\r
1181// big ass check, if an ogl swap buffer is needed\r
1182////////////////////////////////////////////////////////////////////////\r
1183\r
1184void updateDisplayIfChanged(void)\r
1185{\r
1186BOOL bUp;\r
1187\r
1188if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && \r
1189 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))\r
1190 {\r
1191 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && \r
1192 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) \r
1193 return; // nothing has changed? fine, no swap buffer needed\r
1194 }\r
1195else // some res change?\r
1196 {\r
1197 glLoadIdentity();\r
1198 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution\r
1199 PSXDisplay.DisplayModeNew.y, 0, -1, 1);\r
1200 if(bKeepRatio) SetAspectRatio();\r
1201 }\r
1202\r
1203bDisplayNotSet = TRUE; // re-calc offsets/display area\r
1204\r
1205bUp=FALSE;\r
1206if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)\r
1207 {\r
1208 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet\r
1209 ResetTextureArea(FALSE);\r
1210 bUp=TRUE;\r
1211 }\r
1212\r
1213PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos\r
1214PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;\r
1215PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;\r
1216PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;\r
1217 \r
1218PSXDisplay.DisplayEnd.x= // calc new ends\r
1219 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1220PSXDisplay.DisplayEnd.y=\r
1221 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1222PreviousPSXDisplay.DisplayEnd.x=\r
1223 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1224PreviousPSXDisplay.DisplayEnd.y=\r
1225 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1226\r
1227ChangeDispOffsetsX();\r
1228\r
1229if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)\r
1230\r
1231if(bUp) updateDisplay(); // yeah, real update (swap buffer)\r
1232}\r
1233\r
1234////////////////////////////////////////////////////////////////////////\r
1235// window mode <-> fullscreen mode (windows)\r
1236////////////////////////////////////////////////////////////////////////\r
1237\r
1238#ifdef _WINDOWS\r
1239void ChangeWindowMode(void)\r
1240{\r
1241 GPUclose();\r
1242 bWindowMode=!bWindowMode;\r
1243 GPUopen(hWWindow);\r
1244 bChangeWinMode=FALSE;\r
1245}\r
1246#endif\r
1247\r
1248////////////////////////////////////////////////////////////////////////\r
1249// swap update check (called by psx vsync function)\r
1250////////////////////////////////////////////////////////////////////////\r
1251\r
1252BOOL bSwapCheck(void)\r
1253{\r
1254static int iPosCheck=0;\r
1255static PSXPoint_t pO;\r
1256static PSXPoint_t pD;\r
1257static int iDoAgain=0;\r
1258\r
1259if(PSXDisplay.DisplayPosition.x==pO.x &&\r
1260 PSXDisplay.DisplayPosition.y==pO.y &&\r
1261 PSXDisplay.DisplayEnd.x==pD.x &&\r
1262 PSXDisplay.DisplayEnd.y==pD.y)\r
1263 iPosCheck++;\r
1264else iPosCheck=0;\r
1265\r
1266pO=PSXDisplay.DisplayPosition;\r
1267pD=PSXDisplay.DisplayEnd;\r
1268\r
1269if(iPosCheck<=4) return FALSE;\r
1270\r
1271iPosCheck=4;\r
1272\r
1273if(PSXDisplay.Interlaced) return FALSE;\r
1274\r
1275if (bNeedInterlaceUpdate||\r
1276 bNeedRGB24Update ||\r
1277 bNeedUploadAfter|| \r
1278 bNeedUploadTest || \r
1279 iDoAgain\r
1280 )\r
1281 {\r
1282 iDoAgain=0;\r
1283 if(bNeedUploadAfter) \r
1284 iDoAgain=1;\r
1285 if(bNeedUploadTest && PSXDisplay.InterlacedTest)\r
1286 iDoAgain=1;\r
1287\r
1288 bDisplayNotSet = TRUE;\r
1289 updateDisplay();\r
1290\r
1291 PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;\r
1292 PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;\r
1293 PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;\r
1294 PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;\r
1295 pO=PSXDisplay.DisplayPosition;\r
1296 pD=PSXDisplay.DisplayEnd;\r
1297\r
1298 return TRUE;\r
1299 }\r
1300\r
1301return FALSE;\r
1302} \r
1303////////////////////////////////////////////////////////////////////////\r
1304// gun cursor func: player=0-7, x=0-511, y=0-255\r
1305////////////////////////////////////////////////////////////////////////\r
1306\r
1307////////////////////////////////////////////////////////////////////////\r
1308// update lace is called every VSync. Basically we limit frame rate \r
1309// here, and in interlaced mode we swap ogl display buffers.\r
1310////////////////////////////////////////////////////////////////////////\r
1311\r
1312static unsigned short usFirstPos=2;\r
1313\r
1314#ifdef _WINDOWS\r
1315void CALLBACK GPUupdateLace(void)\r
1316#else\r
1317void CALLBACK GPU_updateLace(void)\r
1318#endif\r
1319{\r
1320if(!(dwActFixes&0x1000)) \r
1321 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)\r
1322\r
1323if(!(dwActFixes&128)) // normal frame limit func\r
1324 CheckFrameRate();\r
1325\r
1326if(iOffscreenDrawing==4) // special check if high offscreen drawing is on\r
1327 {\r
1328 if(bSwapCheck()) return;\r
1329 }\r
1330\r
1331if(PSXDisplay.Interlaced) // interlaced mode?\r
1332 {\r
1333 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)\r
1334 {\r
1335 updateDisplay(); // -> swap buffers (new frame)\r
1336 }\r
1337 }\r
1338else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?\r
1339 {\r
1340 updateFrontDisplay(); // -> update front buffer\r
1341 }\r
1342else if(usFirstPos==1) // initial updates (after startup)\r
1343 {\r
1344 updateDisplay();\r
1345 }\r
1346\r
1347#ifdef _WINDOWS\r
1348if(bChangeWinMode) ChangeWindowMode();\r
1349#endif\r
1350}\r
1351\r
1352////////////////////////////////////////////////////////////////////////\r
1353// process read request from GPU status register\r
1354////////////////////////////////////////////////////////////////////////\r
1355\r
1356#ifdef _WINDOWS\r
1357unsigned long CALLBACK GPUreadStatus(void)\r
1358#else\r
1359unsigned long CALLBACK GPU_readStatus(void)\r
1360#endif\r
1361{\r
1362if(dwActFixes&0x1000) // CC game fix\r
1363 {\r
1364 static int iNumRead=0;\r
1365 if((iNumRead++)==2)\r
1366 {\r
1367 iNumRead=0;\r
1368 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)\r
1369 }\r
1370 }\r
1371\r
1372if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread...\r
1373 {\r
1374 iFakePrimBusy--;\r
1375\r
1376 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims\r
1377 {\r
1378 GPUIsBusy;\r
1379 GPUIsNotReadyForCommands;\r
1380 }\r
1381 else\r
1382 {\r
1383 GPUIsIdle;\r
1384 GPUIsReadyForCommands;\r
1385 }\r
1386 }\r
1387\r
1388return STATUSREG;\r
1389}\r
1390\r
1391////////////////////////////////////////////////////////////////////////\r
1392// processes data send to GPU status register\r
1393// these are always single packet commands.\r
1394////////////////////////////////////////////////////////////////////////\r
1395\r
1396#ifdef _WINDOWS\r
1397void CALLBACK GPUwriteStatus(unsigned long gdata)\r
1398#else\r
1399void CALLBACK GPU_writeStatus(unsigned long gdata)\r
1400#endif\r
1401{\r
1402unsigned long lCommand=(gdata>>24)&0xff;\r
1403\r
1404#ifdef _WINDOWS\r
1405if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)\r
1406#endif\r
1407\r
1408ulStatusControl[lCommand]=gdata;\r
1409\r
1410switch(lCommand)\r
1411 {\r
1412 //--------------------------------------------------//\r
1413 // reset gpu\r
1414 case 0x00:\r
1415 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));\r
1416 lGPUstatusRet=0x14802000;\r
1417 PSXDisplay.Disabled=1;\r
1418 iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1419 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;\r
1420 drawX=drawY=0;drawW=drawH=0;\r
1421 sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;\r
1422 usMirror=0;\r
1423 GlobalTextAddrX=0;GlobalTextAddrY=0;\r
1424 GlobalTextTP=0;GlobalTextABR=0;\r
1425 PSXDisplay.RGB24=FALSE;\r
1426 PSXDisplay.Interlaced=FALSE;\r
1427 bUsingTWin = FALSE;\r
1428 return;\r
1429\r
1430 // dis/enable display\r
1431 case 0x03: \r
1432 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;\r
1433 PSXDisplay.Disabled = (gdata & 1);\r
1434\r
1435 if(PSXDisplay.Disabled) \r
1436 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;\r
1437 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;\r
1438\r
1439 if (iOffscreenDrawing==4 &&\r
1440 PreviousPSXDisplay.Disabled && \r
1441 !(PSXDisplay.Disabled))\r
1442 {\r
1443\r
1444 if(!PSXDisplay.RGB24)\r
1445 {\r
1446 PrepareFullScreenUpload(TRUE);\r
1447 UploadScreen(TRUE); \r
1448 updateDisplay();\r
1449 }\r
1450 }\r
1451\r
1452 return;\r
1453\r
1454 // setting transfer mode\r
1455 case 0x04:\r
1456 gdata &= 0x03; // only want the lower two bits\r
1457\r
1458 iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1459 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;\r
1460 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;\r
1461\r
1462 STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits\r
1463 STATUSREG|=(gdata << 29); // set the DMA bits according to the received data\r
1464\r
1465 return;\r
1466\r
1467 // setting display position\r
1468 case 0x05: \r
1469 {\r
1470 short sx=(short)(gdata & 0x3ff);\r
1471 short sy;\r
1472\r
1473 if(iGPUHeight==1024)\r
1474 {\r
1475 if(dwGPUVersion==2) \r
1476 sy = (short)((gdata>>12)&0x3ff);\r
1477 else sy = (short)((gdata>>10)&0x3ff);\r
1478 }\r
1479 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later\r
1480\r
1481 if (sy & 0x200) \r
1482 {\r
1483 sy|=0xfc00;\r
1484 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;\r
1485 sy=0;\r
1486 }\r
1487 else PreviousPSXDisplay.DisplayModeNew.y=0;\r
1488\r
1489 if(sx>1000) sx=0;\r
1490\r
1491 if(usFirstPos)\r
1492 {\r
1493 usFirstPos--;\r
1494 if(usFirstPos)\r
1495 {\r
1496 PreviousPSXDisplay.DisplayPosition.x = sx;\r
1497 PreviousPSXDisplay.DisplayPosition.y = sy;\r
1498 PSXDisplay.DisplayPosition.x = sx;\r
1499 PSXDisplay.DisplayPosition.y = sy;\r
1500 }\r
1501 }\r
1502\r
1503 if(dwActFixes&8) \r
1504 {\r
1505 if((!PSXDisplay.Interlaced) &&\r
1506 PreviousPSXDisplay.DisplayPosition.x == sx &&\r
1507 PreviousPSXDisplay.DisplayPosition.y == sy)\r
1508 return;\r
1509\r
1510 PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;\r
1511 PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;\r
1512 PreviousPSXDisplay.DisplayPosition.x = sx;\r
1513 PreviousPSXDisplay.DisplayPosition.y = sy;\r
1514 }\r
1515 else\r
1516 {\r
1517 if((!PSXDisplay.Interlaced) &&\r
1518 PSXDisplay.DisplayPosition.x == sx &&\r
1519 PSXDisplay.DisplayPosition.y == sy)\r
1520 return;\r
1521 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1522 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1523 PSXDisplay.DisplayPosition.x = sx;\r
1524 PSXDisplay.DisplayPosition.y = sy;\r
1525 }\r
1526\r
1527 PSXDisplay.DisplayEnd.x=\r
1528 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1529 PSXDisplay.DisplayEnd.y=\r
1530 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1531\r
1532 PreviousPSXDisplay.DisplayEnd.x=\r
1533 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1534 PreviousPSXDisplay.DisplayEnd.y=\r
1535 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1536\r
1537 bDisplayNotSet = TRUE;\r
1538\r
1539 if (!(PSXDisplay.Interlaced))\r
1540 {\r
1541 updateDisplay();\r
1542 }\r
1543 else\r
1544 if(PSXDisplay.InterlacedTest && \r
1545 ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||\r
1546 (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))\r
1547 PSXDisplay.InterlacedTest--;\r
1548\r
1549 return;\r
1550 }\r
1551\r
1552 // setting width\r
1553 case 0x06:\r
1554\r
1555 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;\r
1556 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;\r
1557\r
1558 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;\r
1559\r
1560 ChangeDispOffsetsX();\r
1561\r
1562 return;\r
1563\r
1564 // setting height\r
1565 case 0x07:\r
1566\r
1567 PreviousPSXDisplay.Height = PSXDisplay.Height;\r
1568\r
1569 PSXDisplay.Range.y0=gdata & 0x3ff;\r
1570 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;\r
1571\r
1572 PSXDisplay.Height = PSXDisplay.Range.y1 - \r
1573 PSXDisplay.Range.y0 +\r
1574 PreviousPSXDisplay.DisplayModeNew.y;\r
1575\r
1576 if (PreviousPSXDisplay.Height != PSXDisplay.Height)\r
1577 {\r
1578 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;\r
1579 ChangeDispOffsetsY();\r
1580 updateDisplayIfChanged();\r
1581 }\r
1582 return;\r
1583\r
1584 // setting display infos\r
1585 case 0x08:\r
1586\r
1587 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];\r
1588\r
1589 if (gdata&0x04) PSXDisplay.Double=2;\r
1590 else PSXDisplay.Double=1;\r
1591 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;\r
1592\r
1593 ChangeDispOffsetsY();\r
1594 \r
1595 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC\r
1596 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor\r
1597 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace\r
1598\r
1599 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits\r
1600\r
1601 STATUSREG|=\r
1602 (((gdata & 0x03) << 17) | \r
1603 ((gdata & 0x40) << 10)); // set the width bits\r
1604\r
1605 PreviousPSXDisplay.InterlacedNew=FALSE;\r
1606 if (PSXDisplay.InterlacedNew)\r
1607 {\r
1608 if(!PSXDisplay.Interlaced)\r
1609 {\r
1610 PSXDisplay.InterlacedTest=2;\r
1611 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1612 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1613 PreviousPSXDisplay.InterlacedNew=TRUE;\r
1614 }\r
1615\r
1616 STATUSREG|=GPUSTATUS_INTERLACED;\r
1617 }\r
1618 else \r
1619 {\r
1620 PSXDisplay.InterlacedTest=0;\r
1621 STATUSREG&=~GPUSTATUS_INTERLACED;\r
1622 }\r
1623\r
1624 if (PSXDisplay.PAL)\r
1625 STATUSREG|=GPUSTATUS_PAL;\r
1626 else STATUSREG&=~GPUSTATUS_PAL;\r
1627\r
1628 if (PSXDisplay.Double==2)\r
1629 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;\r
1630 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;\r
1631\r
1632 if (PSXDisplay.RGB24New)\r
1633 STATUSREG|=GPUSTATUS_RGB24;\r
1634 else STATUSREG&=~GPUSTATUS_RGB24;\r
1635\r
1636 updateDisplayIfChanged();\r
1637\r
1638 return;\r
1639\r
1640 //--------------------------------------------------//\r
1641 // ask about GPU version and other stuff\r
1642 case 0x10: \r
1643\r
1644 gdata&=0xff;\r
1645\r
1646 switch(gdata) \r
1647 {\r
1648 case 0x02:\r
1649 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos\r
1650 return;\r
1651 case 0x03:\r
1652 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start\r
1653 return;\r
1654 case 0x04:\r
1655 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end\r
1656 return;\r
1657 case 0x05:\r
1658 case 0x06:\r
1659 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset\r
1660 return;\r
1661 case 0x07:\r
1662 if(dwGPUVersion==2)\r
1663 GPUdataRet=0x01;\r
1664 else GPUdataRet=0x02; // gpu type\r
1665 return;\r
1666 case 0x08:\r
1667 case 0x0F: // some bios addr?\r
1668 GPUdataRet=0xBFC03720;\r
1669 return;\r
1670 }\r
1671 return;\r
1672 //--------------------------------------------------//\r
1673 }\r
1674}\r
1675\r
1676////////////////////////////////////////////////////////////////////////\r
1677// vram read/write helpers\r
1678////////////////////////////////////////////////////////////////////////\r
1679\r
1680BOOL bNeedWriteUpload=FALSE;\r
1681\r
1682__inline void FinishedVRAMWrite(void)\r
1683{\r
1684 if(bNeedWriteUpload)\r
1685 {\r
1686 bNeedWriteUpload=FALSE;\r
1687 CheckWriteUpdate();\r
1688 }\r
1689\r
1690 // set register to NORMAL operation\r
1691 iDataWriteMode = DR_NORMAL;\r
1692\r
1693 // reset transfer values, to prevent mis-transfer of data\r
1694 VRAMWrite.ColsRemaining = 0;\r
1695 VRAMWrite.RowsRemaining = 0;\r
1696}\r
1697\r
1698__inline void FinishedVRAMRead(void)\r
1699{\r
1700 // set register to NORMAL operation\r
1701 iDataReadMode = DR_NORMAL;\r
1702 // reset transfer values, to prevent mis-transfer of data\r
1703 VRAMRead.x = 0;\r
1704 VRAMRead.y = 0;\r
1705 VRAMRead.Width = 0;\r
1706 VRAMRead.Height = 0;\r
1707 VRAMRead.ColsRemaining = 0;\r
1708 VRAMRead.RowsRemaining = 0;\r
1709\r
1710 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER\r
1711 STATUSREG&=~GPUSTATUS_READYFORVRAM;\r
1712}\r
1713\r
1714////////////////////////////////////////////////////////////////////////\r
1715// vram read check ex (reading from card's back/frontbuffer if needed...\r
1716// slow!)\r
1717////////////////////////////////////////////////////////////////////////\r
1718\r
1719void CheckVRamReadEx(int x, int y, int dx, int dy)\r
1720{\r
1721 unsigned short sArea;\r
1722 int ux,uy,udx,udy,wx,wy;\r
1723 unsigned short * p1, *p2;\r
1724 float XS,YS;\r
1725 u8 * ps;\r
1726 u8 * px;\r
1727 unsigned short s,sx;\r
1728\r
1729 if(STATUSREG&GPUSTATUS_RGB24) return;\r
1730\r
1731 if(((dx > PSXDisplay.DisplayPosition.x) &&\r
1732 (x < PSXDisplay.DisplayEnd.x) &&\r
1733 (dy > PSXDisplay.DisplayPosition.y) &&\r
1734 (y < PSXDisplay.DisplayEnd.y)))\r
1735 sArea=0;\r
1736 else\r
1737 if((!(PSXDisplay.InterlacedTest) &&\r
1738 (dx > PreviousPSXDisplay.DisplayPosition.x) &&\r
1739 (x < PreviousPSXDisplay.DisplayEnd.x) &&\r
1740 (dy > PreviousPSXDisplay.DisplayPosition.y) &&\r
1741 (y < PreviousPSXDisplay.DisplayEnd.y)))\r
1742 sArea=1;\r
1743 else \r
1744 {\r
1745 return;\r
1746 }\r
1747\r
1748 //////////////\r
1749\r
1750 if(iRenderFVR)\r
1751 {\r
1752 bFullVRam=TRUE;iRenderFVR=2;return;\r
1753 }\r
1754 bFullVRam=TRUE;iRenderFVR=2;\r
1755\r
1756 //////////////\r
1757\r
1758 p2=0;\r
1759\r
1760 if(sArea==0)\r
1761 {\r
1762 ux=PSXDisplay.DisplayPosition.x;\r
1763 uy=PSXDisplay.DisplayPosition.y;\r
1764 udx=PSXDisplay.DisplayEnd.x-ux;\r
1765 udy=PSXDisplay.DisplayEnd.y-uy;\r
1766 if((PreviousPSXDisplay.DisplayEnd.x-\r
1767 PreviousPSXDisplay.DisplayPosition.x)==udx &&\r
1768 (PreviousPSXDisplay.DisplayEnd.y-\r
1769 PreviousPSXDisplay.DisplayPosition.y)==udy)\r
1770 p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + \r
1771 PreviousPSXDisplay.DisplayPosition.x);\r
1772 }\r
1773 else\r
1774 {\r
1775 ux=PreviousPSXDisplay.DisplayPosition.x;\r
1776 uy=PreviousPSXDisplay.DisplayPosition.y;\r
1777 udx=PreviousPSXDisplay.DisplayEnd.x-ux;\r
1778 udy=PreviousPSXDisplay.DisplayEnd.y-uy;\r
1779 if((PSXDisplay.DisplayEnd.x-\r
1780 PSXDisplay.DisplayPosition.x)==udx &&\r
1781 (PSXDisplay.DisplayEnd.y-\r
1782 PSXDisplay.DisplayPosition.y)==udy)\r
1783 p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + \r
1784 PSXDisplay.DisplayPosition.x);\r
1785 }\r
1786\r
1787 p1=(psxVuw + (1024*uy) + ux);\r
1788 if(p1==p2) p2=0;\r
1789\r
1790 x=0;y=0;\r
1791 wx=dx=udx;wy=dy=udy;\r
1792\r
1793 if(udx<=0) return;\r
1794 if(udy<=0) return;\r
1795 if(dx<=0) return;\r
1796 if(dy<=0) return;\r
1797 if(wx<=0) return;\r
1798 if(wy<=0) return;\r
1799\r
1800 XS=(float)rRatioRect.right/(float)wx;\r
1801 YS=(float)rRatioRect.bottom/(float)wy;\r
1802\r
1803 dx=(int)((float)(dx)*XS);\r
1804 dy=(int)((float)(dy)*YS);\r
1805\r
1806 if(dx>iResX) dx=iResX;\r
1807 if(dy>iResY) dy=iResY;\r
1808\r
1809 if(dx<=0) return;\r
1810 if(dy<=0) return;\r
1811\r
1812 // ogl y adjust\r
1813 y=iResY-y-dy;\r
1814\r
1815 x+=rRatioRect.left;\r
1816 y-=rRatioRect.top;\r
1817\r
1818 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1819\r
1820 if(!pGfxCardScreen)\r
1821 {\r
1822 glPixelStorei(GL_PACK_ALIGNMENT,1);\r
1823 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);\r
1824 }\r
1825\r
1826 ps=pGfxCardScreen;\r
1827 \r
1828 //if(!sArea) glReadBuffer(GL_FRONT);\r
1829\r
1830 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);\r
1831 \r
1832 //if(!sArea) glReadBuffer(GL_BACK);\r
1833\r
1834 s=0;\r
1835\r
1836 XS=(float)dx/(float)(udx);\r
1837 YS=(float)dy/(float)(udy+1);\r
1838 \r
1839 for(y=udy;y>0;y--)\r
1840 {\r
1841 for(x=0;x<udx;x++)\r
1842 {\r
1843 if(p1>=psxVuw && p1<psxVuw_eom)\r
1844 {\r
1845 px=ps+(3*((int)((float)x * XS))+\r
1846 (3*dx)*((int)((float)y*YS)));\r
1847 sx=(*px)>>3;px++;\r
1848 s=sx;\r
1849 sx=(*px)>>3;px++;\r
1850 s|=sx<<5;\r
1851 sx=(*px)>>3;\r
1852 s|=sx<<10;\r
1853 s&=~0x8000;\r
1854 *p1=s;\r
1855 }\r
1856 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;\r
1857\r
1858 p1++;\r
1859 if(p2) p2++;\r
1860 }\r
1861\r
1862 p1 += 1024 - udx;\r
1863 if(p2) p2 += 1024 - udx;\r
1864 }\r
1865}\r
1866\r
1867////////////////////////////////////////////////////////////////////////\r
1868// vram read check (reading from card's back/frontbuffer if needed... \r
1869// slow!)\r
1870////////////////////////////////////////////////////////////////////////\r
1871\r
1872void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)\r
1873{\r
1874 unsigned short sArea;unsigned short * p;\r
1875 int ux,uy,udx,udy,wx,wy;float XS,YS;\r
1876 u8 * ps, * px;\r
1877 unsigned short s=0,sx;\r
1878\r
1879 if(STATUSREG&GPUSTATUS_RGB24) return;\r
1880\r
1881 if(((dx > PSXDisplay.DisplayPosition.x) &&\r
1882 (x < PSXDisplay.DisplayEnd.x) &&\r
1883 (dy > PSXDisplay.DisplayPosition.y) &&\r
1884 (y < PSXDisplay.DisplayEnd.y)))\r
1885 sArea=0;\r
1886 else\r
1887 if((!(PSXDisplay.InterlacedTest) &&\r
1888 (dx > PreviousPSXDisplay.DisplayPosition.x) &&\r
1889 (x < PreviousPSXDisplay.DisplayEnd.x) &&\r
1890 (dy > PreviousPSXDisplay.DisplayPosition.y) &&\r
1891 (y < PreviousPSXDisplay.DisplayEnd.y)))\r
1892 sArea=1;\r
1893 else \r
1894 {\r
1895 return;\r
1896 }\r
1897\r
1898 if(dwActFixes&0x40)\r
1899 {\r
1900 if(iRenderFVR)\r
1901 {\r
1902 bFullVRam=TRUE;iRenderFVR=2;return;\r
1903 }\r
1904 bFullVRam=TRUE;iRenderFVR=2;\r
1905 }\r
1906\r
1907 ux=x;uy=y;udx=dx;udy=dy;\r
1908\r
1909 if(sArea==0)\r
1910 {\r
1911 x -=PSXDisplay.DisplayPosition.x;\r
1912 dx-=PSXDisplay.DisplayPosition.x;\r
1913 y -=PSXDisplay.DisplayPosition.y;\r
1914 dy-=PSXDisplay.DisplayPosition.y;\r
1915 wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;\r
1916 wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;\r
1917 }\r
1918 else\r
1919 {\r
1920 x -=PreviousPSXDisplay.DisplayPosition.x;\r
1921 dx-=PreviousPSXDisplay.DisplayPosition.x;\r
1922 y -=PreviousPSXDisplay.DisplayPosition.y;\r
1923 dy-=PreviousPSXDisplay.DisplayPosition.y;\r
1924 wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;\r
1925 wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;\r
1926 }\r
1927 if(x<0) {ux-=x;x=0;}\r
1928 if(y<0) {uy-=y;y=0;}\r
1929 if(dx>wx) {udx-=(dx-wx);dx=wx;}\r
1930 if(dy>wy) {udy-=(dy-wy);dy=wy;}\r
1931 udx-=ux;\r
1932 udy-=uy;\r
1933 \r
1934 p=(psxVuw + (1024*uy) + ux);\r
1935\r
1936 if(udx<=0) return;\r
1937 if(udy<=0) return;\r
1938 if(dx<=0) return;\r
1939 if(dy<=0) return;\r
1940 if(wx<=0) return;\r
1941 if(wy<=0) return;\r
1942\r
1943 XS=(float)rRatioRect.right/(float)wx;\r
1944 YS=(float)rRatioRect.bottom/(float)wy;\r
1945\r
1946 dx=(int)((float)(dx)*XS);\r
1947 dy=(int)((float)(dy)*YS);\r
1948 x=(int)((float)x*XS);\r
1949 y=(int)((float)y*YS);\r
1950\r
1951 dx-=x;\r
1952 dy-=y;\r
1953\r
1954 if(dx>iResX) dx=iResX;\r
1955 if(dy>iResY) dy=iResY;\r
1956\r
1957 if(dx<=0) return;\r
1958 if(dy<=0) return;\r
1959\r
1960 // ogl y adjust\r
1961 y=iResY-y-dy;\r
1962\r
1963 x+=rRatioRect.left;\r
1964 y-=rRatioRect.top;\r
1965\r
1966 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1967\r
1968 if(!pGfxCardScreen)\r
1969 {\r
1970 glPixelStorei(GL_PACK_ALIGNMENT,1);\r
1971 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);\r
1972 }\r
1973\r
1974 ps=pGfxCardScreen;\r
1975 \r
1976// if(bFront) glReadBuffer(GL_FRONT);\r
1977\r
1978 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);\r
1979 \r
1980// if(bFront) glReadBuffer(GL_BACK);\r
1981\r
1982 XS=(float)dx/(float)(udx);\r
1983 YS=(float)dy/(float)(udy+1);\r
1984 \r
1985 for(y=udy;y>0;y--)\r
1986 {\r
1987 for(x=0;x<udx;x++)\r
1988 {\r
1989 if(p>=psxVuw && p<psxVuw_eom)\r
1990 {\r
1991 px=ps+(3*((int)((float)x * XS))+\r
1992 (3*dx)*((int)((float)y*YS)));\r
1993 sx=(*px)>>3;px++;\r
1994 s=sx;\r
1995 sx=(*px)>>3;px++;\r
1996 s|=sx<<5;\r
1997 sx=(*px)>>3;\r
1998 s|=sx<<10;\r
1999 s&=~0x8000;\r
2000 *p=s;\r
2001 }\r
2002 p++;\r
2003 }\r
2004 p += 1024 - udx;\r
2005 }\r
2006}\r
2007\r
2008////////////////////////////////////////////////////////////////////////\r
2009// core read from vram\r
2010////////////////////////////////////////////////////////////////////////\r
2011\r
2012#ifdef _WINDOWS\r
2013void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize)\r
2014#else\r
2015void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize)\r
2016#endif\r
2017{\r
2018int i;\r
2019\r
2020if(iDataReadMode!=DR_VRAMTRANSFER) return;\r
2021\r
2022GPUIsBusy;\r
2023\r
2024// adjust read ptr, if necessary\r
2025while(VRAMRead.ImagePtr>=psxVuw_eom)\r
2026 VRAMRead.ImagePtr-=iGPUHeight*1024;\r
2027while(VRAMRead.ImagePtr<psxVuw)\r
2028 VRAMRead.ImagePtr+=iGPUHeight*1024;\r
2029\r
2030if((iFrameReadType&1 && iSize>1) &&\r
2031 !(iDrawnSomething==2 &&\r
2032 VRAMRead.x == VRAMWrite.x &&\r
2033 VRAMRead.y == VRAMWrite.y &&\r
2034 VRAMRead.Width == VRAMWrite.Width &&\r
2035 VRAMRead.Height == VRAMWrite.Height))\r
2036 CheckVRamRead(VRAMRead.x,VRAMRead.y,\r
2037 VRAMRead.x+VRAMRead.RowsRemaining,\r
2038 VRAMRead.y+VRAMRead.ColsRemaining,\r
2039 TRUE);\r
2040\r
2041for(i=0;i<iSize;i++)\r
2042 {\r
2043 // do 2 seperate 16bit reads for compatibility (wrap issues)\r
2044 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))\r
2045 {\r
2046 // lower 16 bit\r
2047 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;\r
2048\r
2049 VRAMRead.ImagePtr++;\r
2050 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
2051 VRAMRead.RowsRemaining --;\r
2052\r
2053 if(VRAMRead.RowsRemaining<=0)\r
2054 {\r
2055 VRAMRead.RowsRemaining = VRAMRead.Width;\r
2056 VRAMRead.ColsRemaining--;\r
2057 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
2058 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
2059 }\r
2060\r
2061 // higher 16 bit (always, even if it's an odd width)\r
2062 GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;\r
2063 *pMem++=GPUdataRet;\r
2064\r
2065 if(VRAMRead.ColsRemaining <= 0)\r
2066 {FinishedVRAMRead();goto ENDREAD;}\r
2067\r
2068 VRAMRead.ImagePtr++;\r
2069 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
2070 VRAMRead.RowsRemaining--;\r
2071 if(VRAMRead.RowsRemaining<=0)\r
2072 {\r
2073 VRAMRead.RowsRemaining = VRAMRead.Width;\r
2074 VRAMRead.ColsRemaining--;\r
2075 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
2076 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
2077 }\r
2078 if(VRAMRead.ColsRemaining <= 0)\r
2079 {FinishedVRAMRead();goto ENDREAD;}\r
2080 }\r
2081 else {FinishedVRAMRead();goto ENDREAD;}\r
2082 }\r
2083\r
2084ENDREAD:\r
2085GPUIsIdle;\r
2086}\r
2087\r
2088#ifdef _WINDOWS\r
2089unsigned long CALLBACK GPUreadData(void)\r
2090#else\r
2091unsigned long CALLBACK GPU_readData(void)\r
2092#endif\r
2093{\r
2094 unsigned long l;\r
2095#ifdef _WINDOWS\r
2096 GPUreadDataMem(&l,1);\r
2097#else\r
2098 GPU_readDataMem(&l,1);\r
2099#endif \r
2100 return GPUdataRet;\r
2101}\r
2102\r
2103////////////////////////////////////////////////////////////////////////\r
2104// helper table to know how much data is used by drawing commands\r
2105////////////////////////////////////////////////////////////////////////\r
2106\r
2107const u8 primTableCX[256] =\r
2108{\r
2109 // 00\r
2110 0,0,3,0,0,0,0,0,\r
2111 // 08\r
2112 0,0,0,0,0,0,0,0,\r
2113 // 10\r
2114 0,0,0,0,0,0,0,0,\r
2115 // 18\r
2116 0,0,0,0,0,0,0,0,\r
2117 // 20\r
2118 4,4,4,4,7,7,7,7,\r
2119 // 28\r
2120 5,5,5,5,9,9,9,9,\r
2121 // 30\r
2122 6,6,6,6,9,9,9,9,\r
2123 // 38\r
2124 8,8,8,8,12,12,12,12,\r
2125 // 40\r
2126 3,3,3,3,0,0,0,0,\r
2127 // 48\r
2128// 5,5,5,5,6,6,6,6, //FLINE\r
2129 254,254,254,254,254,254,254,254,\r
2130 // 50\r
2131 4,4,4,4,0,0,0,0,\r
2132 // 58\r
2133// 7,7,7,7,9,9,9,9, // LINEG3 LINEG4\r
2134 255,255,255,255,255,255,255,255,\r
2135 // 60\r
2136 3,3,3,3,4,4,4,4, // TILE SPRT\r
2137 // 68\r
2138 2,2,2,2,3,3,3,3, // TILE1\r
2139 // 70\r
2140 2,2,2,2,3,3,3,3,\r
2141 // 78\r
2142 2,2,2,2,3,3,3,3,\r
2143 // 80\r
2144 4,0,0,0,0,0,0,0,\r
2145 // 88\r
2146 0,0,0,0,0,0,0,0,\r
2147 // 90\r
2148 0,0,0,0,0,0,0,0,\r
2149 // 98\r
2150 0,0,0,0,0,0,0,0,\r
2151 // a0\r
2152 3,0,0,0,0,0,0,0,\r
2153 // a8\r
2154 0,0,0,0,0,0,0,0,\r
2155 // b0\r
2156 0,0,0,0,0,0,0,0,\r
2157 // b8\r
2158 0,0,0,0,0,0,0,0,\r
2159 // c0\r
2160 3,0,0,0,0,0,0,0,\r
2161 // c8\r
2162 0,0,0,0,0,0,0,0,\r
2163 // d0\r
2164 0,0,0,0,0,0,0,0,\r
2165 // d8\r
2166 0,0,0,0,0,0,0,0,\r
2167 // e0\r
2168 0,1,1,1,1,1,1,0,\r
2169 // e8\r
2170 0,0,0,0,0,0,0,0,\r
2171 // f0\r
2172 0,0,0,0,0,0,0,0,\r
2173 // f8\r
2174 0,0,0,0,0,0,0,0\r
2175};\r
2176\r
2177////////////////////////////////////////////////////////////////////////\r
2178// processes data send to GPU data register\r
2179////////////////////////////////////////////////////////////////////////\r
2180\r
2181#ifdef _WINDOWS\r
2182void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)\r
2183#else\r
2184void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize)\r
2185#endif\r
2186{\r
2187u8 command;\r
2188unsigned long gdata=0;\r
2189int i=0;\r
2190GPUIsBusy;\r
2191GPUIsNotReadyForCommands;\r
2192\r
2193STARTVRAM:\r
2194\r
2195if(iDataWriteMode==DR_VRAMTRANSFER)\r
2196 {\r
2197 // make sure we are in vram\r
2198 while(VRAMWrite.ImagePtr>=psxVuw_eom)\r
2199 VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
2200 while(VRAMWrite.ImagePtr<psxVuw)\r
2201 VRAMWrite.ImagePtr+=iGPUHeight*1024;\r
2202\r
2203 // now do the loop\r
2204 while(VRAMWrite.ColsRemaining>0)\r
2205 {\r
2206 while(VRAMWrite.RowsRemaining>0)\r
2207 {\r
2208 if(i>=iSize) {goto ENDVRAM;}\r
2209 i++;\r
2210\r
2211 gdata=*pMem++;\r
2212\r
2213 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;\r
2214 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
2215 VRAMWrite.RowsRemaining --;\r
2216\r
2217 if(VRAMWrite.RowsRemaining <= 0)\r
2218 {\r
2219 VRAMWrite.ColsRemaining--;\r
2220 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width\r
2221 {\r
2222 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);\r
2223 FinishedVRAMWrite();\r
2224 goto ENDVRAM;\r
2225 }\r
2226 VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
2227 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
2228 }\r
2229\r
2230 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);\r
2231 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
2232 VRAMWrite.RowsRemaining --;\r
2233 }\r
2234\r
2235 VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
2236 VRAMWrite.ColsRemaining--;\r
2237 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
2238 }\r
2239\r
2240 FinishedVRAMWrite();\r
2241 }\r
2242\r
2243ENDVRAM:\r
2244\r
2245if(iDataWriteMode==DR_NORMAL)\r
2246 {\r
2247 void (* *primFunc)(u8 *);\r
2248 if(bSkipNextFrame) primFunc=primTableSkip;\r
2249 else primFunc=primTableJ;\r
2250\r
2251 for(;i<iSize;)\r
2252 {\r
2253 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;\r
2254\r
2255 gdata=*pMem++;i++;\r
2256\r
2257 if(gpuDataC == 0)\r
2258 {\r
2259 command = (u8)((gdata>>24) & 0xff);\r
2260\r
2261 if(primTableCX[command])\r
2262 {\r
2263 gpuDataC = primTableCX[command];\r
2264 gpuCommand = command;\r
2265 gpuDataM[0] = gdata;\r
2266 gpuDataP = 1;\r
2267 }\r
2268 else continue;\r
2269 }\r
2270 else\r
2271 {\r
2272 gpuDataM[gpuDataP] = gdata;\r
2273 if(gpuDataC>128)\r
2274 {\r
2275 if((gpuDataC==254 && gpuDataP>=3) ||\r
2276 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))\r
2277 {\r
2278 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)\r
2279 gpuDataP=gpuDataC-1;\r
2280 }\r
2281 }\r
2282 gpuDataP++;\r
2283 }\r
2284\r
2285 if(gpuDataP == gpuDataC)\r
2286 {\r
2287 gpuDataC=gpuDataP=0;\r
2288 primFunc[gpuCommand]((u8 *)gpuDataM);\r
2289\r
2290 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games\r
2291 iFakePrimBusy=4;\r
2292 }\r
2293 } \r
2294 }\r
2295\r
2296GPUdataRet=gdata;\r
2297\r
2298GPUIsReadyForCommands;\r
2299GPUIsIdle; \r
2300}\r
2301\r
2302////////////////////////////////////////////////////////////////////////\r
2303\r
2304#ifdef _WINDOWS\r
2305void CALLBACK GPUwriteData(unsigned long gdata)\r
2306#else\r
2307void CALLBACK GPU_writeData(unsigned long gdata)\r
2308#endif\r
2309{\r
2310#ifdef _WINDOWS\r
2311 GPUwriteDataMem(&gdata,1);\r
2312#else\r
2313 GPU_writeDataMem(&gdata,1);\r
2314#endif \r
2315}\r
2316\r
2317////////////////////////////////////////////////////////////////////////\r
2318// this function will be removed soon (or 'soonish') (or never)\r
2319////////////////////////////////////////////////////////////////////////\r
2320\r
2321void CALLBACK GPUsetMode(unsigned int gdata)\r
2322{\r
2323 // ignore old psemu setmode:\r
2324\r
2325 // imageTransfer = gdata;\r
2326 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;\r
2327 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;\r
2328}\r
2329\r
2330// and this function will be removed soon as well, hehehe...\r
2331long CALLBACK GPUgetMode(void)\r
2332{\r
2333 // ignore old psemu setmode\r
2334 // return imageTransfer;\r
2335\r
2336long iT=0;\r
2337\r
2338if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;\r
2339if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;\r
2340\r
2341return iT;\r
2342}\r
2343\r
2344////////////////////////////////////////////////////////////////////////\r
2345// call config dlg (Windows + Linux)\r
2346////////////////////////////////////////////////////////////////////////\r
2347\r
2348#ifndef _WINDOWS\r
2349\r
2350/*#include <unistd.h>\r
2351\r
2352void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool\r
2353{\r
2354 FILE * cf;s8 filename[255],t[255];\r
2355\r
2356 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first\r
2357 cf=fopen(filename,"rb");\r
2358 if(cf!=NULL)\r
2359 {\r
2360 fclose(cf);\r
2361 getcwd(t,255);\r
2362 chdir("cfg");\r
2363 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2364 system(filename);\r
2365 chdir(t);\r
2366 }\r
2367 else\r
2368 {\r
2369 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder\r
2370 cf=fopen(filename,"rb");\r
2371 if(cf!=NULL)\r
2372 {\r
2373 fclose(cf);\r
2374 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2375 system(filename);\r
2376 }\r
2377 else\r
2378 {\r
2379 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder\r
2380 cf=fopen(filename,"rb");\r
2381 if(cf!=NULL)\r
2382 {\r
2383 fclose(cf);\r
2384 getcwd(t,255);\r
2385 chdir(getenv("HOME"));\r
2386 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2387 system(filename);\r
2388 chdir(t);\r
2389 }\r
2390 else printf("cfgPeopsMesaGL not found!\n");\r
2391 }\r
2392 }\r
2393}\r
2394*/\r
2395#endif\r
2396\r
2397\r
2398#ifdef _WINDOWS\r
2399long CALLBACK GPUconfigure(void)\r
2400#else\r
2401long CALLBACK GPU_configure(void)\r
2402#endif\r
2403{\r
2404\r
2405#ifdef _WINDOWS\r
2406// HWND hWP=GetActiveWindow();\r
2407// DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),\r
2408// hWP,(DLGPROC)CfgDlgProc);\r
2409#else\r
2410\r
2411// StartCfgTool("CFG");\r
2412\r
2413#endif\r
2414\r
2415 return 0;\r
2416}\r
2417\r
2418////////////////////////////////////////////////////////////////////////\r
2419// sets all kind of act fixes\r
2420////////////////////////////////////////////////////////////////////////\r
2421\r
2422void SetFixes(void)\r
2423{\r
2424 ReInitFrameCap();\r
2425\r
2426 if(dwActFixes & 0x2000) \r
2427 dispWidths[4]=384;\r
2428 else dispWidths[4]=368;\r
2429}\r
2430\r
2431////////////////////////////////////////////////////////////////////////\r
2432// Pete Special: make an 'intelligent' dma chain check (<-Tekken3)\r
2433////////////////////////////////////////////////////////////////////////\r
2434\r
2435unsigned long lUsedAddr[3];\r
2436\r
2437__inline BOOL CheckForEndlessLoop(unsigned long laddr)\r
2438{\r
2439if(laddr==lUsedAddr[1]) return TRUE;\r
2440if(laddr==lUsedAddr[2]) return TRUE;\r
2441\r
2442if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;\r
2443else lUsedAddr[2]=laddr;\r
2444lUsedAddr[0]=laddr;\r
2445return FALSE;\r
2446}\r
2447\r
2448////////////////////////////////////////////////////////////////////////\r
2449// core gives a dma chain to gpu: same as the gpuwrite interface funcs\r
2450////////////////////////////////////////////////////////////////////////\r
2451\r
2452#ifdef _WINDOWS\r
2453long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)\r
2454#else\r
2455long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr)\r
2456#endif\r
2457{\r
2458unsigned long dmaMem;\r
2459u8 * baseAddrB;\r
2460short count;unsigned int DMACommandCounter = 0;\r
2461\r
2462if(bIsFirstFrame) GLinitialize();\r
2463\r
2464GPUIsBusy;\r
2465\r
2466lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;\r
2467\r
2468baseAddrB = (u8*) baseAddrL;\r
2469\r
2470do\r
2471 {\r
2472 if(iGPUHeight==512) addr&=0x1FFFFC;\r
2473\r
2474 if(DMACommandCounter++ > 2000000) break;\r
2475 if(CheckForEndlessLoop(addr)) break;\r
2476\r
2477 count = baseAddrB[addr+3];\r
2478\r
2479 dmaMem=addr+4;\r
2480\r
2481#ifdef _WINDOWS\r
2482 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);\r
2483#else\r
2484 if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count);\r
2485#endif\r
2486 \r
2487 addr = baseAddrL[addr>>2]&0xffffff;\r
2488 }\r
2489while (addr != 0xffffff);\r
2490\r
2491GPUIsIdle;\r
2492\r
2493return 0;\r
2494}\r
2495 \r
2496////////////////////////////////////////////////////////////////////////\r
2497// show about dlg\r
2498////////////////////////////////////////////////////////////////////////\r
2499\r
2500#ifdef _WINDOWS\r
2501void CALLBACK GPUabout(void)\r
2502#else\r
2503void CALLBACK GPU_about(void)\r
2504#endif\r
2505{\r
2506\r
2507}\r
2508\r
2509////////////////////////////////////////////////////////////////////////\r
2510// We are ever fine ;)\r
2511////////////////////////////////////////////////////////////////////////\r
2512\r
2513#ifdef _WINDOWS\r
2514long CALLBACK GPUtest(void)\r
2515#else\r
2516long CALLBACK GPU_test(void)\r
2517#endif\r
2518{\r
2519 // if test fails this function should return negative value for error (unable to continue)\r
2520 // and positive value for warning (can continue but output might be crappy)\r
2521\r
2522 return 0;\r
2523}\r
2524\r
2525////////////////////////////////////////////////////////////////////////\r
2526// save state funcs\r
2527////////////////////////////////////////////////////////////////////////\r
2528\r
2529////////////////////////////////////////////////////////////////////////\r
2530\r
2531#ifdef _WINDOWS\r
2532long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)\r
2533#else\r
2534long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)\r
2535#endif\r
2536{\r
2537if(ulGetFreezeData==2) \r
2538 {\r
2539 long lSlotNum=*((long *)pF);\r
2540 if(lSlotNum<0) return 0;\r
2541 if(lSlotNum>8) return 0;\r
2542 lSelectedSlot=lSlotNum+1;\r
2543 return 1;\r
2544 }\r
2545\r
2546if(!pF) return 0; \r
2547if(pF->ulFreezeVersion!=1) return 0;\r
2548\r
2549if(ulGetFreezeData==1)\r
2550 {\r
2551 pF->ulStatus=STATUSREG;\r
2552 memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));\r
2553 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);\r
2554\r
2555 return 1;\r
2556 }\r
2557\r
2558if(ulGetFreezeData!=0) return 0;\r
2559\r
2560STATUSREG=pF->ulStatus;\r
2561memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));\r
2562memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);\r
2563\r
2564ResetTextureArea(TRUE);\r
2565\r
2566#ifdef _WINDOWS\r
2567 GPUwriteStatus(ulStatusControl[0]);\r
2568 GPUwriteStatus(ulStatusControl[1]);\r
2569 GPUwriteStatus(ulStatusControl[2]);\r
2570 GPUwriteStatus(ulStatusControl[3]);\r
2571 GPUwriteStatus(ulStatusControl[8]);\r
2572 GPUwriteStatus(ulStatusControl[6]);\r
2573 GPUwriteStatus(ulStatusControl[7]);\r
2574 GPUwriteStatus(ulStatusControl[5]);\r
2575 GPUwriteStatus(ulStatusControl[4]);\r
2576#else\r
2577 GPU_writeStatus(ulStatusControl[0]);\r
2578 GPU_writeStatus(ulStatusControl[1]);\r
2579 GPU_writeStatus(ulStatusControl[2]);\r
2580 GPU_writeStatus(ulStatusControl[3]);\r
2581 GPU_writeStatus(ulStatusControl[8]);\r
2582 GPU_writeStatus(ulStatusControl[6]);\r
2583 GPU_writeStatus(ulStatusControl[7]);\r
2584 GPU_writeStatus(ulStatusControl[5]);\r
2585 GPU_writeStatus(ulStatusControl[4]);\r
2586#endif\r
2587 return 1;\r
2588}\r
2589\r
2590////////////////////////////////////////////////////////////////////////\r
2591// special "emu infos" / "emu effects" functions\r
2592////////////////////////////////////////////////////////////////////////\r
2593\r
2594//00 = black\r
2595//01 = white\r
2596//10 = red\r
2597//11 = transparent\r
2598\r
2599u8 cFont[10][120]=\r
2600{\r
2601// 0\r
2602{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2603 0x80,0x00,0x00,0x00,0x00,0x00,\r
2604 0x80,0x00,0x00,0x00,0x00,0x00,\r
2605 0x80,0x00,0x00,0x00,0x00,0x00,\r
2606 0x80,0x00,0x00,0x00,0x00,0x00,\r
2607 0x80,0x00,0x05,0x54,0x00,0x00,\r
2608 0x80,0x00,0x14,0x05,0x00,0x00,\r
2609 0x80,0x00,0x14,0x05,0x00,0x00,\r
2610 0x80,0x00,0x14,0x05,0x00,0x00,\r
2611 0x80,0x00,0x14,0x05,0x00,0x00,\r
2612 0x80,0x00,0x14,0x05,0x00,0x00,\r
2613 0x80,0x00,0x14,0x05,0x00,0x00,\r
2614 0x80,0x00,0x14,0x05,0x00,0x00,\r
2615 0x80,0x00,0x14,0x05,0x00,0x00,\r
2616 0x80,0x00,0x05,0x54,0x00,0x00,\r
2617 0x80,0x00,0x00,0x00,0x00,0x00,\r
2618 0x80,0x00,0x00,0x00,0x00,0x00,\r
2619 0x80,0x00,0x00,0x00,0x00,0x00,\r
2620 0x80,0x00,0x00,0x00,0x00,0x00,\r
2621 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2622},\r
2623// 1\r
2624{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2625 0x80,0x00,0x00,0x00,0x00,0x00,\r
2626 0x80,0x00,0x00,0x00,0x00,0x00,\r
2627 0x80,0x00,0x00,0x00,0x00,0x00,\r
2628 0x80,0x00,0x00,0x00,0x00,0x00,\r
2629 0x80,0x00,0x00,0x50,0x00,0x00,\r
2630 0x80,0x00,0x05,0x50,0x00,0x00,\r
2631 0x80,0x00,0x00,0x50,0x00,0x00,\r
2632 0x80,0x00,0x00,0x50,0x00,0x00,\r
2633 0x80,0x00,0x00,0x50,0x00,0x00,\r
2634 0x80,0x00,0x00,0x50,0x00,0x00,\r
2635 0x80,0x00,0x00,0x50,0x00,0x00,\r
2636 0x80,0x00,0x00,0x50,0x00,0x00,\r
2637 0x80,0x00,0x00,0x50,0x00,0x00,\r
2638 0x80,0x00,0x05,0x55,0x00,0x00,\r
2639 0x80,0x00,0x00,0x00,0x00,0x00,\r
2640 0x80,0x00,0x00,0x00,0x00,0x00,\r
2641 0x80,0x00,0x00,0x00,0x00,0x00,\r
2642 0x80,0x00,0x00,0x00,0x00,0x00,\r
2643 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2644},\r
2645// 2\r
2646{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2647 0x80,0x00,0x00,0x00,0x00,0x00,\r
2648 0x80,0x00,0x00,0x00,0x00,0x00,\r
2649 0x80,0x00,0x00,0x00,0x00,0x00,\r
2650 0x80,0x00,0x00,0x00,0x00,0x00,\r
2651 0x80,0x00,0x05,0x54,0x00,0x00,\r
2652 0x80,0x00,0x14,0x05,0x00,0x00,\r
2653 0x80,0x00,0x00,0x05,0x00,0x00,\r
2654 0x80,0x00,0x00,0x05,0x00,0x00,\r
2655 0x80,0x00,0x00,0x14,0x00,0x00,\r
2656 0x80,0x00,0x00,0x50,0x00,0x00,\r
2657 0x80,0x00,0x01,0x40,0x00,0x00,\r
2658 0x80,0x00,0x05,0x00,0x00,0x00,\r
2659 0x80,0x00,0x14,0x00,0x00,0x00,\r
2660 0x80,0x00,0x15,0x55,0x00,0x00,\r
2661 0x80,0x00,0x00,0x00,0x00,0x00,\r
2662 0x80,0x00,0x00,0x00,0x00,0x00,\r
2663 0x80,0x00,0x00,0x00,0x00,0x00,\r
2664 0x80,0x00,0x00,0x00,0x00,0x00,\r
2665 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2666},\r
2667// 3\r
2668{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2669 0x80,0x00,0x00,0x00,0x00,0x00,\r
2670 0x80,0x00,0x00,0x00,0x00,0x00,\r
2671 0x80,0x00,0x00,0x00,0x00,0x00,\r
2672 0x80,0x00,0x00,0x00,0x00,0x00,\r
2673 0x80,0x00,0x05,0x54,0x00,0x00,\r
2674 0x80,0x00,0x14,0x05,0x00,0x00,\r
2675 0x80,0x00,0x00,0x05,0x00,0x00,\r
2676 0x80,0x00,0x00,0x05,0x00,0x00,\r
2677 0x80,0x00,0x01,0x54,0x00,0x00,\r
2678 0x80,0x00,0x00,0x05,0x00,0x00,\r
2679 0x80,0x00,0x00,0x05,0x00,0x00,\r
2680 0x80,0x00,0x00,0x05,0x00,0x00,\r
2681 0x80,0x00,0x14,0x05,0x00,0x00,\r
2682 0x80,0x00,0x05,0x54,0x00,0x00,\r
2683 0x80,0x00,0x00,0x00,0x00,0x00,\r
2684 0x80,0x00,0x00,0x00,0x00,0x00,\r
2685 0x80,0x00,0x00,0x00,0x00,0x00,\r
2686 0x80,0x00,0x00,0x00,0x00,0x00,\r
2687 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2688},\r
2689// 4\r
2690{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2691 0x80,0x00,0x00,0x00,0x00,0x00,\r
2692 0x80,0x00,0x00,0x00,0x00,0x00,\r
2693 0x80,0x00,0x00,0x00,0x00,0x00,\r
2694 0x80,0x00,0x00,0x00,0x00,0x00,\r
2695 0x80,0x00,0x00,0x14,0x00,0x00,\r
2696 0x80,0x00,0x00,0x54,0x00,0x00,\r
2697 0x80,0x00,0x01,0x54,0x00,0x00,\r
2698 0x80,0x00,0x01,0x54,0x00,0x00,\r
2699 0x80,0x00,0x05,0x14,0x00,0x00,\r
2700 0x80,0x00,0x14,0x14,0x00,0x00,\r
2701 0x80,0x00,0x15,0x55,0x00,0x00,\r
2702 0x80,0x00,0x00,0x14,0x00,0x00,\r
2703 0x80,0x00,0x00,0x14,0x00,0x00,\r
2704 0x80,0x00,0x00,0x55,0x00,0x00,\r
2705 0x80,0x00,0x00,0x00,0x00,0x00,\r
2706 0x80,0x00,0x00,0x00,0x00,0x00,\r
2707 0x80,0x00,0x00,0x00,0x00,0x00,\r
2708 0x80,0x00,0x00,0x00,0x00,0x00,\r
2709 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2710},\r
2711// 5\r
2712{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2713 0x80,0x00,0x00,0x00,0x00,0x00,\r
2714 0x80,0x00,0x00,0x00,0x00,0x00,\r
2715 0x80,0x00,0x00,0x00,0x00,0x00,\r
2716 0x80,0x00,0x00,0x00,0x00,0x00,\r
2717 0x80,0x00,0x15,0x55,0x00,0x00,\r
2718 0x80,0x00,0x14,0x00,0x00,0x00,\r
2719 0x80,0x00,0x14,0x00,0x00,0x00,\r
2720 0x80,0x00,0x14,0x00,0x00,0x00,\r
2721 0x80,0x00,0x15,0x54,0x00,0x00,\r
2722 0x80,0x00,0x00,0x05,0x00,0x00,\r
2723 0x80,0x00,0x00,0x05,0x00,0x00,\r
2724 0x80,0x00,0x00,0x05,0x00,0x00,\r
2725 0x80,0x00,0x14,0x05,0x00,0x00,\r
2726 0x80,0x00,0x05,0x54,0x00,0x00,\r
2727 0x80,0x00,0x00,0x00,0x00,0x00,\r
2728 0x80,0x00,0x00,0x00,0x00,0x00,\r
2729 0x80,0x00,0x00,0x00,0x00,0x00,\r
2730 0x80,0x00,0x00,0x00,0x00,0x00,\r
2731 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2732},\r
2733// 6\r
2734{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2735 0x80,0x00,0x00,0x00,0x00,0x00,\r
2736 0x80,0x00,0x00,0x00,0x00,0x00,\r
2737 0x80,0x00,0x00,0x00,0x00,0x00,\r
2738 0x80,0x00,0x00,0x00,0x00,0x00,\r
2739 0x80,0x00,0x01,0x54,0x00,0x00,\r
2740 0x80,0x00,0x05,0x00,0x00,0x00,\r
2741 0x80,0x00,0x14,0x00,0x00,0x00,\r
2742 0x80,0x00,0x14,0x00,0x00,0x00,\r
2743 0x80,0x00,0x15,0x54,0x00,0x00,\r
2744 0x80,0x00,0x15,0x05,0x00,0x00,\r
2745 0x80,0x00,0x14,0x05,0x00,0x00,\r
2746 0x80,0x00,0x14,0x05,0x00,0x00,\r
2747 0x80,0x00,0x14,0x05,0x00,0x00,\r
2748 0x80,0x00,0x05,0x54,0x00,0x00,\r
2749 0x80,0x00,0x00,0x00,0x00,0x00,\r
2750 0x80,0x00,0x00,0x00,0x00,0x00,\r
2751 0x80,0x00,0x00,0x00,0x00,0x00,\r
2752 0x80,0x00,0x00,0x00,0x00,0x00,\r
2753 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2754},\r
2755// 7\r
2756{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2757 0x80,0x00,0x00,0x00,0x00,0x00,\r
2758 0x80,0x00,0x00,0x00,0x00,0x00,\r
2759 0x80,0x00,0x00,0x00,0x00,0x00,\r
2760 0x80,0x00,0x00,0x00,0x00,0x00,\r
2761 0x80,0x00,0x15,0x55,0x00,0x00,\r
2762 0x80,0x00,0x14,0x05,0x00,0x00,\r
2763 0x80,0x00,0x00,0x14,0x00,0x00,\r
2764 0x80,0x00,0x00,0x14,0x00,0x00,\r
2765 0x80,0x00,0x00,0x50,0x00,0x00,\r
2766 0x80,0x00,0x00,0x50,0x00,0x00,\r
2767 0x80,0x00,0x01,0x40,0x00,0x00,\r
2768 0x80,0x00,0x01,0x40,0x00,0x00,\r
2769 0x80,0x00,0x05,0x00,0x00,0x00,\r
2770 0x80,0x00,0x05,0x00,0x00,0x00,\r
2771 0x80,0x00,0x00,0x00,0x00,0x00,\r
2772 0x80,0x00,0x00,0x00,0x00,0x00,\r
2773 0x80,0x00,0x00,0x00,0x00,0x00,\r
2774 0x80,0x00,0x00,0x00,0x00,0x00,\r
2775 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2776},\r
2777// 8\r
2778{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2779 0x80,0x00,0x00,0x00,0x00,0x00,\r
2780 0x80,0x00,0x00,0x00,0x00,0x00,\r
2781 0x80,0x00,0x00,0x00,0x00,0x00,\r
2782 0x80,0x00,0x00,0x00,0x00,0x00,\r
2783 0x80,0x00,0x05,0x54,0x00,0x00,\r
2784 0x80,0x00,0x14,0x05,0x00,0x00,\r
2785 0x80,0x00,0x14,0x05,0x00,0x00,\r
2786 0x80,0x00,0x14,0x05,0x00,0x00,\r
2787 0x80,0x00,0x05,0x54,0x00,0x00,\r
2788 0x80,0x00,0x14,0x05,0x00,0x00,\r
2789 0x80,0x00,0x14,0x05,0x00,0x00,\r
2790 0x80,0x00,0x14,0x05,0x00,0x00,\r
2791 0x80,0x00,0x14,0x05,0x00,0x00,\r
2792 0x80,0x00,0x05,0x54,0x00,0x00,\r
2793 0x80,0x00,0x00,0x00,0x00,0x00,\r
2794 0x80,0x00,0x00,0x00,0x00,0x00,\r
2795 0x80,0x00,0x00,0x00,0x00,0x00,\r
2796 0x80,0x00,0x00,0x00,0x00,0x00,\r
2797 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2798},\r
2799// 9\r
2800{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2801 0x80,0x00,0x00,0x00,0x00,0x00,\r
2802 0x80,0x00,0x00,0x00,0x00,0x00,\r
2803 0x80,0x00,0x00,0x00,0x00,0x00,\r
2804 0x80,0x00,0x00,0x00,0x00,0x00,\r
2805 0x80,0x00,0x05,0x54,0x00,0x00,\r
2806 0x80,0x00,0x14,0x05,0x00,0x00,\r
2807 0x80,0x00,0x14,0x05,0x00,0x00,\r
2808 0x80,0x00,0x14,0x05,0x00,0x00,\r
2809 0x80,0x00,0x14,0x15,0x00,0x00,\r
2810 0x80,0x00,0x05,0x55,0x00,0x00,\r
2811 0x80,0x00,0x00,0x05,0x00,0x00,\r
2812 0x80,0x00,0x00,0x05,0x00,0x00,\r
2813 0x80,0x00,0x00,0x14,0x00,0x00,\r
2814 0x80,0x00,0x05,0x50,0x00,0x00,\r
2815 0x80,0x00,0x00,0x00,0x00,0x00,\r
2816 0x80,0x00,0x00,0x00,0x00,0x00,\r
2817 0x80,0x00,0x00,0x00,0x00,0x00,\r
2818 0x80,0x00,0x00,0x00,0x00,0x00,\r
2819 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2820}\r
2821};\r
2822\r
2823////////////////////////////////////////////////////////////////////////\r
2824\r
2825void PaintPicDot(u8 * p,u8 c)\r
2826{\r
2827 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}\r
2828 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}\r
2829 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}\r
2830}\r
2831\r
2832////////////////////////////////////////////////////////////////////////\r
2833\r
2834#ifdef _WINDOWS\r
2835void CALLBACK GPUgetScreenPic(u8 * pMem)\r
2836#else\r
2837long CALLBACK GPU_getScreenPic(u8 * pMem)\r
2838#endif\r
2839{\r
2840 float XS,YS;int x,y,v;\r
2841 u8 * ps, * px, * pf;\r
2842 u8 c;\r
2843\r
2844 if(!pGfxCardScreen)\r
2845 {\r
2846 glPixelStorei(GL_PACK_ALIGNMENT,1);\r
2847 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);\r
2848 }\r
2849\r
2850 ps=pGfxCardScreen;\r
2851\r
2852// glReadBuffer(GL_FRONT);\r
2853\r
2854 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);\r
2855 \r
2856// glReadBuffer(GL_BACK);\r
2857\r
2858 XS=(float)iResX/128;\r
2859 YS=(float)iResY/96;\r
2860 pf=pMem;\r
2861\r
2862 for(y=96;y>0;y--)\r
2863 {\r
2864 for(x=0;x<128;x++)\r
2865 {\r
2866 px=ps+(3*((int)((float)x * XS))+\r
2867 (3*iResX)*((int)((float)y*YS)));\r
2868 *(pf+0)=*(px+2);\r
2869 *(pf+1)=*(px+1);\r
2870 *(pf+2)=*(px+0);\r
2871 pf+=3;\r
2872 }\r
2873 }\r
2874\r
2875 /////////////////////////////////////////////////////////////////////\r
2876 // generic number/border painter\r
2877\r
2878 pf=pMem+(103*3);\r
2879\r
2880 for(y=0;y<20;y++)\r
2881 {\r
2882 for(x=0;x<6;x++)\r
2883 {\r
2884 c=cFont[lSelectedSlot][x+y*6];\r
2885 v=(c&0xc0)>>6;\r
2886 PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect\r
2887 v=(c&0x30)>>4;\r
2888 PaintPicDot(pf,(u8)v);pf+=3;\r
2889 v=(c&0x0c)>>2;\r
2890 PaintPicDot(pf,(u8)v);pf+=3;\r
2891 v=c&0x03;\r
2892 PaintPicDot(pf,(u8)v);pf+=3;\r
2893 }\r
2894 pf+=104*3;\r
2895 }\r
2896\r
2897 pf=pMem;\r
2898 for(x=0;x<128;x++)\r
2899 {\r
2900 *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2901 *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2902 *(pf+(95*128*3))=0xff;*pf++=0xff;\r
2903 }\r
2904 pf=pMem;\r
2905 for(y=0;y<96;y++)\r
2906 {\r
2907 *(pf+(127*3))=0x00;*pf++=0x00;\r
2908 *(pf+(127*3))=0x00;*pf++=0x00;\r
2909 *(pf+(127*3))=0xff;*pf++=0xff;\r
2910 pf+=127*3;\r
2911 }\r
2912\r
2913}\r
2914\r
2915////////////////////////////////////////////////////////////////////////\r
2916\r
2917#ifdef _WINDOWS\r
2918void CALLBACK GPUshowScreenPic(u8 * pMem)\r
2919#else\r
2920long CALLBACK GPU_showScreenPic(u8 * pMem)\r
2921#endif\r
2922{\r
2923// DestroyPic();\r
2924// if(pMem==0) return;\r
2925// CreatePic(pMem);\r
2926}\r
2927\r
2928////////////////////////////////////////////////////////////////////////\r
2929\r
2930void CALLBACK GPUsetfix(unsigned long dwFixBits)\r
2931{\r
2932 dwEmuFixes=dwFixBits;\r
2933}\r
2934\r
2935////////////////////////////////////////////////////////////////////////\r
2936 \r
2937void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)\r
2938{\r
2939 int iVibVal;\r
2940\r
2941 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width\r
2942 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);\r
2943 else iVibVal=1;\r
2944 // big rumble: 4...15 sp ; small rumble 1...3 sp\r
2945 if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10));\r
2946 else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));\r
2947\r
2948 srand(timeGetTime()); // init rand (will be used in BufferSwap)\r
2949\r
2950 iRumbleTime=15; // let the rumble last 16 buffer swaps\r
2951}\r
2952 \r
2953////////////////////////////////////////////////////////////////////////\r
2954// main emu can set display infos (A/M/G/D) \r
2955////////////////////////////////////////////////////////////////////////\r
2956\r
2957void CALLBACK GPUdisplayFlags(unsigned long dwFlags)\r
2958{\r
2959// dwCoreFlags=dwFlags;\r
2960}\r