From a013ae33063383b8fbdd6537d1f0348ddacac663 Mon Sep 17 00:00:00 2001 From: zones Date: Sun, 20 Feb 2011 20:27:20 +0900 Subject: [PATCH] Mac,Unix: Add 256*448,478 support / Mac:code cleanup --- filter/blit.cpp | 17 + filter/blit.h | 1 + macosx/mac-render.cpp | 1938 ++++++++++++----------------------------- unix/x11.cpp | 33 +- 4 files changed, 619 insertions(+), 1370 deletions(-) diff --git a/filter/blit.cpp b/filter/blit.cpp index c3dca16e..4a6d100c 100644 --- a/filter/blit.cpp +++ b/filter/blit.cpp @@ -327,6 +327,23 @@ void S9xBlitPixHiRes16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRo } } +void S9xBlitPixDoubled16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + for (; height; height--) + { + uint16 *dP = (uint16 *) dstPtr, *bP = (uint16 *) srcPtr; + + for (int i = 0; i < width; i++) + { + *dP++ = *bP; + *dP++ = *bP++; + } + + srcPtr += srcRowBytes; + dstPtr += dstRowBytes; + } +} + void S9xBlitPixScaledTV16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) { uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta; diff --git a/filter/blit.h b/filter/blit.h index 493c4f6d..39cb3c9b 100644 --- a/filter/blit.h +++ b/filter/blit.h @@ -192,6 +192,7 @@ void S9xBlitNTSCFilterSet (const snes_ntsc_setup_t *); void S9xBlitPixSmall16 (uint8 *, int, uint8 *, int, int, int); void S9xBlitPixScaled16 (uint8 *, int, uint8 *, int, int, int); void S9xBlitPixHiRes16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixDoubled16 (uint8 *, int, uint8 *, int, int, int); void S9xBlitPixScaledTV16 (uint8 *, int, uint8 *, int, int, int); void S9xBlitPixHiResTV16 (uint8 *, int, uint8 *, int, int, int); void S9xBlitPixHiResMixedTV16 (uint8 *, int, uint8 *, int, int, int); diff --git a/macosx/mac-render.cpp b/macosx/mac-render.cpp index a8c03424..9bb6bd8f 100644 --- a/macosx/mac-render.cpp +++ b/macosx/mac-render.cpp @@ -210,6 +210,8 @@ #include "mac-screenshot.h" #include "mac-render.h" +typedef void (* Blitter) (uint8 *, int, uint8 *, int, int, int); + static OSStatus BlitMPGLTask (void *); static OSStatus PrepareMPBlitGL (void); static void S9xInitFullScreen (void); @@ -228,19 +230,14 @@ static void S9xInitCoreImage (void); static void S9xDeinitCoreImage (void); static void S9xPutImageOpenGL (int, int); static void S9xPutImageBlitGL (int, int); -static void S9xPutImageCoreImage (int, int); -static void S9xPutImageOverscanOpenGL (int, int); -static void S9xPutImageOverscanBlitGL (int, int); -static void S9xPutImageOverscanCoreImage (int, int); static void S9xPutImageBlitGL2 (int, int); -static void S9xPutImageBlitGL2CoreImage (int, int); static void GLMakeScreenMesh (GLfloat *, int, int); static void GLMakeTextureMesh (GLfloat *, int, int, float, float); - -#define BYTES_PER_PIXEL 2 - -#define kMarginDouble ((kMacWindowHeight - (SNES_HEIGHT << 1)) >> 1) -#define kMarginDoubleExt ((kMacWindowHeight - (SNES_HEIGHT_EXTENDED << 1)) >> 1) +static void GLPrepareTexture (bool8, int, int, int, int, int, int); +static inline void RenderBlitScreen (Blitter, int, int, int, int, int, uint16 *); +#ifndef MAC_LEOPARD_TIGER_PANTHER_SUPPORT +static void SetBestDisplayMode (int, int); +#endif enum { @@ -252,6 +249,7 @@ enum enum { kGL256256 = 0, + kGL256512, kGL512256, kGL512512, kGLBlit2x, @@ -268,6 +266,8 @@ enum kSC2xExtend, kSC2xNHiRes, kSC2xEHiRes, + kSC2xNInter, + kSC2xEInter, kSC3xNormal, kSC3xExtend, kSC3xNHiRes, @@ -283,15 +283,12 @@ enum kSCMeshY = 9 }; -typedef void (* Blitter) (uint8 *, int, uint8 *, int, int, int); - typedef struct { Blitter blitFn; int nx; int srcWidth; int srcHeight; - int srcRowBytes; int copyWidth; int copyHeight; uint16 *gfxBuffer; @@ -308,6 +305,9 @@ typedef struct GLint texW[kGLNumTextures]; GLint texH[kGLNumTextures]; GLboolean rangeExt; + GLint storage_hint; + GLint storage_apple; + GLfloat agp_texturing; } OpenGLData; static uint16 *gfxScreen[2], @@ -321,7 +321,7 @@ static MPTaskID taskID = NULL; static MPQueueID notificationQueue = NULL, taskQueue = NULL; static MPSemaphoreID readySemaphore = NULL; -static MPData *mpDataBuffer = NULL; +static MPData *mpBlit = NULL; static OpenGLData OpenGL; static CGLContextObj glContext; @@ -354,17 +354,16 @@ static const int ntsc_width = SNES_NTSC_OUT_WIDTH(SNES_WIDTH); // 602 void InitGraphics (void) { - int safebuffersize = 520 * 520 * BYTES_PER_PIXEL - 512 * 512 * BYTES_PER_PIXEL; + int safemarginbytes = (520 * 520 - 512 * 512) * 2; - GFX.Pitch = 512 * BYTES_PER_PIXEL; + snesScreenA = (uint16 *) calloc( 520 * 520 * 2, 1); + snesScreenB = (uint16 *) calloc( 520 * 520 * 2, 1); + blitGLBuffer = (uint8 *) calloc(1024 * 1024 * 2, 1); - snesScreenA = (uint16 *) calloc( 520 * 520 * BYTES_PER_PIXEL, 1); - snesScreenB = (uint16 *) calloc( 520 * 520 * BYTES_PER_PIXEL, 1); - blitGLBuffer = (uint8 *) calloc(1024 * 1024 * BYTES_PER_PIXEL, 1); - - gfxScreen[0] = snesScreenA + (safebuffersize >> 2); - gfxScreen[1] = snesScreenB + (safebuffersize >> 2); + gfxScreen[0] = snesScreenA + (safemarginbytes >> 2); + gfxScreen[1] = snesScreenB + (safemarginbytes >> 2); + GFX.Pitch = 512 * 2; GFX.Screen = gfxScreen[0]; if (!snesScreenA || !snesScreenB || !blitGLBuffer) @@ -432,215 +431,43 @@ void DeinitGraphics (void) } } -static OSStatus BlitMPGLTask (void *parameter) -{ - OSStatus err = noErr; - int32 theCommand, param1, param2; - - printf("MP: Entered BlitGL thread.\n"); - - for (;;) - { - err = MPWaitOnQueue(taskQueue, (void **) &theCommand, (void **) ¶m1, (void **) ¶m2, kDurationForever); - if (err) - break; - - if (theCommand == kMPBlitFrame) - { - switch (mpDataBuffer->nx) - { - case -1: - (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); - break; - - case -2: - if (mpDataBuffer->srcHeight > SNES_HEIGHT_EXTENDED) - (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); - else - { - uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); - int aligned = ((ntsc_width + 2) >> 1) << 1; - (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, tmpBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); - S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, mpDataBuffer->copyHeight); - mpDataBuffer->copyHeight *= 2; - } - - break; - - default: - int dstbytes = (OpenGL.rangeExt ? mpDataBuffer->copyWidth : ((mpDataBuffer->copyWidth > 512) ? 1024 : 512)) * 2; - (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, dstbytes, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); - break; - } - - if (!ciFilterEnable) - S9xPutImageBlitGL2(mpDataBuffer->copyWidth, mpDataBuffer->copyHeight); - else - S9xPutImageBlitGL2CoreImage(mpDataBuffer->copyWidth, mpDataBuffer->copyHeight); - MPSignalSemaphore(readySemaphore); - } - else - if (theCommand == kMPBlitNone) - MPSignalSemaphore(readySemaphore); - else - if (theCommand == kMPBlitDone) - break; - else - { - err = userCanceledErr; - break; - } - } - - MPFree(mpDataBuffer); - MPDeleteSemaphore(readySemaphore); - MPDeleteQueue(taskQueue); - mpDataBuffer = NULL; - readySemaphore = NULL; - taskQueue = NULL; - - printf("MP: Exited BlitGL thread.\n"); - - return (err); -} - -static OSStatus PrepareMPBlitGL (void) -{ - OSStatus err; - - mpDataBuffer = (MPData *) MPAllocateAligned(sizeof(MPData), kMPAllocateDefaultAligned, kMPAllocateClearMask); - if (!mpDataBuffer) - return (memFullErr); - - err = MPCreateQueue(¬ificationQueue); - if (err == noErr) - { - err = MPCreateQueue(&taskQueue); - if (err == noErr) - { - err = MPCreateBinarySemaphore(&readySemaphore); - if (err == noErr) - { - MPSignalSemaphore(readySemaphore); - err = MPCreateTask(BlitMPGLTask, NULL, 0, notificationQueue, NULL, NULL, 0, &taskID); - } - } - } - - return (err); -} - void DrawPauseScreen (CGContextRef ctx, HIRect bounds) { CGImageRef image; - CGRect crt; - int top, bottom, left, right, width, height; + CGRect rct; + float sh, mh, rofs, ry; - width = IPPU.RenderedScreenWidth; - height = IPPU.RenderedScreenHeight; - - if ((width == 0) || (height == 0)) + if ((IPPU.RenderedScreenWidth == 0) || (IPPU.RenderedScreenHeight == 0)) return; - top = left = 0; + sh = (float) ((IPPU.RenderedScreenHeight > 256) ? IPPU.RenderedScreenHeight : IPPU.RenderedScreenHeight * 2); + mh = (float) (SNES_HEIGHT_EXTENDED * 2); - if (width > 256) + if (drawoverscan) { - right = width; - - if (height > 256) - { - bottom = height; - - if (!drawoverscan) - { - if (height < (SNES_HEIGHT_EXTENDED << 1)) - { - top = kMarginDouble; - bottom += kMarginDouble; - } - else - { - top = kMarginDoubleExt; - bottom += kMarginDoubleExt; - } - } - } - else - { - bottom = height << 1; - - if (!drawoverscan) - { - if (height < SNES_HEIGHT_EXTENDED) - { - top = kMarginDouble; - bottom += kMarginDouble; - } - else - { - top = kMarginDoubleExt; - bottom += kMarginDoubleExt; - } - } - } + rofs = (mh - sh) / mh; + ry = sh / mh; + } + else + if (windowExtend) + { + rofs = (mh - sh) / mh / 2.0f; + ry = sh / mh; } else { - right = width << 1; - bottom = height << 1; - - if (!drawoverscan) - { - if (height < SNES_HEIGHT_EXTENDED) - { - top = kMarginDouble; - bottom += kMarginDouble; - } - else - { - top = kMarginDoubleExt; - bottom += kMarginDoubleExt; - } - } + rofs = 0.0f; + ry = 1.0f; } image = CreateGameScreenCGImage(); if (image) { - float rx, ry; - int ofs; - - rx = bounds.size.width / 512.0f; - - if (!drawoverscan) - { - if (windowExtend) - { - ofs = top; - ry = bounds.size.height / (float) kMacWindowHeight; - } - else - { - ofs = 0; - ry = bounds.size.height / (float) ((height <= 256) ? (height << 1) : height); - } - } - else - { - ofs = kMacWindowHeight - ((height <= 256) ? (height << 1) : height); - ry = bounds.size.height / (float) kMacWindowHeight; - } - CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); CGContextFillRect(ctx, bounds); - crt = CGRectMake(0, 0, right - left, bottom - top); - crt.size.width *= rx; - crt.size.height *= ry; - crt.origin.x = (float) (int) (rx * (float) left); - crt.origin.y = (float) (int) (ry * (float) ofs); - CGContextDrawImage(ctx, crt, image); + rct = CGRectMake(0.0f, bounds.size.height * rofs, bounds.size.width, bounds.size.height * ry); + CGContextDrawImage(ctx, rct, image); CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 0.5f); CGContextFillRect(ctx, bounds); @@ -672,25 +499,16 @@ void DrawFreezeDefrostScreen (uint8 *draw) else memcpy(blitGLBuffer, draw, w * h * 2); - if (!ciFilterEnable) - S9xPutImageBlitGL2(512, kMacWindowHeight); - else - S9xPutImageBlitGL2CoreImage(512, kMacWindowHeight); + S9xPutImageBlitGL2(512, kMacWindowHeight); } void ClearGFXScreen (void) { - uint16 *p, *q; - - p = gfxScreen[0]; - q = gfxScreen[1]; - - for (int x = 0; x < 512; x++) - for (int y = 0; y < 512; y++) - *p++ = *q++ = 0; + memset(gfxScreen[0], 0, 512 * 512 * 2); + memset(gfxScreen[1], 0, 512 * 512 * 2); + memset(blitGLBuffer, 0, 1024 * 1024 * 2); S9xBlitClearDelta(); - memset(blitGLBuffer, 0, 1024 * 1024 * BYTES_PER_PIXEL); imageWidth[0] = imageHeight[0] = 0; imageWidth[1] = imageHeight[1] = 0; @@ -721,31 +539,9 @@ void ClearGFXScreen (void) } } -static void S9xInitFullScreen (void) +#ifndef MAC_LEOPARD_TIGER_PANTHER_SUPPORT +static void SetBestDisplayMode (int width, int height) { - DeinitGameWindow(); - - size_t width, height; - - width = autoRes ? 640 : CGDisplayPixelsWide(gGameDisplayID); - height = autoRes ? 480 : CGDisplayPixelsHigh(gGameDisplayID); - -#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT - CFDictionaryRef mode; - boolean_t exactMatch; - size_t depth = gl32bit ? 32 : 16; - - oldDisplayMode = CGDisplayCurrentMode(gGameDisplayID); - - mode = CGDisplayBestModeForParameters(gGameDisplayID, depth, width, height, &exactMatch); - - CGDisplayCapture(gGameDisplayID); - CGDisplaySwitchToMode(gGameDisplayID, mode); -#else - oldDisplayModeRef = CGDisplayCopyDisplayMode(gGameDisplayID); - - CGDisplayCapture(gGameDisplayID); - if (autoRes || !gl32bit) { CGError err; @@ -771,7 +567,7 @@ static void S9xInitFullScreen (void) r = CFStringCompare(pix, pixenc, 0) == kCFCompareEqualTo; CFRelease(pix); - if (w == width && h == height && r) + if (w == (size_t) width && h == (size_t) height && r) break; } @@ -780,6 +576,31 @@ static void S9xInitFullScreen (void) CFRelease(array); } +} +#endif + +static void S9xInitFullScreen (void) +{ + DeinitGameWindow(); + + size_t width, height; + + width = autoRes ? 640 : CGDisplayPixelsWide(gGameDisplayID); + height = autoRes ? 480 : CGDisplayPixelsHigh(gGameDisplayID); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CFDictionaryRef mode; + boolean_t exactMatch; + size_t depth = gl32bit ? 32 : 16; + + oldDisplayMode = CGDisplayCurrentMode(gGameDisplayID); + mode = CGDisplayBestModeForParameters(gGameDisplayID, depth, width, height, &exactMatch); + CGDisplayCapture(gGameDisplayID); + CGDisplaySwitchToMode(gGameDisplayID, mode); +#else + oldDisplayModeRef = CGDisplayCopyDisplayMode(gGameDisplayID); + CGDisplayCapture(gGameDisplayID); + SetBestDisplayMode(width, height); #endif CGDisplayErr cgErr; @@ -831,47 +652,12 @@ static void S9xInitWindowMode (void) size_t depth = gl32bit ? 32 : 16; oldDisplayMode = CGDisplayCurrentMode(gGameDisplayID); - mode = CGDisplayBestModeForParameters(gGameDisplayID, depth, width, height, &exactMatch); if (exactMatch) CGDisplaySwitchToMode(gGameDisplayID, mode); #else oldDisplayModeRef = CGDisplayCopyDisplayMode(gGameDisplayID); - - if (autoRes || !gl32bit) - { - CGError err; - CGDisplayModeRef mode; - CFArrayRef array; - CFStringRef pixenc, pix; - CFIndex n, i; - size_t w, h; - bool r; - - pixenc = gl32bit ? CFSTR(IO32BitDirectPixels) : CFSTR(IO16BitDirectPixels); - - array = CGDisplayCopyAllDisplayModes(gGameDisplayID, NULL); - n = CFArrayGetCount(array); - - for (i = 0; i < n; i++) - { - mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(array, i); - - w = CGDisplayModeGetWidth(mode); - h = CGDisplayModeGetHeight(mode); - pix = CGDisplayModeCopyPixelEncoding(mode); - r = CFStringCompare(pix, pixenc, 0) == kCFCompareEqualTo; - CFRelease(pix); - - if (w == width && h == height && r) - break; - } - - if (i < n) - err = CGDisplaySetDisplayMode(gGameDisplayID, mode, NULL); - - CFRelease(array); - } + SetBestDisplayMode(width, height); #endif InitGameWindow(); @@ -1015,6 +801,93 @@ static void S9xDeinitBlitGL (void) } } +static void GLPrepareTexture (bool8 useRange, int texNo, int rangeOnW, int rangeOnH, int rangeOffW, int rangeOffH, int filter) +{ + bool8 rangeAvailable = OpenGL.rangeExt & useRange; + + OpenGL.texW[texNo] = rangeAvailable ? rangeOnW : rangeOffW; + OpenGL.texH[texNo] = rangeAvailable ? rangeOnH : rangeOffH; + + OpenGL.vertex[texNo][0] = 0; + OpenGL.vertex[texNo][1] = 0; + OpenGL.vertex[texNo][2] = rangeAvailable ? rangeOnW : 1; + OpenGL.vertex[texNo][3] = 0; + OpenGL.vertex[texNo][4] = rangeAvailable ? rangeOnW : 1; + OpenGL.vertex[texNo][5] = rangeAvailable ? rangeOnH : 1; + OpenGL.vertex[texNo][6] = 0; + OpenGL.vertex[texNo][7] = rangeAvailable ? rangeOnH : 1; + + glBindTexture(OpenGL.target, OpenGL.textures[texNo]); + + if (rangeAvailable) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[texNo] * OpenGL.texH[texNo] * 2, GFX.Screen); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, OpenGL.storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, OpenGL.agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, filter); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[texNo], OpenGL.texH[texNo], 0, OpenGL.format, OpenGL.type, GFX.Screen); +} + +static void GLMakeScreenMesh (GLfloat *vertex3D, int meshx, int meshy) +{ + GLfloat *v; + float warp; + + v = vertex3D; + warp = macCurvatureWarp * 0.001f; + + for (int y = 0; y < meshy; y++) + { + for (int x = 0; x <= meshx; x++) + { + float u1, v1, v2; + + u1 = -1.0f + 2.0f / (float) meshx * (float) x; + v1 = -1.0f + 2.0f / (float) meshy * (float) y; + v2 = -1.0f + 2.0f / (float) meshy * (float) (y + 1); + + *v++ = u1; + *v++ = v2; + *v++ = -1.0f - (u1 * u1 + v2 * v2) * warp; + + *v++ = u1; + *v++ = v1; + *v++ = -1.0f - (u1 * u1 + v1 * v1) * warp; + } + } +} + +static void GLMakeTextureMesh (GLfloat *vertex2D, int meshx, int meshy, float lx, float ly) +{ + GLfloat *v; + + v = vertex2D; + + for (int y = meshy; y > 0; y--) + { + for (int x = 0; x <= meshx; x++) + { + float u1, v1, v2; + + u1 = lx / (float) meshx * (float) x; + v1 = ly / (float) meshy * (float) y; + v2 = ly / (float) meshy * (float) (y - 1); + + *v++ = u1; + *v++ = v2; + + *v++ = u1; + *v++ = v1; + } + } +} + static void S9xInitOpenGLContext (void) { OpenGL.internal_format = GL_RGB5_A1; @@ -1023,19 +896,13 @@ static void S9xInitOpenGLContext (void) OpenGL.rangeExt = gluCheckExtension((const GLubyte *) "GL_APPLE_texture_range", glGetString(GL_EXTENSIONS)); OpenGL.target = OpenGL.rangeExt ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D; - GLint storage_hint = GL_STORAGE_SHARED_APPLE; - GLint storage_apple = 1; - GLfloat agp_texturing = 0.0f; - - storage_apple = extraOptions.glUseClientStrageApple ? 1 : 0; - - agp_texturing = extraOptions.glUseTexturePriority ? 0.0f : 1.0f; - + OpenGL.storage_apple = extraOptions.glUseClientStrageApple ? 1 : 0; + OpenGL.agp_texturing = extraOptions.glUseTexturePriority ? 0.0f : 1.0f; switch (extraOptions.glStorageHint) { - case 1: storage_hint = GL_STORAGE_PRIVATE_APPLE; break; - case 2: storage_hint = GL_STORAGE_CACHED_APPLE; break; - case 3: storage_hint = GL_STORAGE_SHARED_APPLE; break; + case 1: OpenGL.storage_hint = GL_STORAGE_PRIVATE_APPLE; break; + case 2: OpenGL.storage_hint = GL_STORAGE_CACHED_APPLE; break; + case 3: OpenGL.storage_hint = GL_STORAGE_SHARED_APPLE; break; } if (screencurvature || videoMode >= VIDEOMODE_NTSC_C || extraOptions.glForceNoTextureRectangle) @@ -1061,264 +928,19 @@ static void S9xInitOpenGLContext (void) glGenTextures(kGLNumTextures, OpenGL.textures); - glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, storage_apple); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, OpenGL.storage_apple); glPixelStorei(GL_UNPACK_ALIGNMENT, 8); - // 256 * 224/239 - - OpenGL.texW[kGL256256] = 256; - OpenGL.texH[kGL256256] = OpenGL.rangeExt ? SNES_HEIGHT_EXTENDED : 256; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGL256256][0] = 0; OpenGL.vertex[kGL256256][1] = 0; - OpenGL.vertex[kGL256256][2] = OpenGL.texW[kGL256256]; OpenGL.vertex[kGL256256][3] = 0; - OpenGL.vertex[kGL256256][4] = OpenGL.texW[kGL256256]; OpenGL.vertex[kGL256256][5] = OpenGL.texH[kGL256256]; - OpenGL.vertex[kGL256256][6] = 0; OpenGL.vertex[kGL256256][7] = OpenGL.texH[kGL256256]; - } - else - { - OpenGL.vertex[kGL256256][0] = 0.0f; OpenGL.vertex[kGL256256][1] = 0.0f; - OpenGL.vertex[kGL256256][2] = 1.0f; OpenGL.vertex[kGL256256][3] = 0.0f; - OpenGL.vertex[kGL256256][4] = 1.0f; OpenGL.vertex[kGL256256][5] = 1.0f; - OpenGL.vertex[kGL256256][6] = 0.0f; OpenGL.vertex[kGL256256][7] = 1.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGL256256]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL256256] * OpenGL.texH[kGL256256] * BYTES_PER_PIXEL, GFX.Screen); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL256256], OpenGL.texH[kGL256256], 0, OpenGL.format, OpenGL.type, GFX.Screen); - - // 512 * 224/239 - - OpenGL.texW[kGL512256] = 512; - OpenGL.texH[kGL512256] = OpenGL.rangeExt ? SNES_HEIGHT_EXTENDED : 256; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGL512256][0] = 0; OpenGL.vertex[kGL512256][1] = 0; - OpenGL.vertex[kGL512256][2] = OpenGL.texW[kGL512256]; OpenGL.vertex[kGL512256][3] = 0; - OpenGL.vertex[kGL512256][4] = OpenGL.texW[kGL512256]; OpenGL.vertex[kGL512256][5] = OpenGL.texH[kGL512256]; - OpenGL.vertex[kGL512256][6] = 0; OpenGL.vertex[kGL512256][7] = OpenGL.texH[kGL512256]; - } - else - { - OpenGL.vertex[kGL512256][0] = 0.0f; OpenGL.vertex[kGL512256][1] = 0.0f; - OpenGL.vertex[kGL512256][2] = 1.0f; OpenGL.vertex[kGL512256][3] = 0.0f; - OpenGL.vertex[kGL512256][4] = 1.0f; OpenGL.vertex[kGL512256][5] = 1.0f; - OpenGL.vertex[kGL512256][6] = 0.0f; OpenGL.vertex[kGL512256][7] = 1.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGL512256]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL512256] * OpenGL.texH[kGL512256] * BYTES_PER_PIXEL, GFX.Screen); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL512256], OpenGL.texH[kGL512256], 0, OpenGL.format, OpenGL.type, GFX.Screen); - - // 512 * 448/478 - - OpenGL.texW[kGL512512] = 512; - OpenGL.texH[kGL512512] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED << 1) : 512; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGL512512][0] = 0; OpenGL.vertex[kGL512512][1] = 0; - OpenGL.vertex[kGL512512][2] = OpenGL.texW[kGL512512]; OpenGL.vertex[kGL512512][3] = 0; - OpenGL.vertex[kGL512512][4] = OpenGL.texW[kGL512512]; OpenGL.vertex[kGL512512][5] = OpenGL.texH[kGL512512]; - OpenGL.vertex[kGL512512][6] = 0; OpenGL.vertex[kGL512512][7] = OpenGL.texH[kGL512512]; - } - else - { - OpenGL.vertex[kGL512512][0] = 0.0f; OpenGL.vertex[kGL512512][1] = 0.0f; - OpenGL.vertex[kGL512512][2] = 1.0f; OpenGL.vertex[kGL512512][3] = 0.0f; - OpenGL.vertex[kGL512512][4] = 1.0f; OpenGL.vertex[kGL512512][5] = 1.0f; - OpenGL.vertex[kGL512512][6] = 0.0f; OpenGL.vertex[kGL512512][7] = 1.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGL512512]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL512512] * OpenGL.texH[kGL512512] * BYTES_PER_PIXEL, GFX.Screen); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL512512], OpenGL.texH[kGL512512], 0, OpenGL.format, OpenGL.type, GFX.Screen); - - // Blit 2x - - OpenGL.texW[kGLBlit2x] = 512; - OpenGL.texH[kGLBlit2x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 2) : 512; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGLBlit2x][0] = 0; OpenGL.vertex[kGLBlit2x][1] = 0; - OpenGL.vertex[kGLBlit2x][2] = OpenGL.texW[kGLBlit2x]; OpenGL.vertex[kGLBlit2x][3] = 0; - OpenGL.vertex[kGLBlit2x][4] = OpenGL.texW[kGLBlit2x]; OpenGL.vertex[kGLBlit2x][5] = OpenGL.texH[kGLBlit2x]; - OpenGL.vertex[kGLBlit2x][6] = 0; OpenGL.vertex[kGLBlit2x][7] = OpenGL.texH[kGLBlit2x]; - } - else - { - OpenGL.vertex[kGLBlit2x][0] = 0.0f; OpenGL.vertex[kGLBlit2x][1] = 0.0f; - OpenGL.vertex[kGLBlit2x][2] = 1.0f; OpenGL.vertex[kGLBlit2x][3] = 0.0f; - OpenGL.vertex[kGLBlit2x][4] = 1.0f; OpenGL.vertex[kGLBlit2x][5] = 1.0f; - OpenGL.vertex[kGLBlit2x][6] = 0.0f; OpenGL.vertex[kGLBlit2x][7] = 1.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit2x]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit2x] * OpenGL.texH[kGLBlit2x] * BYTES_PER_PIXEL, blitGLBuffer); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit2x], OpenGL.texH[kGLBlit2x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); - - // Blit 3x - - OpenGL.texW[kGLBlit3x] = OpenGL.rangeExt ? (SNES_WIDTH * 3) : 1024; - OpenGL.texH[kGLBlit3x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 3) : 1024; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGLBlit3x][0] = 0; OpenGL.vertex[kGLBlit3x][1] = 0; - OpenGL.vertex[kGLBlit3x][2] = OpenGL.texW[kGLBlit3x]; OpenGL.vertex[kGLBlit3x][3] = 0; - OpenGL.vertex[kGLBlit3x][4] = OpenGL.texW[kGLBlit3x]; OpenGL.vertex[kGLBlit3x][5] = OpenGL.texH[kGLBlit3x]; - OpenGL.vertex[kGLBlit3x][6] = 0; OpenGL.vertex[kGLBlit3x][7] = OpenGL.texH[kGLBlit3x]; - } - else - { - OpenGL.vertex[kGLBlit3x][0] = 0.0f; OpenGL.vertex[kGLBlit3x][1] = 0.0f; - OpenGL.vertex[kGLBlit3x][2] = SNES_WIDTH * 3 / 1024.0f; OpenGL.vertex[kGLBlit3x][3] = 0.0f; - OpenGL.vertex[kGLBlit3x][4] = SNES_WIDTH * 3 / 1024.0f; OpenGL.vertex[kGLBlit3x][5] = SNES_HEIGHT_EXTENDED * 3 / 1024.0f; - OpenGL.vertex[kGLBlit3x][6] = 0.0f; OpenGL.vertex[kGLBlit3x][7] = SNES_HEIGHT_EXTENDED * 3 / 1024.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit3x]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit3x] * OpenGL.texH[kGLBlit3x] * BYTES_PER_PIXEL, blitGLBuffer); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit3x], OpenGL.texH[kGLBlit3x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); - - // Blit 4x - - OpenGL.texW[kGLBlit4x] = 1024; - OpenGL.texH[kGLBlit4x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 4) : 1024; - - if (OpenGL.rangeExt) - { - OpenGL.vertex[kGLBlit4x][0] = 0; OpenGL.vertex[kGLBlit4x][1] = 0; - OpenGL.vertex[kGLBlit4x][2] = OpenGL.texW[kGLBlit4x]; OpenGL.vertex[kGLBlit4x][3] = 0; - OpenGL.vertex[kGLBlit4x][4] = OpenGL.texW[kGLBlit4x]; OpenGL.vertex[kGLBlit4x][5] = OpenGL.texH[kGLBlit4x]; - OpenGL.vertex[kGLBlit4x][6] = 0; OpenGL.vertex[kGLBlit4x][7] = OpenGL.texH[kGLBlit4x]; - } - else - { - OpenGL.vertex[kGLBlit4x][0] = 0.0f; OpenGL.vertex[kGLBlit4x][1] = 0.0f; - OpenGL.vertex[kGLBlit4x][2] = 1.0f; OpenGL.vertex[kGLBlit4x][3] = 0.0f; - OpenGL.vertex[kGLBlit4x][4] = 1.0f; OpenGL.vertex[kGLBlit4x][5] = 1.0f; - OpenGL.vertex[kGLBlit4x][6] = 0.0f; OpenGL.vertex[kGLBlit4x][7] = 1.0f; - } - - glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit4x]); - - if (OpenGL.rangeExt) - { - glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit4x] * OpenGL.texH[kGLBlit4x] * BYTES_PER_PIXEL, blitGLBuffer); - glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); - } - - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit4x], OpenGL.texH[kGLBlit4x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); - - // Blit NTSC 602 * 224/239 - - OpenGL.texW[kGLNTS256] = 1024; - OpenGL.texH[kGLNTS256] = 256; - - OpenGL.vertex[kGLNTS256][0] = 0.0f; OpenGL.vertex[kGLNTS256][1] = 0.0f; - OpenGL.vertex[kGLNTS256][2] = 1.0f; OpenGL.vertex[kGLNTS256][3] = 0.0f; - OpenGL.vertex[kGLNTS256][4] = 1.0f; OpenGL.vertex[kGLNTS256][5] = 1.0f; - OpenGL.vertex[kGLNTS256][6] = 0.0f; OpenGL.vertex[kGLNTS256][7] = 1.0f; - - glBindTexture(OpenGL.target, OpenGL.textures[kGLNTS256]); - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLNTS256], OpenGL.texH[kGLNTS256], 0, OpenGL.format, OpenGL.type, blitGLBuffer); - - // Blit NTSC 602 * 448/478 - - OpenGL.texW[kGLNTS512] = 1024; - OpenGL.texH[kGLNTS512] = 512; - - OpenGL.vertex[kGLNTS512][0] = 0.0f; OpenGL.vertex[kGLNTS512][1] = 0.0f; - OpenGL.vertex[kGLNTS512][2] = 1.0f; OpenGL.vertex[kGLNTS512][3] = 0.0f; - OpenGL.vertex[kGLNTS512][4] = 1.0f; OpenGL.vertex[kGLNTS512][5] = 1.0f; - OpenGL.vertex[kGLNTS512][6] = 0.0f; OpenGL.vertex[kGLNTS512][7] = 1.0f; - - glBindTexture(OpenGL.target, OpenGL.textures[kGLNTS512]); - glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLNTS512], OpenGL.texH[kGLNTS512], 0, OpenGL.format, OpenGL.type, blitGLBuffer); - - // + int filter = (videoMode == VIDEOMODE_SMOOTH) ? GL_LINEAR : GL_NEAREST; + GLPrepareTexture(true, kGL256256, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 256, 256, filter); + GLPrepareTexture(true, kGL256512, SNES_WIDTH, SNES_HEIGHT_EXTENDED * 2, 256, 512, filter); + GLPrepareTexture(true, kGL512256, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED, 512, 256, filter); + GLPrepareTexture(true, kGL512512, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 512, 512, filter); + GLPrepareTexture(true, kGLBlit2x, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 512, 512, GL_LINEAR); + GLPrepareTexture(true, kGLBlit3x, SNES_WIDTH * 3, SNES_HEIGHT_EXTENDED * 3, 1024, 1024, GL_LINEAR); + GLPrepareTexture(true, kGLBlit4x, SNES_WIDTH * 4, SNES_HEIGHT_EXTENDED * 4, 1024, 1024, GL_LINEAR); + GLPrepareTexture(false, kGLNTS256, 1024, 256, 1024, 256, GL_LINEAR); + GLPrepareTexture(false, kGLNTS512, 1024, 512, 1024, 512, GL_LINEAR); if (!screencurvature) { @@ -1343,35 +965,32 @@ static void S9xInitOpenGLContext (void) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - scTexArray[kSC2xNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC2xNormal], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 256.0f); + int mesh = (kSCMeshX + 1) * 2 * kSCMeshY * 2; + scTexArray[kSC2xNormal] = new GLfloat [mesh]; + scTexArray[kSC2xExtend] = new GLfloat [mesh]; + scTexArray[kSC2xNHiRes] = new GLfloat [mesh]; + scTexArray[kSC2xEHiRes] = new GLfloat [mesh]; + scTexArray[kSC2xNInter] = new GLfloat [mesh]; + scTexArray[kSC2xEInter] = new GLfloat [mesh]; + scTexArray[kSC3xNormal] = new GLfloat [mesh]; + scTexArray[kSC3xExtend] = new GLfloat [mesh]; + scTexArray[kSC3xNHiRes] = new GLfloat [mesh]; + scTexArray[kSC3xEHiRes] = new GLfloat [mesh]; + scTexArray[kSCNTNormal] = new GLfloat [mesh]; + scTexArray[kSCNTExtend] = new GLfloat [mesh]; - scTexArray[kSC2xExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC2xExtend], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 256.0f); - - scTexArray[kSC2xNHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC2xNHiRes], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 512.0f); - - scTexArray[kSC2xEHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC2xEHiRes], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 512.0f); - - scTexArray[kSC3xNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC3xNormal], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 1024.0f); - - scTexArray[kSC3xExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC3xExtend], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 1024.0f); - - scTexArray[kSC3xNHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC3xNHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 2048.0f); - - scTexArray[kSC3xEHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSC3xEHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 2048.0f); - - scTexArray[kSCNTNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSCNTNormal], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 224.0f / 256.0f); - - scTexArray[kSCNTExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; - GLMakeTextureMesh(scTexArray[kSCNTExtend], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 239.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSC2xNormal], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSC2xExtend], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSC2xNHiRes], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 512.0f); + GLMakeTextureMesh(scTexArray[kSC2xEHiRes], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 512.0f); + GLMakeTextureMesh(scTexArray[kSC2xNInter], kSCMeshX, kSCMeshY, 256.0f / 512.0f, 224.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSC2xEInter], kSCMeshX, kSCMeshY, 256.0f / 512.0f, 239.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSC3xNormal], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 1024.0f); + GLMakeTextureMesh(scTexArray[kSC3xExtend], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 1024.0f); + GLMakeTextureMesh(scTexArray[kSC3xNHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 2048.0f); + GLMakeTextureMesh(scTexArray[kSC3xEHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 2048.0f); + GLMakeTextureMesh(scTexArray[kSCNTNormal], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 224.0f / 256.0f); + GLMakeTextureMesh(scTexArray[kSCNTExtend], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 239.0f / 256.0f); scScnArray = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 3]; GLMakeScreenMesh(scScnArray, kSCMeshX, kSCMeshY); @@ -1410,6 +1029,8 @@ static void S9xDeinitOpenGLContext (void) delete [] scTexArray[kSC2xExtend]; delete [] scTexArray[kSC2xNHiRes]; delete [] scTexArray[kSC2xEHiRes]; + delete [] scTexArray[kSC2xNInter]; + delete [] scTexArray[kSC2xEInter]; delete [] scTexArray[kSC3xNormal]; delete [] scTexArray[kSC3xExtend]; delete [] scTexArray[kSC3xNHiRes]; @@ -1422,6 +1043,8 @@ static void S9xDeinitOpenGLContext (void) scTexArray[kSC2xExtend] = NULL; scTexArray[kSC2xNHiRes] = NULL; scTexArray[kSC2xEHiRes] = NULL; + scTexArray[kSC2xNInter] = NULL; + scTexArray[kSC2xEInter] = NULL; scTexArray[kSC3xNormal] = NULL; scTexArray[kSC3xExtend] = NULL; scTexArray[kSC3xNHiRes] = NULL; @@ -1606,6 +1229,106 @@ bool8 S9xContinueUpdate (int width, int height) return (true); } +static inline void RenderBlitScreen (Blitter Fn, int x, int sW, int sH, int cW, int cH, uint16 *buf) +{ + switch (x) + { + case -1: + (Fn) ((uint8 *) buf, sW * 2, blitGLBuffer, 1024 * 2, sW, sH); + break; + + case -2: + if (sH > SNES_HEIGHT_EXTENDED) + (Fn) ((uint8 *) buf, sW * 2, blitGLBuffer, 1024 * 2, sW, sH); + else + { + uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * 2); + int aligned = ((ntsc_width + 2) >> 1) << 1; + (Fn) ((uint8 *) buf, sW * 2, tmpBuffer, 1024 * 2, sW, sH); + S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, cH); + cH *= 2; + } + + break; + + default: + int dstbytes = (OpenGL.rangeExt ? cW : ((cW > 512) ? 1024 : ((cW > 256) ? 512 : 256))) * 2; + (Fn) ((uint8 *) buf, sW * 2, blitGLBuffer, dstbytes, sW, sH); + break; + } + + S9xPutImageBlitGL2(cW, cH); +} + +static OSStatus PrepareMPBlitGL (void) +{ + OSStatus err; + + mpBlit = (MPData *) MPAllocateAligned(sizeof(MPData), kMPAllocateDefaultAligned, kMPAllocateClearMask); + if (!mpBlit) + return (memFullErr); + + err = MPCreateQueue(¬ificationQueue); + if (err == noErr) + { + err = MPCreateQueue(&taskQueue); + if (err == noErr) + { + err = MPCreateBinarySemaphore(&readySemaphore); + if (err == noErr) + { + MPSignalSemaphore(readySemaphore); + err = MPCreateTask(BlitMPGLTask, NULL, 0, notificationQueue, NULL, NULL, 0, &taskID); + } + } + } + + return (err); +} + +static OSStatus BlitMPGLTask (void *parameter) +{ + OSStatus err = noErr; + int32 theCommand, param1, param2; + + printf("MP: Entered BlitGL thread.\n"); + + for (;;) + { + err = MPWaitOnQueue(taskQueue, (void **) &theCommand, (void **) ¶m1, (void **) ¶m2, kDurationForever); + if (err) + break; + + if (theCommand == kMPBlitFrame) + { + RenderBlitScreen(mpBlit->blitFn, mpBlit->nx, mpBlit->srcWidth, mpBlit->srcHeight, mpBlit->copyWidth, mpBlit->copyHeight, mpBlit->gfxBuffer); + MPSignalSemaphore(readySemaphore); + } + else + if (theCommand == kMPBlitNone) + MPSignalSemaphore(readySemaphore); + else + if (theCommand == kMPBlitDone) + break; + else + { + err = userCanceledErr; + break; + } + } + + MPFree(mpBlit); + MPDeleteSemaphore(readySemaphore); + MPDeleteQueue(taskQueue); + mpBlit = NULL; + readySemaphore = NULL; + taskQueue = NULL; + + printf("MP: Exited BlitGL thread.\n"); + + return (err); +} + void S9xPutImage (int width, int height) { static float fps = 0.0f; @@ -1672,44 +1395,38 @@ void S9xPutImage (int width, int height) } } - if (!drawoverscan) + switch (drawingMethod) { - switch (drawingMethod) - { - case kDrawingOpenGL: - if (!ciFilterEnable) - S9xPutImageOpenGL(width, height); - else - S9xPutImageCoreImage(width, height); - break; + case kDrawingOpenGL: + S9xPutImageOpenGL(width, height); + break; - case kDrawingBlitGL: - S9xPutImageBlitGL(width, height); - } - } - else - { - switch (drawingMethod) - { - case kDrawingOpenGL: - if (!ciFilterEnable) - S9xPutImageOverscanOpenGL(width, height); - else - S9xPutImageOverscanCoreImage(width, height); - break; - - case kDrawingBlitGL: - S9xPutImageOverscanBlitGL(width, height); - } + case kDrawingBlitGL: + S9xPutImageBlitGL(width, height); + break; } } static void S9xPutImageOpenGL (int width, int height) { - if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) + int orig_height = height; + + if ((imageWidth[0] != width) || (imageHeight[0] != height)) + windowResizeCount += 2; + + if (windowResizeCount > 0) { - if ((imageWidth[0] != width) || (imageHeight[0] != height)) - windowResizeCount += 2; + if (drawoverscan && (height % SNES_HEIGHT == 0)) + { + int pitch = width << 1; + int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); + + for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) + extarea[i] = 0; + + height = extbtm; + } int vh = (height > 256) ? height : (height << 1); @@ -1747,60 +1464,82 @@ static void S9xPutImageOpenGL (int width, int height) glViewport(0, ((kMacWindowHeight - vh) >> 1) * wh / kMacWindowHeight, ww, vh * wh / kMacWindowHeight); } - windowResizeCount--; - - textureNum = (width <= 256) ? kGL256256 : ((height <= 256) ? kGL512256 : kGL512512); - OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = OpenGL.rangeExt ? height : (vh / 512.0f); - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); + + if (!ciFilterEnable) + { + textureNum = (width <= 256) ? ((height <= 256) ? kGL256256 : kGL256512) : ((height <= 256) ? kGL512256 : kGL512512); + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = OpenGL.rangeExt ? height : (vh / 512.0f); + glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); + } + else + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, orig_height - height, orig_height, -1, 1); + + if (cgGameImage) + CGImageRelease(cgGameImage); + cgGameImage = CreateGameScreenCGImage(); + } imageWidth[0] = width; imageHeight[0] = height; - } - glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, GFX.Screen); - - if (!screencurvature) - { - glBegin(GL_QUADS); - - glTexCoord2fv(&OpenGL.vertex[textureNum][6]); - glVertex2f(-1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][4]); - glVertex2f( 1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][2]); - glVertex2f( 1.0f, 1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][0]); - glVertex2f(-1.0f, 1.0f); - - glEnd(); + windowResizeCount--; } else { - GLfloat *t, *s; - int tex; - - if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) - tex = kSC2xNormal; - else - tex = kSC2xExtend; - - t = scTexArray[tex]; - s = scScnArray; - - for (int i = 0; i < kSCMeshY; i++) - { - glTexCoordPointer(2, GL_FLOAT, 0, t); - glVertexPointer(3, GL_FLOAT, 0, s); - glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); - - t += (kSCMeshX + 1) * 2 * 2; - s += (kSCMeshX + 1) * 2 * 3; - } + if (drawoverscan) + height = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; } - glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + if (!ciFilterEnable) + { + glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, GFX.Screen); + + if (!screencurvature) + { + glBegin(GL_QUADS); + + glTexCoord2fv(&OpenGL.vertex[textureNum][6]); + glVertex2f(-1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][4]); + glVertex2f( 1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][2]); + glVertex2f( 1.0f, 1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][0]); + glVertex2f(-1.0f, 1.0f); + + glEnd(); + } + else + { + GLfloat *t, *s; + + t = scTexArray[(height % SNES_HEIGHT) ? kSC2xExtend : kSC2xNormal]; + s = scScnArray; + + for (int i = 0; i < kSCMeshY; i++) + { + glTexCoordPointer(2, GL_FLOAT, 0, t); + glVertexPointer(3, GL_FLOAT, 0, s); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); + + t += (kSCMeshX + 1) * 2 * 2; + s += (kSCMeshX + 1) * 2 * 3; + } + } + + glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + } + else + { + CGRect src; + + src = CGRectMake(0, 0, width, orig_height); + DrawWithCoreImageFilter(src, cgGameImage); + } if (fullscreen) CGLFlushDrawable(glContext); @@ -1813,36 +1552,68 @@ static void S9xPutImageBlitGL (int width, int height) Blitter blitFn; int copyWidth, copyHeight; - if (videoMode == VIDEOMODE_TV) - if ((width <= 256) && ((imageWidth[whichBuf] != width) || (imageHeight[whichBuf] != height))) + if ((imageWidth[whichBuf] != width) || (imageHeight[whichBuf] != height)) + { + if ((videoMode == VIDEOMODE_TV) && (width <= 256)) S9xBlitClearDelta(); + if (drawoverscan && (height % SNES_HEIGHT == 0)) + { + memset(blitGLBuffer, 0, 1024 * 1024 * 2); + + int pitch = width << 1; + int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); + + for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) + extarea[i] = 0; + + height = extbtm; + } + } + else + { + if (drawoverscan) + height = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + } + switch (nx) { default: case 2: - if (width <= 256) + if (height <= 256) { - copyWidth = width * 2; - copyHeight = height * 2; - - switch (videoMode) + if (width <= 256) { - default: - case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; - case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; - case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; - case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; - case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; - case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + copyWidth = width * 2; + copyHeight = height * 2; + + switch (videoMode) + { + default: + case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; + case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; + case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; + case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; + case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; + case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + } + } + else + { + if (videoMode == VIDEOMODE_TV) + { + copyWidth = width; + copyHeight = height * 2; + blitFn = S9xBlitPixHiResTV16; + } + else + { + copyWidth = width; + copyHeight = height; + blitFn = S9xBlitPixSmall16; + } } - } - else - if ((videoMode == VIDEOMODE_TV) && (height <= 256)) - { - copyWidth = width; - copyHeight = height * 2; - blitFn = S9xBlitPixHiResTV16; } else { @@ -1854,7 +1625,7 @@ static void S9xPutImageBlitGL (int width, int height) break; case 3: - if (width <= 256) + if (width <= 256 && height <= 256) { copyWidth = width * 3; copyHeight = height * 3; @@ -1870,18 +1641,25 @@ static void S9xPutImageBlitGL (int width, int height) break; case 4: - if (width <= 256) + if (width <= 256 && height <= 256) { copyWidth = width * 4; copyHeight = height * 4; blitFn = S9xBlitPixHQ4x16; } else + if (width > 256 && height > 256) { copyWidth = width * 2; copyHeight = height * 2; blitFn = S9xBlitPixHQ2x16; } + else + { + copyWidth = width; + copyHeight = height; + blitFn = S9xBlitPixSmall16; + } break; @@ -1905,14 +1683,13 @@ static void S9xPutImageBlitGL (int width, int height) { MPWaitOnSemaphore(readySemaphore, kDurationForever); - mpDataBuffer->nx = nx; - mpDataBuffer->blitFn = blitFn; - mpDataBuffer->srcWidth = width; - mpDataBuffer->srcHeight = height; - mpDataBuffer->srcRowBytes = width * 2; - mpDataBuffer->copyWidth = copyWidth; - mpDataBuffer->copyHeight = copyHeight; - mpDataBuffer->gfxBuffer = GFX.Screen; + mpBlit->nx = nx; + mpBlit->blitFn = blitFn; + mpBlit->srcWidth = width; + mpBlit->srcHeight = height; + mpBlit->copyWidth = copyWidth; + mpBlit->copyHeight = copyHeight; + mpBlit->gfxBuffer = GFX.Screen; MPNotifyQueue(taskQueue, (void *) kMPBlitFrame, 0, 0); @@ -1920,462 +1697,16 @@ static void S9xPutImageBlitGL (int width, int height) GFX.Screen = gfxScreen[whichBuf]; } else - { - switch (nx) - { - case -1: - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); - break; - - case -2: - if (height > SNES_HEIGHT_EXTENDED) - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); - else - { - uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); - int aligned = ((ntsc_width + 2) >> 1) << 1; - blitFn((uint8 *) GFX.Screen, width * 2, tmpBuffer, 1024 * 2, width, height); - S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, copyHeight); - copyHeight *= 2; - } - - break; - - default: - int dstbytes = (OpenGL.rangeExt ? copyWidth : ((copyWidth > 512) ? 1024 : 512)) * 2; - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, dstbytes, width, height); - break; - } - - if (!ciFilterEnable) - S9xPutImageBlitGL2(copyWidth, copyHeight); - else - S9xPutImageBlitGL2CoreImage(copyWidth, copyHeight); - } -} - -static void S9xPutImageCoreImage (int width, int height) -{ - if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) - { - if ((imageWidth[0] != width) || (imageHeight[0] != height)) - windowResizeCount += 2; - - int vh = (height > 256) ? height : (height << 1); - - if (fullscreen) - { - CGLSetCurrentContext(glContext); - - glViewport(0, 0, glScreenW, glScreenH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (glstretch) - { - float fpw = (float) glScreenH / vh * 512.0f; - int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); - - glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); - } - else - glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); - } - else - { - int ww = (int) gWindowRect.size.width, - wh = (int) gWindowRect.size.height; - - aglSetCurrentContext(agContext); - aglUpdateContext(agContext); - - glViewport(0, 0, ww, wh); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (windowExtend) - glViewport(0, ((kMacWindowHeight - vh) >> 1) * wh / kMacWindowHeight, ww, vh * wh / kMacWindowHeight); - } - - windowResizeCount--; - - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, 0, height, -1, 1); - - if (cgGameImage) - CGImageRelease(cgGameImage); - cgGameImage = CreateGameScreenCGImage(); - - imageWidth[0] = width; - imageHeight[0] = height; - } - - CGRect src; - - src = CGRectMake(0, 0, width, height); - DrawWithCoreImageFilter(src, cgGameImage); - - if (fullscreen) - CGLFlushDrawable(glContext); - else - aglSwapBuffers(agContext); -} - -static void S9xPutImageOverscanOpenGL (int width, int height) -{ - if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) - { - if ((imageWidth[0] != width) || (imageHeight[0] != height)) - windowResizeCount += 2; - - if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) - { - int pitch = width << 1; - int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; - uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); - - for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) - extarea[i] = 0; - } - - const int vh = SNES_HEIGHT_EXTENDED << 1; - - if (fullscreen) - { - CGLSetCurrentContext(glContext); - - glViewport(0, 0, glScreenW, glScreenH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (glstretch) - { - float fpw = (float) glScreenH / vh * 512.0f; - int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); - - glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); - } - else - glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); - } - else - { - int ww = (int) gWindowRect.size.width, - wh = (int) gWindowRect.size.height; - - aglSetCurrentContext(agContext); - aglUpdateContext(agContext); - - glViewport(0, 0, ww, wh); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - } - - windowResizeCount--; - - textureNum = (width <= 256) ? kGL256256 : ((height <= 256) ? kGL512256 : kGL512512); - OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = OpenGL.rangeExt ? ((height > 256) ? vh : SNES_HEIGHT_EXTENDED) : (vh / 512.0f); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); - - imageWidth[0] = width; - imageHeight[0] = height; - } - - glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, GFX.Screen); - - if (!screencurvature) - { - glBegin(GL_QUADS); - - glTexCoord2fv(&OpenGL.vertex[textureNum][6]); - glVertex2f(-1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][4]); - glVertex2f( 1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][2]); - glVertex2f( 1.0f, 1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][0]); - glVertex2f(-1.0f, 1.0f); - - glEnd(); - } - else - { - GLfloat *t, *s; - - t = scTexArray[kSC2xExtend]; - s = scScnArray; - - for (int i = 0; i < kSCMeshY; i++) - { - glTexCoordPointer(2, GL_FLOAT, 0, t); - glVertexPointer(3, GL_FLOAT, 0, s); - glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); - - t += (kSCMeshX + 1) * 2 * 2; - s += (kSCMeshX + 1) * 2 * 3; - } - } - - glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); - - if (fullscreen) - CGLFlushDrawable(glContext); - else - aglSwapBuffers(agContext); -} - -static void S9xPutImageOverscanBlitGL (int width, int height) -{ - Blitter blitFn; - int copyWidth, copyHeight, extbtm; - - extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; - - if ((imageWidth[whichBuf] != width) || (imageHeight[whichBuf] != height)) - { - if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) - { - const unsigned int pitch = 1024; - unsigned int i; - uint32 *extarea; - - extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); - for (i = 0; i < (((extbtm - height) * pitch) >> 2); i++) - extarea[i] = 0; - - memset(blitGLBuffer, 0, 1024 * 1024 * BYTES_PER_PIXEL); - } - - if (videoMode == VIDEOMODE_TV) - if (width <= 256) - S9xBlitClearDelta(); - } - - switch (nx) - { - default: - case 2: - if (width <= 256) - { - copyWidth = width * 2; - copyHeight = SNES_HEIGHT_EXTENDED * 2; - - switch (videoMode) - { - default: - case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; - case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; - case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; - case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; - case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; - case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; - } - } - else - if ((videoMode == VIDEOMODE_TV) && (height <= 256)) - { - copyWidth = width; - copyHeight = SNES_HEIGHT_EXTENDED * 2; - blitFn = S9xBlitPixHiResTV16; - } - else - { - copyWidth = width; - copyHeight = extbtm; - blitFn = S9xBlitPixSmall16; - } - - break; - - case 3: - if (width <= 256) - { - copyWidth = width * 3; - copyHeight = SNES_HEIGHT_EXTENDED * 3; - blitFn = S9xBlitPixHQ3x16; - } - else - { - copyWidth = width; - copyHeight = extbtm; - blitFn = S9xBlitPixSmall16; - } - - break; - - case 4: - if (width <= 256) - { - copyWidth = width * 4; - copyHeight = SNES_HEIGHT_EXTENDED * 4; - blitFn = S9xBlitPixHQ4x16; - } - else - { - copyWidth = width * 2; - copyHeight = extbtm * 2; - blitFn = S9xBlitPixHQ2x16; - } - - break; - - case -1: - case -2: - copyWidth = ntsc_width; - copyHeight = extbtm; - - if (width <= 256) - blitFn = S9xBlitPixNTSC16; - else - blitFn = S9xBlitPixHiResNTSC16; - - break; - } - - imageWidth[whichBuf] = width; - imageHeight[whichBuf] = height; - - if (multiprocessor) - { - MPWaitOnSemaphore(readySemaphore, kDurationForever); - - mpDataBuffer->nx = nx; - mpDataBuffer->blitFn = blitFn; - mpDataBuffer->srcWidth = width; - mpDataBuffer->srcHeight = height; - mpDataBuffer->srcRowBytes = width * 2; - mpDataBuffer->copyWidth = copyWidth; - mpDataBuffer->copyHeight = copyHeight; - mpDataBuffer->gfxBuffer = GFX.Screen; - - MPNotifyQueue(taskQueue, (void *) kMPBlitFrame, 0, 0); - - whichBuf = 1 - whichBuf; - GFX.Screen = gfxScreen[whichBuf]; - } - else - { - switch (nx) - { - case -1: - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); - break; - - case -2: - if (height > SNES_HEIGHT_EXTENDED) - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); - else - { - uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); - int aligned = ((ntsc_width + 2) >> 1) << 1; - blitFn((uint8 *) GFX.Screen, width * 2, tmpBuffer, 1024 * 2, width, height); - S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, copyHeight); - copyHeight *= 2; - } - - break; - - default: - int dstbytes = (OpenGL.rangeExt ? copyWidth : ((copyWidth > 512) ? 1024 : 512)) * 2; - blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, dstbytes, width, height); - break; - } - - if (!ciFilterEnable) - S9xPutImageBlitGL2(copyWidth, copyHeight); - else - S9xPutImageBlitGL2CoreImage(copyWidth, copyHeight); - } -} - -static void S9xPutImageOverscanCoreImage (int width, int height) -{ - int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; - - if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) - { - if ((imageWidth[0] != width) || (imageHeight[0] != height)) - windowResizeCount += 2; - - if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) - { - int pitch = width << 1; - uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); - - for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) - extarea[i] = 0; - } - - const int vh = SNES_HEIGHT_EXTENDED << 1; - - if (fullscreen) - { - CGLSetCurrentContext(glContext); - - glViewport(0, 0, glScreenW, glScreenH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (glstretch) - { - float fpw = (float) glScreenH / vh * 512.0f; - int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); - - glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); - } - else - glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); - } - else - { - int ww = (int) gWindowRect.size.width, - wh = (int) gWindowRect.size.height; - - aglSetCurrentContext(agContext); - aglUpdateContext(agContext); - - glViewport(0, 0, ww, wh); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - } - - windowResizeCount--; - - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height - extbtm, height, -1, 1); - - if (cgGameImage) - CGImageRelease(cgGameImage); - cgGameImage = CreateGameScreenCGImage(); - - imageWidth[0] = width; - imageHeight[0] = height; - } - - CGRect src; - - src = CGRectMake(0, 0, width, height); - DrawWithCoreImageFilter(src, cgGameImage); - - if (fullscreen) - CGLFlushDrawable(glContext); - else - aglSwapBuffers(agContext); + RenderBlitScreen(blitFn, nx, width, height, copyWidth, copyHeight, GFX.Screen); } static void S9xPutImageBlitGL2 (int blit_width, int blit_height) { - if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height) || (windowResizeCount > 0)) - { - if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height)) - windowResizeCount += 2; + if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height)) + windowResizeCount += 2; + if (windowResizeCount > 0) + { if (fullscreen) { CGLSetCurrentContext(glContext); @@ -2386,9 +1717,10 @@ static void S9xPutImageBlitGL2 (int blit_width, int blit_height) if (glstretch) { - int sh = (blit_width > blit_height * 2) ? (blit_height * 2) : blit_height; + int sh = (blit_width < blit_height) ? (blit_height >> 1) : ((blit_width > blit_height * 2) ? (blit_height << 1) : blit_height); float fpw = (float) glScreenH / (float) sh * (float) blit_width; int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); } else @@ -2428,193 +1760,137 @@ static void S9xPutImageBlitGL2 (int blit_width, int blit_height) } } - windowResizeCount--; - - if (nx < 0) - textureNum = (blit_height > SNES_HEIGHT_EXTENDED) ? kGLNTS512 : kGLNTS256; - else + if (!ciFilterEnable) { - switch (blit_width / SNES_WIDTH) - { - default: - case 2: textureNum = kGLBlit2x; break; - case 3: textureNum = kGLBlit3x; break; - case 4: textureNum = kGLBlit4x; break; - } - } - - if (nx < 0) - { - int sh = (blit_height > 256) ? 512 : 256; - OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / 1024.0f; - OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sh; - glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024); - } - else - { - if (OpenGL.rangeExt) - { - OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width; - OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height; - glPixelStorei(GL_UNPACK_ROW_LENGTH, blit_width); - } + if (nx < 0) + textureNum = (blit_height > 256) ? kGLNTS512 : kGLNTS256; else { - int sl = (blit_width > 512) ? 1024 : 512; - OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / (float) sl; - OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sl; - glPixelStorei(GL_UNPACK_ROW_LENGTH, sl); - } - } - - glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); - - prevBlitWidth = blit_width; - prevBlitHeight = blit_height; - } - - glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, blitGLBuffer); - - if (!screencurvature) - { - glBegin(GL_QUADS); - - glTexCoord2fv(&OpenGL.vertex[textureNum][6]); - glVertex2f(-1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][4]); - glVertex2f( 1.0f, -1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][2]); - glVertex2f( 1.0f, 1.0f); - glTexCoord2fv(&OpenGL.vertex[textureNum][0]); - glVertex2f(-1.0f, 1.0f); - - glEnd(); - } - else - { - GLfloat *t, *s; - int tex; - - if (nx < 0) - tex = (blit_height % SNES_HEIGHT) ? kSCNTExtend : kSCNTNormal; - else - if (blit_width > blit_height * 2) - { - if (blit_width / SNES_WIDTH != 3) - tex = (blit_height % SNES_HEIGHT) ? kSC2xEHiRes : kSC2xNHiRes; - else - tex = (blit_height % SNES_HEIGHT) ? kSC3xEHiRes : kSC3xNHiRes; - } - else - { - if (blit_width / SNES_WIDTH != 3) - tex = (blit_height % SNES_HEIGHT) ? kSC2xExtend : kSC2xNormal; - else - tex = (blit_height % SNES_HEIGHT) ? kSC3xExtend : kSC3xNormal; - } - - t = scTexArray[tex]; - s = scScnArray; - - for (int i = 0; i < kSCMeshY; i++) - { - glTexCoordPointer(2, GL_FLOAT, 0, t); - glVertexPointer(3, GL_FLOAT, 0, s); - glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); - - t += (kSCMeshX + 1) * 2 * 2; - s += (kSCMeshX + 1) * 2 * 3; - } - } - - glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); - - if (fullscreen) - CGLFlushDrawable(glContext); - else - aglSwapBuffers(agContext); -} - -static void S9xPutImageBlitGL2CoreImage (int blit_width, int blit_height) -{ - if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height) || (windowResizeCount > 0)) - { - if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height)) - windowResizeCount += 2; - - if (fullscreen) - { - CGLSetCurrentContext(glContext); - - glViewport(0, 0, glScreenW, glScreenH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (glstretch) - { - int sh = (blit_width > blit_height * 2) ? (blit_height * 2) : blit_height; - float fpw = (float) glScreenH / (float) sh * (float) blit_width; - int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); - glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); - } - else - { - int sw, sh; - - if (nx < 0) + switch (blit_width / SNES_WIDTH) { - sw = ntsc_width; - sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * 2; + default: + case 1: + case 2: textureNum = kGLBlit2x; break; + case 3: textureNum = kGLBlit3x; break; + case 4: textureNum = kGLBlit4x; break; + } + } + + if (nx < 0) + { + int sh = (blit_height > 256) ? 512 : 256; + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / 1024.0f; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sh; + glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024); + } + else + { + if (OpenGL.rangeExt) + { + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height; + glPixelStorei(GL_UNPACK_ROW_LENGTH, blit_width); } else { - sw = SNES_WIDTH * nx; - sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * nx; + int sl = (blit_width > 512) ? 1024 : 512; + int sh = (blit_height > 512) ? 1024 : 512; + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / (float) sl; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sh; + glPixelStorei(GL_UNPACK_ROW_LENGTH, (blit_width > 512) ? 1024 : ((blit_width > 256) ? 512 : 256)); } - - glViewport((glScreenW - sw) >> 1, (glScreenH - sh) >> 1, sw, sh); } + + glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); } else { - int ww = (int) gWindowRect.size.width, - wh = (int) gWindowRect.size.height; + int sl = OpenGL.rangeExt ? blit_width : ((blit_width > 512) ? 1024 : ((blit_width > 256) ? 512 : 256)); - aglSetCurrentContext(agContext); - aglUpdateContext(agContext); + glPixelStorei(GL_UNPACK_ROW_LENGTH, sl); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, blit_width, 0, blit_height, -1, 1); - glViewport(0, 0, ww, wh); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (windowExtend) - { - int bh = (blit_height % SNES_HEIGHT) ? (SNES_HEIGHT_EXTENDED << 1) : (SNES_HEIGHT << 1); - glViewport(0, ((kMacWindowHeight - bh) >> 1) * wh / kMacWindowHeight, ww, bh * wh / kMacWindowHeight); - } + if (cgBlitImage) + CGImageRelease(cgBlitImage); + cgBlitImage = CreateBlitScreenCGImage(blit_width, blit_height, sl << 1, blitGLBuffer); } - windowResizeCount--; - - int sl = OpenGL.rangeExt ? blit_width : ((blit_width > 512) ? 1024 : 512); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, sl); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, blit_width, 0, blit_height, -1, 1); - - if (cgBlitImage) - CGImageRelease(cgBlitImage); - cgBlitImage = CreateBlitScreenCGImage(blit_width, blit_height, sl << 1, blitGLBuffer); - prevBlitWidth = blit_width; prevBlitHeight = blit_height; + + windowResizeCount--; } - CGRect src; + if (!ciFilterEnable) + { + glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, blitGLBuffer); - src = CGRectMake(0, 0, blit_width, blit_height); - DrawWithCoreImageFilter(src, cgBlitImage); + if (!screencurvature) + { + glBegin(GL_QUADS); + + glTexCoord2fv(&OpenGL.vertex[textureNum][6]); + glVertex2f(-1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][4]); + glVertex2f( 1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][2]); + glVertex2f( 1.0f, 1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][0]); + glVertex2f(-1.0f, 1.0f); + + glEnd(); + } + else + { + GLfloat *t, *s; + int tex; + + if (nx < 0) + tex = (blit_height % SNES_HEIGHT) ? kSCNTExtend : kSCNTNormal; + else + if (blit_width > blit_height * 2) + { + if (blit_width / SNES_WIDTH != 3) + tex = (blit_height % SNES_HEIGHT) ? kSC2xEHiRes : kSC2xNHiRes; + else + tex = (blit_height % SNES_HEIGHT) ? kSC3xEHiRes : kSC3xNHiRes; + } + else + if (blit_width > blit_height) + { + if (blit_width / SNES_WIDTH != 3) + tex = (blit_height % SNES_HEIGHT) ? kSC2xExtend : kSC2xNormal; + else + tex = (blit_height % SNES_HEIGHT) ? kSC3xExtend : kSC3xNormal; + } + else + tex = (blit_height % SNES_HEIGHT) ? kSC2xEInter : kSC2xNInter; + + t = scTexArray[tex]; + s = scScnArray; + + for (int i = 0; i < kSCMeshY; i++) + { + glTexCoordPointer(2, GL_FLOAT, 0, t); + glVertexPointer(3, GL_FLOAT, 0, s); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); + + t += (kSCMeshX + 1) * 2 * 2; + s += (kSCMeshX + 1) * 2 * 3; + } + } + + glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + } + else + { + CGRect src; + + src = CGRectMake(0, 0, blit_width, blit_height); + DrawWithCoreImageFilter(src, cgBlitImage); + } if (fullscreen) CGLFlushDrawable(glContext); @@ -2622,60 +1898,6 @@ static void S9xPutImageBlitGL2CoreImage (int blit_width, int blit_height) aglSwapBuffers(agContext); } -static void GLMakeScreenMesh (GLfloat *vertex3D, int meshx, int meshy) -{ - GLfloat *v; - float warp; - - v = vertex3D; - warp = macCurvatureWarp * 0.001f; - - for (int y = 0; y < meshy; y++) - { - for (int x = 0; x <= meshx; x++) - { - float u1, v1, v2; - - u1 = -1.0f + 2.0f / (float) meshx * (float) x; - v1 = -1.0f + 2.0f / (float) meshy * (float) y; - v2 = -1.0f + 2.0f / (float) meshy * (float) (y + 1); - - *v++ = u1; - *v++ = v2; - *v++ = -1.0f - (u1 * u1 + v2 * v2) * warp; - - *v++ = u1; - *v++ = v1; - *v++ = -1.0f - (u1 * u1 + v1 * v1) * warp; - } - } -} - -static void GLMakeTextureMesh (GLfloat *vertex2D, int meshx, int meshy, float lx, float ly) -{ - GLfloat *v; - - v = vertex2D; - - for (int y = meshy; y > 0; y--) - { - for (int x = 0; x <= meshx; x++) - { - float u1, v1, v2; - - u1 = lx / (float) meshx * (float) x; - v1 = ly / (float) meshy * (float) y; - v2 = ly / (float) meshy * (float) (y - 1); - - *v++ = u1; - *v++ = v2; - - *v++ = u1; - *v++ = v1; - } - } -} - void S9xTextMode (void) { return; diff --git a/unix/x11.cpp b/unix/x11.cpp index abcb3b74..5066f8f6 100644 --- a/unix/x11.cpp +++ b/unix/x11.cpp @@ -789,19 +789,28 @@ void S9xPutImage (int width, int height) if (width <= SNES_WIDTH) { - copyWidth = width * 2; - copyHeight = height * 2; - - switch (GUI.video_mode) + if (height > SNES_HEIGHT_EXTENDED) { - case VIDEOMODE_BLOCKY: blitFn = S9xBlitPixScaled16; break; - case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; - case VIDEOMODE_SMOOTH: blitFn = S9xBlitPixSmooth16; break; - case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; - case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; - case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; - case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; - case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + copyWidth = width * 2; + copyHeight = height; + blitFn = S9xBlitPixDoubled16; + } + else + { + copyWidth = width * 2; + copyHeight = height * 2; + + switch (GUI.video_mode) + { + case VIDEOMODE_BLOCKY: blitFn = S9xBlitPixScaled16; break; + case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; + case VIDEOMODE_SMOOTH: blitFn = S9xBlitPixSmooth16; break; + case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; + case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; + case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; + case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; + case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + } } } else