diff --git a/Common.mak b/Common.mak
index f101b27cc..e10a6eca8 100644
--- a/Common.mak
+++ b/Common.mak
@@ -940,6 +940,8 @@ ifeq ($(PLATFORM),WINDOWS)
LIBS += -lmingwex -lgdi32 -lpthread
ifeq ($(RENDERTYPE),WIN)
LIBS += -ldxguid
+ else ifeq ($(SDL_TARGET),1)
+ LIBS += -ldxguid -lmingw32 -limm32 -lole32 -loleaut32 -lversion
else
LIBS += -ldxguid_sdl -lmingw32 -limm32 -lole32 -loleaut32 -lversion
endif
diff --git a/GNUmakefile b/GNUmakefile
index c39c6d314..79c65e475 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -192,6 +192,7 @@ engine_objs := \
osd.cpp \
pragmas.cpp \
scriptfile.cpp \
+ softsurface.cpp \
mmulti_null.cpp \
mutex.cpp \
xxhash.c \
diff --git a/platform/Windows/eduke32.vcxproj b/platform/Windows/eduke32.vcxproj
index 8f164a390..d11d1c420 100644
--- a/platform/Windows/eduke32.vcxproj
+++ b/platform/Windows/eduke32.vcxproj
@@ -141,6 +141,7 @@
+
@@ -300,6 +301,7 @@
+
diff --git a/platform/Windows/eduke32.vcxproj.filters b/platform/Windows/eduke32.vcxproj.filters
index 6b4645bc8..627bba27c 100644
--- a/platform/Windows/eduke32.vcxproj.filters
+++ b/platform/Windows/eduke32.vcxproj.filters
@@ -579,6 +579,9 @@
build\headers
+
+ build\headers
+
@@ -1031,6 +1034,9 @@
build\source
+
+ build\source
+
diff --git a/platform/Windows/msvc.mak b/platform/Windows/msvc.mak
index 2b78ccc86..7f844a3aa 100644
--- a/platform/Windows/msvc.mak
+++ b/platform/Windows/msvc.mak
@@ -184,6 +184,7 @@ ENGINE_OBJS= \
$(ENGINE_OBJ)\winbits.$o \
$(ENGINE_OBJ)\xxhash.$o \
$(ENGINE_OBJ)\screenshot.$o \
+ $(ENGINE_OBJ)\softsurface.$o \
$(ENGINE_OBJ)\mhk.$o \
$(ENGINE_OBJ)\pngwrite.$o \
$(ENGINE_OBJ)\miniz.$o \
diff --git a/source/build/include/build.h b/source/build/include/build.h
index 9e9117172..1a587781d 100644
--- a/source/build/include/build.h
+++ b/source/build/include/build.h
@@ -663,7 +663,7 @@ EXTERN int16_t thewall[MAXWALLSB];
EXTERN uspritetype *tspriteptr[MAXSPRITESONSCREEN + 1];
EXTERN int32_t wx1, wy1, wx2, wy2;
-EXTERN int32_t xdim, ydim, numpages;
+EXTERN int32_t xdim, ydim, numpages, upscalefactor;
EXTERN int32_t yxaspect, viewingrange;
EXTERN intptr_t *ylookup;
@@ -1055,7 +1055,7 @@ intptr_t tileCreate(int16_t tilenume, int32_t xsiz, int32_t ysiz);
void tileCopySection(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, int32_t tilenume2, int32_t sx2, int32_t sy2);
void squarerotatetile(int16_t tilenume);
-int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32_t dabpp);
+int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daupscaledydim, int32_t dabpp, int32_t daupscalefactor);
void videoNextPage(void);
void videoSetCorrectedAspect();
void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
diff --git a/source/build/include/glsurface.h b/source/build/include/glsurface.h
index 880fe9214..dea8bf564 100644
--- a/source/build/include/glsurface.h
+++ b/source/build/include/glsurface.h
@@ -1,5 +1,5 @@
/*
- * glsurface.cpp
+ * glsurface.h
* A 32-bit rendering surface that can quickly blit 8-bit paletted buffers implemented in OpenGL.
*
* Copyright © 2018, Alex Dawson. All rights reserved.
@@ -15,7 +15,7 @@
// glsurface will still render at the full size of the screen.
// If a surface already exists, glsurface_destroy() will be automatically called before re-initializing.
// Returns whether or not the glsurface could be successfully initialized.
-bool glsurface_initialize(vec2_t inputBufferResolution);
+bool glsurface_initialize(vec2_t bufferResolution);
// Destroy an existing surface.
void glsurface_destroy();
diff --git a/source/build/include/softsurface.h b/source/build/include/softsurface.h
new file mode 100644
index 000000000..1317e0266
--- /dev/null
+++ b/source/build/include/softsurface.h
@@ -0,0 +1,47 @@
+/*
+ * softsurface.h
+ * An 8-bit rendering surface that can quickly upscale and blit 8-bit paletted buffers to an external 32-bit screen buffer.
+ *
+ * Copyright © 2018, Alex Dawson. All rights reserved.
+ */
+
+#ifndef SOFTSURFACE_H_
+#define SOFTSURFACE_H_
+
+#include "compat.h"
+
+// Initialize the softsurface with the Software renderer's buffer resolution.
+// If the Software renderer's resolution and the actual resolution don't match,
+// softsurface will still render at the full size of the screen.
+// If a surface already exists, softsurface_destroy() will be automatically called before re-initializing.
+// Returns whether or not the softsurface could be successfully initialized.
+bool softsurface_initialize(vec2_t bufferResolution,
+ vec2_t destBufferResolution);
+
+// Destroy an existing surface.
+void softsurface_destroy();
+
+// Sets the palette to contain the RGBA byte buffer pointed to by pPalette.
+// destRedMask/destGreenMask/destBlueMask mask the bits that represent each colour component in the destination buffer's pixel format.
+// If the surface is not initialized, the function returns immediately.
+void softsurface_setPalette(void* pPalette,
+ uint32_t destRedMask,
+ uint32_t destGreenMask,
+ uint32_t destBlueMask);
+
+// Returns a pointer to the start of the surface's 8-bit pixel buffer
+// Returns NULL if the surface is not initialized.
+uint8_t* softsurface_getBuffer();
+
+// Returns the resolution of the surface's buffer
+vec2_t softsurface_getBufferResolution();
+
+// Returns the resolution of the destination buffer
+vec2_t softsurface_getDestinationBufferResolution();
+
+// Blit the surface's pixel buffer to the destination buffer using the palette set with softsurface_setPalette().
+// If the surface is not initialized, the function returns immediately.
+void softsurface_blitBuffer(uint32_t* destBuffer,
+ uint32_t destBpp);
+
+#endif /* SOFTSURFACE_H_ */
diff --git a/source/build/src/2d.cpp b/source/build/src/2d.cpp
index 482d21755..f581714cc 100644
--- a/source/build/src/2d.cpp
+++ b/source/build/src/2d.cpp
@@ -110,10 +110,10 @@ static void drawlinegl(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t
{
// setpolymost2dview(); // JBF 20040205: more efficient setup
- glViewport(0, 0, xres, yres);
+ glViewport(0, 0, xdim, ydim);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- glOrtho(0, xres, yres, 0, -1, 1);
+ glOrtho(0, xdim, ydim, 0, -1, 1);
if (videoGetRenderMode() == REND_POLYMER)
{
glMatrixMode(GL_MODELVIEW);
@@ -274,7 +274,7 @@ int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col
swaplong(&y1, &y2);
}
- if (x1 >= xres || x2 < 0)
+ if (x1 >= xdim || x2 < 0)
return 0;
if (x1 < 0)
@@ -283,10 +283,10 @@ int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col
x1 = 0;
}
- if (x2 >= xres)
+ if (x2 >= xdim)
{
- if (d.y) y2 += scale(xres-1-x2, d.y, d.x);
- x2 = xres-1;
+ if (d.y) y2 += scale(xdim-1-x2, d.y, d.x);
+ x2 = xdim-1;
}
if ((d.x < 0 && d.y >= 0) || (d.y < 0 && d.x >= 0))
@@ -301,14 +301,14 @@ int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col
if (y1 < 0)
{
if (d.x)
- x1 = clamp(x1 + scale(0 - y1, d.x, d.y), 0, xres - 1);
+ x1 = clamp(x1 + scale(0 - y1, d.x, d.y), 0, xdim - 1);
y1 = 0;
}
if (y2 >= ydim16)
{
if (d.x)
- x2 = clamp(x2 + scale(ydim16-1-y2, d.x, d.y), 0, xres-1);
+ x2 = clamp(x2 + scale(ydim16-1-y2, d.x, d.y), 0, xdim-1);
y2 = ydim16-1;
}
@@ -319,7 +319,7 @@ int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col
}
//if (ox1||ox2||oy1||oy2)
- // if (x1<0||x1>=xres || y2<0||y2>=yres)
+ // if (x1<0||x1>=xdim || y2<0||y2>=ydim)
// attach_here();
d.x = klabs(x2-x1)+1;
@@ -450,9 +450,9 @@ void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char c
}
if (r < 0) r = -r;
- if (x1+r < 0 || y1+r < 0 || x1-r >= xres || y1-r >= ydim16) return;
+ if (x1+r < 0 || y1+r < 0 || x1-r >= xdim || y1-r >= ydim16) return;
- uint32_t const uxres = xres, uydim16 = ydim16;
+ uint32_t const uxdim = xdim, uydim16 = ydim16;
/*
* d
@@ -473,13 +473,13 @@ void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char c
if (drawlinepat == 0xffffffff || drawlinepat & pow2long[(++patc)&31])
{
- if ((uint32_t) y1 < uydim16 && (uint32_t) (x1+r) < uxres)
+ if ((uint32_t) y1 < uydim16 && (uint32_t) (x1+r) < uxdim)
drawpixel((char *) (p+r), col); // a
- if ((uint32_t) x1 < uxres && (uint32_t) (y1+r) < uydim16)
+ if ((uint32_t) x1 < uxdim && (uint32_t) (y1+r) < uydim16)
drawpixel((char *) (p+(r*bytesperline)), col); // b
- if ((uint32_t) y1 < uydim16 && (uint32_t) (x1-r) < uxres)
+ if ((uint32_t) y1 < uydim16 && (uint32_t) (x1-r) < uxdim)
drawpixel((char *) (p-r), col); // c
- if ((uint32_t) x1 < uxres && (uint32_t) (y1-r) < uydim16)
+ if ((uint32_t) x1 < uxdim && (uint32_t) (y1-r) < uydim16)
drawpixel((char *) (p-(r*bytesperline)), col); // d
}
@@ -510,21 +510,21 @@ void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char c
if (drawlinepat & pow2long[(++patc) & 31])
{
- if ((uint32_t) (x1 + yp) < uxres && (uint32_t) (y1 + xp) < uydim16)
+ if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
drawpixel_safe((char *) (p + yp + xpbpl), col); // 1
- if ((uint32_t) (x1 + xp) < uxres && (uint32_t) (y1 + yp) < uydim16)
+ if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
drawpixel_safe((char *) (p + xp + ypbpl), col); // 2
- if ((uint32_t) (x1 - xp) < uxres && (uint32_t) (y1 + yp) < uydim16)
+ if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
drawpixel_safe((char *) (p - xp + ypbpl), col); // 3
- if ((uint32_t) (x1 - yp) < uxres && (uint32_t) (y1 + xp) < uydim16)
+ if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
drawpixel_safe((char *) (p - yp + xpbpl), col); // 4
- if ((uint32_t) (x1 - yp) < uxres && (uint32_t) (y1 - xp) < uydim16)
+ if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
drawpixel_safe((char *) (p - yp - xpbpl), col); // 5
- if ((uint32_t) (x1 - xp) < uxres && (uint32_t) (y1 - yp) < uydim16)
+ if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
drawpixel_safe((char *) (p - xp - ypbpl), col); // 6
- if ((uint32_t) (x1 + xp) < uxres && (uint32_t) (y1 - yp) < uydim16)
+ if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
drawpixel_safe((char *) (p + xp - ypbpl), col); // 7
- if ((uint32_t) (x1 + yp) < uxres && (uint32_t) (y1 - xp) < uydim16)
+ if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
drawpixel_safe((char *) (p + yp - xpbpl), col); // 8
}
} while (yp > xp);
@@ -553,21 +553,21 @@ void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char c
int32_t const ypbpl = yp*bytesperline;
int32_t const xpbpl = xp*bytesperline;
- if ((uint32_t) (x1 + yp) < uxres && (uint32_t) (y1 + xp) < uydim16)
+ if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
drawpixel_safe((char *) (p + yp + xpbpl), col); // 1
- if ((uint32_t) (x1 + xp) < uxres && (uint32_t) (y1 + yp) < uydim16)
+ if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
drawpixel_safe((char *) (p + xp + ypbpl), col); // 2
- if ((uint32_t) (x1 - xp) < uxres && (uint32_t) (y1 + yp) < uydim16)
+ if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 + yp) < uydim16)
drawpixel_safe((char *) (p - xp + ypbpl), col); // 3
- if ((uint32_t) (x1 - yp) < uxres && (uint32_t) (y1 + xp) < uydim16)
+ if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 + xp) < uydim16)
drawpixel_safe((char *) (p - yp + xpbpl), col); // 4
- if ((uint32_t) (x1 - yp) < uxres && (uint32_t) (y1 - xp) < uydim16)
+ if ((uint32_t) (x1 - yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
drawpixel_safe((char *) (p - yp - xpbpl), col); // 5
- if ((uint32_t) (x1 - xp) < uxres && (uint32_t) (y1 - yp) < uydim16)
+ if ((uint32_t) (x1 - xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
drawpixel_safe((char *) (p - xp - ypbpl), col); // 6
- if ((uint32_t) (x1 + xp) < uxres && (uint32_t) (y1 - yp) < uydim16)
+ if ((uint32_t) (x1 + xp) < uxdim && (uint32_t) (y1 - yp) < uydim16)
drawpixel_safe((char *) (p + xp - ypbpl), col); // 7
- if ((uint32_t) (x1 + yp) < uxres && (uint32_t) (y1 - xp) < uydim16)
+ if ((uint32_t) (x1 + yp) < uxdim && (uint32_t) (y1 - xp) < uydim16)
drawpixel_safe((char *) (p + yp - xpbpl), col); // 8
} while (yp > xp);
@@ -579,7 +579,7 @@ void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char c
//
void clear2dscreen(void)
{
- int32_t const clearsz = (ydim16 <= yres - STATUS2DSIZ2) ? yres - STATUS2DSIZ2 : yres;
+ int32_t const clearsz = (ydim16 <= ydim - STATUS2DSIZ2) ? ydim - STATUS2DSIZ2 : ydim;
videoBeginDrawing(); //{{{
Bmemset((char *) frameplace, 0, bytesperline*clearsz);
videoEndDrawing(); //}}}
@@ -1380,11 +1380,11 @@ void polymostSet2dView(void)
#ifdef USE_OPENGL
if (videoGetRenderMode() < REND_POLYMOST) return;
- glViewport(0, 0, xres, yres);
+ glViewport(0, 0, xdim, ydim);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- glOrtho(0, xres, yres, 0, -1, 1);
+ glOrtho(0, xdim, ydim, 0, -1, 1);
if (videoGetRenderMode() == REND_POLYMER)
{
diff --git a/source/build/src/baselayer.cpp b/source/build/src/baselayer.cpp
index bd03c829f..710e8ff1f 100644
--- a/source/build/src/baselayer.cpp
+++ b/source/build/src/baselayer.cpp
@@ -128,8 +128,8 @@ int32_t mouseReadAbs(vec2_t * const pResult, vec2_t const * const pInput)
int32_t const xwidth = max(scale(240<<16, xdim, ydim), 320<<16);
- pResult->x = scale(pInput->x, xwidth, xdim) - ((xwidth>>1) - (320<<15));
- pResult->y = scale(pInput->y, 200<<16, ydim);
+ pResult->x = scale(pInput->x, xwidth, xres) - ((xwidth>>1) - (320<<15));
+ pResult->y = scale(pInput->y, 200<<16, yres);
return 1;
}
diff --git a/source/build/src/build.cpp b/source/build/src/build.cpp
index e2e6ee44b..43abce968 100644
--- a/source/build/src/build.cpp
+++ b/source/build/src/build.cpp
@@ -279,7 +279,7 @@ int32_t osdcmd_restartvid(osdfuncparm_t const * const UNUSED(parm))
if (!in3dmode()) return OSDCMD_OK;
videoResetMode();
- if (videoSetGameMode(fullscreen,xdim,ydim,bpp))
+ if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
return OSDCMD_OK;
@@ -288,7 +288,7 @@ int32_t osdcmd_restartvid(osdfuncparm_t const * const UNUSED(parm))
static int32_t osdcmd_vidmode(osdfuncparm_t const * const parm)
{
- int32_t newx = xdim, newy = ydim, newbpp = bpp, newfullscreen = fullscreen;
+ int32_t newx = xres, newy = yres, newbpp = bpp, newfullscreen = fullscreen;
#ifdef USE_OPENGL
int32_t tmp;
#endif
@@ -335,7 +335,7 @@ static int32_t osdcmd_vidmode(osdfuncparm_t const * const parm)
return OSDCMD_OK;
}
- if (videoSetGameMode(newfullscreen,newx,newy,newbpp))
+ if (videoSetGameMode(newfullscreen,newx,newy,newbpp,upscalefactor))
OSD_Printf("vidmode: Mode change failed!\n");
xdimgame = newx;
@@ -769,7 +769,7 @@ int app_main(int argc, char const * const * argv)
g_videoBrightness = 0.0;
videoSetPalette(0,0,0);
- if (videoSetGameMode(fullscreen, xdim2d, ydim2d, 8) < 0)
+ if (videoSetGameMode(fullscreen, xdim2d, ydim2d, 8, upscalefactor) < 0)
{
CallExtUnInit();
engineUnInit();
@@ -792,7 +792,7 @@ int app_main(int argc, char const * const * argv)
}
else
{
- if (videoSetGameMode(fullscreen, xdimgame, ydimgame, bppgame) < 0)
+ if (videoSetGameMode(fullscreen, xdimgame, ydimgame, bppgame, upscalefactor) < 0)
{
CallExtUnInit();
engineUnInit();
@@ -8269,7 +8269,7 @@ CANCEL:
fixspritesectors();
- if (videoSetGameMode(fullscreen,xdimgame,ydimgame,bppgame) < 0)
+ if (videoSetGameMode(fullscreen,xdimgame,ydimgame,bppgame,upscalefactor) < 0)
{
initprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
CallExtUnInit();
diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp
index bd5a8c252..ce0352faf 100644
--- a/source/build/src/engine.cpp
+++ b/source/build/src/engine.cpp
@@ -21,6 +21,7 @@
#include "baselayer.h"
#include "scriptfile.h"
+#include "softsurface.h"
#ifdef USE_OPENGL
# include "glad/glad.h"
# include "glsurface.h"
@@ -2336,8 +2337,8 @@ static inline void wallmosts_finish(int16_t *mostbuf, int32_t z1, int32_t z2,
#if 0
// enable for paranoia:
- ix1 = clamp(ix1, 0, xres-1);
- ix2 = clamp(ix2, 0, xres-1);
+ ix1 = clamp(ix1, 0, xdim-1);
+ ix2 = clamp(ix2, 0, xdim-1);
if (ix2-ix1 < 0)
swaplong(&ix1, &ix2);
#endif
@@ -6518,13 +6519,13 @@ static void dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t
// bound clipping rectangle to screen
if (cx1 < 0) cx1 = 0;
- else if (cx1 > xres-1) cx1 = xres-1;
+ else if (cx1 > xdim-1) cx1 = xdim-1;
if (cy1 < 0) cy1 = 0;
- else if (cy1 > yres-1) cy1 = yres-1;
+ else if (cy1 > ydim-1) cy1 = ydim-1;
if (cx2 < 0) cx2 = 0;
- else if (cx2 > xres-1) cx2 = xres-1;
+ else if (cx2 > xdim-1) cx2 = xdim-1;
if (cy2 < 0) cy2 = 0;
- else if (cy2 > yres-1) cy2 = yres-1;
+ else if (cy2 > ydim-1) cy2 = ydim-1;
xsiz = tilesiz[picnum].x;
ysiz = tilesiz[picnum].y;
@@ -9826,11 +9827,21 @@ static void videoAllocateBuffers(void)
ysavecnt = YSAVES;
nodesperline = tabledivide32_noinline(YSAVES, ydim);
-#ifdef USE_OPENGL
- extern char nogl;
- if (videoGetRenderMode() == REND_CLASSIC && !nogl)
+#ifdef RENDERTYPESDL
+ if (videoGetRenderMode() == REND_CLASSIC)
{
- glsurface_initialize({xdim, ydim});
+# ifdef USE_OPENGL
+ extern char nogl;
+ if (!nogl)
+ {
+ glsurface_initialize({ xdim, ydim });
+ }
+ else
+# endif
+ {
+ softsurface_initialize({ xdim, ydim },
+ { xres, yres });
+ }
}
#endif
}
@@ -9863,7 +9874,7 @@ static void PolymostProcessVoxels(void)
//
// JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen)
extern char videomodereset;
-int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32_t dabpp)
+int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daupscaledydim, int32_t dabpp, int32_t daupscalefactor)
{
int32_t j;
@@ -9872,11 +9883,11 @@ int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32
if (nogl) dabpp = 8;
#endif
- daxdim = max(320, daxdim);
- daydim = max(200, daydim);
+ daupscaledxdim = max(320, daupscaledxdim);
+ daupscaledydim = max(200, daupscaledydim);
- if (in3dmode() && videomodereset == 0 &&
- (davidoption == fullscreen) && (xdim == daxdim) && (ydim == daydim) && (bpp == dabpp))
+ if (in3dmode() && videomodereset == 0 && (davidoption == fullscreen) &&
+ (xres == daupscaledxdim) && (yres == daupscaledydim) && (bpp == dabpp) && (upscalefactor == daupscalefactor))
return 0;
Bstrcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI."
@@ -9891,7 +9902,7 @@ int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32
j = bpp;
g_lastpalettesum = 0;
- if (videoSetMode(daxdim,daydim,dabpp,davidoption) < 0) return -1;
+ if (videoSetMode(daupscaledxdim,daupscaledydim,dabpp,davidoption) < 0) return -1;
// Workaround possible bugs in the GL driver
makeasmwriteable();
@@ -9901,14 +9912,25 @@ int32_t videoSetGameMode(char davidoption, int32_t daxdim, int32_t daydim, int32
else rendmode = REND_CLASSIC;
#endif
- xdim = daxdim;
- ydim = daydim;
+ upscalefactor = max(1, min(tabledivide32(yres, 200), daupscalefactor));
+ //POGOTODO: Polymost/Polymer could work with upscaling with a couple more changes
+ int32_t scalefactor = upscalefactor;
+#ifdef RENDERTYPESDL
+ if (bpp != 8)
+#endif
+ {
+ scalefactor = 1;
+ }
+ xdim = daupscaledxdim/scalefactor;
+ ydim = daupscaledydim/scalefactor;
#ifdef USE_OPENGL
- fxdim = (float) daxdim;
- fydim = (float) daydim;
+ fxdim = (float) xdim;
+ fydim = (float) ydim;
#endif
+ OSD_ResizeDisplay(xdim, ydim);
+
videoAllocateBuffers();
#ifdef HIGH_PRECISION_SPRITE
@@ -12297,7 +12319,7 @@ void videoClearScreen(int32_t dacol)
#endif
videoBeginDrawing(); //{{{
- Bmemset((void *)frameplace,dacol,bytesperline*yres);
+ Bmemset((void *)frameplace,dacol,bytesperline*ydim);
videoEndDrawing(); //}}}
//nextpage();
@@ -12761,20 +12783,22 @@ void videoSet2dMode(int32_t daxdim, int32_t daydim)
ydim = yres;
#ifdef USE_OPENGL
- fxdim = (float) xres;
- fydim = (float) yres;
+ fxdim = (float) xdim;
+ fydim = (float) ydim;
rendmode = REND_CLASSIC;
#endif
+ OSD_ResizeDisplay(xdim, ydim);
+
videoAllocateBuffers();
- ydim16 = yres - STATUS2DSIZ2;
- halfxdim16 = xres >> 1;
- midydim16 = ydim16 >> 1; // scale(200,yres,480);
+ ydim16 = ydim - STATUS2DSIZ2;
+ halfxdim16 = xdim >> 1;
+ midydim16 = ydim16 >> 1; // scale(200,ydim,480);
videoBeginDrawing(); //{{{
- Bmemset((char *)frameplace, 0, yres*bytesperline);
+ Bmemset((char *)frameplace, 0, ydim*bytesperline);
videoEndDrawing(); //}}}
}
diff --git a/source/build/src/glsurface.cpp b/source/build/src/glsurface.cpp
index 1150a1263..4bde7d503 100644
--- a/source/build/src/glsurface.cpp
+++ b/source/build/src/glsurface.cpp
@@ -56,14 +56,14 @@ static GLuint compileShader(GLenum shaderType, const char* const source)
return shaderID;
}
-bool glsurface_initialize(vec2_t inputBufferResolution)
+bool glsurface_initialize(vec2_t bufferResolution)
{
if (buffer)
glsurface_destroy();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- bufferRes = inputBufferResolution;
+ bufferRes = bufferResolution;
buffer = Xaligned_alloc(16, bufferRes.x * bufferRes.y);
glGenBuffers(1, &quadVertsID);
diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp
index 85f6bb44c..fa54cdb72 100644
--- a/source/build/src/palette.cpp
+++ b/source/build/src/palette.cpp
@@ -8,10 +8,6 @@
#include "a.h"
#include "xxhash.h"
-#ifdef USE_OPENGL
-# include "glsurface.h"
-#endif
-
uint8_t *basepaltable[MAXBASEPALS] = { palette };
uint8_t basepalreset=1;
uint8_t curbasepal;
@@ -742,7 +738,6 @@ void videoSetPalette(char dabrightness, uint8_t dapalid, uint8_t flags)
if (palsumdidchange || newpalettesum != g_lastpalettesum)
{
- glsurface_setPalette(curpalettefaded);
// if ((flags&1) == 0)
videoUpdatePalette(0, 256);
}
@@ -826,7 +821,6 @@ void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
if (newpalettesum != lastpalettesum || newpalettesum != g_lastpalettesum)
{
- glsurface_setPalette(curpalettefaded);
videoUpdatePalette(0, 256);
}
diff --git a/source/build/src/polymer.cpp b/source/build/src/polymer.cpp
index bd1acc80f..93eea908e 100644
--- a/source/build/src/polymer.cpp
+++ b/source/build/src/polymer.cpp
@@ -924,7 +924,7 @@ void polymer_glinit(void)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- glViewport(windowxy1.x, yres-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
+ glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
// texturing
glEnable(GL_TEXTURE_2D);
@@ -2029,7 +2029,7 @@ static void polymer_displayrooms(const int16_t dacursectnum)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[0].fbo);
glPushAttrib(GL_VIEWPORT_BIT);
- glViewport(windowxy1.x, yres-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
+ glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp
index 9eeefe0d5..ca3476004 100644
--- a/source/build/src/polymost.cpp
+++ b/source/build/src/polymost.cpp
@@ -1503,7 +1503,7 @@ static void resizeglcheck(void)
glox1 = (float)windowxy1.x; gloy1 = (float)windowxy1.y;
glox2 = (float)windowxy2.x; gloy2 = (float)windowxy2.y;
- glViewport(windowxy1.x-(fovcorrect/2), yres-(windowxy2.y+1),
+ glViewport(windowxy1.x-(fovcorrect/2), ydim-(windowxy2.y+1),
ourxdimen+fovcorrect, windowxy2.y-windowxy1.y+1);
glMatrixMode(GL_PROJECTION);
@@ -6950,7 +6950,7 @@ void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a,
tspr.cstat = globalorientation = (dastat&RS_TRANS1) | ((dastat&RS_TRANS2)<<4) | ((dastat&RS_YFLIP)<<1);
if ((dastat&(RS_AUTO|RS_NOCLIP)) == RS_AUTO)
- glViewport(windowxy1.x, yres-(windowxy2.y+1), windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
+ glViewport(windowxy1.x, ydim-(windowxy2.y+1), windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
else
{
glViewport(0, 0, xdim, ydim);
@@ -7870,7 +7870,7 @@ static int32_t osdcmd_cvar_set_polymost(osdfuncparm_t const * const parm)
{
texcache_invalidate();
videoResetMode();
- if (videoSetGameMode(fullscreen,xdim,ydim,bpp))
+ if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
}
diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp
index 8e6ddaadd..7fa9a1378 100644
--- a/source/build/src/sdlayer.cpp
+++ b/source/build/src/sdlayer.cpp
@@ -13,6 +13,7 @@
#include "engine_priv.h"
#include "palette.h"
+#include "softsurface.h"
#ifdef USE_OPENGL
# include "glad/glad.h"
# include "glbuild.h"
@@ -37,7 +38,6 @@
# include "wiibits.h"
# include
# include
-# define SDL_DISABLE_8BIT_BUFFER
#endif
#if SDL_MAJOR_VERSION != 1
@@ -69,18 +69,10 @@ char quitevent=0, appactive=1, novideo=0;
// video
static SDL_Surface *sdl_surface/*=NULL*/;
-#if !defined SDL_DISABLE_8BIT_BUFFER
-static SDL_Surface *sdl_buffersurface=NULL;
-#else
-# define sdl_buffersurface sdl_surface
-#endif
#if SDL_MAJOR_VERSION==2
-static SDL_Palette *sdl_palptr=NULL;
static SDL_Window *sdl_window=NULL;
static SDL_GLContext sdl_context=NULL;
-static SDL_Texture *sdl_texture=NULL;
-static SDL_Renderer *sdl_renderer=NULL;
#endif
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
@@ -99,7 +91,9 @@ char nogl=0;
#endif
static int32_t vsync_renderlayer;
int32_t maxrefreshfreq=0;
+#if SDL_MAJOR_VERSION==2
static uint32_t currentVBlankInterval=0;
+#endif
// last gamma, contrast, brightness
static float lastvidgcb[3];
@@ -547,7 +541,7 @@ int32_t videoSetVsync(int32_t newSync)
vsync_renderlayer = newSync;
videoResetMode();
- if (videoSetGameMode(fullscreen, xdim, ydim, bpp))
+ if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
}
@@ -675,10 +669,12 @@ void uninitsystem(void)
#endif
#ifdef USE_OPENGL
+# if SDL_MAJOR_VERSION!=1
SDL_GL_UnloadLibrary();
-#ifdef POLYMER
+# endif
+# ifdef POLYMER
unloadglulibrary();
-#endif
+# endif
#endif
}
@@ -1265,33 +1261,15 @@ int32_t videoCheckMode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t fo
return nearest;
}
-static int32_t needpalupdate;
-static SDL_Color sdlayer_pal[256];
-
static void destroy_window_resources()
{
-#if !defined SDL_DISABLE_8BIT_BUFFER
- if (sdl_buffersurface)
- SDL_FreeSurface(sdl_buffersurface);
-
- sdl_buffersurface = NULL;
-#endif
/* We should NOT destroy the window surface. This is done automatically
when SDL_DestroyWindow or SDL_SetVideoMode is called. */
#if SDL_MAJOR_VERSION == 2
- if (sdl_renderer && sdl_texture && sdl_surface)
- SDL_FreeSurface(sdl_surface);
- sdl_surface = NULL;
if (sdl_context)
SDL_GL_DeleteContext(sdl_context);
sdl_context = NULL;
- if (sdl_texture)
- SDL_DestroyTexture(sdl_texture);
- sdl_texture = NULL;
- if (sdl_renderer)
- SDL_DestroyRenderer(sdl_renderer);
- sdl_renderer = NULL;
if (sdl_window)
SDL_DestroyWindow(sdl_window);
sdl_window = NULL;
@@ -1425,10 +1403,7 @@ void sdlayer_setvideomode_opengl(void)
int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t *regrab)
{
if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (c == bpp) && !videomodereset)
- {
- OSD_ResizeDisplay(xres, yres);
return 0;
- }
if (videoCheckMode(x, y, c, fs, 0) < 0)
return -1;
@@ -1461,7 +1436,11 @@ int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, in
if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (bpp != 0) && !videomodereset)
return 0;
}
+ else
#endif
+ {
+ softsurface_destroy();
+ }
// clear last gamma/contrast/brightness so that it will be set anew
lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
@@ -1488,7 +1467,6 @@ void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int
lockcount = 0;
modechange = 1;
videomodereset = 0;
- OSD_ResizeDisplay(xres, yres);
// save the current system gamma to determine if gamma is available
#ifndef EDUKE32_GLES
@@ -1537,55 +1515,6 @@ void setrefreshrate(void)
currentVBlankInterval = 1000/newmode.refresh_rate;
}
-static void sdl_trycreaterenderer_fail(char const * const failurepoint)
-{
- initprintf("Falling back to SDL_GetWindowSurface: %s failed: %s\n", failurepoint, SDL_GetError());
- SDL_DestroyRenderer(sdl_renderer);
- sdl_renderer = NULL;
-}
-
-static void sdl_trycreaterenderer(int32_t const x, int32_t const y)
-{
- int const flags = SDL_RENDERER_ACCELERATED | (vsync_renderlayer ? SDL_RENDERER_PRESENTVSYNC : 0);
-
- sdl_renderer = SDL_CreateRenderer(sdl_window, -1, flags);
- if (!sdl_renderer)
- {
- sdl_trycreaterenderer_fail("SDL_CreateRenderer");
- return;
- }
-
- SDL_RendererInfo sdl_rendererinfo;
- SDL_GetRendererInfo(sdl_renderer, &sdl_rendererinfo);
-
- if (sdl_rendererinfo.flags & SDL_RENDERER_SOFTWARE) // this would be useless
- {
- initprintf("Falling back to SDL_GetWindowSurface: software SDL_Renderer \"%s\" provides no benefit.\n", sdl_rendererinfo.name);
- SDL_DestroyRenderer(sdl_renderer);
- sdl_renderer = NULL;
- return;
- }
-
- initprintf("Trying SDL_Renderer \"%s\"\n", sdl_rendererinfo.name);
-
- sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, x, y);
- if (!sdl_texture)
- {
- sdl_trycreaterenderer_fail("SDL_CreateTexture");
- return;
- }
-
- sdl_surface = SDL_CreateRGBSurface(0, x, y, 32, 0, 0, 0, 0);
-
- if (!sdl_surface)
- {
- SDL_DestroyTexture(sdl_texture);
- sdl_texture = NULL;
- sdl_trycreaterenderer_fail("SDL_CreateRGBSurface");
- return;
- }
-}
-
int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
{
int32_t regrab = 0, ret;
@@ -1684,8 +1613,6 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
setrefreshrate();
- sdl_trycreaterenderer(x, y);
-
if (!sdl_surface)
{
sdl_surface = SDL_GetWindowSurface(sdl_window);
@@ -1693,19 +1620,6 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
SDL2_VIDEO_ERR("SDL_GetWindowSurface");
}
-#if !defined SDL_DISABLE_8BIT_BUFFER
- sdl_buffersurface = SDL_CreateRGBSurface(0, x, y, c, 0, 0, 0, 0);
-
- if (!sdl_buffersurface)
- SDL2_VIDEO_ERR("SDL_CreateRGBSurface");
-#endif
-
- if (!sdl_palptr)
- sdl_palptr = SDL_AllocPalette(256);
-
- if (SDL_SetSurfacePalette(sdl_buffersurface, sdl_palptr) < 0)
- initprintf("SDL_SetSurfacePalette failed: %s\n", SDL_GetError());
-
SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? SDL_WINDOW_FULLSCREEN : 0));
}
@@ -1752,6 +1666,7 @@ void videoBeginDrawing(void)
if (offscreenrendering) return;
+#ifdef USE_OPENGL
if (!nogl)
{
frameplace = (intptr_t)glsurface_getBuffer();
@@ -1763,16 +1678,13 @@ void videoBeginDrawing(void)
}
return;
}
+#endif
- if (SDL_MUSTLOCK(sdl_buffersurface)) SDL_LockSurface(sdl_buffersurface);
- frameplace = (intptr_t)sdl_buffersurface->pixels;
-
- if (sdl_buffersurface->pitch != bytesperline || modechange)
+ frameplace = (intptr_t)softsurface_getBuffer();
+ if (modechange)
{
- bytesperline = sdl_buffersurface->pitch;
-
+ bytesperline = xdim;
calc_ylookup(bytesperline, ydim);
-
modechange=0;
}
}
@@ -1794,10 +1706,6 @@ void videoEndDrawing(void)
if (!offscreenrendering) frameplace = 0;
if (lockcount == 0) return;
lockcount = 0;
-
- if (offscreenrendering || !nogl) return;
-
- if (SDL_MUSTLOCK(sdl_buffersurface)) SDL_UnlockSurface(sdl_buffersurface);
}
//
@@ -1854,27 +1762,11 @@ void videoShowFrame(int32_t w)
while (lockcount) videoEndDrawing();
}
- // deferred palette updating
- if (needpalupdate)
- {
- if (SDL_SetPaletteColors(sdl_palptr, sdlayer_pal, 0, 256) < 0)
- initprintf("SDL_SetPaletteColors failed: %s\n", SDL_GetError());
- needpalupdate = 0;
- }
+ if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
+ softsurface_blitBuffer((uint32_t*) sdl_surface->pixels, sdl_surface->format->BitsPerPixel);
+ if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
-#if !defined SDL_DISABLE_8BIT_BUFFER
- SDL_BlitSurface(sdl_buffersurface, NULL, sdl_surface, NULL);
-#endif
-
- if (sdl_renderer && sdl_texture)
- {
- SDL_UpdateTexture(sdl_texture, NULL, sdl_surface->pixels, sdl_surface->pitch);
-
- SDL_RenderClear(sdl_renderer);
- SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
- SDL_RenderPresent(sdl_renderer);
- }
- else if (SDL_UpdateWindowSurface(sdl_window))
+ if (SDL_UpdateWindowSurface(sdl_window))
{
// If a fullscreen X11 window is minimized then this may be required.
// FIXME: What to do if this fails...
@@ -1888,21 +1780,24 @@ void videoShowFrame(int32_t w)
//
int32_t videoUpdatePalette(int32_t start, int32_t num)
{
+ UNREFERENCED_PARAMETER(start);
+ UNREFERENCED_PARAMETER(num);
+
if (bpp > 8)
return 0; // no palette in opengl
- Bmemcpy(sdlayer_pal, curpalettefaded, 256 * 4);
-
- for (native_t i = start, n = num; n > 0; i++, n--)
- curpalettefaded[i].f =
-#if SDL_MAJOR_VERSION == 1
- sdlayer_pal[i].unused
-#else
- sdlayer_pal[i].a
+#ifdef USE_OPENGL
+ if (!nogl)
+ glsurface_setPalette(curpalettefaded);
+ else
#endif
- = 0;
-
- needpalupdate = 1;
+ {
+ if (sdl_surface)
+ softsurface_setPalette(curpalettefaded,
+ sdl_surface->format->Rmask,
+ sdl_surface->format->Gmask,
+ sdl_surface->format->Bmask);
+ }
return 0;
}
diff --git a/source/build/src/sdlayer12.cpp b/source/build/src/sdlayer12.cpp
index a1e3d8ab3..e0789387a 100644
--- a/source/build/src/sdlayer12.cpp
+++ b/source/build/src/sdlayer12.cpp
@@ -26,7 +26,7 @@ int32_t videoSetVsync(int32_t newSync)
vsync_renderlayer = newSync;
videoResetMode();
- if (videoSetGameMode(fullscreen, xdim, ydim, bpp))
+ if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
return newSync;
@@ -251,12 +251,8 @@ void videoGetModes(void)
pf.BitsPerPixel = cdepths[j];
pf.BytesPerPixel = cdepths[j] >> 3;
-#if !defined SDL_DISABLE_8BIT_BUFFER
// We convert paletted contents to non-paletted
modes = SDL_ListModes((cdepths[j] == 8) ? NULL : &pf, SURFACE_FLAGS | SDL_FULLSCREEN);
-#else
- modes = SDL_ListModes(&pf, SURFACE_FLAGS | SDL_FULLSCREEN);
-#endif
if (modes == (SDL_Rect **)0)
{
@@ -325,7 +321,14 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
#endif
ret = setvideomode_sdlcommon(&x, &y, c, fs, ®rab);
- if (ret != 1) return ret;
+ if (ret != 1)
+ {
+ if (ret == 0)
+ {
+ setvideomode_sdlcommonpost(x, y, c, fs, regrab);
+ }
+ return ret;
+ }
// restore gamma before we change video modes if it was changed
if (sdl_surface && gammabrightness)
@@ -340,7 +343,7 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
#ifdef USE_OPENGL
- if (c > 8)
+ if (c > 8 || !nogl)
{
int32_t i, j, multisamplecheck = (glmultisample > 0);
@@ -395,34 +398,21 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
initprintf("Unable to set video mode!\n");
return -1;
}
-
-#ifdef _WIN32
- loadglextensions();
-#endif
} while (multisamplecheck--);
+
+ gladLoadGLLoader(SDL_GL_GetProcAddress);
}
else
#endif // defined USE_OPENGL
{
-#if !defined SDL_DISABLE_8BIT_BUFFER
// We convert paletted contents to non-paletted
sdl_surface = SDL_SetVideoMode(x, y, 0, SURFACE_FLAGS | ((fs & 1) ? SDL_FULLSCREEN : 0));
-#else
- sdl_surface = SDL_SetVideoMode(x, y, c, SURFACE_FLAGS | ((fs & 1) ? SDL_FULLSCREEN : 0));
-#endif
+
if (!sdl_surface)
{
initprintf("Unable to set video mode!\n");
return -1;
}
-#if !defined SDL_DISABLE_8BIT_BUFFER
- sdl_buffersurface = SDL_CreateRGBSurface(SURFACE_FLAGS, x, y, c, 0, 0, 0, 0);
- if (!sdl_buffersurface)
- {
- initprintf("Unable to set video mode: SDL_CreateRGBSurface failed: %s\n", SDL_GetError());
- return -1;
- }
-#endif
}
setvideomode_sdlcommonpost(x, y, c, fs, regrab);
@@ -438,10 +428,17 @@ void videoShowFrame(int32_t w)
UNREFERENCED_PARAMETER(w);
#ifdef USE_OPENGL
- if (bpp > 8)
+ if (!nogl)
{
- if (palfadedelta)
- fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
+ if (bpp > 8)
+ {
+ if (palfadedelta)
+ fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
+ }
+ else
+ {
+ glsurface_blitBuffer();
+ }
SDL_GL_SwapBuffers();
return;
@@ -456,16 +453,10 @@ void videoShowFrame(int32_t w)
while (lockcount) videoEndDrawing();
}
- // deferred palette updating
- if (needpalupdate)
- {
- SDL_SetColors(sdl_buffersurface, sdlayer_pal, 0, 256);
- needpalupdate = 0;
- }
+ if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
+ softsurface_blitBuffer((uint32_t*) sdl_surface->pixels, sdl_surface->format->BitsPerPixel);
+ if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
-#if !defined SDL_DISABLE_8BIT_BUFFER
- SDL_BlitSurface(sdl_buffersurface, NULL, sdl_surface, NULL);
-#endif
SDL_Flip(sdl_surface);
}
diff --git a/source/build/src/softsurface.cpp b/source/build/src/softsurface.cpp
new file mode 100644
index 000000000..4d1487803
--- /dev/null
+++ b/source/build/src/softsurface.cpp
@@ -0,0 +1,207 @@
+/*
+ * softsurface.cpp
+ * An 8-bit rendering surface that can quickly upscale and blit 8-bit paletted buffers to an external 32-bit buffer.
+ *
+ * Copyright © 2018, Alex Dawson. All rights reserved.
+ */
+
+#include "softsurface.h"
+
+#include "pragmas.h"
+#include "build.h"
+
+static uint8_t* buffer;
+static vec2_t bufferRes;
+
+static vec2_t destBufferRes;
+
+static uint32_t xScale16;
+static uint32_t yScale16;
+static uint32_t recXScale16;
+
+static uint32_t pPal[256];
+
+// lookup table to find the source position within a scanline
+static uint16_t* scanPosLookupTable;
+
+static uint32_t roundUp(uint32_t num, uint32_t multiple)
+{
+ return (num+multiple-1)/multiple * multiple;
+}
+
+static uint32_t countTrailingZeros(uint32_t u)
+{
+#if (defined __GNUC__ && __GNUC__>=3) || defined __clang__
+ return __builtin_ctz(u);
+#elif defined _MSC_VER
+ uint32_t result;
+ _BitScanForward(&result, u);
+ return result;
+#else
+ uint32_t last = u;
+ for (; u != 0; last = u, u >>= 1);
+ return last;
+#endif
+}
+
+bool softsurface_initialize(vec2_t bufferResolution,
+ vec2_t destBufferResolution)
+{
+ if (buffer)
+ softsurface_destroy();
+
+ bufferRes = bufferResolution;
+ destBufferRes = destBufferResolution;
+
+ xScale16 = divscale16(destBufferRes.x, bufferRes.x);
+ yScale16 = divscale16(destBufferRes.y, bufferRes.y);
+ recXScale16 = divscale16(bufferRes.x, destBufferRes.x);
+
+ // allocate one continuous block of memory large enough to hold the buffer, the palette,
+ // and the scanPosLookupTable while maintaining alignment for each
+ uint32_t bufferSize = roundUp(bufferRes.x * bufferRes.y, 16);
+ buffer = (uint8_t*) Xaligned_alloc(16, bufferSize + sizeof(uint16_t)*destBufferRes.x);
+ scanPosLookupTable = (uint16_t*) (buffer + bufferSize);
+
+ // calculate the scanPosLookupTable for horizontal scaling
+ uint32_t incr = recXScale16;
+ for (int32_t i = 0; i < destBufferRes.x; ++i)
+ {
+ scanPosLookupTable[i] = incr >> 16;
+ incr += recXScale16;
+ }
+
+ return true;
+}
+
+void softsurface_destroy()
+{
+ if (!buffer)
+ return;
+
+ ALIGNED_FREE_AND_NULL(buffer);
+ scanPosLookupTable = 0;
+
+ xScale16 = 0;
+ yScale16 = 0;
+ recXScale16 = 0;
+
+ bufferRes = {};
+ destBufferRes = {};
+}
+
+void softsurface_setPalette(void* pPalette,
+ uint32_t destRedMask,
+ uint32_t destGreenMask,
+ uint32_t destBlueMask)
+{
+ if (!buffer)
+ return;
+ if (!pPalette)
+ return;
+
+ uint32_t destRedShift = countTrailingZeros(destRedMask);
+ uint32_t destRedLoss = 8 - countTrailingZeros((destRedMask>>destRedShift)+1);
+ uint32_t destGreenShift = countTrailingZeros(destGreenMask);
+ uint32_t destGreenLoss = 8 - countTrailingZeros((destGreenMask>>destGreenShift)+1);
+ uint32_t destBlueShift = countTrailingZeros(destBlueMask);
+ uint32_t destBlueLoss = 8 - countTrailingZeros((destBlueMask>>destBlueShift)+1);
+
+ uint8_t* pUI8Palette = (uint8_t*) pPalette;
+ for (int i = 0; i < 256; ++i)
+ {
+ pPal[i] = ((pUI8Palette[sizeof(uint32_t)*i] >> destRedLoss << destRedShift) & destRedMask) |
+ ((pUI8Palette[sizeof(uint32_t)*i+1] >> destGreenLoss << destGreenShift) & destGreenMask) |
+ ((pUI8Palette[sizeof(uint32_t)*i+2] >> destBlueLoss << destBlueShift) & destBlueMask);
+ }
+}
+
+uint8_t* softsurface_getBuffer()
+{
+ return buffer;
+}
+
+vec2_t softsurface_getBufferResolution()
+{
+ return bufferRes;
+}
+
+vec2_t softsurface_getDestinationBufferResolution()
+{
+ return destBufferRes;
+}
+
+#define BLIT(x) pDst[x] = *((UINTTYPE*)(pPal+pSrc[pScanPos[x]]))
+#define BLIT2(x) BLIT(x); BLIT(x+1)
+#define BLIT4(x) BLIT2(x); BLIT2(x+2)
+#define BLIT8(x) BLIT4(x); BLIT4(x+4)
+#define BLIT16(x) BLIT8(x); BLIT8(x+8)
+#define BLIT32(x) BLIT16(x); BLIT16(x+16)
+#define BLIT64(x) BLIT32(x); BLIT32(x+32)
+template
+void softsurface_blitBufferInternal(UINTTYPE* destBuffer)
+{
+ const uint8_t* __restrict pSrc = buffer;
+ UINTTYPE* __restrict pDst = destBuffer;
+ const UINTTYPE* const pEnd = destBuffer+destBufferRes.x*mulscale16(yScale16, bufferRes.y);
+ uint32_t remainder = 0;
+ while (pDst < pEnd)
+ {
+ uint16_t* __restrict pScanPos = scanPosLookupTable;
+ UINTTYPE* const pScanEnd = pDst+destBufferRes.x;
+ while (pDst < pScanEnd-64)
+ {
+ BLIT64(0);
+ pDst += 64;
+ pScanPos += 64;
+ }
+ while (pDst < pScanEnd)
+ {
+ BLIT(0);
+ ++pDst;
+ ++pScanPos;
+ }
+ pSrc += bufferRes.x;
+
+ static const uint32_t MASK16 = (1<<16)-1;
+ uint32_t linesCopied = 1;
+ uint32_t linesToCopy = yScale16+remainder;
+ remainder = linesToCopy & MASK16;
+ linesToCopy = (linesToCopy >> 16)-1;
+ const UINTTYPE* const __restrict pScanLineSrc = pDst-destBufferRes.x;
+ while (linesToCopy)
+ {
+ uint32_t lines = min(linesCopied, linesToCopy);
+ memcpy(pDst, pScanLineSrc, sizeof(UINTTYPE)*lines*destBufferRes.x);
+ pDst += lines*destBufferRes.x;
+ linesToCopy -= lines;
+ }
+ }
+}
+
+void softsurface_blitBuffer(uint32_t* destBuffer,
+ uint32_t destBpp)
+{
+ if (!buffer)
+ return;
+ if (!destBuffer)
+ return;
+
+ switch (destBpp)
+ {
+ case 15:
+ softsurface_blitBufferInternal((uint16_t*) destBuffer);
+ break;
+ case 16:
+ softsurface_blitBufferInternal((uint16_t*) destBuffer);
+ break;
+ case 24:
+ softsurface_blitBufferInternal(destBuffer);
+ break;
+ case 32:
+ softsurface_blitBufferInternal(destBuffer);
+ break;
+ default:
+ return;
+ }
+}
diff --git a/source/build/src/winlayer.cpp b/source/build/src/winlayer.cpp
index 7178b483c..eb10f7beb 100644
--- a/source/build/src/winlayer.cpp
+++ b/source/build/src/winlayer.cpp
@@ -1592,10 +1592,7 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
int32_t modenum;
if ((fs == fullscreen) && (x == xres) && (y == yres) && (c == bpp) && !videomodereset)
- {
- OSD_ResizeDisplay(xres,yres);
return 0;
- }
modenum = videoCheckMode(&x,&y,c,fs,0);
if (modenum < 0) return -1;
@@ -1637,7 +1634,6 @@ int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
if (inp) AcquireInputDevices(1);
modechange=1;
videomodereset = 0;
- OSD_ResizeDisplay(xres,yres);
return 0;
}
@@ -3190,7 +3186,6 @@ static BOOL CreateAppWindow(int32_t modenum)
//bytesperline = width;
modechange = 1;
- OSD_ResizeDisplay(xres,yres);
UpdateWindow(hWindow);
@@ -3522,7 +3517,7 @@ static LRESULT CALLBACK WndProcCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPA
}
realfs = fullscreen;
silentvideomodeswitch = 1;
- videoSetGameMode(!fullscreen,xdim,ydim,bpp);
+ videoSetGameMode(!fullscreen,xres,yres,bpp,upscalefactor);
ShowWindow(hWindow, SW_MINIMIZE);
}
else if (appactive && realfs)
@@ -3535,7 +3530,7 @@ static LRESULT CALLBACK WndProcCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPA
ShowWindow(hWindow, SW_RESTORE);
SetForegroundWindow(hWindow);
SetFocus(hWindow);
- videoSetGameMode(realfs,xdim,ydim,bpp);
+ videoSetGameMode(realfs,xres,yres,bpp,upscalefactor);
silentvideomodeswitch = 0;
realfs = 0;
}
diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp
index da14fb97d..c2b753818 100644
--- a/source/duke3d/src/game.cpp
+++ b/source/duke3d/src/game.cpp
@@ -187,10 +187,10 @@ void G_HandleSpecialKeys(void)
if (g_networkMode != NET_DEDICATED_SERVER && ALT_IS_PRESSED && KB_KeyPressed(sc_Enter))
{
- if (videoSetGameMode(!ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP))
+ if (videoSetGameMode(!ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP,ud.detail))
{
OSD_Printf(OSD_ERROR "Failed setting fullscreen video mode.\n");
- if (videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP))
+ if (videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP, ud.detail))
G_GameExit("Failed to recover from failure to set fullscreen video mode.\n");
}
else ud.config.ScreenMode = !ud.config.ScreenMode;
@@ -281,7 +281,7 @@ void G_GameExit(const char *msg)
g_mostConcurrentPlayers > 1 && g_player[myconnectindex].ps->gm&MODE_GAME && GTFLAGS(GAMETYPE_SCORESHEET) && *msg == ' ')
{
G_BonusScreen(1);
- videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP);
+ videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP,ud.detail);
}
// shareware and TEN screens
@@ -772,7 +772,6 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
int32_t floorZ, ceilZ;
int32_t tiltcx, tiltcy, tiltcs=0; // JBF 20030807
- int pixelDoubling = 0;
int const vr = divscale22(1, sprite[pPlayer->i].yrepeat + 28);
int screenTilting = (videoGetRenderMode() == REND_CLASSIC && ((ud.screen_tilting && pPlayer->rotscrnang
#ifdef SPLITSCREEN_MOD_HACKS
@@ -896,12 +895,6 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
#endif
pPlayer->orotscrnang = pPlayer->rotscrnang;
}
- else if (ud.detail && videoGetRenderMode()==REND_CLASSIC)
- {
- pixelDoubling = 1;
- g_halveScreenArea = 1;
- G_UpdateScreenArea();
- }
if (pPlayer->newowner < 0)
{
@@ -1107,39 +1100,6 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
walock[TILE_TILT] = 199;
}
}
- else if (pixelDoubling)
- {
- Bassert(g_halfScreen.xdimen!=0);
- g_halveScreenArea = 0;
- G_UpdateScreenArea();
-
- videoBeginDrawing();
- {
- uint8_t *const f = (uint8_t *)frameplace;
- const int32_t x1=g_halfScreen.x1, y1=g_halfScreen.y1;
- const int32_t xd=g_halfScreen.xdimen, yd=g_halfScreen.ydimen;
- int32_t dx, dy;
-
- // Commented out: naive, per-byte access version.
- // Live: optimized version: may access memory unaligned, relies
- // on little-endian byte ordering.
-
- for (dy=2*yd-1; dy>=0; dy--)
-// for (dx=2*xd-1; dx>=0; dx--)
- for (dx=2*xd-4; dx>=0; dx-=4)
- {
- const int32_t ylsrc = ylookup[y1+(dy>>1)];
- const int32_t yldst = ylookup[y1+dy];
-
-// f[yldst+x1+dx] = f[ylsrc+x1+(dx>>1)];
- uint8_t pixr = f[ylsrc+x1+((dx+3)>>1)];
- uint8_t pixl = f[ylsrc+x1+((dx+1)>>1)];
-
- B_BUF32(&f[yldst+x1+dx], pixl|(pixl<<8)|(pixr<<16)|(pixr<<24));
- }
- }
- videoEndDrawing();
- }
}
G_RestoreInterpolations();
@@ -6549,7 +6509,7 @@ int app_main(int argc, char const * const * argv)
if (g_networkMode != NET_DEDICATED_SERVER)
{
- if (videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP) < 0)
+ if (videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP,ud.detail) < 0)
{
vec2_t const res[] = {
{ ud.config.ScreenWidth, ud.config.ScreenHeight }, { 800, 600 }, { 640, 480 }, { 320, 240 },
@@ -6567,7 +6527,7 @@ int app_main(int argc, char const * const * argv)
int resIdx = 0;
int bppIdx = 0;
- while (videoSetGameMode(0, res[resIdx].x, res[resIdx].y, bpp[bppIdx]) < 0)
+ while (videoSetGameMode(0, res[resIdx].x, res[resIdx].y, bpp[bppIdx], ud.detail) < 0)
{
initprintf("Failure setting video mode %dx%dx%d windowed! Attempting safer mode...\n", res[resIdx].x, res[resIdx].y,
bpp[bppIdx]);
diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp
index b5642f989..de2369e1a 100644
--- a/source/duke3d/src/gamestructures.cpp
+++ b/source/duke3d/src/gamestructures.cpp
@@ -308,8 +308,8 @@ void __fastcall VM_SetUserdef(int32_t const labelNum, int32_t const lParm2, int3
case USERDEFS_M_RESPAWN_INVENTORY: ud.m_respawn_inventory = iSet; break;
case USERDEFS_M_RECSTAT: ud.m_recstat = iSet; break;
case USERDEFS_M_MONSTERS_OFF: ud.m_monsters_off = iSet; break;
- // REMINDER: must implement "boolean" setters like this in Lunatic, too.
- case USERDEFS_DETAIL: ud.detail = !!iSet; break;
+ // REMINDER: must implement "boolean" setters like "!!iSet" in Lunatic, too.
+ case USERDEFS_DETAIL: ud.detail = clamp(iSet, 1, 16); break;
case USERDEFS_M_FFIRE: ud.m_ffire = iSet; break;
case USERDEFS_FFIRE: ud.ffire = iSet; break;
case USERDEFS_M_PLAYER_SKILL: ud.m_player_skill = iSet; break;
diff --git a/source/duke3d/src/menus.cpp b/source/duke3d/src/menus.cpp
index 5cf29548f..3b068274c 100644
--- a/source/duke3d/src/menus.cpp
+++ b/source/duke3d/src/menus.cpp
@@ -548,8 +548,11 @@ static MenuLink_t MEO_DISPLAYSETUP_COLORCORR = { MENU_COLCORR, MA_Advance, };
static MenuEntry_t ME_DISPLAYSETUP_COLORCORR = MAKE_MENUENTRY( "Color Correction", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_COLORCORR, Link );
-static MenuOption_t MEO_DISPLAYSETUP_PIXELDOUBLING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &ud.detail );
-static MenuEntry_t ME_DISPLAYSETUP_PIXELDOUBLING = MAKE_MENUENTRY( "Pixel Doubling:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_PIXELDOUBLING, Option );
+static char const *MEOSN_DISPLAYSETUP_UPSCALING[] = { "None", "2x", "4x", "8x", "16x", };
+static int32_t MEOSV_DISPLAYSETUP_UPSCALING[] = { 1, 2, 4, 8, 16, };
+static MenuOptionSet_t MEOS_DISPLAYSETUP_UPSCALING = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_UPSCALING, MEOSV_DISPLAYSETUP_UPSCALING, 0x0 );
+static MenuOption_t MEO_DISPLAYSETUP_UPSCALING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_DISPLAYSETUP_UPSCALING, &ud.detail );
+static MenuEntry_t ME_DISPLAYSETUP_UPSCALING = MAKE_MENUENTRY( "Upscaling:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_UPSCALING, Option );
#ifndef EDUKE32_ANDROID_MENU
@@ -733,7 +736,7 @@ static MenuEntry_t *MEL_DISPLAYSETUP[] = {
&ME_DISPLAYSETUP_VIDEOSETUP,
&ME_DISPLAYSETUP_ASPECTRATIO,
#endif
- &ME_DISPLAYSETUP_PIXELDOUBLING,
+ &ME_DISPLAYSETUP_UPSCALING,
};
#ifdef USE_OPENGL
@@ -1992,7 +1995,7 @@ static void Menu_Pre(MenuID_t cm)
MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_FULLSCREEN, !(resolution[nr].flags & RES_FS));
MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_APPLY,
- (xdim == resolution[nr].xdim && ydim == resolution[nr].ydim &&
+ (xres == resolution[nr].xdim && yres == resolution[nr].ydim &&
videoGetRenderMode() == newrendermode && fullscreen == newfullscreen
&& vsync == newvsync
)
@@ -3031,7 +3034,7 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry)
if (entry == &ME_VIDEOSETUP_APPLY)
{
- resolution_t p = { xdim, ydim, fullscreen, bpp, 0 };
+ resolution_t p = { xres, yres, fullscreen, bpp, 0 };
int32_t prend = videoGetRenderMode();
int32_t pvsync = vsync;
@@ -3041,9 +3044,9 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry)
int32_t nrend = newrendermode;
int32_t nvsync = newvsync;
- if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax) < 0)
+ if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax, upscalefactor) < 0)
{
- if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax) < 0)
+ if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax, upscalefactor) < 0)
{
videoSetRenderMode(prend);
G_GameExit("Failed restoring old video mode.");
@@ -3061,8 +3064,8 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry)
videoSetRenderMode(nrend);
vsync = videoSetVsync(nvsync);
ud.config.ScreenMode = fullscreen;
- ud.config.ScreenWidth = xdim;
- ud.config.ScreenHeight = ydim;
+ ud.config.ScreenWidth = xres;
+ ud.config.ScreenHeight = yres;
ud.config.ScreenBPP = bpp;
}
else if (entry == &ME_SOUND_RESTART)
@@ -3271,6 +3274,13 @@ static void Menu_EntryOptionDidModify(MenuEntry_t *entry)
entry == &ME_PLAYER_COLOR ||
entry == &ME_PLAYER_TEAM)
G_UpdatePlayerFromMenu();
+ else if (entry == &ME_DISPLAYSETUP_UPSCALING)
+ {
+ if (in3dmode())
+ {
+ videoSetGameMode(fullscreen, xres, yres, bpp, ud.detail);
+ }
+ }
#ifdef USE_OPENGL
else if (entry == &ME_DISPLAYSETUP_ANISOTROPY || entry == &ME_DISPLAYSETUP_TEXFILTER)
gltexapplyprops();
@@ -3290,7 +3300,7 @@ static void Menu_EntryOptionDidModify(MenuEntry_t *entry)
if (domodechange)
{
videoResetMode();
- if (videoSetGameMode(fullscreen, xdim, ydim, bpp))
+ if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
onvideomodechange(ud.config.ScreenBPP>8);
G_RefreshLights();
@@ -4048,7 +4058,7 @@ static void Menu_AboutToStartDisplaying(Menu_t * m)
newresolution = 0;
for (size_t i = 0; i < MAXVALIDMODES; ++i)
{
- if (resolution[i].xdim == xdim && resolution[i].ydim == ydim)
+ if (resolution[i].xdim == xres && resolution[i].ydim == yres)
{
newresolution = i;
break;
diff --git a/source/duke3d/src/osdcmds.cpp b/source/duke3d/src/osdcmds.cpp
index 66ab6067c..01557ecd9 100644
--- a/source/duke3d/src/osdcmds.cpp
+++ b/source/duke3d/src/osdcmds.cpp
@@ -420,7 +420,7 @@ int32_t osdcmd_restartvid(osdfuncparm_t const * const UNUSED(parm))
{
UNREFERENCED_CONST_PARAMETER(parm);
videoResetMode();
- if (videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP))
+ if (videoSetGameMode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP,ud.detail))
G_GameExit("restartvid: Reset failed...\n");
onvideomodechange(ud.config.ScreenBPP>8);
G_UpdateScreenArea();
@@ -471,10 +471,10 @@ static int32_t osdcmd_vidmode(osdfuncparm_t const * const parm)
break;
}
- if (videoSetGameMode(newfs,newwidth,newheight,newbpp))
+ if (videoSetGameMode(newfs,newwidth,newheight,newbpp,upscalefactor))
{
initprintf("vidmode: Mode change failed!\n");
- if (videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP))
+ if (videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP, upscalefactor))
G_GameExit("vidmode: Reset failed!\n");
}
ud.config.ScreenBPP = newbpp;
@@ -1490,7 +1490,14 @@ static int32_t osdcmd_cvar_set_game(osdfuncparm_t const * const parm)
if (r != OSDCMD_OK) return r;
- if (!Bstrcasecmp(parm->name, "r_size"))
+ if (!Bstrcasecmp(parm->name, "r_upscalefactor"))
+ {
+ if (in3dmode())
+ {
+ videoSetGameMode(fullscreen, xres, yres, bpp, ud.detail);
+ }
+ }
+ else if (!Bstrcasecmp(parm->name, "r_size"))
{
ud.statusbarmode = (ud.screen_size < 8);
G_UpdateScreenArea();
@@ -1709,7 +1716,7 @@ int32_t registerosdcommands(void)
{ "r_shadows", "enable/disable sprite and model shadows", (void *)&ud.shadows, CVAR_BOOL, 0, 1 },
{ "r_size", "change size of viewable area", (void *)&ud.screen_size, CVAR_INT|CVAR_FUNCPTR, 0, 64 },
{ "r_rotatespritenowidescreen", "pass bit 1024 to all CON rotatesprite calls", (void *)&g_rotatespriteNoWidescreen, CVAR_BOOL|CVAR_FUNCPTR, 0, 1 },
- { "r_pixeldoubling", "enable/disable pixel doubling in the software renderer", (void *) &ud.detail, CVAR_BOOL, 0, 1 },
+ { "r_upscalefactor", "increase performance by rendering at upscalefactor less than the screen resolution and upscale to the full resolution in the software renderer", (void *)&ud.detail, CVAR_INT|CVAR_FUNCPTR, 1, 16 },
{ "r_precache", "enable/disable the pre-level caching routine", (void *)&ud.config.useprecache, CVAR_BOOL, 0, 1 },
{ "r_ambientlight", "sets the global map light level",(void *)&r_ambientlight, CVAR_FLOAT|CVAR_FUNCPTR, 0, 10 },
diff --git a/source/duke3d/src/premap.cpp b/source/duke3d/src/premap.cpp
index c9eb2ccff..645822a8a 100644
--- a/source/duke3d/src/premap.cpp
+++ b/source/duke3d/src/premap.cpp
@@ -30,9 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# include "lunatic_game.h"
#endif
-halfdimen_t g_halfScreen;
-int32_t g_halveScreenArea = 0;
-
static int32_t g_whichPalForPlayer = 9;
static uint8_t precachehightile[2][MAXTILES>>3];
@@ -566,19 +563,6 @@ void G_UpdateScreenArea(void)
y2 = ud.returnvar[2];
}
- if (g_halveScreenArea)
- {
- int32_t ourxdimen=x2-x1, ourydimen=y2-y1;
-
- g_halfScreen.x1 = x1;
- g_halfScreen.y1 = y1;
- g_halfScreen.xdimen = (ourxdimen>>1);
- g_halfScreen.ydimen = (ourydimen>>1);
-
- x2 = x1 + (ourxdimen>>1);
- y2 = y1 + (ourydimen>>1);
- }
-
videoSetViewableArea(x1,y1,x2-1,y2-1);
}
@@ -1772,7 +1756,7 @@ int G_EnterLevel(int gameMode)
FX_StopAllSounds();
S_ClearSoundLocks();
FX_SetReverb(0);
- videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP);
+ videoSetGameMode(ud.config.ScreenMode, ud.config.ScreenWidth, ud.config.ScreenHeight, ud.config.ScreenBPP, upscalefactor);
}
if (Menu_HaveUserMap())
diff --git a/source/duke3d/src/premap.h b/source/duke3d/src/premap.h
index 0a0d51e7e..5b554cd51 100644
--- a/source/duke3d/src/premap.h
+++ b/source/duke3d/src/premap.h
@@ -27,14 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
extern "C" {
#endif
-typedef struct {
- int32_t x1, y1;
- int32_t xdimen, ydimen;
-} halfdimen_t;
-
-extern halfdimen_t g_halfScreen;
-extern int32_t g_halveScreenArea;
-
extern int32_t g_levelTextTime;
extern int32_t voting,vote_map,vote_episode;
extern palette_t CrosshairColors;
diff --git a/source/duke3d/src/screens.cpp b/source/duke3d/src/screens.cpp
index fd27c1929..46a60ba79 100644
--- a/source/duke3d/src/screens.cpp
+++ b/source/duke3d/src/screens.cpp
@@ -1212,7 +1212,7 @@ void G_DisplayRest(int32_t smoothratio)
int32_t a = VM_OnEventWithReturn(EVENT_DISPLAYPOINTER, g_player[screenpeek].ps->i, screenpeek, CROSSHAIR);
if ((unsigned) a < MAXTILES)
{
- vec2_t pointerpos = { ud.returnvar[0], ud.returnvar[1] };
+ vec2_t pointerpos = { tabledivide32(ud.returnvar[0], upscalefactor), tabledivide32(ud.returnvar[1], upscalefactor) };
uint8_t pointer_pal = CROSSHAIR_PAL;
uint32_t pointer_o = 1|2;
uint32_t pointer_scale = 65536;