📄 gl_draw.c
字号:
/*Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )http://www.zsnes.comhttp://sourceforge.net/projects/zsneshttps://zsnes.bountysource.comThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "../cfg.h"#include "../gblhdr.h"#include "../asm_call.h"#define BYTE unsigned char#define WORD unsigned short#define DWORD unsigned long//C++ style code in C#define bool unsigned char#define true 1#define false 0// FUNCTIONSvoid hq2x_16b(void);// VIDEO VARIABLESextern SDL_Surface *surface;extern int SurfaceX, SurfaceY;extern int SurfaceLocking;extern DWORD BitDepth;// OPENGL VARIABLESstatic unsigned short *glvidbuffer = 0;static GLuint gltextures[4];static int gltexture256, gltexture512;static int glfilters = GL_NEAREST;static int glscanready = 0;extern Uint8 GUIOn2;extern unsigned int vidbuffer;extern unsigned char curblank;extern BYTE GUIRESIZE[];void gl_clearwin();void UpdateVFrame();void gl_scanlines();bool OGLModeCheck();int gl_start(int width, int height, int req_depth, int FullScreen){ Uint32 flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE | SDL_OPENGL; int i; flags |= (GUIRESIZE[cvidmode] ? SDL_RESIZABLE : 0); flags |= (FullScreen ? SDL_FULLSCREEN : 0); SurfaceX = width; SurfaceY = height; surface = SDL_SetVideoMode(SurfaceX, SurfaceY, req_depth, flags); if (surface == NULL) { fprintf(stderr, "Could not set %dx%d-GL video mode.\n",SurfaceX, SurfaceY); return false; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);#if (SDL_MAJOR_VERSION > 1) || ((SDL_MINOR_VERSION > 2) || ((SDL_MINOR_VERSION == 2) && (SDL_PATCHLEVEL >= 10))) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);#endif if (!glvidbuffer) { glvidbuffer = (unsigned short *) malloc(512 * 512 * sizeof(short)); } gl_clearwin(); SDL_WarpMouse(SurfaceX / 4, SurfaceY / 4); // Grab mouse in fullscreen mode FullScreen ? SDL_WM_GrabInput(SDL_GRAB_ON) : SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_WM_SetCaption("ZSNES", "ZSNES"); SDL_ShowCursor(0); /* Setup some GL stuff */ glEnable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_2D); glViewport(0, 0, SurfaceX, SurfaceY); /* * gltextures[0]: 2D texture, 256x224 * gltextures[1]: 2D texture, 512x224 * gltextures[3]: 1D texture, 256 lines of alternating alpha */ glGenTextures(4, gltextures); for (i = 0; i < 3; i++) { glBindTexture(GL_TEXTURE_2D, gltextures[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfilters); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfilters); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } if (scanlines) gl_scanlines(); return true;}void gl_end(){ if (glvidbuffer) { glDeleteTextures(4, gltextures); free(glvidbuffer); glvidbuffer = 0; }}extern DWORD AddEndBytes;extern DWORD NumBytesPerLine;extern unsigned char *WinVidMemStart;extern unsigned char NGNoTransp;void copy640x480x16bwin(void);extern unsigned char SpecialLine[224]; /* 0 if lo-res, > 0 if hi-res */void gl_clearwin(){ glClear(GL_COLOR_BUFFER_BIT); memset(glvidbuffer, 0, 512 * 448 * 2);}/* gl_drawspan: * Puts a quad on the screen for hires/lores portions, starting at line start, * and ending at line end.. * Builds the 256x256/512x256 textures if gltexture256 or gltexture512 == 0 */static void gl_drawspan(int hires, int start, int end){ int i, j; switch (hires) { case 0: break; case 3: case 7: hires = 2; break; default: hires = 1; break; } if (hires) { if (hires != gltexture512) { unsigned short *vbuf1 = &((unsigned short *) vidbuffer)[16]; unsigned short *vbuf2 = &((unsigned short *) vidbuffer)[75036 * 2 + 16]; unsigned short *vbuf = &glvidbuffer[0]; if (hires>1) // mode 7 { for (j = 224; j--;) { for (i = 256; i--;) *vbuf++ = *vbuf1++; for (i = 256; i--;) *vbuf++ = *vbuf2++; vbuf1 += 32; vbuf2 += 32; } glBindTexture(GL_TEXTURE_2D, gltextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 512, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glvidbuffer); gltexture512 = 2; } else { for (j = 224; j--;) { for (i = 256; i--;) { *vbuf++ = *vbuf1++; *vbuf++ = *vbuf2++; } vbuf1 += 32; vbuf2 += 32; // skip the two 16-pixel-wide columns } glBindTexture(GL_TEXTURE_2D, gltextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glvidbuffer); gltexture512 = 1; } } glBindTexture(GL_TEXTURE_2D, gltextures[1]); glBegin(GL_QUADS); glTexCoord2f(0.0f, (224.0 / 256.0) * (start / 224.0)); glVertex2f(-1.0f, (112 - start) / 112.0); glTexCoord2f(1.0f, (224.0 / 256.0) * (start / 224.0)); glVertex2f(1.0f, (112 - start) / 112.0); glTexCoord2f(1.0f, (224.0 / 256.0) * (end / 224.0)); glVertex2f(1.0f, (112 - end) / 112.0); glTexCoord2f(0.0f, (224.0 / 256.0) * (end / 224.0)); glVertex2f(-1.0f, (112 - end) / 112.0); glEnd(); } else { glBindTexture(GL_TEXTURE_2D, gltextures[0]); if (!gltexture256) { glPixelStorei(GL_UNPACK_SKIP_PIXELS, 16); glPixelStorei(GL_UNPACK_ROW_LENGTH, 288); glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, ((unsigned short *) vidbuffer) + 288); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); gltexture256 = 1; } glBegin(GL_QUADS); glTexCoord2f(0.0f, (224.0 / 256.0) * (start / 224.0)); glVertex2f(-1.0f, (112 - start) / 112.0); glTexCoord2f(1.0f, (224.0 / 256.0) * (start / 224.0)); glVertex2f(1.0f, (112 - start) / 112.0); glTexCoord2f(1.0f, (224.0 / 256.0) * (end / 224.0)); glVertex2f(1.0f, (112 - end) / 112.0); glTexCoord2f(0.0f, (224.0 / 256.0) * (end / 224.0)); glVertex2f(-1.0f, (112 - end) / 112.0); glEnd(); }}void gl_drawwin(){ int i; NGNoTransp = 0; // Set this value to 1 within the appropriate // video mode if you want to add a custom // transparency routine or hardware // transparency. This only works if // the value of newengen is equal to 1. // (see ProcessTransparencies in newgfx16.asm // for ZSNES' current transparency code) UpdateVFrame(); if (curblank || !OGLModeCheck()) return; if (BilinearFilter) { glfilters = GL_LINEAR; if (GUIOn2 && !FilteredGUI) glfilters = GL_NEAREST; } else { glfilters = GL_NEAREST; } if (SurfaceX >= 512 && (hqFilter || En2xSaI)) { AddEndBytes = 0; NumBytesPerLine = 1024; WinVidMemStart = (void *) glvidbuffer; if (hqFilter) hq2x_16b(); else asm_call(copy640x480x16bwin); /* Display 1 512x448 quad for the 512x448 buffer */ glBindTexture(GL_TEXTURE_2D, gltextures[1]); glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glvidbuffer); glDisable (GL_DEPTH_TEST); glDisable (GL_LIGHTING); glDisable (GL_BLEND); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 448.0f / 512.0f); glVertex3f(1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 448.0f / 512.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glEnd(); } else { /* * This code splits the hires/lores portions up, and draws * them with gl_drawspan */ int lasthires, lasthires_line = 0; gltexture256 = gltexture512 = 0; lasthires = SpecialLine[1]; for (i = 0; i < 224; i++) { if (SpecialLine[i + 1]) { if (lasthires) continue; gl_drawspan(lasthires, lasthires_line, i); lasthires = SpecialLine[i + 1]; lasthires_line = i; } else { if (!lasthires) continue; gl_drawspan(lasthires, lasthires_line, i); lasthires = SpecialLine[i + 1]; lasthires_line = i; } } if (i - lasthires_line > 1) gl_drawspan(lasthires, lasthires_line, i); /* * This is here rather than right outside this if because the * GUI doesn't allow scanlines to be selected while filters are * on.. There is no technical reason they can't be on while * filters are on, however. Feel free to change the GUI, and * move this outside the if (En2xSaI) {}, if you do. */ if (scanlines) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); if (scanlines != glscanready) gl_scanlines(); glBlendFunc(GL_DST_COLOR, GL_ZERO); glBindTexture(GL_TEXTURE_1D, gltextures[3]); glBegin(GL_QUADS); for (i = 0; i < SurfaceY; i += 256) { glTexCoord1f(0.0f); glVertex3f(-1.0f, (SurfaceY - i * 2.0) / SurfaceY, -1.0f); glTexCoord1f(0.0f); glVertex3f(1.0f, (SurfaceY - i * 2.0) / SurfaceY, -1.0f); glTexCoord1f(1.0f); glVertex3f(1.0f, (SurfaceY - (i + 256) * 2.0) / SurfaceY, -1.0f); glTexCoord1f(1.0f); glVertex3f(-1.0f, (SurfaceY - (i + 256) * 2.0) / SurfaceY, -1.0f); } glEnd(); glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); } } SDL_GL_SwapBuffers();}void gl_scanlines(void){ GLubyte scanbuffer[256][4]; int i, j = scanlines==1 ? 0 : (scanlines==2 ? 192 : 128); for (i = 0; i < 256; i += 2) { scanbuffer[i][0] = scanbuffer[i][1] = scanbuffer[i][2] = j; scanbuffer[i][3] = 0xFF; scanbuffer[i+1][0] = scanbuffer[i+1][1] = scanbuffer[i+1][2] = 0xFF; scanbuffer[i+1][3] = 0xFF; } glBindTexture(GL_TEXTURE_1D, gltextures[3]); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, scanbuffer); glscanready = scanlines;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -