| 1 | /*************************************************************************** |
| 2 | begin : Sun Mar 08 2009 |
| 3 | copyright : (C) 1999-2009 by Pete Bernert |
| 4 | email : BlackDove@addcom.de |
| 5 | |
| 6 | PCSX rearmed rework (C) notaz, 2012 |
| 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 | #include "gpuDraw.c" |
| 20 | #include "gpuTexture.c" |
| 21 | #include "gpuPrim.c" |
| 22 | #include "hud.c" |
| 23 | |
| 24 | static const short dispWidths[8] = {256,320,512,640,368,384,512,640}; |
| 25 | short g_m1,g_m2,g_m3; |
| 26 | short DrawSemiTrans; |
| 27 | |
| 28 | short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords |
| 29 | long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; |
| 30 | long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; |
| 31 | |
| 32 | unsigned long dwGPUVersion; |
| 33 | int iGPUHeight=512; |
| 34 | int iGPUHeightMask=511; |
| 35 | int GlobalTextIL; |
| 36 | |
| 37 | unsigned char *psxVub; |
| 38 | unsigned short *psxVuw; |
| 39 | |
| 40 | GLfloat gl_z=0.0f; |
| 41 | BOOL bNeedInterlaceUpdate; |
| 42 | BOOL bNeedRGB24Update; |
| 43 | BOOL bChangeWinMode; |
| 44 | long lGPUstatusRet; |
| 45 | unsigned long ulGPUInfoVals[16]; |
| 46 | VRAMLoad_t VRAMWrite; |
| 47 | VRAMLoad_t VRAMRead; |
| 48 | int iDataWriteMode; |
| 49 | int iDataReadMode; |
| 50 | |
| 51 | long lClearOnSwap; |
| 52 | long lClearOnSwapColor; |
| 53 | BOOL bSkipNextFrame; |
| 54 | |
| 55 | PSXDisplay_t PSXDisplay; |
| 56 | PSXDisplay_t PreviousPSXDisplay; |
| 57 | TWin_t TWin; |
| 58 | BOOL bDisplayNotSet; |
| 59 | BOOL bNeedWriteUpload; |
| 60 | int iLastRGB24; |
| 61 | |
| 62 | // don't do GL vram read |
| 63 | void CheckVRamRead(int x, int y, int dx, int dy, bool bFront) |
| 64 | { |
| 65 | } |
| 66 | |
| 67 | void CheckVRamReadEx(int x, int y, int dx, int dy) |
| 68 | { |
| 69 | } |
| 70 | |
| 71 | void SetFixes(void) |
| 72 | { |
| 73 | } |
| 74 | |
| 75 | static void PaintBlackBorders(void) |
| 76 | { |
| 77 | short s; |
| 78 | glDisable(GL_SCISSOR_TEST); glError(); |
| 79 | if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} glError(); |
| 80 | if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} glError(); |
| 81 | if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} glError(); |
| 82 | glDisable(GL_ALPHA_TEST); glError(); |
| 83 | |
| 84 | glEnable(GL_ALPHA_TEST); glError(); |
| 85 | glEnable(GL_SCISSOR_TEST); glError(); |
| 86 | } |
| 87 | |
| 88 | static void fps_update(void); |
| 89 | |
| 90 | void updateDisplay(void) |
| 91 | { |
| 92 | bFakeFrontBuffer=FALSE; |
| 93 | bRenderFrontBuffer=FALSE; |
| 94 | |
| 95 | if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? |
| 96 | { |
| 97 | PrepareFullScreenUpload(-1); |
| 98 | UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram |
| 99 | bNeedUploadTest=FALSE; |
| 100 | bNeedInterlaceUpdate=FALSE; |
| 101 | bNeedUploadAfter=FALSE; |
| 102 | bNeedRGB24Update=FALSE; |
| 103 | } |
| 104 | else |
| 105 | if(bNeedInterlaceUpdate) // smaller upload? |
| 106 | { |
| 107 | bNeedInterlaceUpdate=FALSE; |
| 108 | xrUploadArea=xrUploadAreaIL; // -> upload this rect |
| 109 | UploadScreen(TRUE); |
| 110 | } |
| 111 | |
| 112 | if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 |
| 113 | |
| 114 | if(PSXDisplay.Disabled) // display disabled? |
| 115 | { |
| 116 | // moved here |
| 117 | glDisable(GL_SCISSOR_TEST); glError(); |
| 118 | glClearColor(0,0,0,128); glError(); // -> clear whole backbuffer |
| 119 | glClear(uiBufferBits); glError(); |
| 120 | glEnable(GL_SCISSOR_TEST); glError(); |
| 121 | gl_z=0.0f; |
| 122 | bDisplayNotSet = TRUE; |
| 123 | } |
| 124 | |
| 125 | if(iDrawnSomething) |
| 126 | { |
| 127 | fps_update(); |
| 128 | eglSwapBuffers(display, surface); |
| 129 | iDrawnSomething=0; |
| 130 | } |
| 131 | |
| 132 | if(lClearOnSwap) // clear buffer after swap? |
| 133 | { |
| 134 | GLclampf g,b,r; |
| 135 | |
| 136 | if(bDisplayNotSet) // -> set new vals |
| 137 | SetOGLDisplaySettings(1); |
| 138 | |
| 139 | g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col |
| 140 | b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; |
| 141 | r=((GLclampf)RED(lClearOnSwapColor))/255.0f; |
| 142 | glDisable(GL_SCISSOR_TEST); glError(); |
| 143 | glClearColor(r,g,b,128); glError(); // -> clear |
| 144 | glClear(uiBufferBits); glError(); |
| 145 | glEnable(GL_SCISSOR_TEST); glError(); |
| 146 | lClearOnSwap=0; // -> done |
| 147 | } |
| 148 | else |
| 149 | { |
| 150 | if(iZBufferDepth) // clear zbuffer as well (if activated) |
| 151 | { |
| 152 | glDisable(GL_SCISSOR_TEST); glError(); |
| 153 | glClear(GL_DEPTH_BUFFER_BIT); glError(); |
| 154 | glEnable(GL_SCISSOR_TEST); glError(); |
| 155 | } |
| 156 | } |
| 157 | gl_z=0.0f; |
| 158 | |
| 159 | // additional uploads immediatly after swapping |
| 160 | if(bNeedUploadAfter) // upload wanted? |
| 161 | { |
| 162 | bNeedUploadAfter=FALSE; |
| 163 | bNeedUploadTest=FALSE; |
| 164 | UploadScreen(-1); // -> upload |
| 165 | } |
| 166 | |
| 167 | if(bNeedUploadTest) |
| 168 | { |
| 169 | bNeedUploadTest=FALSE; |
| 170 | if(PSXDisplay.InterlacedTest && |
| 171 | //iOffscreenDrawing>2 && |
| 172 | PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && |
| 173 | PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && |
| 174 | PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && |
| 175 | PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) |
| 176 | { |
| 177 | PrepareFullScreenUpload(TRUE); |
| 178 | UploadScreen(TRUE); |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | void updateFrontDisplay(void) |
| 184 | { |
| 185 | if(PreviousPSXDisplay.Range.x0|| |
| 186 | PreviousPSXDisplay.Range.y0) |
| 187 | PaintBlackBorders(); |
| 188 | |
| 189 | bFakeFrontBuffer=FALSE; |
| 190 | bRenderFrontBuffer=FALSE; |
| 191 | |
| 192 | if(iDrawnSomething) // linux: |
| 193 | eglSwapBuffers(display, surface); |
| 194 | } |
| 195 | |
| 196 | static void ChangeDispOffsetsX(void) // CENTER X |
| 197 | { |
| 198 | long lx,l;short sO; |
| 199 | |
| 200 | if(!PSXDisplay.Range.x1) return; // some range given? |
| 201 | |
| 202 | l=PSXDisplay.DisplayMode.x; |
| 203 | |
| 204 | l*=(long)PSXDisplay.Range.x1; // some funky calculation |
| 205 | l/=2560;lx=l;l&=0xfffffff8; |
| 206 | |
| 207 | if(l==PreviousPSXDisplay.Range.x1) return; // some change? |
| 208 | |
| 209 | sO=PreviousPSXDisplay.Range.x0; // store old |
| 210 | |
| 211 | if(lx>=PSXDisplay.DisplayMode.x) // range bigger? |
| 212 | { |
| 213 | PreviousPSXDisplay.Range.x1= // -> take display width |
| 214 | PSXDisplay.DisplayMode.x; |
| 215 | PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 |
| 216 | } |
| 217 | else // range smaller? center it |
| 218 | { |
| 219 | PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) |
| 220 | PreviousPSXDisplay.Range.x0= // -> calc start pos |
| 221 | (PSXDisplay.Range.x0-500)/8; |
| 222 | if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet |
| 223 | PreviousPSXDisplay.Range.x0=0; |
| 224 | |
| 225 | if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much |
| 226 | PSXDisplay.DisplayMode.x) |
| 227 | { |
| 228 | PreviousPSXDisplay.Range.x0= // -> adjust start |
| 229 | PSXDisplay.DisplayMode.x-lx; |
| 230 | PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | if(sO!=PreviousPSXDisplay.Range.x0) // something changed? |
| 235 | { |
| 236 | bDisplayNotSet=TRUE; // -> recalc display stuff |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | //////////////////////////////////////////////////////////////////////// |
| 241 | |
| 242 | static void ChangeDispOffsetsY(void) // CENTER Y |
| 243 | { |
| 244 | int iT;short sO; // store previous y size |
| 245 | |
| 246 | if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC |
| 247 | |
| 248 | if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) |
| 249 | { |
| 250 | PreviousPSXDisplay.Range.y1= // -> store width |
| 251 | PSXDisplay.DisplayModeNew.y; |
| 252 | |
| 253 | sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset |
| 254 | if(sO<0) sO=0; |
| 255 | |
| 256 | PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too |
| 257 | } |
| 258 | else sO=0; // else no offset |
| 259 | |
| 260 | if(sO!=PreviousPSXDisplay.Range.y0) // something changed? |
| 261 | { |
| 262 | PreviousPSXDisplay.Range.y0=sO; |
| 263 | bDisplayNotSet=TRUE; // -> recalc display stuff |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | static void updateDisplayIfChanged(void) |
| 268 | { |
| 269 | BOOL bUp; |
| 270 | |
| 271 | if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && |
| 272 | (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x)) |
| 273 | { |
| 274 | if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && |
| 275 | (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) |
| 276 | return; // nothing has changed? fine, no swap buffer needed |
| 277 | } |
| 278 | else // some res change? |
| 279 | { |
| 280 | glLoadIdentity(); glError(); |
| 281 | glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution |
| 282 | PSXDisplay.DisplayModeNew.y, 0, -1, 1); glError(); |
| 283 | if(bKeepRatio) SetAspectRatio(); |
| 284 | } |
| 285 | |
| 286 | bDisplayNotSet = TRUE; // re-calc offsets/display area |
| 287 | |
| 288 | bUp=FALSE; |
| 289 | if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) |
| 290 | { |
| 291 | PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet |
| 292 | ResetTextureArea(FALSE); |
| 293 | bUp=TRUE; |
| 294 | } |
| 295 | |
| 296 | PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos |
| 297 | PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; |
| 298 | PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; |
| 299 | PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; |
| 300 | |
| 301 | PSXDisplay.DisplayEnd.x= // calc new ends |
| 302 | PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; |
| 303 | PSXDisplay.DisplayEnd.y= |
| 304 | PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; |
| 305 | PreviousPSXDisplay.DisplayEnd.x= |
| 306 | PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; |
| 307 | PreviousPSXDisplay.DisplayEnd.y= |
| 308 | PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; |
| 309 | |
| 310 | ChangeDispOffsetsX(); |
| 311 | if(bUp) updateDisplay(); // yeah, real update (swap buffer) |
| 312 | } |
| 313 | |
| 314 | #define GPUwriteStatus_ext GPUwriteStatus_ext // for gpulib to see this |
| 315 | void GPUwriteStatus_ext(unsigned long gdata) |
| 316 | { |
| 317 | switch((gdata>>24)&0xff) |
| 318 | { |
| 319 | case 0x00: |
| 320 | PSXDisplay.Disabled=1; |
| 321 | PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; |
| 322 | drawX=drawY=0;drawW=drawH=0; |
| 323 | sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; |
| 324 | usMirror=0; |
| 325 | GlobalTextAddrX=0;GlobalTextAddrY=0; |
| 326 | GlobalTextTP=0;GlobalTextABR=0; |
| 327 | PSXDisplay.RGB24=FALSE; |
| 328 | PSXDisplay.Interlaced=FALSE; |
| 329 | bUsingTWin = FALSE; |
| 330 | return; |
| 331 | |
| 332 | case 0x03: |
| 333 | PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; |
| 334 | PSXDisplay.Disabled = (gdata & 1); |
| 335 | |
| 336 | if (iOffscreenDrawing==4 && |
| 337 | PreviousPSXDisplay.Disabled && |
| 338 | !(PSXDisplay.Disabled)) |
| 339 | { |
| 340 | |
| 341 | if(!PSXDisplay.RGB24) |
| 342 | { |
| 343 | PrepareFullScreenUpload(TRUE); |
| 344 | UploadScreen(TRUE); |
| 345 | updateDisplay(); |
| 346 | } |
| 347 | } |
| 348 | return; |
| 349 | |
| 350 | case 0x05: |
| 351 | { |
| 352 | short sx=(short)(gdata & 0x3ff); |
| 353 | short sy; |
| 354 | |
| 355 | sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later |
| 356 | if (sy & 0x200) |
| 357 | { |
| 358 | sy|=0xfc00; |
| 359 | PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; |
| 360 | sy=0; |
| 361 | } |
| 362 | else PreviousPSXDisplay.DisplayModeNew.y=0; |
| 363 | |
| 364 | if(sx>1000) sx=0; |
| 365 | |
| 366 | if(dwActFixes&8) |
| 367 | { |
| 368 | if((!PSXDisplay.Interlaced) && |
| 369 | PreviousPSXDisplay.DisplayPosition.x == sx && |
| 370 | PreviousPSXDisplay.DisplayPosition.y == sy) |
| 371 | return; |
| 372 | |
| 373 | PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; |
| 374 | PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; |
| 375 | PreviousPSXDisplay.DisplayPosition.x = sx; |
| 376 | PreviousPSXDisplay.DisplayPosition.y = sy; |
| 377 | } |
| 378 | else |
| 379 | { |
| 380 | if((!PSXDisplay.Interlaced) && |
| 381 | PSXDisplay.DisplayPosition.x == sx && |
| 382 | PSXDisplay.DisplayPosition.y == sy) |
| 383 | return; |
| 384 | PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; |
| 385 | PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; |
| 386 | PSXDisplay.DisplayPosition.x = sx; |
| 387 | PSXDisplay.DisplayPosition.y = sy; |
| 388 | } |
| 389 | |
| 390 | PSXDisplay.DisplayEnd.x= |
| 391 | PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; |
| 392 | PSXDisplay.DisplayEnd.y= |
| 393 | PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; |
| 394 | |
| 395 | PreviousPSXDisplay.DisplayEnd.x= |
| 396 | PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; |
| 397 | PreviousPSXDisplay.DisplayEnd.y= |
| 398 | PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; |
| 399 | |
| 400 | bDisplayNotSet = TRUE; |
| 401 | |
| 402 | if (!(PSXDisplay.Interlaced)) |
| 403 | { |
| 404 | updateDisplay(); |
| 405 | } |
| 406 | else |
| 407 | if(PSXDisplay.InterlacedTest && |
| 408 | ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| |
| 409 | (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) |
| 410 | PSXDisplay.InterlacedTest--; |
| 411 | return; |
| 412 | } |
| 413 | |
| 414 | case 0x06: |
| 415 | PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; |
| 416 | PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; |
| 417 | |
| 418 | PSXDisplay.Range.x1-=PSXDisplay.Range.x0; |
| 419 | |
| 420 | ChangeDispOffsetsX(); |
| 421 | return; |
| 422 | |
| 423 | case 0x07: |
| 424 | PreviousPSXDisplay.Height = PSXDisplay.Height; |
| 425 | |
| 426 | PSXDisplay.Range.y0=gdata & 0x3ff; |
| 427 | PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; |
| 428 | |
| 429 | PSXDisplay.Height = PSXDisplay.Range.y1 - |
| 430 | PSXDisplay.Range.y0 + |
| 431 | PreviousPSXDisplay.DisplayModeNew.y; |
| 432 | |
| 433 | if (PreviousPSXDisplay.Height != PSXDisplay.Height) |
| 434 | { |
| 435 | PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; |
| 436 | ChangeDispOffsetsY(); |
| 437 | updateDisplayIfChanged(); |
| 438 | } |
| 439 | return; |
| 440 | |
| 441 | case 0x08: |
| 442 | PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; |
| 443 | |
| 444 | if (gdata&0x04) PSXDisplay.Double=2; |
| 445 | else PSXDisplay.Double=1; |
| 446 | PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; |
| 447 | |
| 448 | ChangeDispOffsetsY(); |
| 449 | |
| 450 | PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC |
| 451 | PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor |
| 452 | PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace |
| 453 | |
| 454 | PreviousPSXDisplay.InterlacedNew=FALSE; |
| 455 | if (PSXDisplay.InterlacedNew) |
| 456 | { |
| 457 | if(!PSXDisplay.Interlaced) |
| 458 | { |
| 459 | PSXDisplay.InterlacedTest=2; |
| 460 | PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; |
| 461 | PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; |
| 462 | PreviousPSXDisplay.InterlacedNew=TRUE; |
| 463 | } |
| 464 | } |
| 465 | else |
| 466 | { |
| 467 | PSXDisplay.InterlacedTest=0; |
| 468 | } |
| 469 | updateDisplayIfChanged(); |
| 470 | return; |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | ///////////////////////////////////////////////////////////////////////////// |
| 475 | |
| 476 | #include <stdint.h> |
| 477 | |
| 478 | #include "../gpulib/gpu.c" |
| 479 | |
| 480 | static int is_opened; |
| 481 | |
| 482 | static void set_vram(void *vram) |
| 483 | { |
| 484 | psxVub=vram; |
| 485 | psxVuw=(unsigned short *)psxVub; |
| 486 | } |
| 487 | |
| 488 | int renderer_init(void) |
| 489 | { |
| 490 | set_vram(gpu.vram); |
| 491 | |
| 492 | PSXDisplay.RGB24 = FALSE; // init some stuff |
| 493 | PSXDisplay.Interlaced = FALSE; |
| 494 | PSXDisplay.DrawOffset.x = 0; |
| 495 | PSXDisplay.DrawOffset.y = 0; |
| 496 | PSXDisplay.DisplayMode.x= 320; |
| 497 | PSXDisplay.DisplayMode.y= 240; |
| 498 | PSXDisplay.Disabled = FALSE; |
| 499 | PSXDisplay.Range.x0=0; |
| 500 | PSXDisplay.Range.x1=0; |
| 501 | PSXDisplay.Double = 1; |
| 502 | |
| 503 | lGPUstatusRet = 0x14802000; |
| 504 | |
| 505 | return 0; |
| 506 | } |
| 507 | |
| 508 | void renderer_finish(void) |
| 509 | { |
| 510 | } |
| 511 | |
| 512 | void renderer_notify_res_change(void) |
| 513 | { |
| 514 | } |
| 515 | |
| 516 | extern const unsigned char cmd_lengths[256]; |
| 517 | |
| 518 | // XXX: mostly dupe code from soft peops |
| 519 | int do_cmd_list(unsigned int *list, int list_len, int *last_cmd) |
| 520 | { |
| 521 | unsigned int cmd, len; |
| 522 | unsigned int *list_start = list; |
| 523 | unsigned int *list_end = list + list_len; |
| 524 | |
| 525 | for (; list < list_end; list += 1 + len) |
| 526 | { |
| 527 | cmd = *list >> 24; |
| 528 | len = cmd_lengths[cmd]; |
| 529 | if (list + 1 + len > list_end) { |
| 530 | cmd = -1; |
| 531 | break; |
| 532 | } |
| 533 | |
| 534 | #ifndef TEST |
| 535 | if (cmd == 0xa0 || cmd == 0xc0) |
| 536 | break; // image i/o, forward to upper layer |
| 537 | else if ((cmd & 0xf8) == 0xe0) |
| 538 | gpu.ex_regs[cmd & 7] = list[0]; |
| 539 | #endif |
| 540 | |
| 541 | primTableJ[cmd]((void *)list); |
| 542 | |
| 543 | switch(cmd) |
| 544 | { |
| 545 | case 0x48 ... 0x4F: |
| 546 | { |
| 547 | uint32_t num_vertexes = 2; |
| 548 | uint32_t *list_position = &(list[3]); |
| 549 | |
| 550 | while(1) |
| 551 | { |
| 552 | if(list_position >= list_end) { |
| 553 | cmd = -1; |
| 554 | goto breakloop; |
| 555 | } |
| 556 | |
| 557 | if((*list_position & 0xf000f000) == 0x50005000) |
| 558 | break; |
| 559 | |
| 560 | list_position++; |
| 561 | num_vertexes++; |
| 562 | } |
| 563 | |
| 564 | len += (num_vertexes - 2); |
| 565 | break; |
| 566 | } |
| 567 | |
| 568 | case 0x58 ... 0x5F: |
| 569 | { |
| 570 | uint32_t num_vertexes = 2; |
| 571 | uint32_t *list_position = &(list[4]); |
| 572 | |
| 573 | while(1) |
| 574 | { |
| 575 | if(list_position >= list_end) { |
| 576 | cmd = -1; |
| 577 | goto breakloop; |
| 578 | } |
| 579 | |
| 580 | if((*list_position & 0xf000f000) == 0x50005000) |
| 581 | break; |
| 582 | |
| 583 | list_position += 2; |
| 584 | num_vertexes++; |
| 585 | } |
| 586 | |
| 587 | len += (num_vertexes - 2) * 2; |
| 588 | break; |
| 589 | } |
| 590 | |
| 591 | #ifdef TEST |
| 592 | case 0xA0: // sys -> vid |
| 593 | { |
| 594 | short *slist = (void *)list; |
| 595 | uint32_t load_width = slist[4]; |
| 596 | uint32_t load_height = slist[5]; |
| 597 | uint32_t load_size = load_width * load_height; |
| 598 | |
| 599 | len += load_size / 2; |
| 600 | break; |
| 601 | } |
| 602 | #endif |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | breakloop: |
| 607 | gpu.ex_regs[1] &= ~0x1ff; |
| 608 | gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff; |
| 609 | |
| 610 | *last_cmd = cmd; |
| 611 | return list - list_start; |
| 612 | } |
| 613 | |
| 614 | void renderer_sync_ecmds(uint32_t *ecmds) |
| 615 | { |
| 616 | cmdTexturePage((unsigned char *)&ecmds[1]); |
| 617 | cmdTextureWindow((unsigned char *)&ecmds[2]); |
| 618 | cmdDrawAreaStart((unsigned char *)&ecmds[3]); |
| 619 | cmdDrawAreaEnd((unsigned char *)&ecmds[4]); |
| 620 | cmdDrawOffset((unsigned char *)&ecmds[5]); |
| 621 | cmdSTP((unsigned char *)&ecmds[6]); |
| 622 | } |
| 623 | |
| 624 | void renderer_update_caches(int x, int y, int w, int h) |
| 625 | { |
| 626 | VRAMWrite.x = x; |
| 627 | VRAMWrite.y = y; |
| 628 | VRAMWrite.Width = w; |
| 629 | VRAMWrite.Height = h; |
| 630 | if(is_opened) |
| 631 | CheckWriteUpdate(); |
| 632 | } |
| 633 | |
| 634 | void renderer_flush_queues(void) |
| 635 | { |
| 636 | } |
| 637 | |
| 638 | void renderer_set_interlace(int enable, int is_odd) |
| 639 | { |
| 640 | } |
| 641 | |
| 642 | int vout_init(void) |
| 643 | { |
| 644 | return 0; |
| 645 | } |
| 646 | |
| 647 | int vout_finish(void) |
| 648 | { |
| 649 | return 0; |
| 650 | } |
| 651 | |
| 652 | void vout_update(void) |
| 653 | { |
| 654 | if(PSXDisplay.Interlaced) // interlaced mode? |
| 655 | { |
| 656 | if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) |
| 657 | { |
| 658 | updateDisplay(); // -> swap buffers (new frame) |
| 659 | } |
| 660 | } |
| 661 | else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? |
| 662 | { |
| 663 | updateFrontDisplay(); // -> update front buffer |
| 664 | } |
| 665 | } |
| 666 | |
| 667 | void vout_blank(void) |
| 668 | { |
| 669 | } |
| 670 | |
| 671 | void vout_set_config(const struct rearmed_cbs *cbs) |
| 672 | { |
| 673 | } |
| 674 | |
| 675 | static struct rearmed_cbs *cbs; |
| 676 | |
| 677 | long GPUopen(void **dpy) |
| 678 | { |
| 679 | int ret; |
| 680 | |
| 681 | iResX = cbs->screen_w; |
| 682 | iResY = cbs->screen_h; |
| 683 | rRatioRect.left = rRatioRect.top=0; |
| 684 | rRatioRect.right = iResX; |
| 685 | rRatioRect.bottom = iResY; |
| 686 | |
| 687 | bDisplayNotSet = TRUE; |
| 688 | bSetClip = TRUE; |
| 689 | CSTEXTURE = CSVERTEX = CSCOLOR = 0; |
| 690 | |
| 691 | InitializeTextureStore(); // init texture mem |
| 692 | |
| 693 | ret = GLinitialize(cbs->gles_display, cbs->gles_surface); |
| 694 | MakeDisplayLists(); |
| 695 | |
| 696 | is_opened = 1; |
| 697 | return ret; |
| 698 | } |
| 699 | |
| 700 | long GPUclose(void) |
| 701 | { |
| 702 | is_opened = 0; |
| 703 | |
| 704 | KillDisplayLists(); |
| 705 | GLcleanup(); // close OGL |
| 706 | return 0; |
| 707 | } |
| 708 | |
| 709 | /* acting as both renderer and vout handler here .. */ |
| 710 | void renderer_set_config(const struct rearmed_cbs *cbs_) |
| 711 | { |
| 712 | cbs = (void *)cbs_; // ugh.. |
| 713 | |
| 714 | iOffscreenDrawing = 0; |
| 715 | iZBufferDepth = 0; |
| 716 | iFrameReadType = 0; |
| 717 | bKeepRatio = TRUE; |
| 718 | |
| 719 | dwActFixes = cbs->gpu_peopsgl.dwActFixes; |
| 720 | bDrawDither = cbs->gpu_peopsgl.bDrawDither; |
| 721 | iFilterType = cbs->gpu_peopsgl.iFilterType; |
| 722 | iFrameTexType = cbs->gpu_peopsgl.iFrameTexType; |
| 723 | iUseMask = cbs->gpu_peopsgl.iUseMask; |
| 724 | bOpaquePass = cbs->gpu_peopsgl.bOpaquePass; |
| 725 | bAdvancedBlend = cbs->gpu_peopsgl.bAdvancedBlend; |
| 726 | bUseFastMdec = cbs->gpu_peopsgl.bUseFastMdec; |
| 727 | iTexGarbageCollection = cbs->gpu_peopsgl.iTexGarbageCollection; |
| 728 | iVRamSize = cbs->gpu_peopsgl.iVRamSize; |
| 729 | |
| 730 | if (cbs->pl_set_gpu_caps) |
| 731 | cbs->pl_set_gpu_caps(GPU_CAP_OWNS_DISPLAY); |
| 732 | |
| 733 | if (is_opened && cbs->gles_display != NULL && cbs->gles_surface != NULL) { |
| 734 | // HACK.. |
| 735 | GPUclose(); |
| 736 | GPUopen(NULL); |
| 737 | } |
| 738 | |
| 739 | set_vram(gpu.vram); |
| 740 | } |
| 741 | |
| 742 | void SetAspectRatio(void) |
| 743 | { |
| 744 | if (cbs->pl_get_layer_pos) |
| 745 | cbs->pl_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom); |
| 746 | |
| 747 | glScissor(rRatioRect.left, |
| 748 | iResY-(rRatioRect.top+rRatioRect.bottom), |
| 749 | rRatioRect.right,rRatioRect.bottom); |
| 750 | glViewport(rRatioRect.left, |
| 751 | iResY-(rRatioRect.top+rRatioRect.bottom), |
| 752 | rRatioRect.right,rRatioRect.bottom); |
| 753 | glError(); |
| 754 | } |
| 755 | |
| 756 | static void fps_update(void) |
| 757 | { |
| 758 | char buf[16]; |
| 759 | |
| 760 | cbs->flip_cnt++; |
| 761 | if(cbs->flips_per_sec != 0) |
| 762 | { |
| 763 | snprintf(buf,sizeof(buf),"%2d %4.1f",cbs->flips_per_sec,cbs->vsps_cur); |
| 764 | DisplayText(buf, 0); |
| 765 | } |
| 766 | if(cbs->cpu_usage != 0) |
| 767 | { |
| 768 | snprintf(buf,sizeof(buf),"%3d",cbs->cpu_usage); |
| 769 | DisplayText(buf, 1); |
| 770 | } |
| 771 | } |
| 772 | |
| 773 | void renderer_sync(void) |
| 774 | { |
| 775 | } |
| 776 | |
| 777 | void renderer_notify_update_lace(int updated) |
| 778 | { |
| 779 | } |