From 47a02d45cba3c005b160d57e23394a9f4c7d5e0d Mon Sep 17 00:00:00 2001 From: hpsolo <> Date: Sun, 3 Jun 2001 06:49:43 +0000 Subject: [PATCH] Almost forgot... --- zsnes/src/linux/gl_draw.c | 431 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 zsnes/src/linux/gl_draw.c diff --git a/zsnes/src/linux/gl_draw.c b/zsnes/src/linux/gl_draw.c new file mode 100644 index 00000000..9000bfd9 --- /dev/null +++ b/zsnes/src/linux/gl_draw.c @@ -0,0 +1,431 @@ +#include +#include +#include +#include +#include "SDL.h" +#ifdef __OPENGL__ +#include +#endif + +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long + +typedef enum +{ FALSE = 0, TRUE = !FALSE } +BOOL; + +// SDL VIDEO VARIOABLES +static SDL_Surface *surface; +static int SurfaceX, SurfaceY; +static int SurfaceLocking = 0; + +// OPENGL VARIABLES +static unsigned short *glvidbuffer = 0; +static GLuint gltextures[4]; +static int gltexture256, gltexture512; +static int glfilters = GL_NEAREST; +extern Uint8 En2xSaI, scanlines; +extern Uint8 BilinearFilter; +extern Uint8 FilteredGUI; +extern Uint8 GUIOn2; + +extern unsigned int vidbuffer; + +int gl_start(int width, int height, int req_depth, int FullScreen) +{ + Uint32 flags = + SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE | SDL_OPENGL; + GLubyte scanbuffer[256]; + int i; + + flags |= (FullScreen ? SDL_FULLSCREEN : 0); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + 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; + } + + SurfaceLocking = SDL_MUSTLOCK(surface); + 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-GL Linux", "ZSNES"); + SDL_ShowCursor(0); + + /* Setup some GL stuff */ + glvidbuffer = malloc(512 * 512 * 2); + + glEnable(GL_TEXTURE_1D); + glEnable(GL_TEXTURE_2D); + + glViewport(0, 0, SurfaceX, SurfaceY); + + /* + * gltextures[0]: 2D texture, 256x224 + * gltextures[1]: 2D texture, Left half of 512x224 + * gltextures[2]: 2D texture, Right half of 512x224 + * gltextures[3]: 1D texture, 256 lines of alternating alpha + */ + glGenTextures(4, gltextures); + + /* Initialize the scanline texture (alternating opaque/transparent) */ + for (i = 0; i < 256; i += 2) + { + scanbuffer[i] = 0xff; + scanbuffer[i + 1] = 0; + } + + 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_LUMINANCE_ALPHA, 256, 0, GL_ALPHA, + GL_UNSIGNED_BYTE, scanbuffer); + + return TRUE; +} + +void gl_end() +{ + glDeleteTextures(4, gltextures); + free(glvidbuffer); +} + +static void LockSurface(void) +{ + if (SurfaceLocking) + SDL_LockSurface(surface); +} + +static void UnlockSurface(void) +{ + if (SurfaceLocking) + SDL_UnlockSurface(surface); + SDL_GL_SwapBuffers(); +} + +extern DWORD AddEndBytes; +extern DWORD NumBytesPerLine; +extern unsigned char *WinVidMemStart; +extern unsigned char FPUCopy; +extern unsigned char NGNoTransp; +extern unsigned char newengen; +extern void copy640x480x16bwin(void); +extern unsigned char SpecialLine[224]; /* 0 if lo-res, > 0 if hi-res */ + +void gl_clearwin() +{ + glClear(GL_COLOR_BUFFER_BIT); + if (En2xSaI) + 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; + + if (hires) + { + if (!gltexture512) + { + unsigned short *vbuf1 = + &((unsigned short *) vidbuffer)[16]; + unsigned short *vbuf2 = + &((unsigned short *) vidbuffer)[75036 * 2 + 16]; + unsigned short *vbuf = &glvidbuffer[0]; + + for (j = 0; j < 224; j++) + { + for (i = 0; i < 256; i++) + { + *vbuf++ = *vbuf1++; + *vbuf++ = *vbuf2++; + } + vbuf1 += 32; + vbuf2 += 32; // skip the two 16-pixel-wide columns + } + + glBindTexture(GL_TEXTURE_2D, gltextures[1]); + 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); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 512); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + glvidbuffer + 512); + + glBindTexture(GL_TEXTURE_2D, gltextures[2]); + 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); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 256); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 512); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + glvidbuffer + 512); + + 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(0.0f, (112 - start) / 112.0); + glTexCoord2f(1.0f, (224.0 / 256.0) * (end / 224.0)); + glVertex2f(0.0f, (112 - end) / 112.0); + glTexCoord2f(0.0f, (224.0 / 256.0) * (end / 224.0)); + glVertex2f(-1.0f, (112 - end) / 112.0); + glEnd(); + + glBindTexture(GL_TEXTURE_2D, gltextures[2]); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, (224.0 / 256.0) * (start / 224.0)); + glVertex2f(0.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(0.0f, (112 - end) / 112.0); + glEnd(); + } + else + { + glBindTexture(GL_TEXTURE_2D, gltextures[0]); + if (!gltexture256) + { + 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); + 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); + + 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) + + LockSurface(); + + if (BilinearFilter) + { + glfilters = GL_LINEAR; + if (GUIOn2 && !FilteredGUI) + glfilters = GL_NEAREST; + } + else + { + glfilters = GL_NEAREST; + } + + glLoadIdentity(); + + if (En2xSaI) + { + /* We have to use copy640x480x16bwin for 2xSaI */ + AddEndBytes = 0; + NumBytesPerLine = 1024; + WinVidMemStart = (void *) glvidbuffer; + __asm__ __volatile__("call copy640x480x16bwin" + ::: "memory", "eax", "ebx", "ecx", "edx", "esi", "edi"); + + /* Display 4 256x256 quads for the 512x448 buffer */ + 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); + + /* Upper left quad */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 512); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glvidbuffer); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(-1.0f, 1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(0.0f, 1.0f, -1.0f); + glTexCoord2f(1.0f, (224.0 / 256.0)); + glVertex3f(0.0f, 0.0f, -1.0f); + glTexCoord2f(0.0f, (224.0 / 256.0)); + glVertex3f(-1.0f, 0.0f, -1.0f); + glEnd(); + + /* Upper right quad */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 512); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + glvidbuffer + 256); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(0.0f, 1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(1.0f, 1.0f, -1.0f); + glTexCoord2f(1.0f, (224.0 / 256.0)); + glVertex3f(1.0f, 0.0f, -1.0f); + glTexCoord2f(0.0f, (224.0 / 256.0)); + glVertex3f(0.0f, 0.0f, -1.0f); + glEnd(); + + /* Lower left quad */ + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 512); + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + glvidbuffer + 512 * 224); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(-1.0f, 0.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(0.0f, 0.0f, -1.0f); + glTexCoord2f(1.0f, (224.0 / 256.0)); + glVertex3f(0.0f, -1.0f, -1.0f); + glTexCoord2f(0.0f, (224.0 / 256.0)); + glVertex3f(-1.0f, -1.0f, -1.0f); + glEnd(); + + /* Lower right quad */ + glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + glvidbuffer + 512 * 224 + 256); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(0.0f, 0.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(1.0f, 0.0f, -1.0f); + glTexCoord2f(1.0f, (224.0 / 256.0)); + glVertex3f(1.0f, -1.0f, -1.0f); + glTexCoord2f(0.0f, (224.0 / 256.0)); + glVertex3f(0.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 = 1; i < 222; 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; + } + } + 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); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_1D, gltextures[3]); + glColor4f(1.0f, 1.0f, 1.0f, + scanlines == 1 ? 1.0f : (scanlines == + 2 ? 0.25f : 0.50f)); + for (i = 0; i < SurfaceY; i += 256) + { + glBegin(GL_QUADS); + 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); + } + } + UnlockSurface(); +}