Well, this is kind of embarrassing, I did some changes and everything went well but restoring the low detail modes wasn't as easy as i expected. The engine has seen a good amount of changes in 9 years. So now it compiles and links but crashes as soon as i start a new game with a divide by zero error. Actually i expected that. I've been trying to debug this with some breakpoints but crashes earlier, i really don't know where to start.
It's mostly done but I don't understand this code very well partly due to the lack of comments and i've been guessing here and there, i'm not familiar with global variables either.
There has been some remodularization (r_utility) and important changes to the status bar code. I think the use of realviewwidth/realviewheight and viewwidth/viewheight as well as detailxshift/detailyshift is a problem.
So i'm afraid i need help to fix this, a hand from one of the developers would be greatly appreciated but obviously i know i cannot count on it. Any experienced programmer with some knowledge of the ZDoom/Doom engine could be of help. I know some c++ but sadly i think i'm not up to the task.
I've uploaded the thing to GitHub and i'm attaching a diff patch with the latest changes to be applied with gnu32 patch, as i've mentioned i think this is mostly done and would be great if someone could have a look at this patch and give some hints of finish the job. I've added a preliminary quad horiz and double vert mode (i don't expect it to work) to allow the original low detail mode from higher resolutions and would be playable @320 for a somewhat cool retro look.
May be i could/should create a branch with the detail changes, i still don't know very well how git works. Thanks in advance.
https://github.com/drfrag666/ZDoom-LE
Code: Select all
diff -rupN zdoom-le/src/am_map.cpp zdoom-maint/src/am_map.cpp
--- zdoom-le/src/am_map.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/am_map.cpp 2017-02-26 12:25:33.148416900 +0100
@@ -3030,8 +3030,8 @@ void AM_Drawer ()
{
f_x = viewwindowx;
f_y = viewwindowy;
- f_w = viewwidth;
- f_h = viewheight;
+ f_w = realviewwidth;
+ f_h = realviewheight;
f_p = screen->GetPitch ();
}
AM_activateNewScale();
diff -rupN zdoom-le/src/asm_ia32/misc.asm zdoom-maint/src/asm_ia32/misc.asm
--- zdoom-le/src/asm_ia32/misc.asm 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/asm_ia32/misc.asm 2017-02-28 12:51:59.968971400 +0100
@@ -37,6 +37,9 @@ BITS 32
%define DoBlending_MMX _DoBlending_MMX
%define BestColor_MMX _BestColor_MMX
+%define DoubleHoriz_MMX _DoubleHoriz_MMX
+%define DoubleHorizVert_MMX _DoubleHorizVert_MMX
+%define DoubleVert_ASM _DoubleVert_ASM
%endif
@@ -198,3 +201,182 @@ BestColor_MMX:
pop ebx
emms
ret
+
+;-----------------------------------------------------------
+;
+; DoubleHoriz_MMX
+;
+; Stretches an image horizontally using MMX instructions.
+; The source image is assumed to occupy the right half
+; of the destination image.
+;
+; height of source
+; width of source
+; dest pointer (at end of row)
+; pitch
+;
+;-----------------------------------------------------------
+
+GLOBAL DoubleHoriz_MMX
+
+DoubleHoriz_MMX:
+ mov edx,[esp+8] ; edx = width
+ push edi
+
+ neg edx ; make edx negative so we can count up
+ mov edi,[esp+16] ; edi = dest pointer
+
+ sar edx,2 ; and make edx count groups of 4 pixels
+ push ebp
+
+ mov ebp,edx ; ebp = # of columns remaining in this row
+ push ebx
+
+ mov ebx,[esp+28] ; ebx = pitch
+ mov ecx,[esp+16] ; ecx = # of rows remaining
+
+.loop movq mm0,[edi+ebp*4]
+
+.loop2 movq mm1,mm0
+ punpcklbw mm0,mm0 ; double left 4 pixels
+
+ movq mm2,[edi+ebp*4+8]
+ punpckhbw mm1,mm1 ; double right 4 pixels
+
+ movq [edi+ebp*8],mm0 ; write left pixels
+ movq mm0,mm2
+
+ movq [edi+ebp*8+8],mm1 ; write right pixels
+
+ add ebp,2 ; increment counter
+ jnz .loop2 ; repeat until done with this row
+
+
+ add edi,ebx ; move edi to next row
+ dec ecx ; decrease row counter
+
+ mov ebp,edx ; prep ebp for next row
+ jnz .loop ; repeat until every row is done
+
+ emms
+ pop ebx
+ pop ebp
+ pop edi
+ ret
+
+;-----------------------------------------------------------
+;
+; DoubleHorizVert_MMX
+;
+; Stretches an image horizontally and vertically using
+; MMX instructions. The source image is assumed to occupy
+; the right half of the destination image and to leave
+; every other line unused for expansion.
+;
+; height of source
+; width of source
+; dest pointer (at end of row)
+; pitch
+;
+;-----------------------------------------------------------
+
+GLOBAL DoubleHorizVert_MMX
+
+DoubleHorizVert_MMX:
+ mov edx,[esp+8] ; edx = width
+ push edi
+
+ neg edx ; make edx negative so we can count up
+ mov edi,[esp+16] ; edi = dest pointer
+
+ sar edx,2 ; and make edx count groups of 4 pixels
+ push ebp
+
+ mov ebp,edx ; ebp = # of columns remaining in this row
+ push ebx
+
+ mov ebx,[esp+28] ; ebx = pitch
+ mov ecx,[esp+16] ; ecx = # of rows remaining
+
+ push esi
+ lea esi,[edi+ebx]
+
+.loop movq mm0,[edi+ebp*4] ; get 8 pixels
+
+ movq mm1,mm0
+ punpcklbw mm0,mm0 ; double left 4
+
+ punpckhbw mm1,mm1 ; double right 4
+ add ebp,2 ; increment counter
+
+ movq [edi+ebp*8-16],mm0 ; write them back out
+
+ movq [edi+ebp*8-8],mm1
+
+ movq [esi+ebp*8-16],mm0
+
+ movq [esi+ebp*8-8],mm1
+
+ jnz .loop ; repeat until done with this row
+
+ lea edi,[edi+ebx*2] ; move edi and esi to next row
+ lea esi,[esi+ebx*2]
+
+ dec ecx ; decrease row counter
+ mov ebp,edx ; prep ebp for next row
+
+ jnz .loop ; repeat until every row is done
+
+ emms
+ pop esi
+ pop ebx
+ pop ebp
+ pop edi
+ ret
+
+;-----------------------------------------------------------
+;
+; DoubleVert_ASM
+;
+; Stretches an image vertically using regular x86
+; instructions. The source image should be interleaved.
+;
+; height of source
+; width of source
+; source/dest pointer
+; pitch
+;
+;-----------------------------------------------------------
+
+GLOBAL DoubleVert_ASM
+
+DoubleVert_ASM:
+ mov edx,[esp+16] ; edx = pitch
+ mov eax,[esp+4] ; eax = # of rows left
+
+ push esi
+ mov esi,[esp+16]
+
+ push edi
+ lea edi,[esi+edx]
+
+ shl edx,1 ; edx = pitch*2
+ mov ecx,[esp+16]
+
+ sub edx,ecx ; edx = dist from end of one line to start of next
+ shr ecx,2
+
+.loop rep movsd
+
+ mov ecx,[esp+16]
+ add esi,edx
+
+ add edi,edx
+ shr ecx,2
+
+ dec eax
+ jnz .loop
+
+ pop edi
+ pop esi
+ ret
diff -rupN zdoom-le/src/asm_ia32/tmap.asm zdoom-maint/src/asm_ia32/tmap.asm
--- zdoom-le/src/asm_ia32/tmap.asm 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/asm_ia32/tmap.asm 2017-02-26 12:25:34.910517700 +0100
@@ -51,7 +51,7 @@ FUZZTABLE equ 50
%define fuzzpos _fuzzpos
%define fuzzoffset _fuzzoffset
%define NormalLight _NormalLight
-%define viewheight _viewheight
+%define realviewheight _realviewheight
%define fuzzviewheight _fuzzviewheight
%define CPU _CPU
@@ -103,7 +103,7 @@ EXTERN centery
EXTERN fuzzpos
EXTERN fuzzoffset
EXTERN NormalLight
-EXTERN viewheight
+EXTERN realviewheight
EXTERN fuzzviewheight
EXTERN CPU
diff -rupN zdoom-le/src/ct_chat.cpp zdoom-maint/src/ct_chat.cpp
--- zdoom-le/src/ct_chat.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/ct_chat.cpp 2017-02-26 12:25:36.960634900 +0100
@@ -238,7 +238,7 @@ void CT_Drawer (void)
int screen_height = con_scaletext > 1? SCREENHEIGHT/2 : SCREENHEIGHT;
int st_y = con_scaletext > 1? ST_Y/2 : ST_Y;
- y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y;
+ y += ((SCREENHEIGHT == realviewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y;
promptwidth = SmallFont->StringWidth (prompt) * scalex;
x = SmallFont->GetCharWidth ('_') * scalex * 2 + promptwidth;
diff -rupN zdoom-le/src/d_main.cpp zdoom-maint/src/d_main.cpp
--- zdoom-le/src/d_main.cpp 2017-02-24 21:45:43.962225500 +0100
+++ zdoom-maint/src/d_main.cpp 2017-03-05 00:28:00.701817800 +0100
@@ -762,7 +762,7 @@ void D_Display ()
StatusBar->BlendView (blend);
}
screen->SetBlendingRect(viewwindowx, viewwindowy,
- viewwindowx + viewwidth, viewwindowy + viewheight);
+ viewwindowx + realviewwidth, viewwindowy + realviewheight);
Renderer->RenderView(&players[consoleplayer]);
@@ -777,9 +777,9 @@ void D_Display ()
if (automapactive)
{
int saved_ST_Y = ST_Y;
- if (hud_althud && viewheight == SCREENHEIGHT)
+ if (hud_althud && realviewheight == SCREENHEIGHT)
{
- ST_Y = viewheight;
+ ST_Y = realviewheight;
}
AM_Drawer ();
ST_Y = saved_ST_Y;
@@ -789,7 +789,7 @@ void D_Display ()
V_RefreshViewBorder ();
}
- if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
+ if (hud_althud && realviewheight == SCREENHEIGHT && screenblocks > 10)
{
StatusBar->DrawBottomStuff (HUD_AltHud);
if (DrawFSHUD || automapactive) DrawHUD();
@@ -797,7 +797,7 @@ void D_Display ()
StatusBar->DrawTopStuff (HUD_AltHud);
}
else
- if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
+ if (realviewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
{
EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None;
StatusBar->DrawBottomStuff (state);
diff -rupN zdoom-le/src/doomstat.h zdoom-maint/src/doomstat.h
--- zdoom-le/src/doomstat.h 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/doomstat.h 2017-02-26 12:30:44.021197800 +0100
@@ -122,7 +122,10 @@ extern int viewwindowy;
extern "C" int viewheight;
extern "C" int viewwidth;
extern "C" int halfviewwidth; // [RH] Half view width, for plane drawing
-
+extern "C" int realviewwidth; // [RH] Physical width of view window
+extern "C" int realviewheight; // [RH] Physical height of view window
+extern "C" int detailxshift; // [RH] X shift for horizontal detail level
+extern "C" int detailyshift; // [RH] Y shift for vertical detail level
diff -rupN zdoom-le/src/g_shared/shared_sbar.cpp zdoom-maint/src/g_shared/shared_sbar.cpp
--- zdoom-le/src/g_shared/shared_sbar.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/g_shared/shared_sbar.cpp 2017-02-26 12:47:49.952877700 +0100
@@ -1185,8 +1185,8 @@ void DBaseStatusBar::DrawCrosshair ()
}
screen->DrawTexture (CrosshairImage,
- viewwidth / 2 + viewwindowx,
- viewheight / 2 + viewwindowy,
+ realviewwidth / 2 + viewwindowx,
+ realviewheight / 2 + viewwindowy,
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_AlphaChannel, true,
diff -rupN zdoom-le/src/menu/menu.cpp zdoom-maint/src/menu/menu.cpp
--- zdoom-le/src/menu/menu.cpp 2017-02-23 15:03:12.575603700 +0100
+++ zdoom-maint/src/menu/menu.cpp 2017-03-07 10:16:44.881858300 +0100
@@ -715,7 +715,11 @@ void M_Drawer (void)
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
{
- if (DMenu::CurrentMenu->DimAllowed()) screen->Dim(fade);
+ if (DMenu::CurrentMenu->DimAllowed())
+ {
+ screen->Dim(fade);
+ V_SetBorderNeedRefresh();
+ }
DMenu::CurrentMenu->Drawer();
}
}
diff -rupN zdoom-le/src/r_draw.cpp zdoom-maint/src/r_draw.cpp
--- zdoom-le/src/r_draw.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_draw.cpp 2017-03-08 11:12:00.240263800 +0100
@@ -52,7 +52,7 @@ extern int ST_Y;
//
// All drawing to the view buffer is accomplished in this file.
-// The other refresh files only know about ccordinates,
+// The other refresh files only know about coordinates,
// not the architecture of the frame buffer.
// Conveniently, the frame buffer is a linear one,
// and we need only the base address,
@@ -67,6 +67,19 @@ BYTE *dc_destorg;
}
int scaledviewwidth;
+extern "C" {
+int realviewwidth; // [RH] Physical width of view window
+int realviewheight; // [RH] Physical height of view window
+int detailxshift; // [RH] X shift for horizontal detail level
+int detailyshift; // [RH] Y shift for vertical detail level
+}
+
+#ifdef X86_ASM
+extern "C" void STACK_ARGS DoubleHoriz_MMX (int height, int width, BYTE *dest, int pitch);
+extern "C" void STACK_ARGS DoubleHorizVert_MMX (int height, int width, BYTE *dest, int pitch);
+extern "C" void STACK_ARGS DoubleVert_ASM (int height, int width, BYTE *dest, int pitch);
+#endif
+
// [RH] Pointers to the different column drawers.
// These get changed depending on the current
// screen depth and asm/no asm.
@@ -117,6 +130,8 @@ const BYTE* bufplce[4];
int dccount;
}
+cycle_t DetailDoubleCycles;
+
int dc_fillcolor;
BYTE *dc_translation;
BYTE shadetables[NUMCOLORMAPS*16*256];
@@ -2165,6 +2180,132 @@ const BYTE *R_GetColumn (FTexture *tex,
}
+// [RH] Double pixels in the view window horizontally
+// and/or vertically (or not at all).
+void R_DetailDouble ()
+{
+ if (!viewactive) return;
+ DetailDoubleCycles.Reset();
+ DetailDoubleCycles.Clock();
+
+ switch ((detailxshift << 1) | detailyshift)
+ {
+ case 1: // y-double
+#ifdef X86_ASM
+ DoubleVert_ASM (viewheight, viewwidth, dc_destorg, RenderTarget->GetPitch());
+#else
+ {
+ int rowsize = realviewwidth;
+ int pitch = RenderTarget->GetPitch();
+ int y;
+ BYTE *line;
+
+ line = dc_destorg;
+ for (y = viewheight; y != 0; --y, line += pitch<<1)
+ {
+ memcpy (line+pitch, line, rowsize);
+ }
+ }
+#endif
+ break;
+
+ case 2: // x-double
+#ifdef X86_ASM
+ if (CPU.bMMX && (viewwidth&15)==0)
+ {
+ DoubleHoriz_MMX (viewheight, viewwidth, dc_destorg+viewwidth, RenderTarget->GetPitch());
+ }
+ else
+#endif
+ {
+ int rowsize = viewwidth;
+ int pitch = RenderTarget->GetPitch();
+ int y,x;
+ BYTE *linefrom, *lineto;
+
+ linefrom = dc_destorg;
+ for (y = viewheight; y != 0; --y, linefrom += pitch)
+ {
+ lineto = linefrom - viewwidth;
+ for (x = 0; x < rowsize; ++x)
+ {
+ BYTE c = linefrom[x];
+ lineto[x*2] = c;
+ lineto[x*2+1] = c;
+ }
+ }
+ }
+ break;
+
+ case 3: // x- and y-double
+#ifdef X86_ASM
+ if (CPU.bMMX && (viewwidth&15)==0 && 0)
+ {
+ DoubleHorizVert_MMX (viewheight, viewwidth, dc_destorg+viewwidth, RenderTarget->GetPitch());
+ }
+ else
+#endif
+ {
+ int rowsize = viewwidth;
+ int realpitch = RenderTarget->GetPitch();
+ int pitch = realpitch << 1;
+ int y,x;
+ BYTE *linefrom, *lineto;
+
+ linefrom = dc_destorg;
+ for (y = viewheight; y != 0; --y, linefrom += pitch)
+ {
+ lineto = linefrom - viewwidth;
+ for (x = 0; x < rowsize; ++x)
+ {
+ BYTE c = linefrom[x];
+ lineto[x*2] = c;
+ lineto[x*2+1] = c;
+ lineto[x*2+realpitch] = c;
+ lineto[x*2+realpitch+1] = c;
+ }
+ }
+ }
+ break;
+
+ case 5: // x-quad and y-double placeholder
+ {
+ int rowsize = viewwidth;
+ int realpitch = RenderTarget->GetPitch();
+ int pitch = realpitch << 1;
+ int y,x;
+ BYTE *linefrom, *lineto;
+
+ linefrom = dc_destorg;
+ for (y = viewheight; y != 0; --y, linefrom += pitch)
+ {
+ lineto = linefrom - viewwidth;
+ for (x = 0; x < rowsize; ++x)
+ {
+ BYTE c = linefrom[x];
+ lineto[x*4] = c;
+ lineto[x*4+1] = c;
+ lineto[x*4+2] = c;
+ lineto[x*4+3] = c;
+ lineto[x*4+realpitch] = c;
+ lineto[x*4+realpitch+1] = c;
+ lineto[x*4+realpitch+2] = c;
+ lineto[x*4+realpitch+3] = c;
+ }
+ }
+ }
+ break;
+ }
+ DetailDoubleCycles.Unclock();
+}
+
+ADD_STAT(detail)
+{
+ FString out;
+ out.Format ("doubling = %04.1f ms", DetailDoubleCycles.TimeMS());
+ return out;
+}
+
// [RH] Initialize the column drawer pointers
void R_InitColumnDrawers ()
{
diff -rupN zdoom-le/src/r_draw.h zdoom-maint/src/r_draw.h
--- zdoom-le/src/r_draw.h 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_draw.h 2017-02-26 20:13:57.297240700 +0100
@@ -257,6 +257,9 @@ extern FDynamicColormap ShadeFakeColorma
extern BYTE identitymap[256];
extern BYTE *dc_translation;
+// [RH] Double view pixels by detail mode
+void R_DetailDouble (void);
+
// [RH] Added for muliresolution support
void R_InitShadeMaps();
void R_InitFuzzTable (int fuzzoff);
diff -rupN zdoom-le/src/r_main.cpp zdoom-maint/src/r_main.cpp
--- zdoom-le/src/r_main.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_main.cpp 2017-03-08 10:09:06.784608100 +0100
@@ -146,6 +146,8 @@ angle_t xtoviewangle[MAXWIDTH+1];
bool foggy; // [RH] ignore extralight and fullbright?
int r_actualextralight;
+extern int setdetail; // Defined in r_utility.cpp
+
void (*colfunc) (void);
void (*basecolfunc) (void);
void (*fuzzcolfunc) (void);
@@ -275,8 +277,8 @@ void R_SetVisibility (float vis)
else
r_WallVisibility = r_BaseVisibility;
- r_WallVisibility = FixedMul (Scale (InvZtoScale, SCREENWIDTH*BaseRatioSizes[WidescreenRatio][1],
- viewwidth*SCREENHEIGHT*3), FixedMul (r_WallVisibility, FocalTangent));
+ r_WallVisibility = FixedMul (Scale (InvZtoScale, SCREENWIDTH*(BaseRatioSizes[WidescreenRatio][1]<<detailyshift),
+ (viewwidth<<detailxshift)*SCREENHEIGHT*3), FixedMul (r_WallVisibility, FocalTangent));
// Prevent overflow on floors/ceilings. Note that the calculation of
// MaxVisForFloor means that planes less than two units from the player's
@@ -334,6 +336,38 @@ CCMD (r_visibility)
//==========================================================================
//
+// CVAR r_detail
+//
+// Selects a pixel doubling mode
+//
+//==========================================================================
+
+CUSTOM_CVAR (Int, r_detail, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
+{
+ static bool badrecovery = false;
+
+ if (badrecovery)
+ {
+ badrecovery = false;
+ return;
+ }
+
+ if (self < 0 || self > 5 || self == 4)
+ {
+ Printf ("Bad detail mode. (Use 0-3)\n");
+ badrecovery = true;
+ self = (detailyshift << 1) | detailxshift;
+ return;
+ }
+
+ setdetail = self;
+ setsizeneeded = true;
+}
+
+void R_SetDetail (int detail);
+
+//==========================================================================
+//
// R_SetWindow
//
//==========================================================================
@@ -342,6 +376,12 @@ void R_SWRSetWindow(int windowSize, int
{
int virtheight, virtwidth, virtwidth2, virtheight2;
+ viewwidth = realviewwidth >> detailxshift;
+ viewheight = realviewheight >> detailyshift;
+ fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to
+ freelookviewheight >>= detailyshift;
+ halfviewwidth = (viewwidth >> 1) - 1;
+
if (!bRenderingToCanvas)
{ // Set r_viewsize cvar to reflect the current view size
UCVarValue value;
@@ -352,15 +392,14 @@ void R_SWRSetWindow(int windowSize, int
r_viewsize.ForceSet (value, CVAR_String);
}
- fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to
- halfviewwidth = (viewwidth >> 1) - 1;
-
lastcenteryfrac = 1<<30;
+ centery = viewheight/2;
+ centerx = viewwidth/2;
centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS;
- virtwidth = virtwidth2 = fullWidth;
- virtheight = virtheight2 = fullHeight;
+ virtwidth = virtwidth2 = fullWidth >> detailxshift;
+ virtheight = virtheight2 = fullHeight >> detailyshift;
if (Is54Aspect(trueratio))
{
@@ -397,8 +436,8 @@ void R_SWRSetWindow(int windowSize, int
R_InitTextureMapping ();
- MaxVisForWall = FixedMul (Scale (InvZtoScale, SCREENWIDTH*r_Yaspect,
- viewwidth*SCREENHEIGHT), FocalTangent);
+ MaxVisForWall = FixedMul (Scale (InvZtoScale, SCREENWIDTH*(r_Yaspect<<detailyshift),
+ (viewwidth<<detailxshift)*SCREENHEIGHT), FocalTangent);
MaxVisForWall = FixedDiv (0x7fff0000, MaxVisForWall);
MaxVisForFloor = Scale (FixedDiv (0x7fff0000, viewheight<<(FRACBITS-2)), FocalLengthY, 160*FRACUNIT);
@@ -422,6 +461,7 @@ CUSTOM_CVAR (Int, r_columnmethod, 1, CVA
}
else
{ // Trigger the change
+ r_detail.Callback ();
setsizeneeded = true;
}
}
@@ -706,13 +746,22 @@ void R_EnterMirror (drawseg_t *ds, int d
//
//==========================================================================
-void R_SetupBuffer ()
+void R_SetupBuffer (bool inview)
{
static BYTE *lastbuff = NULL;
int pitch = RenderTarget->GetPitch();
BYTE *lineptr = RenderTarget->GetBuffer() + viewwindowy*pitch + viewwindowx;
+ if (inview)
+ {
+ pitch <<= detailyshift;
+ }
+ if (detailxshift)
+ {
+ lineptr += viewwidth;
+ }
+
if (dc_pitch != pitch || lineptr != lastbuff)
{
if (dc_pitch != pitch)
@@ -747,7 +796,7 @@ void R_RenderActorView (AActor *actor, b
fakeActive = 0; // kg3D - reset fake floor indicator
R_3D_ResetClip(); // reset clips (floor/ceiling)
- R_SetupBuffer ();
+ R_SetupBuffer (true);
R_SetupFrame (actor);
// Clear buffers.
@@ -829,7 +878,15 @@ void R_RenderActorView (AActor *actor, b
}
WallMirrors.Clear ();
interpolator.RestoreInterpolations ();
- R_SetupBuffer ();
+
+ // If there is vertical doubling, and the view window is not an even height,
+ // draw a black line at the bottom of the view window.
+ if (detailyshift && viewwindowy == 0 && (realviewheight & 1))
+ {
+ screen->Clear (0, realviewheight-1, realviewwidth, realviewheight, 0, 0);
+ }
+
+ R_SetupBuffer (false);
// If we don't want shadered colormaps, NULL it now so that the
// copy to the screen does not use a special colormap shader.
@@ -850,12 +907,15 @@ void R_RenderActorView (AActor *actor, b
void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas,
int x, int y, int width, int height, bool dontmaplines)
{
+ const int saveddetail = detailxshift | (detailyshift << 1);
const bool savedviewactive = viewactive;
- viewwidth = width;
+ detailxshift = detailyshift = 0;
+ realviewwidth = viewwidth = width;
RenderTarget = canvas;
bRenderingToCanvas = true;
+ R_SetDetail (0);
R_SetWindow (12, width, height, height);
viewwindowx = x;
viewwindowy = y;
@@ -865,9 +925,10 @@ void R_RenderViewToCanvas (AActor *actor
RenderTarget = screen;
bRenderingToCanvas = false;
+ R_SetDetail (saveddetail);
R_ExecuteSetViewSize ();
screen->Lock (true);
- R_SetupBuffer ();
+ R_SetupBuffer (false);
screen->Unlock ();
viewactive = savedviewactive;
}
diff -rupN zdoom-le/src/r_main.h zdoom-maint/src/r_main.h
--- zdoom-le/src/r_main.h 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_main.h 2017-02-27 00:51:36.702162700 +0100
@@ -129,7 +129,7 @@ void R_InitTextureMapping ();
// Called by G_Drawer.
void R_RenderActorView (AActor *actor, bool dontmaplines = false);
-void R_SetupBuffer ();
+void R_SetupBuffer (bool inview);
void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines = false);
diff -rupN zdoom-le/src/r_plane.cpp zdoom-maint/src/r_plane.cpp
--- zdoom-le/src/r_plane.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_plane.cpp 2017-02-27 00:57:05.190951200 +0100
@@ -536,7 +536,7 @@ void R_ClearPlanes (bool fullclear)
// [RH] clip ceiling to console bottom
clearbufshort (ceilingclip, viewwidth,
!screen->Accel2D && ConBottom > viewwindowy && !bRenderingToCanvas
- ? (ConBottom - viewwindowy) : 0);
+ ? ((ConBottom - viewwindowy) >> detailyshift) : 0);
lastopening = 0;
}
diff -rupN zdoom-le/src/r_sky.cpp zdoom-maint/src/r_sky.cpp
--- zdoom-le/src/r_sky.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_sky.cpp 2017-02-27 11:33:40.865297200 +0100
@@ -54,6 +54,7 @@ CUSTOM_CVAR (Bool, r_stretchsky, true, C
R_InitSkyMap ();
}
+extern "C" int detailxshift, detailyshift;
fixed_t freelookviewheight;
//==========================================================================
@@ -112,8 +113,8 @@ void R_InitSkyMap ()
if (viewwidth != 0 && viewheight != 0)
{
- skyiscale = (r_Yaspect*FRACUNIT) / ((freelookviewheight * viewwidth) / viewwidth);
- skyscale = (((freelookviewheight * viewwidth) / viewwidth) << FRACBITS) /
+ skyiscale = (r_Yaspect*FRACUNIT) / (((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift));
+ skyscale = ((((freelookviewheight<<detailxshift) * viewwidth) / (viewwidth<<detailxshift)) << FRACBITS) /
(r_Yaspect);
skyiscale = Scale (skyiscale, FieldOfView, 2048);
diff -rupN zdoom-le/src/r_state.h zdoom-maint/src/r_state.h
--- zdoom-le/src/r_state.h 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_state.h 2017-02-27 11:35:14.220636800 +0100
@@ -34,7 +34,9 @@
//
extern "C" int viewwidth;
+extern "C" int realviewwidth;
extern "C" int viewheight;
+extern "C" int realviewheight;
//
// Lookup tables for map data.
diff -rupN zdoom-le/src/r_swrenderer.cpp zdoom-maint/src/r_swrenderer.cpp
--- zdoom-le/src/r_swrenderer.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_swrenderer.cpp 2017-03-04 19:02:27.687892100 +0100
@@ -109,6 +109,7 @@ void FSoftwareRenderer::PrecacheTexture(
void FSoftwareRenderer::RenderView(player_t *player)
{
R_RenderActorView (player->mo);
+ R_DetailDouble (); // [RH] Apply detail mode expansion
// [RH] Let cameras draw onto textures that were visible this frame.
FCanvasTextureInfo::UpdateAll ();
}
@@ -188,7 +189,7 @@ void FSoftwareRenderer::OnModeSet ()
RenderTarget = screen;
screen->Lock (true);
- R_SetupBuffer ();
+ R_SetupBuffer (false);
screen->Unlock ();
}
diff -rupN zdoom-le/src/r_things.cpp zdoom-maint/src/r_things.cpp
--- zdoom-le/src/r_things.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_things.cpp 2017-03-06 18:31:25.842789900 +0100
@@ -124,6 +124,7 @@ short screenheightarray[MAXWIDTH];
EXTERN_CVAR (Bool, r_drawplayersprites)
EXTERN_CVAR (Bool, r_drawvoxels)
+EXTERN_CVAR (Int, r_detail)
//
// INITIALIZATION FUNCTIONS
@@ -1224,15 +1225,21 @@ void R_DrawPSprite (pspdef_t* psp, int p
// calculate edges of the shape
tx = sx-((320/2)<<FRACBITS);
- tx -= tex->GetScaledLeftOffset() << FRACBITS;
- x1 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
+ tx -= tex->GetScaledLeftOffset() << FRACBITS;
+ if (r_detail == 0 || r_detail == 2)
+ x1 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
+ else
+ x1 = (centerxfrac + FixedMul (tx, pspritexscale/2)) >>FRACBITS;
// off the right side
if (x1 > viewwidth)
return;
tx += tex->GetScaledWidth() << FRACBITS;
- x2 = ((centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS);
+ if (r_detail == 0 || r_detail == 2)
+ x2 = (centerxfrac + FixedMul (tx, pspritexscale)) >>FRACBITS;
+ else
+ x2 = (centerxfrac + FixedMul (tx, pspritexscale/2)) >>FRACBITS;
// off the left side
if (x2 <= 0)
@@ -1246,7 +1253,7 @@ void R_DrawPSprite (pspdef_t* psp, int p
vis->texturemid = MulScale16((BASEYCENTER<<FRACBITS) - sy, tex->yScale) + (tex->TopOffset << FRACBITS);
if (camera->player && (RenderTarget != screen ||
- viewheight == RenderTarget->GetHeight() ||
+ realviewheight == RenderTarget->GetHeight() ||
(RenderTarget->GetWidth() > 320 && !st_scale)))
{ // Adjust PSprite for fullscreen views
AWeapon *weapon = NULL;
@@ -1256,7 +1263,7 @@ void R_DrawPSprite (pspdef_t* psp, int p
}
if (pspnum <= ps_flash && weapon != NULL && weapon->YAdjust != 0)
{
- if (RenderTarget != screen || viewheight == RenderTarget->GetHeight())
+ if (RenderTarget != screen || realviewheight == RenderTarget->GetHeight())
{
vis->texturemid -= weapon->YAdjust;
}
@@ -1274,19 +1281,28 @@ void R_DrawPSprite (pspdef_t* psp, int p
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth : x2;
vis->xscale = DivScale16(pspritexscale, tex->xScale);
- vis->yscale = DivScale16(pspriteyscale, tex->yScale);
+ if (r_detail == 0 || r_detail == 2)
+ vis->yscale = DivScale16(pspriteyscale, tex->yScale);
+ else
+ vis->yscale = DivScale16(pspriteyscale/2, tex->yScale);
vis->Translation = 0; // [RH] Use default colors
vis->pic = tex;
vis->ColormapNum = 0;
if (flip)
{
- vis->xiscale = -MulScale16(pspritexiscale, tex->xScale);
+ if (r_detail == 0 || r_detail == 2)
+ vis->xiscale = -MulScale16(pspritexiscale, tex->xScale);
+ else
+ vis->xiscale = -MulScale16(pspritexiscale*2, tex->xScale);
vis->startfrac = (tex->GetWidth() << FRACBITS) - 1;
}
else
{
- vis->xiscale = MulScale16(pspritexiscale, tex->xScale);
+ if (r_detail == 0 || r_detail == 2)
+ vis->xiscale = MulScale16(pspritexiscale, tex->xScale);
+ else
+ vis->xiscale = MulScale16(pspritexiscale*2, tex->xScale);
vis->startfrac = 0;
}
@@ -2514,7 +2530,7 @@ void R_DrawParticle (vissprite_t *vis)
fg = fg2rgb[color];
}
- spacing = RenderTarget->GetPitch() - countbase;
+ spacing = (RenderTarget->GetPitch()<<detailyshift) - countbase;
dest = ylookup[yl] + x1 + dc_destorg;
do
diff -rupN zdoom-le/src/r_utility.cpp zdoom-maint/src/r_utility.cpp
--- zdoom-le/src/r_utility.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_utility.cpp 2017-03-07 18:47:05.783755200 +0100
@@ -132,7 +132,7 @@ bool LocalKeyboardTurner;
float LastFOV;
int WidescreenRatio;
-int setblocks;
+int setblocks, setdetail = -1;
int extralight;
bool setsizeneeded;
fixed_t FocalTangent;
@@ -395,6 +395,24 @@ void R_SetViewSize (int blocks)
//==========================================================================
//
+// R_SetDetail
+//
+//==========================================================================
+
+void R_SetDetail (int detail)
+{
+ if (detail != 5) {
+ detailxshift = detail & 1;
+ detailyshift = (detail >> 1) & 1;
+ }
+ else {
+ detailxshift = 2;
+ detailyshift = 1;
+ }
+}
+
+//==========================================================================
+//
// R_SetWindow
//
//==========================================================================
@@ -405,19 +423,19 @@ void R_SetWindow (int windowSize, int fu
if (windowSize >= 11)
{
- viewwidth = fullWidth;
- freelookviewheight = viewheight = fullHeight;
+ realviewwidth = fullWidth;
+ freelookviewheight = realviewheight = fullHeight;
}
else if (windowSize == 10)
{
- viewwidth = fullWidth;
- viewheight = stHeight;
+ realviewwidth = fullWidth;
+ realviewheight = stHeight;
freelookviewheight = fullHeight;
}
else
{
- viewwidth = ((setblocks*fullWidth)/10) & (~15);
- viewheight = ((setblocks*stHeight)/10)&~7;
+ realviewwidth = ((setblocks*fullWidth)/10) & (~15);
+ realviewheight = ((setblocks*stHeight)/10)&~7;
freelookviewheight = ((setblocks*fullHeight)/10)&~7;
}
@@ -429,8 +447,8 @@ void R_SetWindow (int windowSize, int fu
// [RH] Sky height fix for screens not 200 (or 240) pixels tall
R_InitSkyMap ();
- centery = viewheight/2;
- centerx = viewwidth/2;
+ centery = realviewheight/2;
+ centerx = realviewwidth/2;
if (Is54Aspect(WidescreenRatio))
{
centerxwide = centerx;
@@ -467,13 +485,19 @@ void R_ExecuteSetViewSize ()
setsizeneeded = false;
V_SetBorderNeedRefresh();
+ if (setdetail >= 0)
+ {
+ R_SetDetail (setdetail);
+ setdetail = -1;
+ }
+
R_SetWindow (setblocks, SCREENWIDTH, SCREENHEIGHT, ST_Y);
// Handle resize, e.g. smaller view windows with border and/or status bar.
- viewwindowx = (screen->GetWidth() - viewwidth) >> 1;
+ viewwindowx = (screen->GetWidth() - (viewwidth<<detailxshift)) >> 1;
// Same with base row offset.
- viewwindowy = (viewwidth == screen->GetWidth()) ? 0 : (ST_Y - viewheight) >> 1;
+ viewwindowy = ((viewwidth<<detailxshift) == screen->GetWidth()) ? 0 : (ST_Y - (viewheight<<detailyshift)) >> 1;
}
//==========================================================================
diff -rupN zdoom-le/src/r_utility.h zdoom-maint/src/r_utility.h
--- zdoom-le/src/r_utility.h 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/r_utility.h 2017-02-27 00:50:51.467575500 +0100
@@ -19,6 +19,10 @@ extern int viewpitch;
extern "C" int centerx, centerxwide;
extern "C" int centery;
+// [RH] New detail modes
+extern "C" int detailxshift;
+extern "C" int detailyshift;
+
extern int setblocks;
extern fixed_t viewtancos;
diff -rupN zdoom-le/src/s_sound.cpp zdoom-maint/src/s_sound.cpp
--- zdoom-le/src/s_sound.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/s_sound.cpp 2017-03-07 10:12:23.391399100 +0100
@@ -740,8 +740,8 @@ static void CalcPosVel(int type, const A
if (type == SOURCE_Actor && actor != NULL)
{
vel->X = FIXED2FLOAT(actor->velx) * TICRATE;
- vel->Y = FIXED2FLOAT(actor->velz) * TICRATE;
- vel->Z = FIXED2FLOAT(actor->vely) * TICRATE;
+ vel->Y = FIXED2FLOAT(actor->vely) * TICRATE;
+ vel->Z = FIXED2FLOAT(actor->velz) * TICRATE;
}
else
{
diff -rupN zdoom-le/src/v_draw.cpp zdoom-maint/src/v_draw.cpp
--- zdoom-le/src/v_draw.cpp 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/src/v_draw.cpp 2017-02-26 12:45:50.287033200 +0100
@@ -1499,17 +1499,17 @@ static void V_DrawViewBorder (void)
ST_SetNeedRefresh();
}
- if (viewwidth == SCREENWIDTH)
+ if (realviewwidth == SCREENWIDTH)
{
return;
}
V_DrawBorder (0, 0, SCREENWIDTH, viewwindowy);
- V_DrawBorder (0, viewwindowy, viewwindowx, viewheight + viewwindowy);
- V_DrawBorder (viewwindowx + viewwidth, viewwindowy, SCREENWIDTH, viewheight + viewwindowy);
- V_DrawBorder (0, viewwindowy + viewheight, SCREENWIDTH, ST_Y);
+ V_DrawBorder (0, viewwindowy, viewwindowx, realviewheight + viewwindowy);
+ V_DrawBorder (viewwindowx + realviewwidth, viewwindowy, SCREENWIDTH, realviewheight + viewwindowy);
+ V_DrawBorder (0, viewwindowy + realviewheight, SCREENWIDTH, ST_Y);
- V_DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
+ V_DrawFrame (viewwindowx, viewwindowy, realviewwidth, realviewheight);
V_MarkRect (0, 0, SCREENWIDTH, ST_Y);
}
@@ -1526,7 +1526,7 @@ static void V_DrawTopBorder ()
FTexture *p;
int offset;
- if (viewwidth == SCREENWIDTH)
+ if (realviewwidth == SCREENWIDTH)
return;
offset = gameinfo.Border.offset;
@@ -1534,24 +1534,24 @@ static void V_DrawTopBorder ()
if (viewwindowy < 34)
{
V_DrawBorder (0, 0, viewwindowx, 34);
- V_DrawBorder (viewwindowx, 0, viewwindowx + viewwidth, viewwindowy);
- V_DrawBorder (viewwindowx + viewwidth, 0, SCREENWIDTH, 34);
+ V_DrawBorder (viewwindowx, 0, viewwindowx + realviewwidth, viewwindowy);
+ V_DrawBorder (viewwindowx + realviewwidth, 0, SCREENWIDTH, 34);
p = TexMan(gameinfo.Border.t);
screen->FlatFill(viewwindowx, viewwindowy - p->GetHeight(),
- viewwindowx + viewwidth, viewwindowy, p, true);
+ viewwindowx + realviewwidth, viewwindowy, p, true);
p = TexMan(gameinfo.Border.l);
screen->FlatFill(viewwindowx - p->GetWidth(), viewwindowy,
viewwindowx, 35, p, true);
p = TexMan(gameinfo.Border.r);
- screen->FlatFill(viewwindowx + viewwidth, viewwindowy,
- viewwindowx + viewwidth + p->GetWidth(), 35, p, true);
+ screen->FlatFill(viewwindowx + realviewwidth, viewwindowy,
+ viewwindowx + realviewwidth + p->GetWidth(), 35, p, true);
p = TexMan(gameinfo.Border.tl);
screen->DrawTexture (p, viewwindowx - offset, viewwindowy - offset, TAG_DONE);
p = TexMan(gameinfo.Border.tr);
- screen->DrawTexture (p, viewwindowx + viewwidth, viewwindowy - offset, TAG_DONE);
+ screen->DrawTexture (p, viewwindowx + realviewwidth, viewwindowy - offset, TAG_DONE);
}
else
{
diff -rupN zdoom-le/wadsrc/static/menudef.txt zdoom-maint/wadsrc/static/menudef.txt
--- zdoom-le/wadsrc/static/menudef.txt 2016-04-18 10:59:02.000000000 +0200
+++ zdoom-maint/wadsrc/static/menudef.txt 2017-03-06 21:29:42.384634700 +0100
@@ -594,6 +594,15 @@ OptionMenu "JoystickConfigMenu"
//
//-------------------------------------------------------------------------------------------
+OptionValue DetailModes
+{
+ 0.0, "High"
+ 1.0, "Double Horizontally"
+ 2.0, "Double Vertically"
+ 3.0, "Double Horiz and Vert"
+ 5.0, "Quad Horiz and Double Vert"
+}
+
OptionValue ColumnMethods
{
0.0, "Original"
@@ -661,7 +670,8 @@ OptionMenu "VideoOptions"
Option "Vertical Sync", "vid_vsync", "OnOff"
Option "Rendering Interpolation", "cl_capfps", "OffOn"
Option "Column render mode", "r_columnmethod", "ColumnMethods"
-
+ Option "Detail mode", "r_detail", "DetailModes"
+
StaticText " "
Option "Screen wipe style", "wipetype", "Wipes"