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