1 /***************************************************************************
2 draw.c - description
3 -------------------
4 begin : Sun Mar 08 2009
5 copyright : (C) 1999-2009 by Pete Bernert
6 web : www.pbernert.com
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 "stdafx.h"
20
21 #define _IN_DRAW
22
23 #include "externals.h"
24 #include "gpu.h"
25 #include "draw.h"
26 #include "prim.h"
27 #include "texture.h"
28 #include "menu.h"
29
30 #include "gte_accuracy.h"
31
32 #if defined(_MACGL)
33 // if you use it, you must include it
34 #include <OpenGL/gl.h>
35 #include <OpenGL/glext.h>
36 #include "drawgl.h"
37 #endif
38 ////////////////////////////////////////////////////////////////////////////////////
39 // defines
40
41 #define SIGNBIT 0x800
42 #define S_MASK 0xf000
43 #define L_MASK 0xfffff000
44
45 // ownscale: some ogl drivers have buggy texture matrix funcs, so it
46 // is safer to calc sow/tow ourselves
47
48 #ifdef OWNSCALE
49
50 #define ST_FACSPRITE 255.99f
51 #define ST_BFFACSPRITE 0.5f/256.0f
52 #define ST_BFFACSPRITESORT 0.333f/256.0f
53
54 #define ST_OFFSET 0.5f/256.0f;
55
56 #define ST_FAC 255.99f
57 #define ST_BFFAC 0.5f/256.0f
58 #define ST_BFFACSORT 0.333f/256.0f
59
60 #define ST_FACTRI 255.99f
61 #define ST_BFFACTRI 0.5f/256.0f
62 #define ST_BFFACTRISORT 0.333f/256.0f
63
64 #define ST_FACVRAMX 255.0f
65 #define ST_FACVRAM 256.0f
66
67 ///////////////////////////////////////////////////////////////
68
69 #else
70
71 #define ST_BFFACSPRITE 0.5f
72 #define ST_BFFACSPRITESORT 0.333f
73
74 #define ST_BFFAC 0.5f
75 #define ST_BFFACSORT 0.333f
76
77 #define ST_BFFACTRI 0.5f
78 #define ST_BFFACTRISORT 0.333f
79
80 #define ST_OFFSET 0.5f;
81
82 #endif
83
84 ////////////////////////////////////////////////////////////////////////////////////
85 // draw globals; most will be initialized again later (by config or checks)
86
87 #ifdef _WINDOWS
88 HDC dcGlobal = NULL;
89 HWND hWWindow;
90 #endif
91
92 BOOL bIsFirstFrame = TRUE;
93
94 // resolution/ratio vars
95
96 int iResX;
97 int iResY;
98 BOOL bKeepRatio = FALSE;
99 BOOL bForceRatio43 = FALSE;
100 RECT rRatioRect;
101
102 // psx mask related vars
103
104 BOOL bCheckMask = FALSE;
105 int iUseMask = 0;
106 int iSetMask = 0;
107 unsigned short sSetMask = 0;
108 uint32_t lSetMask = 0;
109
110 // drawing/coord vars
111
112 OGLVertex vertex[4];
113 GLubyte gl_ux[8];
114 GLubyte gl_vy[8];
115 short sprtY,sprtX,sprtH,sprtW;
116
117 // drawing options
118
119 BOOL bOpaquePass;
120 BOOL bAdvancedBlend;
121 BOOL bUseLines;
122 BOOL bUseAntiAlias;
123 int iTexQuality;
124 int iUsePalTextures=1;
125 BOOL bSnapShot=FALSE;
126 BOOL bSmallAlpha=FALSE;
127 int iShowFPS=0;
128 BOOL bGteAccuracy;
129
130 // OGL extension support
131
132 int iForceVSync=-1;
133 int iUseExts=0;
134 BOOL bGLExt;
135 BOOL bGLFastMovie=FALSE;
136 BOOL bGLSoft;
137 BOOL bGLBlend;
138 #if defined (_MACGL) // always supported on OSX > 10.4.3
139 #define glBlendEquationEXTEx glBlendEquationEXT
140 #define glColorTableEXTEx glColorTableEXT
141 #else
142 PFNGLBLENDEQU glBlendEquationEXTEx=NULL;
143 PFNGLCOLORTABLEEXT glColorTableEXTEx=NULL;
144 #endif
145 // gfx card buffer infos
146
147 int iDepthFunc=0;
148 int iZBufferDepth=0;
149 GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT;
150
151 ////////////////////////////////////////////////////////////////////////
152 // Set OGL pixel format
153 ////////////////////////////////////////////////////////////////////////
154
155 #ifdef _WINDOWS
bSetupPixelFormat(HDC hDC)156 BOOL bSetupPixelFormat(HDC hDC)
157 {
158 int pixelformat;
159 static PIXELFORMATDESCRIPTOR pfd =
160 {
161 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
162 1, // version number
163 PFD_DRAW_TO_WINDOW | // support window
164 PFD_SUPPORT_OPENGL | // support OpenGL
165 PFD_DOUBLEBUFFER, // double buffered
166 PFD_TYPE_RGBA, // RGBA type
167 16, // 16-bit color depth (adjusted later)
168 0, 0, 0, 0, 0, 0, // color bits ignored
169 0, // no alpha buffer
170 0, // shift bit ignored
171 0, // no accumulation buffer
172 0, 0, 0, 0, // accum bits ignored
173 0, // z-buffer
174 0,
175 0, // no auxiliary buffer
176 PFD_MAIN_PLANE, // main layer
177 0, // reserved
178 0, 0, 0 // layer masks ignored
179 };
180
181 pfd.cColorBits=iColDepth; // set user color depth
182 pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask)
183
184 if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0)
185 {
186 MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK);
187 return FALSE;
188 }
189
190 if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE)
191 {
192 MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK);
193 return FALSE;
194 }
195
196 return TRUE;
197 }
198 #endif
199
200 ////////////////////////////////////////////////////////////////////////
201 // Get extension infos (f.e. pal textures / packed pixels)
202 ////////////////////////////////////////////////////////////////////////
203
GetExtInfos(void)204 void GetExtInfos(void)
205 {
206 BOOL bPacked=FALSE; // default: no packed pixel support
207
208 bGLExt=FALSE; // default: no extensions
209 bGLFastMovie=FALSE;
210
211 if(strstr((char *)glGetString(GL_EXTENSIONS), // packed pixels available?
212 "GL_EXT_packed_pixels"))
213 bPacked=TRUE; // -> ok
214
215 if(bPacked && bUse15bitMdec) // packed available and 15bit mdec wanted?
216 bGLFastMovie=TRUE; // -> ok
217
218 if(bPacked && (iTexQuality==1 || iTexQuality==2)) // packed available and 16 bit texture format?
219 {
220 bGLFastMovie=TRUE; // -> ok
221 bGLExt=TRUE;
222 }
223
224 if(iUseExts && // extension support wanted?
225 (strstr((char *)glGetString(GL_EXTENSIONS),
226 "GL_EXT_texture_edge_clamp") ||
227 strstr((char *)glGetString(GL_EXTENSIONS), // -> check clamp support, if yes: use it
228 "GL_SGIS_texture_edge_clamp")))
229 iClampType=GL_TO_EDGE_CLAMP;
230 else iClampType=GL_CLAMP;
231
232 #if !defined (_MACGL) // OSX > 10.4.3 defines this
233 glColorTableEXTEx=(PFNGLCOLORTABLEEXT)NULL; // init ogl palette func pointer
234 #endif
235
236 #ifndef __sun
237 if(iGPUHeight!=1024 && // no pal textures in ZN mode (height=1024)!
238 strstr((char *)glGetString(GL_EXTENSIONS), // otherwise: check ogl support
239 "GL_EXT_paletted_texture"))
240 {
241 iUsePalTextures=1; // -> wow, supported, get func pointer
242
243 #ifdef _WINDOWS
244 glColorTableEXTEx=(PFNGLCOLORTABLEEXT)wglGetProcAddress("glColorTableEXT");
245 #elif defined (_MACGL)
246 // no prob, done already in OSX > 10.4.3
247 #else
248 glColorTableEXTEx=(PFNGLCOLORTABLEEXT)glXGetProcAddress("glColorTableEXT");
249 #endif
250
251 if(glColorTableEXTEx==NULL) iUsePalTextures=0; // -> ha, cheater... no func, no support
252
253 }
254 else iUsePalTextures=0;
255 #else
256 iUsePalTextures=0;
257 #endif
258 }
259
260 ////////////////////////////////////////////////////////////////////////
261 // Setup some stuff depending on user settings or in-game toggle
262 ////////////////////////////////////////////////////////////////////////
263
SetExtGLFuncs(void)264 void SetExtGLFuncs(void)
265 {
266 //----------------------------------------------------//
267
268 SetFixes(); // update fix infos
269
270 //----------------------------------------------------//
271
272 #ifdef _WINDOWS
273 if((iForceVSync>=0) && // force vsync?
274 strstr((char *)glGetString(GL_EXTENSIONS), // and extension available?
275 "WGL_EXT_swap_control"))
276 {
277 PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT=
278 (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
279
280 if(wglSwapIntervalEXT) wglSwapIntervalEXT(iForceVSync);
281 }
282 #endif
283 #ifdef _MACGL
284 SetVSync(iForceVSync);
285 #endif
286 if(iUseExts && !(dwActFixes&1024) && // extensions wanted? and not turned off by game fix?
287 strstr((char *)glGetString(GL_EXTENSIONS), // and blend_subtract available?
288 "GL_EXT_blend_subtract"))
289 { // -> get ogl blend function pointer
290 #ifdef _WINDOWS
291 glBlendEquationEXTEx=(PFNGLBLENDEQU)wglGetProcAddress("glBlendEquationEXT");
292 #elif defined(_MACGL)
293 // no prob, OSX > 10.4.3 has this
294 #else
295 glBlendEquationEXTEx=(PFNGLBLENDEQU)glXGetProcAddress("glBlendEquationEXT");
296 #endif
297 }
298 else // no subtract blending?
299 {
300 if(glBlendEquationEXTEx) // -> change to additive blending (if subract was active)
301 glBlendEquationEXTEx(FUNC_ADD_EXT);
302 #if !defined(_MACGL) // BTW, why set to null? strange...
303 glBlendEquationEXTEx=(PFNGLBLENDEQU)NULL; // -> no more blend function pointer
304 #endif
305 }
306
307 //----------------------------------------------------//
308
309 if(iUseExts && bAdvancedBlend && // advanced blending wanted ?
310 strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail?
311 "GL_EXT_texture_env_combine"))
312 {
313 bUseMultiPass=FALSE;bGLBlend=TRUE; // -> no need for 2 passes, perfect
314
315 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT);
316 glTexEnvf(GL_TEXTURE_ENV, COMBINE_RGB_EXT, GL_MODULATE);
317 glTexEnvf(GL_TEXTURE_ENV, COMBINE_ALPHA_EXT, GL_MODULATE);
318 glTexEnvf(GL_TEXTURE_ENV, RGB_SCALE_EXT, 2.0f);
319 }
320 else // no advanced blending wanted/available:
321 {
322 if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes
323 else bUseMultiPass=FALSE; // -> or simple 'bright color' mode
324 bGLBlend=FALSE; // -> no ext blending!
325
326 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
327 }
328
329 //----------------------------------------------------//
330 // init standard tex quality 0-2, and big alpha mode 3
331
332 if(!(dwActFixes&0x4000) && iFilterType && iTexQuality>=3)
333 bSmallAlpha=TRUE;
334 else bSmallAlpha=FALSE;
335
336 if(bOpaquePass) // opaque mode?
337 {
338 if(dwActFixes&32)
339 {
340 TCF[0]=CP8RGBA_0;
341 PalTexturedColourFn=CP8RGBA; // -> init col func
342 }
343 else
344 {
345 TCF[0]=XP8RGBA_0;
346 PalTexturedColourFn=XP8RGBA; // -> init col func
347 }
348
349 TCF[1]=XP8RGBA_1;
350 glAlphaFunc(GL_GREATER,0.49f);
351 }
352 else // no opaque mode?
353 {
354 TCF[0]=TCF[1]=P8RGBA;
355 PalTexturedColourFn=P8RGBA; // -> init col func
356 glAlphaFunc(GL_NOTEQUAL,0); // --> set alpha func
357 }
358
359 //----------------------------------------------------//
360
361 LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr
362
363 giWantedFMT=GL_RGBA; // init ogl tex format
364
365 switch(iTexQuality) // -> quality:
366 {
367 //--------------------------------------------------//
368 case 0: // -> don't care
369 giWantedRGBA=4;
370 giWantedTYPE=GL_UNSIGNED_BYTE;
371 break;
372 //--------------------------------------------------//
373 case 1: // -> R4G4B4A4
374 if(bGLExt)
375 {
376 giWantedRGBA=GL_RGBA4;
377 giWantedTYPE=GL_UNSIGNED_SHORT_4_4_4_4_EXT;
378 LoadSubTexFn=LoadPackedSubTexturePageSort;
379 if(bOpaquePass)
380 {
381 if(dwActFixes&32) PTCF[0]=CP4RGBA_0;
382 else PTCF[0]=XP4RGBA_0;
383 PTCF[1]=XP4RGBA_1;
384 }
385 else
386 {
387 PTCF[0]=PTCF[1]=P4RGBA;
388 }
389 }
390 else
391 {
392 giWantedRGBA=GL_RGBA4;
393 giWantedTYPE=GL_UNSIGNED_BYTE;
394 }
395 break;
396 //--------------------------------------------------//
397 case 2: // -> R5B5G5A1
398 if(bGLExt)
399 {
400 giWantedRGBA=GL_RGB5_A1;
401 giWantedTYPE=GL_UNSIGNED_SHORT_5_5_5_1_EXT;
402 LoadSubTexFn=LoadPackedSubTexturePageSort;
403 if(bOpaquePass)
404 {
405 if(dwActFixes&32) PTCF[0]=CP5RGBA_0;
406 else PTCF[0]=XP5RGBA_0;
407 PTCF[1]=XP5RGBA_1;
408 }
409 else
410 {
411 PTCF[0]=PTCF[1]=P5RGBA;
412 }
413 }
414 else
415 {
416 giWantedRGBA=GL_RGB5_A1;giWantedTYPE=GL_UNSIGNED_BYTE;
417 }
418 break;
419 //--------------------------------------------------//
420 case 3: // -> R8G8B8A8
421 giWantedRGBA=GL_RGBA8;
422 giWantedTYPE=GL_UNSIGNED_BYTE;
423
424 if(bSmallAlpha)
425 {
426 if(bOpaquePass) // opaque mode?
427 {
428 if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;}
429 else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;}
430 TCF[1]=XP8RGBAEx_1;
431 }
432 }
433
434 break;
435 //--------------------------------------------------//
436 case 4: // -> R8G8B8A8
437 giWantedRGBA = GL_RGBA8;
438 giWantedTYPE = GL_UNSIGNED_BYTE;
439
440 if(strstr((char *)glGetString(GL_EXTENSIONS), // and extension avail?
441 "GL_EXT_bgra"))
442 {
443 giWantedFMT = GL_BGRA_EXT;
444
445 if(bOpaquePass) // opaque mode?
446 {
447 if(bSmallAlpha)
448 {
449 if(dwActFixes&32) {TCF[0]=CP8BGRAEx_0;PalTexturedColourFn=CP8RGBAEx;}
450 else {TCF[0]=XP8BGRAEx_0;PalTexturedColourFn=XP8RGBAEx;}
451 TCF[1]=XP8BGRAEx_1;
452 }
453 else
454 {
455 if(dwActFixes&32) {TCF[0]=CP8BGRA_0;PalTexturedColourFn=CP8RGBA;}
456 else {TCF[0]=XP8BGRA_0;PalTexturedColourFn=XP8RGBA;}
457 TCF[1]=XP8BGRA_1;
458 }
459 }
460 else // no opaque mode?
461 {
462 TCF[0]=TCF[1]=P8BGRA; // -> init col func
463 }
464 }
465 else
466 {
467 iTexQuality=3;
468 if(bSmallAlpha)
469 {
470 if(bOpaquePass) // opaque mode?
471 {
472 if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;}
473 else {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;}
474 TCF[1]=XP8RGBAEx_1;
475 }
476 }
477 }
478
479 break;
480 //--------------------------------------------------//
481 }
482
483 bBlendEnable=FALSE; // init blending: off
484 glDisable(GL_BLEND);
485
486 SetScanTrans(); // init scan lines (if wanted)
487 }
488
489 ////////////////////////////////////////////////////////////////////////
490 // setup scan lines
491 ////////////////////////////////////////////////////////////////////////
492
493 #define R_TSP 0x00,0x45,0x00,0xff
494 #define G_TSP 0x00,0x00,0x45,0xff
495 #define B_TSP 0x45,0x00,0x00,0xff
496 #define O_TSP 0x45,0x45,0x45,0xff
497 #define N_TSP 0x00,0x00,0x00,0xff
498
499 GLuint gTexScanName=0;
500
501 GLubyte texscan[4][16]=
502 {
503 {R_TSP, G_TSP, B_TSP, N_TSP},
504 {O_TSP, N_TSP, O_TSP, N_TSP},
505 {B_TSP, N_TSP, R_TSP, G_TSP},
506 {O_TSP, N_TSP, O_TSP, N_TSP}
507 };
508
CreateScanLines(void)509 void CreateScanLines(void)
510 {
511 if(iUseScanLines)
512 {
513 int y;
514 if(iScanBlend<0) // special scan mask mode
515 {
516 glGenTextures(1, &gTexScanName);
517 glBindTexture(GL_TEXTURE_2D, gTexScanName);
518
519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
521 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
522 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
523 glTexImage2D(GL_TEXTURE_2D, 0, 4, 4, 4, 0,GL_RGBA, GL_UNSIGNED_BYTE, texscan);
524 }
525 else // otherwise simple lines in a display list
526 {
527 uiScanLine=glGenLists(1);
528 glNewList(uiScanLine,GL_COMPILE);
529 #ifdef _MACGL
530 // not mac specific, just commenting out to be friendly
531 // use it if you like
532 // this draws anti-aliased lines with user-chosen color
533 glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
534 glEnable(GL_BLEND | GL_LINE_SMOOTH);
535 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
536 glColor4f(iScanlineColor[0],iScanlineColor[1],iScanlineColor[2],iScanlineColor[3]);
537 glBegin(GL_LINES);
538 for(y=0;y<iResY;y+=2)
539 {
540 glVertex2f(0,y);
541 glVertex2f(iResX,y);
542 }
543 glEnd();
544 glPopAttrib();
545 #else
546 for(y=0;y<iResY;y+=2)
547 {
548 glBegin(GL_QUADS);
549 glVertex2f(0,y);
550 glVertex2f(iResX,y);
551 glVertex2f(iResX,y+1);
552 glVertex2f(0,y+1);
553 glEnd();
554 }
555
556 #endif
557 glEndList();
558 }
559 }
560 }
561
562 ////////////////////////////////////////////////////////////////////////
563 // Initialize OGL
564 ////////////////////////////////////////////////////////////////////////
565
566 #ifdef _WINDOWS
567 HGLRC GLCONTEXT=NULL;
568 #endif
569
GLinitialize()570 int GLinitialize()
571 {
572 #ifdef _WINDOWS
573 HGLRC objectRC;
574 // init
575 dcGlobal = GetDC(hWWindow); // FIRST: dc/rc stuff
576 objectRC = wglCreateContext(dcGlobal);
577 GLCONTEXT=objectRC;
578 wglMakeCurrent(dcGlobal, objectRC);
579 // CheckWGLExtensions(dcGlobal);
580 if(bWindowMode) ReleaseDC(hWWindow,dcGlobal); // win mode: release dc again
581 #endif
582 #if defined (_MACGL)
583 BringContextForward();
584 #endif
585 glViewport(rRatioRect.left, // init viewport by ratio rect
586 iResY-(rRatioRect.top+rRatioRect.bottom),
587 rRatioRect.right,
588 rRatioRect.bottom);
589
590 glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)
591 glEnable(GL_SCISSOR_TEST);
592
593 #ifndef OWNSCALE
594 glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"
595 glLoadIdentity();
596 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack
597 #endif
598
599 glMatrixMode(GL_PROJECTION); // init projection with psx resolution
600 glLoadIdentity();
601 glOrtho(0,PSXDisplay.DisplayMode.x,
602 PSXDisplay.DisplayMode.y, 0, -1, 1);
603
604 if(iZBufferDepth) // zbuffer?
605 {
606 uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;
607 glEnable(GL_DEPTH_TEST);
608 glDepthFunc(GL_ALWAYS);
609 iDepthFunc=1;
610 }
611 else // no zbuffer?
612 {
613 uiBufferBits=GL_COLOR_BUFFER_BIT;
614 glDisable(GL_DEPTH_TEST);
615 }
616
617 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // first buffer clear
618 glClear(uiBufferBits);
619
620 if(bUseLines) // funny lines
621 {
622 glPolygonMode(GL_FRONT, GL_LINE);
623 glPolygonMode(GL_BACK, GL_LINE);
624 }
625 else // or the real filled thing
626 {
627 glPolygonMode(GL_FRONT, GL_FILL);
628 glPolygonMode(GL_BACK, GL_FILL);
629 }
630
631 MakeDisplayLists(); // lists for menu/opaque
632 GetExtInfos(); // get ext infos
633 SetExtGLFuncs(); // init all kind of stuff (tex function pointers)
634
635 glEnable(GL_ALPHA_TEST); // wanna alpha test
636
637 if(!bUseAntiAlias) // no anti-alias (default)
638 {
639 glDisable(GL_LINE_SMOOTH);
640 glDisable(GL_POLYGON_SMOOTH);
641 glDisable(GL_POINT_SMOOTH);
642 }
643 else // wanna try it? glitches galore...
644 {
645 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
646 glEnable(GL_LINE_SMOOTH);
647 glEnable(GL_POLYGON_SMOOTH);
648 glEnable(GL_POINT_SMOOTH);
649 glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
650 glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
651 glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
652 }
653
654 ubGloAlpha=127; // init some drawing vars
655 ubGloColAlpha=127;
656 TWin.UScaleFactor = 1;
657 TWin.VScaleFactor = 1;
658 bDrawMultiPass=FALSE;
659 bTexEnabled=FALSE;
660 bUsingTWin=FALSE;
661
662 if(bDrawDither) glEnable(GL_DITHER); // dither mode
663 else glDisable(GL_DITHER);
664
665 glDisable(GL_FOG); // turn all (currently) unused modes off
666 glDisable(GL_LIGHTING);
667 glDisable(GL_LOGIC_OP);
668 glDisable(GL_STENCIL_TEST);
669 glDisable(GL_TEXTURE_1D);
670 glDisable(GL_TEXTURE_2D);
671 glDisable(GL_CULL_FACE);
672
673 glPixelTransferi(GL_RED_SCALE, 1); // to be sure:
674 glPixelTransferi(GL_RED_BIAS, 0); // init more OGL vals
675 glPixelTransferi(GL_GREEN_SCALE, 1);
676 glPixelTransferi(GL_GREEN_BIAS, 0);
677 glPixelTransferi(GL_BLUE_SCALE, 1);
678 glPixelTransferi(GL_BLUE_BIAS, 0);
679 glPixelTransferi(GL_ALPHA_SCALE, 1);
680 glPixelTransferi(GL_ALPHA_BIAS, 0);
681
682 #ifdef _WINDOWS
683 // detect Windows hw/sw mode (just for info)
684 if(!strcmp("Microsoft Corporation",(LPTSTR)glGetString(GL_VENDOR)) &&
685 !strcmp("GDI Generic", (LPTSTR)glGetString(GL_RENDERER)))
686 bGLSoft=TRUE;
687 else bGLSoft=FALSE;
688 #endif
689
690 glFlush(); // we are done...
691 glFinish();
692
693 CreateScanLines(); // setup scanline stuff (if wanted)
694
695 CheckTextureMemory(); // check available tex memory
696
697 if(bKeepRatio) SetAspectRatio(); // set ratio
698
699 if(iShowFPS) // user wants FPS display on startup?
700 {
701 ulKeybits|=KEY_SHOWFPS; // -> ok, turn display on
702 szDispBuf[0]=0;
703 BuildDispMenu(0);
704 }
705
706 bIsFirstFrame = FALSE; // we have survived the first frame :)
707
708 return 0;
709 }
710
711 ////////////////////////////////////////////////////////////////////////
712 // clean up OGL stuff
713 ////////////////////////////////////////////////////////////////////////
714
GLcleanup()715 void GLcleanup()
716 {
717 KillDisplayLists(); // bye display lists
718
719 if(iUseScanLines) // scanlines used?
720 {
721 if(iScanBlend<0)
722 {
723 if(gTexScanName!=0) // some scanline tex?
724 glDeleteTextures(1, &gTexScanName); // -> delete it
725 gTexScanName=0;
726 }
727 else glDeleteLists(uiScanLine,1); // otherwise del scanline display list
728 }
729
730 CleanupTextureStore(); // bye textures
731
732 #ifdef _WINDOWS
733 wglMakeCurrent(NULL, NULL); // bye context
734 if(GLCONTEXT) wglDeleteContext(GLCONTEXT);
735 if(!bWindowMode && dcGlobal)
736 ReleaseDC(hWWindow,dcGlobal);
737 #endif
738 }
739
740 ////////////////////////////////////////////////////////////////////////
741 ////////////////////////////////////////////////////////////////////////
742 ////////////////////////////////////////////////////////////////////////
743
744 ////////////////////////////////////////////////////////////////////////
745 ////////////////////////////////////////////////////////////////////////
746 ////////////////////////////////////////////////////////////////////////
747
748 ////////////////////////////////////////////////////////////////////////
749 // Offset stuff
750 ////////////////////////////////////////////////////////////////////////
751
752 // please note: it is hardly do-able in a hw/accel plugin to get the
753 // real psx polygon coord mapping right... the following
754 // works not to bad with many games, though
755
CheckCoord4()756 static __inline BOOL CheckCoord4()
757 {
758 if(lx0<0)
759 {
760 if(((lx1-lx0)>CHKMAX_X) ||
761 ((lx2-lx0)>CHKMAX_X))
762 {
763 if(lx3<0)
764 {
765 if((lx1-lx3)>CHKMAX_X) return TRUE;
766 if((lx2-lx3)>CHKMAX_X) return TRUE;
767 }
768 }
769 }
770 if(lx1<0)
771 {
772 if((lx0-lx1)>CHKMAX_X) return TRUE;
773 if((lx2-lx1)>CHKMAX_X) return TRUE;
774 if((lx3-lx1)>CHKMAX_X) return TRUE;
775 }
776 if(lx2<0)
777 {
778 if((lx0-lx2)>CHKMAX_X) return TRUE;
779 if((lx1-lx2)>CHKMAX_X) return TRUE;
780 if((lx3-lx2)>CHKMAX_X) return TRUE;
781 }
782 if(lx3<0)
783 {
784 if(((lx1-lx3)>CHKMAX_X) ||
785 ((lx2-lx3)>CHKMAX_X))
786 {
787 if(lx0<0)
788 {
789 if((lx1-lx0)>CHKMAX_X) return TRUE;
790 if((lx2-lx0)>CHKMAX_X) return TRUE;
791 }
792 }
793 }
794
795
796 if(ly0<0)
797 {
798 if((ly1-ly0)>CHKMAX_Y) return TRUE;
799 if((ly2-ly0)>CHKMAX_Y) return TRUE;
800 }
801 if(ly1<0)
802 {
803 if((ly0-ly1)>CHKMAX_Y) return TRUE;
804 if((ly2-ly1)>CHKMAX_Y) return TRUE;
805 if((ly3-ly1)>CHKMAX_Y) return TRUE;
806 }
807 if(ly2<0)
808 {
809 if((ly0-ly2)>CHKMAX_Y) return TRUE;
810 if((ly1-ly2)>CHKMAX_Y) return TRUE;
811 if((ly3-ly2)>CHKMAX_Y) return TRUE;
812 }
813 if(ly3<0)
814 {
815 if((ly1-ly3)>CHKMAX_Y) return TRUE;
816 if((ly2-ly3)>CHKMAX_Y) return TRUE;
817 }
818
819 return FALSE;
820 }
821
CheckCoord3()822 static __inline BOOL CheckCoord3()
823 {
824 if(lx0<0)
825 {
826 if((lx1-lx0)>CHKMAX_X) return TRUE;
827 if((lx2-lx0)>CHKMAX_X) return TRUE;
828 }
829 if(lx1<0)
830 {
831 if((lx0-lx1)>CHKMAX_X) return TRUE;
832 if((lx2-lx1)>CHKMAX_X) return TRUE;
833 }
834 if(lx2<0)
835 {
836 if((lx0-lx2)>CHKMAX_X) return TRUE;
837 if((lx1-lx2)>CHKMAX_X) return TRUE;
838 }
839 if(ly0<0)
840 {
841 if((ly1-ly0)>CHKMAX_Y) return TRUE;
842 if((ly2-ly0)>CHKMAX_Y) return TRUE;
843 }
844 if(ly1<0)
845 {
846 if((ly0-ly1)>CHKMAX_Y) return TRUE;
847 if((ly2-ly1)>CHKMAX_Y) return TRUE;
848 }
849 if(ly2<0)
850 {
851 if((ly0-ly2)>CHKMAX_Y) return TRUE;
852 if((ly1-ly2)>CHKMAX_Y) return TRUE;
853 }
854
855 return FALSE;
856 }
857
858
CheckCoord2()859 static __inline BOOL CheckCoord2()
860 {
861 if(lx0<0)
862 {
863 if((lx1-lx0)>CHKMAX_X) return TRUE;
864 }
865 if(lx1<0)
866 {
867 if((lx0-lx1)>CHKMAX_X) return TRUE;
868 }
869 if(ly0<0)
870 {
871 if((ly1-ly0)>CHKMAX_Y) return TRUE;
872 }
873 if(ly1<0)
874 {
875 if((ly0-ly1)>CHKMAX_Y) return TRUE;
876 }
877
878 return FALSE;
879 }
880
881 /*
882 //Lewpys "offsetline" func:
883
884 void offsetline(void)
885 {
886 float x0, x1, y0, y1, oolength, xl, yl;
887
888 if(bDisplayNotSet)
889 SetOGLDisplaySettings(1);
890
891 if(!(dwActFixes&16))
892 {
893 if((lx0 & SIGNBIT)) lx0|=S_MASK;
894 else lx0&=~S_MASK;
895 if((lx1 & SIGNBIT)) lx1|=S_MASK;
896 else lx1&=~S_MASK;
897 if((ly0 & SIGNBIT)) ly0|=S_MASK;
898 else ly0&=~S_MASK;
899 if((ly1 & SIGNBIT)) ly1|=S_MASK;
900 else ly1&=~S_MASK;
901 }
902
903 x0 = (float)(lx0 + PSXDisplay.CumulOffset.x);
904 x1 = (float)(lx1 + PSXDisplay.CumulOffset.x);
905 y0 = (float)(ly0 + PSXDisplay.CumulOffset.y);
906 y1 = (float)(ly1 + PSXDisplay.CumulOffset.y);
907
908 oolength = (float)1/((float)sqrt((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2);
909 // oolength = (float)1/((float)sqrt(((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2));
910
911 xl = (x1 - x0) * oolength;
912 yl = (y1 - y0) * oolength;
913
914 x0 += 0.5f;
915 x1 += 0.5f;
916
917 x0 -= xl - yl;
918 x1 += xl + yl;
919 y0 -= yl + xl;
920 y1 += yl - xl;
921
922 vertex[0].x=x0;
923 vertex[1].x=x1;
924 vertex[0].y=y0;
925 vertex[1].y=y1;
926
927 x0 -= yl * 2;
928 x1 -= yl * 2;
929 y0 += xl * 2;
930 y1 += xl * 2;
931
932 vertex[2].x=x1;
933 vertex[3].x=x0;
934 vertex[2].y=y1;
935 vertex[3].y=y0;
936 }
937 */
938
939
940 // Pete's way: a very easy (and hopefully fast) approach for lines
941 // without sqrt... using a small float -> short cast trick :)
942
943 #define VERTEX_OFFX 0.2f
944 #define VERTEX_OFFY 0.2f
945
offsetline(void)946 BOOL offsetline(void)
947 {
948 short x0,x1,y0,y1,dx,dy;float px,py;
949
950 if(bDisplayNotSet)
951 SetOGLDisplaySettings(1);
952
953 if(!(dwActFixes&16))
954 {
955 lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
956 lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
957 ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
958 ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
959
960 if(CheckCoord2()) return TRUE;
961 }
962
963 x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;
964 x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;
965 y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;
966 y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;
967
968 dx=x1-x0;
969 dy=y1-y0;
970
971 if(dx>=0)
972 {
973 if(dy>=0)
974 {
975 px=0.5f;
976 if(dx>dy) py=-0.5f;
977 else if(dx<dy) py= 0.5f;
978 else py= 0.0f;
979 }
980 else
981 {
982 py=-0.5f;
983 dy=-dy;
984 if(dx>dy) px= 0.5f;
985 else if(dx<dy) px=-0.5f;
986 else px= 0.0f;
987 }
988 }
989 else
990 {
991 if(dy>=0)
992 {
993 py=0.5f;
994 dx=-dx;
995 if(dx>dy) px=-0.5f;
996 else if(dx<dy) px= 0.5f;
997 else px= 0.0f;
998 }
999 else
1000 {
1001 px=-0.5f;
1002 if(dx>dy) py=-0.5f;
1003 else if(dx<dy) py= 0.5f;
1004 else py= 0.0f;
1005 }
1006 }
1007
1008 vertex[0].x=(short)((float)x0-px);
1009 vertex[3].x=(short)((float)x0+py);
1010
1011 vertex[0].y=(short)((float)y0-py);
1012 vertex[3].y=(short)((float)y0-px);
1013
1014 vertex[1].x=(short)((float)x1-py);
1015 vertex[2].x=(short)((float)x1+px);
1016
1017 vertex[1].y=(short)((float)y1+px);
1018 vertex[2].y=(short)((float)y1+py);
1019
1020 if(vertex[0].x==vertex[3].x && // ortho rect? done
1021 vertex[1].x==vertex[2].x &&
1022 vertex[0].y==vertex[1].y &&
1023 vertex[2].y==vertex[3].y) return FALSE;
1024 if(vertex[0].x==vertex[1].x &&
1025 vertex[2].x==vertex[3].x &&
1026 vertex[0].y==vertex[3].y &&
1027 vertex[1].y==vertex[2].y) return FALSE;
1028
1029 vertex[0].x-=VERTEX_OFFX; // otherwise a small offset
1030 vertex[0].y-=VERTEX_OFFY; // to get better accuracy
1031 vertex[1].x-=VERTEX_OFFX;
1032 vertex[1].y-=VERTEX_OFFY;
1033 vertex[2].x-=VERTEX_OFFX;
1034 vertex[2].y-=VERTEX_OFFY;
1035 vertex[3].x-=VERTEX_OFFX;
1036 vertex[3].y-=VERTEX_OFFY;
1037
1038 return FALSE;
1039 }
1040
1041 /////////////////////////////////////////////////////////
1042
offset2(void)1043 BOOL offset2(void)
1044 {
1045 if(bDisplayNotSet)
1046 SetOGLDisplaySettings(1);
1047
1048 if(!(dwActFixes&16))
1049 {
1050 lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1051 lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1052 ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1053 ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1054
1055 if(CheckCoord2()) return TRUE;
1056 }
1057
1058 if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1059 {
1060 vertex[0].x=lx0;
1061 vertex[0].y=ly0;
1062 }
1063 if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1064 {
1065 vertex[1].x=lx1;
1066 vertex[1].y=ly1;
1067 }
1068
1069 vertex[0].x+=PSXDisplay.CumulOffset.x;
1070 vertex[1].x+=PSXDisplay.CumulOffset.x;
1071 vertex[0].y+=PSXDisplay.CumulOffset.y;
1072 vertex[1].y+=PSXDisplay.CumulOffset.y;
1073
1074 return FALSE;
1075 }
1076
1077 /////////////////////////////////////////////////////////
1078
offset3(void)1079 BOOL offset3(void)
1080 {
1081 if(bDisplayNotSet)
1082 SetOGLDisplaySettings(1);
1083
1084 if(!(dwActFixes&16))
1085 {
1086 lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1087 lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1088 lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
1089 ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1090 ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1091 ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
1092
1093 if(CheckCoord3()) return TRUE;
1094 }
1095
1096 if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1097 {
1098 vertex[0].x=lx0;
1099 vertex[0].y=ly0;
1100 }
1101 if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1102 {
1103 vertex[1].x=lx1;
1104 vertex[1].y=ly1;
1105 }
1106 if(!getGteVertex(lx2, ly2, &vertex[2].x, &vertex[2].y))
1107 {
1108 vertex[2].x=lx2;
1109 vertex[2].y=ly2;
1110 }
1111
1112 vertex[0].x+=PSXDisplay.CumulOffset.x;
1113 vertex[1].x+=PSXDisplay.CumulOffset.x;
1114 vertex[2].x+=PSXDisplay.CumulOffset.x;
1115 vertex[0].y+=PSXDisplay.CumulOffset.y;
1116 vertex[1].y+=PSXDisplay.CumulOffset.y;
1117 vertex[2].y+=PSXDisplay.CumulOffset.y;
1118
1119 return FALSE;
1120 }
1121
1122 /////////////////////////////////////////////////////////
1123
offset4(void)1124 BOOL offset4(void)
1125 {
1126 if(bDisplayNotSet)
1127 SetOGLDisplaySettings(1);
1128
1129 if(!(dwActFixes&16))
1130 {
1131 lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1132 lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1133 lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
1134 lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);
1135 ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1136 ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1137 ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
1138 ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);
1139
1140 if(CheckCoord4()) return TRUE;
1141 }
1142
1143 if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1144 {
1145 vertex[0].x=lx0;
1146 vertex[0].y=ly0;
1147 }
1148 if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1149 {
1150 vertex[1].x=lx1;
1151 vertex[1].y=ly1;
1152 }
1153 if(!getGteVertex(lx2, ly2, &vertex[2].x, &vertex[2].y))
1154 {
1155 vertex[2].x=lx2;
1156 vertex[2].y=ly2;
1157 }
1158 if(!getGteVertex(lx3, ly3, &vertex[3].x, &vertex[3].y))
1159 {
1160 vertex[3].x=lx3;
1161 vertex[3].y=ly3;
1162 }
1163
1164 vertex[0].x+=PSXDisplay.CumulOffset.x;
1165 vertex[1].x+=PSXDisplay.CumulOffset.x;
1166 vertex[2].x+=PSXDisplay.CumulOffset.x;
1167 vertex[3].x+=PSXDisplay.CumulOffset.x;
1168 vertex[0].y+=PSXDisplay.CumulOffset.y;
1169 vertex[1].y+=PSXDisplay.CumulOffset.y;
1170 vertex[2].y+=PSXDisplay.CumulOffset.y;
1171 vertex[3].y+=PSXDisplay.CumulOffset.y;
1172
1173 return FALSE;
1174 }
1175
1176 /////////////////////////////////////////////////////////
1177
offsetST(void)1178 void offsetST(void)
1179 {
1180 if(bDisplayNotSet)
1181 SetOGLDisplaySettings(1);
1182
1183 if(!(dwActFixes&16))
1184 {
1185 lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1186 ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1187
1188 if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)
1189 lx0+=2048;
1190
1191 if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)
1192 ly0+=2048;
1193 }
1194
1195 ly1 = ly0;
1196 ly2 = ly3 = ly0+sprtH;
1197 lx3 = lx0;
1198 lx1 = lx2 = lx0+sprtW;
1199
1200 vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
1201 vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
1202 vertex[2].x=lx2+PSXDisplay.CumulOffset.x;
1203 vertex[3].x=lx3+PSXDisplay.CumulOffset.x;
1204 vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
1205 vertex[1].y=ly1+PSXDisplay.CumulOffset.y;
1206 vertex[2].y=ly2+PSXDisplay.CumulOffset.y;
1207 vertex[3].y=ly3+PSXDisplay.CumulOffset.y;
1208 }
1209
1210 /////////////////////////////////////////////////////////
1211
offsetScreenUpload(int Position)1212 void offsetScreenUpload(int Position)
1213 {
1214 if(bDisplayNotSet)
1215 SetOGLDisplaySettings(1);
1216
1217 if(Position==-1)
1218 {
1219 int lmdx,lmdy;
1220
1221 lmdx=xrUploadArea.x0;
1222 lmdy=xrUploadArea.y0;
1223
1224 lx0-=lmdx;
1225 ly0-=lmdy;
1226 lx1-=lmdx;
1227 ly1-=lmdy;
1228 lx2-=lmdx;
1229 ly2-=lmdy;
1230 lx3-=lmdx;
1231 ly3-=lmdy;
1232 }
1233 else
1234 if(Position)
1235 {
1236 lx0-=PSXDisplay.DisplayPosition.x;
1237 ly0-=PSXDisplay.DisplayPosition.y;
1238 lx1-=PSXDisplay.DisplayPosition.x;
1239 ly1-=PSXDisplay.DisplayPosition.y;
1240 lx2-=PSXDisplay.DisplayPosition.x;
1241 ly2-=PSXDisplay.DisplayPosition.y;
1242 lx3-=PSXDisplay.DisplayPosition.x;
1243 ly3-=PSXDisplay.DisplayPosition.y;
1244 }
1245 else
1246 {
1247 lx0-=PreviousPSXDisplay.DisplayPosition.x;
1248 ly0-=PreviousPSXDisplay.DisplayPosition.y;
1249 lx1-=PreviousPSXDisplay.DisplayPosition.x;
1250 ly1-=PreviousPSXDisplay.DisplayPosition.y;
1251 lx2-=PreviousPSXDisplay.DisplayPosition.x;
1252 ly2-=PreviousPSXDisplay.DisplayPosition.y;
1253 lx3-=PreviousPSXDisplay.DisplayPosition.x;
1254 ly3-=PreviousPSXDisplay.DisplayPosition.y;
1255 }
1256
1257 vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;
1258 vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;
1259 vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;
1260 vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;
1261 vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;
1262 vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;
1263 vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;
1264 vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;
1265
1266 if(iUseMask)
1267 {
1268 vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
1269 gl_z+=0.00004f;
1270 }
1271 }
1272
1273 /////////////////////////////////////////////////////////
1274
offsetBlk(void)1275 void offsetBlk(void)
1276 {
1277 if(bDisplayNotSet)
1278 SetOGLDisplaySettings(1);
1279
1280 vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1281 vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1282 vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1283 vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1284 vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1285 vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1286 vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1287 vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1288
1289 if(iUseMask)
1290 {
1291 vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
1292 gl_z+=0.00004f;
1293 }
1294 }
1295
1296 ////////////////////////////////////////////////////////////////////////
1297 // texture sow/tow calculations
1298 ////////////////////////////////////////////////////////////////////////
1299
assignTextureVRAMWrite(void)1300 void assignTextureVRAMWrite(void)
1301 {
1302 #ifdef OWNSCALE
1303
1304 vertex[0].sow=0.5f/ ST_FACVRAMX;
1305 vertex[0].tow=0.5f/ ST_FACVRAM;
1306
1307 vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;
1308 vertex[1].tow=0.5f/ ST_FACVRAM;
1309
1310 vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;
1311 vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;
1312
1313 vertex[3].sow=0.5f/ ST_FACVRAMX;
1314 vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;
1315
1316 #else
1317
1318 if(gl_ux[1]==255)
1319 {
1320 vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;
1321 vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;
1322 vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;
1323 vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;
1324 }
1325 else
1326 {
1327 vertex[0].sow=gl_ux[0];
1328 vertex[1].sow=gl_ux[1];
1329 vertex[2].sow=gl_ux[2];
1330 vertex[3].sow=gl_ux[3];
1331 }
1332
1333 vertex[0].tow=gl_vy[0];
1334 vertex[1].tow=gl_vy[1];
1335 vertex[2].tow=gl_vy[2];
1336 vertex[3].tow=gl_vy[3];
1337
1338 #endif
1339 }
1340
1341 GLuint gLastTex=0;
1342 GLuint gLastFMode=(GLuint)-1;
1343
1344 /////////////////////////////////////////////////////////
1345
assignTextureSprite(void)1346 void assignTextureSprite(void)
1347 {
1348 if(bUsingTWin)
1349 {
1350 vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1351 vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;
1352 vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1353 vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;
1354 gLastTex=gTexName;
1355
1356 if(iFilterType>0 && iFilterType<3 && iHiResTextures!=2)
1357 {
1358 float fxmin=65536.0f,fxmax=0.0f,fymin=65536.0f,fymax=0.0f;int i;
1359
1360 for(i=0;i<4;i++)
1361 {
1362 if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1363 if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1364 if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1365 if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1366 }
1367
1368 for(i=0;i<4;i++)
1369 {
1370 #ifdef OWNSCALE
1371 if(vertex[i].sow==fxmin) vertex[i].sow+=0.375f/(float)TWin.Position.x1;
1372 if(vertex[i].sow==fxmax) vertex[i].sow-=0.375f/(float)TWin.Position.x1;
1373 if(vertex[i].tow==fymin) vertex[i].tow+=0.375f/(float)TWin.Position.y1;
1374 if(vertex[i].tow==fymax) vertex[i].tow-=0.375f/(float)TWin.Position.y1;
1375 #else
1376 if(vertex[i].sow==fxmin) vertex[i].sow+=96.0f/(float)TWin.Position.x1;
1377 if(vertex[i].sow==fxmax) vertex[i].sow-=96.0f/(float)TWin.Position.x1;
1378 if(vertex[i].tow==fymin) vertex[i].tow+=96.0f/(float)TWin.Position.y1;
1379 if(vertex[i].tow==fymax) vertex[i].tow-=96.0f/(float)TWin.Position.y1;
1380 #endif
1381 }
1382 }
1383
1384 }
1385 else
1386 {
1387 #ifdef OWNSCALE
1388
1389 vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE;
1390 vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE;
1391 vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE;
1392 vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE;
1393
1394 #else
1395
1396 vertex[0].sow=vertex[3].sow=gl_ux[0];
1397 vertex[1].sow=vertex[2].sow=sSprite_ux2;
1398 vertex[0].tow=vertex[1].tow=gl_vy[0];
1399 vertex[2].tow=vertex[3].tow=sSprite_vy2;
1400
1401 #endif
1402
1403 if(iFilterType>2)
1404 {
1405 if(gLastTex!=gTexName || gLastFMode!=0)
1406 {
1407 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1408 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1409 gLastTex=gTexName;gLastFMode=0;
1410 }
1411 }
1412 }
1413
1414 if(usMirror & 0x1000)
1415 {
1416 vertex[0].sow=vertex[1].sow;
1417 vertex[1].sow=vertex[2].sow=vertex[3].sow;
1418 vertex[3].sow=vertex[0].sow;
1419 }
1420
1421 if(usMirror & 0x2000)
1422 {
1423 vertex[0].tow=vertex[3].tow;
1424 vertex[2].tow=vertex[3].tow=vertex[1].tow;
1425 vertex[1].tow=vertex[0].tow;
1426 }
1427
1428 }
1429
1430 /////////////////////////////////////////////////////////
1431
assignTexture3(void)1432 void assignTexture3(void)
1433 {
1434 if(bUsingTWin)
1435 {
1436 vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1437 vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1438 vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
1439 vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
1440 vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
1441 vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
1442 gLastTex=gTexName;
1443 }
1444 else
1445 {
1446 #ifdef OWNSCALE
1447 vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;
1448 vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;
1449 vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;
1450
1451 vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;
1452 vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;
1453 vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;
1454 #else
1455 vertex[0].sow=gl_ux[0];
1456 vertex[0].tow=gl_vy[0];
1457 vertex[1].sow=gl_ux[1];
1458 vertex[1].tow=gl_vy[1];
1459 vertex[2].sow=gl_ux[2];
1460 vertex[2].tow=gl_vy[2];
1461 #endif
1462
1463 if(iFilterType>2)
1464 {
1465 if(gLastTex!=gTexName || gLastFMode!=1)
1466 {
1467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1469 gLastTex=gTexName;gLastFMode=1;
1470 }
1471 }
1472
1473 if(iFilterType)
1474 {
1475 float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
1476 for(i=0;i<3;i++)
1477 {
1478 if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1479 if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1480 if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1481 if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1482 }
1483
1484 for(i=0;i<3;i++)
1485 {
1486 if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
1487 if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
1488 if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
1489 if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
1490 }
1491 }
1492 }
1493 }
1494
1495 /////////////////////////////////////////////////////////
1496
assignTexture4(void)1497 void assignTexture4(void)
1498 {
1499 if(bUsingTWin)
1500 {
1501 vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1502 vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1503 vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
1504 vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
1505 vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
1506 vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
1507 vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;
1508 vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;
1509 gLastTex=gTexName;
1510 }
1511 else
1512 {
1513 #ifdef OWNSCALE
1514 vertex[0].sow=(float)gl_ux[0] / ST_FAC;
1515 vertex[0].tow=(float)gl_vy[0] / ST_FAC;
1516 vertex[1].sow=(float)gl_ux[1] / ST_FAC;
1517 vertex[1].tow=(float)gl_vy[1] / ST_FAC;
1518 vertex[2].sow=(float)gl_ux[2] / ST_FAC;
1519 vertex[2].tow=(float)gl_vy[2] / ST_FAC;
1520 vertex[3].sow=(float)gl_ux[3] / ST_FAC;
1521 vertex[3].tow=(float)gl_vy[3] / ST_FAC;
1522 #else
1523 vertex[0].sow=gl_ux[0];
1524 vertex[0].tow=gl_vy[0];
1525 vertex[1].sow=gl_ux[1];
1526 vertex[1].tow=gl_vy[1];
1527 vertex[2].sow=gl_ux[2];
1528 vertex[2].tow=gl_vy[2];
1529 vertex[3].sow=gl_ux[3];
1530 vertex[3].tow=gl_vy[3];
1531 #endif
1532
1533 if(iFilterType>2)
1534 {
1535 if(gLastTex!=gTexName || gLastFMode!=1)
1536 {
1537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1538 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1539 gLastTex=gTexName;gLastFMode=1;
1540 }
1541 }
1542
1543 if(iFilterType)
1544 {
1545 float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
1546 for(i=0;i<4;i++)
1547 {
1548 if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1549 if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1550 if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1551 if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1552 }
1553
1554 for(i=0;i<4;i++)
1555 {
1556 if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
1557 if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
1558 if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
1559 if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
1560 }
1561 }
1562 }
1563 }
1564
1565 ////////////////////////////////////////////////////////////////////////
1566 ////////////////////////////////////////////////////////////////////////
1567 ////////////////////////////////////////////////////////////////////////
1568
1569 ////////////////////////////////////////////////////////////////////////
1570 // render pos / buffers
1571 ////////////////////////////////////////////////////////////////////////
1572
1573 #ifndef _WINDOWS
1574 #define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)
1575 #endif
1576
1577 ////////////////////////////////////////////////////////////////////////
1578 // SetDisplaySettings: "simply" calcs the new drawing area and updates
1579 // the ogl clipping (scissor)
1580
1581 BOOL bSetClip=FALSE;
1582
SetOGLDisplaySettings(BOOL DisplaySet)1583 void SetOGLDisplaySettings(BOOL DisplaySet)
1584 {
1585 static RECT rprev={0,0,0,0};
1586 static RECT rC ={0,0,0,0};
1587 static int iOldX=0;
1588 static int iOldY=0;
1589 RECT r;float XS,YS;
1590
1591 bDisplayNotSet = FALSE;
1592
1593 //----------------------------------------------------// that's a whole screen upload
1594 if(!DisplaySet)
1595 {
1596 RECT rX;
1597 PSXDisplay.GDrawOffset.x=0;
1598 PSXDisplay.GDrawOffset.y=0;
1599
1600 PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;
1601 PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;
1602
1603 rprev.left=rprev.left+1;
1604
1605 rX=rRatioRect;
1606 rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);
1607
1608 if(bSetClip || !EqualRect(&rC,&rX))
1609 {
1610 rC=rX;
1611 glScissor(rC.left,rC.top,rC.right,rC.bottom);
1612 bSetClip=FALSE;
1613 }
1614 return;
1615 }
1616 //----------------------------------------------------//
1617
1618 PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;
1619 PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;
1620 PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;
1621 PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;
1622
1623 r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;
1624 r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;
1625
1626 if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)
1627 {
1628 r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;
1629 r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;
1630 }
1631
1632 r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;
1633 r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;
1634
1635 if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)
1636 {
1637 r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;
1638 r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;
1639 }
1640
1641 if(!bSetClip && EqualRect(&r,&rprev) &&
1642 iOldX == PSXDisplay.DisplayMode.x &&
1643 iOldY == PSXDisplay.DisplayMode.y)
1644 return;
1645
1646 rprev = r;
1647 iOldX = PSXDisplay.DisplayMode.x;
1648 iOldY = PSXDisplay.DisplayMode.y;
1649
1650 XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;
1651 YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;
1652
1653 if(PreviousPSXDisplay.Range.x0)
1654 {
1655 short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;
1656
1657 r.left+=PreviousPSXDisplay.Range.x0+1;
1658
1659 r.right+=PreviousPSXDisplay.Range.x0;
1660
1661 if(r.left>s) r.left=s;
1662 if(r.right>s) r.right=s;
1663 }
1664
1665 if(PreviousPSXDisplay.Range.y0)
1666 {
1667 short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;
1668
1669 r.top+=PreviousPSXDisplay.Range.y0+1;
1670 r.bottom+=PreviousPSXDisplay.Range.y0;
1671
1672 if(r.top>s) r.top=s;
1673 if(r.bottom>s) r.bottom=s;
1674 }
1675
1676 // Set the ClipArea variables to reflect the new screen,
1677 // offset from zero (since it is a new display buffer)
1678 r.left = (int)(((float)(r.left)) *XS);
1679 r.top = (int)(((float)(r.top)) *YS);
1680 r.right = (int)(((float)(r.right + 1))*XS);
1681 r.bottom = (int)(((float)(r.bottom + 1))*YS);
1682
1683 // Limit clip area to the screen size
1684 if (r.left > iResX) r.left = iResX;
1685 if (r.left < 0) r.left = 0;
1686 if (r.top > iResY) r.top = iResY;
1687 if (r.top < 0) r.top = 0;
1688 if (r.right > iResX) r.right = iResX;
1689 if (r.right < 0) r.right = 0;
1690 if (r.bottom > iResY) r.bottom = iResY;
1691 if (r.bottom < 0) r.bottom = 0;
1692
1693 r.right -=r.left;
1694 r.bottom-=r.top;
1695 r.top=iResY-(r.top+r.bottom);
1696
1697 r.left+=rRatioRect.left;
1698 r.top -=rRatioRect.top;
1699
1700 if(bSetClip || !EqualRect(&r,&rC))
1701 {
1702 glScissor(r.left,r.top,r.right,r.bottom);
1703 rC=r;
1704 bSetClip=FALSE;
1705 }
1706 }
1707
1708 ////////////////////////////////////////////////////////////////////////
1709 ////////////////////////////////////////////////////////////////////////
1710 ////////////////////////////////////////////////////////////////////////
1711
1712