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