Preserve current legacy presentation and options improvements

This commit is contained in:
raptorreplica committed 2026-10-10 11:07:37 +11:00
1 parent 214789fe87
commit eee082f2ad
15 files changed
+1090 -73

No files matched your search

+3
View File
@@ -183,6 +183,9 @@ ANIMS_Init(
// SUPER SHIELD
ANIMS_Register(FILE149_SHIPGLOW_BLK, 4, HIGH_AIR, 1, 1, A_NORM);
// MACHINE-GUN EJECTA (world-space casing streaks, GUNSTR art)
ANIMS_Register(FILE1c7_GUNSTR_BLK, 4, GROUND, 0, 0, A_NORM);
}
/***************************************************************************
+5
View File
@@ -70,6 +70,11 @@ typedef struct ANIMS_S
#define A_ENERGY_GRAB 19
#define A_SUPER_SHIELD 20
// Machine-gun ejecta: same GUNSTR streak art dropped into world space at
// the wingtips (ground layer, drifts with the map scroll) so casings stay
// behind the plane instead of flicking in place at the gun.
#define A_PLAYER_EJECTA 21
void ANIMS_Clear(void);
ANIMS *ANIMS_Remove(ANIMS *anim);
void ANIMS_Init(void);
+162
View File
@@ -0,0 +1,162 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// AdvMAME scale2x/scale3x filters by Andrea Mazzoleni, reimplemented
// in-repo (GPLv2+, same license as the project). Each source pixel E
// with its neighbors
//
// A B C
// D E F
// G H I
//
// expands to a 2x2 (scale2x) or 3x3 (scale3x) block of output pixels.
// Factor 4 is scale2x applied twice, the reference composition.
//
#include <stdlib.h>
#include "common.h"
#include "i_upscale.h"
// Exact per-byte average of two packed RGBA pixels: the common bits plus
// half the differing bits. The mask keeps the halving inside each byte
// lane, so no carry crosses channels and no unpacking is needed.
static uint32_t pixel_blend(uint32_t x, uint32_t y)
{
return (x & y) + (((x ^ y) >> 1) & 0x7f7f7f7f);
}
static void scale2x_pass(const uint32_t *src, int spitch, int w, int h,
uint32_t *dst, int dpitch)
{
int x, y;
for (y = 0; y < h; ++y)
{
const uint32_t *row = src + y * spitch;
const uint32_t *above = y > 0 ? row - spitch : row;
const uint32_t *below = y < h - 1 ? row + spitch : row;
uint32_t *out0 = dst + (y * 2) * dpitch;
uint32_t *out1 = dst + (y * 2 + 1) * dpitch;
for (x = 0; x < w; ++x)
{
// Out-of-bounds neighbors are treated as E (edges of the
// above/below row aliases and of the x clamp do exactly that).
uint32_t E = row[x];
uint32_t B = above[x];
uint32_t H = below[x];
uint32_t D = x > 0 ? row[x - 1] : E;
uint32_t F = x < w - 1 ? row[x + 1] : E;
uint32_t a, b, c, d;
a = (D == B && D != H && B != F) ? D : E;
b = (B == F && B != D && F != H) ? B : E;
c = (D == H && D != B && H != F) ? D : E;
d = (H == F && H != D && F != B) ? F : E;
out0[x * 2] = a;
out0[x * 2 + 1] = b;
out1[x * 2] = c;
out1[x * 2 + 1] = d;
}
}
}
static void scale3x_pass(const uint32_t *src, int spitch, int w, int h,
uint32_t *dst, int dpitch)
{
int x, y;
for (y = 0; y < h; ++y)
{
const uint32_t *row = src + y * spitch;
const uint32_t *above = y > 0 ? row - spitch : row;
const uint32_t *below = y < h - 1 ? row + spitch : row;
uint32_t *out0 = dst + (y * 3) * dpitch;
uint32_t *out1 = dst + (y * 3 + 1) * dpitch;
uint32_t *out2 = dst + (y * 3 + 2) * dpitch;
for (x = 0; x < w; ++x)
{
uint32_t E = row[x];
uint32_t B = above[x];
uint32_t H = below[x];
uint32_t D = x > 0 ? row[x - 1] : E;
uint32_t F = x < w - 1 ? row[x + 1] : E;
uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8;
a4 = E;
a1 = (B == D) ? D : E;
a5 = (B == F) ? F : E;
a7 = (H == F) ? F : E;
a3 = (H == D) ? D : E;
a0 = (B == D && B != F && D != H) ? D
: ((D == B && D == H && F != H && B != F) ? pixel_blend(D, B) : E);
a2 = (B == F && B != D && F != H) ? F
: ((B == F && H == F && D != H && B != D) ? pixel_blend(B, F) : E);
a6 = (D == H && D != B && H != F) ? D
: ((D == H && H == F && B != F && D != B) ? pixel_blend(D, H) : E);
a8 = (H == F && H != D && F != B) ? F
: ((H == F && F == B && D != B && H != D) ? pixel_blend(H, F) : E);
out0[x * 3] = a0;
out0[x * 3 + 1] = a1;
out0[x * 3 + 2] = a2;
out1[x * 3] = a3;
out1[x * 3 + 1] = a4;
out1[x * 3 + 2] = a5;
out2[x * 3] = a6;
out2[x * 3 + 1] = a7;
out2[x * 3 + 2] = a8;
}
}
}
void I_UpscaleFrame(const uint32_t *src, int srcpitch_px, int w, int h,
uint32_t *dst, int dstpitch_px, int factor)
{
if (factor == 2)
{
scale2x_pass(src, srcpitch_px, w, h, dst, dstpitch_px);
}
else if (factor == 3)
{
scale3x_pass(src, srcpitch_px, w, h, dst, dstpitch_px);
}
else if (factor == 4)
{
// scale2x applied twice (640x400x4 = 1 MB temporary).
uint32_t *tmp = (uint32_t *) malloc(sizeof(uint32_t)
* w * 2 * h * 2);
if (tmp == NULL)
{
EXIT_Error("I_UpscaleFrame: memory");
}
scale2x_pass(src, srcpitch_px, w, h, tmp, w * 2);
scale2x_pass(tmp, w * 2, w * 2, h * 2, dst, dstpitch_px);
free(tmp);
}
else
{
EXIT_Error("I_UpscaleFrame: bad factor %d", factor);
}
}
+28
View File
@@ -0,0 +1,28 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Presentation-level pixel-art upscaler (AdvMAME scale2x/scale3x).
//
#pragma once
#include <stdint.h>
// Upscale a w x h 32-bit RGBA frame by factor (2, 3 or 4) into dst, which
// must be w*factor x h*factor pixels. Pitches are in pixels, not bytes;
// the caller converts surface pitches. No SDL dependency, no global state.
void I_UpscaleFrame(const uint32_t *src, int srcpitch_px, int w, int h,
uint32_t *dst, int dstpitch_px, int factor);
+181 -12
View File
@@ -38,6 +38,7 @@
#include "musapi.h"
#include "prefapi.h"
#include "joyapi.h"
#include "i_upscale.h"
// These are (1) the window (or the full screen) that our game is rendered to
// and (2) the renderer that scales the texture (see below) into this window.
@@ -61,6 +62,12 @@ static SDL_Surface *argbbuffer = NULL;
static SDL_Texture *texture = NULL;
static SDL_Texture *texture_upscaled = NULL;
// HD remaster: when the presentation upscaler is active, the filtered
// factor-sized RGBA frame lands here before going into the streaming
// texture.
static SDL_Surface *argbbuffer_scaled = NULL;
static SDL_Rect blit_rect = {
0,
0,
@@ -117,6 +124,13 @@ int fullscreen_width = 0, fullscreen_height = 0;
static int max_scaling_buffer_pixels = 16000000;
// HD remaster: presentation-level pixel-art upscaler (0 = off, else 2/3/4)
// and scanline overlay (0 = off, 1 = on). Read from [Video] upscaler /
// [Video] scanlines in SETUP.INI at boot only; changing them needs a restart.
static int upscale_factor = 3;
static int scanlines = 0;
// Run in full screen mode? (int type for config code)
// int fullscreen = true;
@@ -218,6 +232,14 @@ void VIDEO_LoadPrefs(void)
aspect_ratio_correct = INI_GetPreferenceLong("Video", "aspect_ratio_correct", 1);
txt_fullscreen = INI_GetPreferenceLong("Video", "txt_fullscreen", 0);
borderless = INI_GetPreferenceLong("Video", "borderless", 0);
upscale_factor = INI_GetPreferenceLong("Video", "upscaler", 3);
scanlines = INI_GetPreferenceLong("Video", "scanlines", 0);
if (upscale_factor != 0 && upscale_factor != 2 && upscale_factor != 3
&& upscale_factor != 4)
{
upscale_factor = 3;
}
}
static bool MouseShouldBeGrabbed()
@@ -854,24 +876,64 @@ void I_FinishUpdate (void)
SDL_LowerBlit(screenbuffer, &blit_rect, argbbuffer, &blit_rect);
// Update the intermediate texture with the contents of the RGBA buffer.
if (upscale_factor > 1)
{
// HD remaster path: filter the RGBA frame into the factor-sized
// surface and stream it directly to screen. The source is already
// integer-scaled by the filter, so the nearest-integer intermediate
// (which exists to sharpen sub-integer fits of a 1x source) is not
// used here.
SDL_UpdateTexture(texture, NULL, argbbuffer->pixels, argbbuffer->pitch);
I_UpscaleFrame((uint32_t *) argbbuffer->pixels,
argbbuffer->pitch / 4,
SCREENWIDTH, SCREENHEIGHT,
(uint32_t *) argbbuffer_scaled->pixels,
argbbuffer_scaled->pitch / 4,
upscale_factor);
// Make sure the pillarboxes are kept clear each frame.
SDL_UpdateTexture(texture, NULL, argbbuffer_scaled->pixels,
argbbuffer_scaled->pitch);
SDL_RenderClear(renderer);
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture, NULL, NULL);
}
else
{
// Update the intermediate texture with the contents of the RGBA buffer.
// Render this intermediate texture into the upscaled texture
// using "nearest" integer scaling.
SDL_UpdateTexture(texture, NULL, argbbuffer->pixels, argbbuffer->pitch);
SDL_SetRenderTarget(renderer, texture_upscaled);
SDL_RenderCopy(renderer, texture, NULL, NULL);
// Make sure the pillarboxes are kept clear each frame.
// Finally, render this upscaled texture to screen using linear scaling.
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture_upscaled, NULL, NULL);
// Render this intermediate texture into the upscaled texture
// using "nearest" integer scaling.
SDL_SetRenderTarget(renderer, texture_upscaled);
SDL_RenderCopy(renderer, texture, NULL, NULL);
// Finally, render this upscaled texture to screen using linear scaling.
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture_upscaled, NULL, NULL);
}
if (scanlines)
{
// Scanline overlay: every third logical row darkened. Logical size
// is 320xactualheight, so the lines stay evenly spaced physical rows
// under any window size.
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 70);
for (int y = 1; y < actualheight; y += 3)
{
SDL_RenderDrawLine(renderer, 0, y, SCREENWIDTH, y);
}
}
// Draw!
@@ -1242,6 +1304,7 @@ void I_GetWindowPosition(int *x, int *y, int w, int h)
}
}
static void RebuildStreamTextures(void);
static void SetVideoMode(void)
{
int w, h;
@@ -1452,6 +1515,33 @@ static void SetVideoMode(void)
SDL_FillRect(argbbuffer, NULL, 0);
}
// HD remaster: with the upscaler active, a factor-sized RGBA surface
// feeds the (factor-sized) streaming texture. Freed alongside
// argbbuffer above on every re-init.
RebuildStreamTextures();
}
// Rebuild the factor-sized RGBA surface and the streaming texture that
// carry the frame at the current upscale_factor. Shared by SetVideoMode
// (full re-init) and the runtime filter setter (I_SetVideoFilter).
static void RebuildStreamTextures(void)
{
if (argbbuffer_scaled != NULL)
{
SDL_FreeSurface(argbbuffer_scaled);
argbbuffer_scaled = NULL;
}
if (upscale_factor > 1)
{
argbbuffer_scaled = SDL_CreateRGBSurfaceWithFormat(0,
SCREENWIDTH * upscale_factor,
SCREENHEIGHT * upscale_factor,
32, pixel_format);
SDL_FillRect(argbbuffer_scaled, NULL, 0);
}
if (texture != NULL)
{
SDL_DestroyTexture(texture);
@@ -1470,13 +1560,92 @@ static void SetVideoMode(void)
texture = SDL_CreateTexture(renderer,
pixel_format,
SDL_TEXTUREACCESS_STREAMING,
SCREENWIDTH, SCREENHEIGHT);
upscale_factor > 1
? SCREENWIDTH * upscale_factor
: SCREENWIDTH,
upscale_factor > 1
? SCREENHEIGHT * upscale_factor
: SCREENHEIGHT);
// Initially create the upscaled texture for rendering to screen
CreateUpscaledTexture(true);
}
//**************************************************************************
// Runtime video option setters (in-game Options dialog)
//
// These only touch presentation resources. Never call SetVideoMode() from
// here: it frees and recreates screenbuffer without re-pointing
// I_VideoBuffer, so the game would keep drawing into freed memory.
//**************************************************************************
void I_SetVideoFilter(int factor)
{
if (factor != 0 && factor != 2 && factor != 3 && factor != 4)
return;
if (factor == upscale_factor)
return;
upscale_factor = factor;
RebuildStreamTextures();
}
void I_SetScanlines(int on)
{
scanlines = on ? 1 : 0;
}
void I_SetVideoResolution(int w, int h)
{
if (fullscreen)
I_SetFullscreen(0);
window_width = w;
window_height = h;
AdjustWindowSize();
SDL_SetWindowSize(screen, window_width, window_height);
// The RESIZED event path in I_FinishUpdate adapts the textures.
}
void I_SetFullscreen(int on)
{
fullscreen = on ? 1 : 0;
SDL_SetWindowFullscreen(screen,
fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if (!fullscreen)
{
AdjustWindowSize();
SDL_SetWindowSize(screen, window_width, window_height);
}
}
void I_SetAspectCorrect(int on)
{
aspect_ratio_correct = on ? 1 : 0;
actualheight = aspect_ratio_correct ? SCREENHEIGHT_4_3 : SCREENHEIGHT;
SDL_RenderSetLogicalSize(renderer, SCREENWIDTH, actualheight);
AdjustWindowSize();
SDL_SetWindowSize(screen, window_width, window_height);
CreateUpscaledTexture(false);
palette_to_set = true;
}
int I_GetVideoFilter(void)
{
return upscale_factor;
}
int I_GetScanlines(void)
{
return scanlines;
}
void I_InitGraphics(uint8_t *pal)
{
SDL_Event dummy;
+10
View File
@@ -37,6 +37,7 @@ extern int window_width;
extern int window_height;
extern int fullscreen;
extern int txt_fullscreen;
extern int aspect_ratio_correct;
extern pixel_t *I_VideoBuffer;
@@ -50,6 +51,15 @@ void I_GetMousePos(int *x, int *y);
void I_SetMousePos(int x, int y);
void I_SetGrabMouseCallback(grabmouse_callback_t func);
void VIDEO_LoadPrefs(void);
// Runtime video option setters (in-game Options dialog)
void I_SetVideoFilter(int factor); // 0/2/3/4, anything else is ignored
void I_SetScanlines(int on);
void I_SetVideoResolution(int w, int h);
void I_SetFullscreen(int on);
void I_SetAspectCorrect(int on);
int I_GetVideoFilter(void);
int I_GetScanlines(void);
void closewindow(void);
bool I_GetNeedResize(bool setonlypos);
int I_VsyncActive(void);
+16 -1
View File
@@ -922,7 +922,22 @@ Do_Game(
b3_flag = 0;
}
if (KBD_IsKey(SC_P) || JOY_IsKeyInGameStart(Start))
if (KBD_IsKey(SC_O))
{
SWD_SetClearFlag(0);
IPT_End();
WIN_Opts();
IPT_Start();
RAP_ClearSides();
RAP_DisplayStats();
SWD_SetClearFlag(1);
IMS_StartAck();
BUT_1 = BUT_2 = BUT_3 = BUT_4 = 0;
b2_flag = 0;
b3_flag = 0;
}
if (KBD_IsKey(SC_P) || JOY_IsKeyInGameStart(Start))
{
while (IMS_IsAck())
{
+6 -2
View File
@@ -633,7 +633,10 @@ SHOTS_PlayerShoot(
cur->move.y2 = 0;
cur->startx = player_cx;
cur->starty = player_cy;
ANIMS_StartAnim(A_PLAYER_SHOOT, o_gun1[playerpic], 0);
// Casing streaks drop into world space (StartGAnim takes the
// top-left; the 8x8 GUNSTR art is centered on the muzzle by hand).
ANIMS_StartGAnim(A_PLAYER_EJECTA,
player_cx + o_gun1[playerpic] - 4, player_cy - 4);
cur = SHOTS_Get();
if (!cur)
@@ -651,7 +654,8 @@ SHOTS_PlayerShoot(
cur->move.y2 = 0;
cur->startx = player_cx;
cur->starty = player_cy;
ANIMS_StartAnim(A_PLAYER_SHOOT, -o_gun1[playerpic] - 1, 0);
ANIMS_StartGAnim(A_PLAYER_EJECTA,
player_cx - o_gun1[playerpic] - 1 - 4, player_cy - 4);
break;
case S_PLASMA_GUNS:
+254 -58
View File
@@ -1,5 +1,6 @@
#include <string.h>
#include <stdio.h>
#include "SDL.h"
#include "common.h"
#include "glbapi.h"
#include "gfxapi.h"
@@ -182,6 +183,178 @@ WIN_OptDraw(
GFX_PutSprite((char*)GLB_GetItem(FILE127_SLIDE_PIC), x + opt_vol[FX_VOL] - 2, y);
}
// WIN_Opts value rows: field + selection icon, keyboard order (matches the
// dialog, top to bottom). The last two are the volume slider rows.
#define OPT_ROWS 8
#define OPT_VALUE_ROWS 6
#define FILTER_COUNT 4
static const int opt_filter_list[FILTER_COUNT] = { 0, 2, 3, 4 };
static const struct
{
int field;
int icon;
} opt_rows[OPT_ROWS] = {
{OPTS_DETAIL, OPTS_PIC1},
{OPTS_FILTER, OPTS_PIC4},
{OPTS_SCANLINES, OPTS_PIC5},
{OPTS_RES, OPTS_PIC6},
{OPTS_FULLSCR, OPTS_PIC7},
{OPTS_ASPECT, OPTS_PIC8},
{OPTS_VMUSIC, OPTS_PIC2},
{OPTS_VFX, OPTS_PIC3}
};
static const struct
{
int w, h;
} res_list[] = {
{640, 480}, {800, 600}, {960, 720}, {1280, 960},
{1600, 1200}, {1920, 1440}
};
#define RES_COUNT ((int)(sizeof(res_list) / sizeof(res_list[0])))
static const char opt_detail_txt[2][16] = {
"LOW DETAIL",
"HIGH DETAIL"
};
static int opt_curd;
static int opt_filter_idx;
static int opt_scan;
static int opt_res_idx;
static int opt_avail[RES_COUNT];
static int opt_fullscr;
static int opt_aspect;
static const char *OPTS_FilterText(char *buf)
{
if (opt_filter_list[opt_filter_idx] == 0)
strcpy(buf, "FILTER OFF");
else
sprintf(buf, "FILTER SCALE %dX", opt_filter_list[opt_filter_idx]);
return buf;
}
static const char *OPTS_ScanText(char *buf)
{
strcpy(buf, opt_scan ? "SCANLINES ON" : "SCANLINES OFF");
return buf;
}
static const char *OPTS_ResText(char *buf)
{
sprintf(buf, "RESOLUTION %dX%d", res_list[opt_res_idx].w,
res_list[opt_res_idx].h);
return buf;
}
static const char *OPTS_FullscrText(char *buf)
{
strcpy(buf, opt_fullscr ? "FULLSCREEN ON" : "FULLSCREEN OFF");
return buf;
}
static const char *OPTS_AspectText(char *buf)
{
strcpy(buf, opt_aspect ? "ASPECT 4:3 ON" : "ASPECT 4:3 OFF");
return buf;
}
/***************************************************************************
OPTS_ShowRow() - Moves the selection arrow icon to a row
***************************************************************************/
static void
OPTS_ShowRow(
int row
)
{
int loop;
for (loop = 0; loop < OPT_ROWS; loop++)
SWD_SetFieldItem(opt_window, opt_rows[loop].icon, -1);
SWD_SetFieldItem(opt_window, opt_rows[row].icon, FILE128_POINT_PIC);
SWD_ShowAllWindows();
GFX_DisplayUpdate();
}
/***************************************************************************
OPTS_StepRow() - Apply one LEFT(-1)/RIGHT(+1) step to an options row:
updates the row state, live-applies the video setting and refreshes the
field text. Returns 1 when the caller should play the slider patch sound.
***************************************************************************/
static int
OPTS_StepRow(
int field,
int dir
)
{
char buf[24];
switch (field)
{
case OPTS_VMUSIC:
opt_vol[MUSIC_VOL] += dir * 8;
if (opt_vol[MUSIC_VOL] < 0)
opt_vol[MUSIC_VOL] = 0;
if (opt_vol[MUSIC_VOL] > 127)
opt_vol[MUSIC_VOL] = 127;
return 0;
case OPTS_VFX:
opt_vol[FX_VOL] += dir * 8;
if (opt_vol[FX_VOL] < 0)
opt_vol[FX_VOL] = 0;
if (opt_vol[FX_VOL] > 127)
opt_vol[FX_VOL] = 127;
return 1;
case OPTS_DETAIL:
opt_curd ^= 1;
SWD_SetFieldText(opt_window, OPTS_DETAIL, opt_detail_txt[opt_curd]);
return 0;
case OPTS_FILTER:
opt_filter_idx = (opt_filter_idx + dir + FILTER_COUNT) % FILTER_COUNT;
I_SetVideoFilter(opt_filter_list[opt_filter_idx]);
SWD_SetFieldText(opt_window, OPTS_FILTER, OPTS_FilterText(buf));
return 0;
case OPTS_SCANLINES:
opt_scan ^= 1;
I_SetScanlines(opt_scan);
SWD_SetFieldText(opt_window, OPTS_SCANLINES, OPTS_ScanText(buf));
return 0;
case OPTS_RES:
do
{
opt_res_idx = (opt_res_idx + dir + RES_COUNT) % RES_COUNT;
} while (!opt_avail[opt_res_idx]);
I_SetVideoResolution(res_list[opt_res_idx].w, res_list[opt_res_idx].h);
SWD_SetFieldText(opt_window, OPTS_RES, OPTS_ResText(buf));
return 0;
case OPTS_FULLSCR:
opt_fullscr ^= 1;
I_SetFullscreen(opt_fullscr);
SWD_SetFieldText(opt_window, OPTS_FULLSCR, OPTS_FullscrText(buf));
return 0;
case OPTS_ASPECT:
opt_aspect ^= 1;
I_SetAspectCorrect(opt_aspect);
SWD_SetFieldText(opt_window, OPTS_ASPECT, OPTS_AspectText(buf));
return 0;
}
return 0;
}
/***************************************************************************
WIN_Opts() - Sets Game Options
***************************************************************************/
@@ -192,35 +365,79 @@ WIN_Opts(
{
SWD_DLG dlg;
int x, y, lx, ly;
int kbactive, patchflag, curd, cur_field;
int kbactive, patchflag, cur_field;
int new_vol;
int fpics[3] = {
OPTS_PIC1, OPTS_PIC2, OPTS_PIC3
};
char detail[2][16] = {
"LOW DETAIL",
"HIGH DETAIL"
};
int loop, diff, best;
SDL_DisplayMode desktop;
char buf[24];
kbactive = 0;
patchflag = 0;
curd = opt_detail;
cur_field = 0;
opt_vol[MUSIC_VOL] = music_volume;
opt_vol[FX_VOL] = fx_volume;
// Video row state from the live settings
opt_curd = opt_detail;
opt_filter_idx = 0;
for (loop = 0; loop < FILTER_COUNT; loop++)
{
if (opt_filter_list[loop] == I_GetVideoFilter())
opt_filter_idx = loop;
}
opt_scan = I_GetScanlines();
opt_fullscr = fullscreen;
opt_aspect = aspect_ratio_correct;
// Resolution presets: skip anything larger than the desktop, start on
// the preset closest in area to the current window size
if (SDL_GetDesktopDisplayMode(0, &desktop) != 0)
desktop.w = desktop.h = 0;
best = 0x7fffffff;
opt_res_idx = 0;
for (loop = 0; loop < RES_COUNT; loop++)
{
opt_avail[loop] = 1;
if (desktop.w && (res_list[loop].w > desktop.w
|| res_list[loop].h > desktop.h))
{
opt_avail[loop] = 0;
continue;
}
diff = res_list[loop].w * res_list[loop].h
- window_width * window_height;
if (diff < 0)
diff = -diff;
if (diff < best)
{
best = diff;
opt_res_idx = loop;
}
}
opt_window = SWD_InitWindow(FILE13f_OPTS_SWD);
SWD_SetFieldText(opt_window, OPTS_DETAIL, detail[curd]);
SWD_SetFieldText(opt_window, OPTS_DETAIL, opt_detail_txt[opt_curd]);
SWD_SetFieldText(opt_window, OPTS_FILTER, OPTS_FilterText(buf));
SWD_SetFieldText(opt_window, OPTS_SCANLINES, OPTS_ScanText(buf));
SWD_SetFieldText(opt_window, OPTS_RES, OPTS_ResText(buf));
SWD_SetFieldText(opt_window, OPTS_FULLSCR, OPTS_FullscrText(buf));
SWD_SetFieldText(opt_window, OPTS_ASPECT, OPTS_AspectText(buf));
SWD_SetWinDrawFunc(opt_window, WIN_OptDraw);
SWD_SetFieldItem(opt_window, OPTS_PIC1, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC2, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC3, -1);
SWD_ShowAllWindows();
OPTS_ShowRow(0);
SND_Patch(FX_SWEP, 127);
GFX_DisplayUpdate();
@@ -284,29 +501,11 @@ WIN_Opts(
break;
case SC_LEFT:
if (cur_field)
{
if (cur_field == 2)
patchflag = 1;
opt_vol[cur_field - 1] -= 8;
if (opt_vol[cur_field - 1] < 0)
opt_vol[cur_field - 1] = 0;
SWD_ShowAllWindows();
GFX_DisplayUpdate();
}
break;
case SC_RIGHT:
if (cur_field)
{
if (cur_field == 2)
patchflag = 1;
opt_vol[cur_field - 1] += 8;
if (opt_vol[cur_field - 1] > 127)
opt_vol[cur_field - 1] = 127;
SWD_ShowAllWindows();
GFX_DisplayUpdate();
}
patchflag = OPTS_StepRow(opt_rows[cur_field].field,
dlg.keypress == SC_RIGHT ? 1 : -1);
SWD_ShowAllWindows();
GFX_DisplayUpdate();
break;
case SC_UP:
@@ -314,33 +513,23 @@ WIN_Opts(
cur_field--;
kbactive = 1;
SND_Patch(FX_SWEP, 127);
SWD_SetFieldItem(opt_window, OPTS_PIC1, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC2, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC3, -1);
SWD_SetFieldItem(opt_window, fpics[cur_field], FILE128_POINT_PIC);
SWD_ShowAllWindows();
GFX_DisplayUpdate();
OPTS_ShowRow(cur_field);
break;
case SC_DOWN:
if (kbactive && cur_field < 2)
if (kbactive && cur_field < OPT_ROWS - 1)
cur_field++;
kbactive = 1;
SND_Patch(FX_SWEP, 127);
SWD_SetFieldItem(opt_window, OPTS_PIC1, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC2, -1);
SWD_SetFieldItem(opt_window, OPTS_PIC3, -1);
SWD_SetFieldItem(opt_window, fpics[cur_field], FILE128_POINT_PIC);
SWD_ShowAllWindows();
GFX_DisplayUpdate();
OPTS_ShowRow(cur_field);
break;
case SC_ENTER:
if (!cur_field)
if (cur_field < OPT_VALUE_ROWS)
{
dlg.cur_act = S_FLD_COMMAND;
dlg.cur_cmd = F_SELECT;
dlg.field = OPTS_DETAIL;
dlg.field = opt_rows[cur_field].field;
}
break;
}
@@ -387,7 +576,7 @@ WIN_Opts(
}
}
opt_detail = curd;
opt_detail = opt_curd;
if (fx_volume != opt_vol[FX_VOL])
fx_volume = opt_vol[FX_VOL];
@@ -414,13 +603,22 @@ WIN_Opts(
INI_PutPreferenceLong("SoundFX", "Volume", fx_volume);
}
INI_PutPreferenceLong("Setup", "Detail", opt_detail);
INI_PutPreferenceLong("Video", "upscaler", I_GetVideoFilter());
INI_PutPreferenceLong("Video", "scanlines", I_GetScanlines());
INI_PutPreferenceLong("Video", "fullscreen", fullscreen);
INI_PutPreferenceLong("Video", "aspect_ratio_correct",
aspect_ratio_correct);
SND_Patch(FX_SWEP, 127);
goto exit_opts;
case OPTS_DETAIL:
case OPTS_FILTER:
case OPTS_SCANLINES:
case OPTS_RES:
case OPTS_FULLSCR:
case OPTS_ASPECT:
SND_Patch(FX_SWEP, 127);
curd ^= 1;
SWD_SetFieldText(opt_window, OPTS_DETAIL, detail[curd]);
OPTS_StepRow(dlg.field, 1);
SWD_ShowAllWindows();
GFX_DisplayUpdate();
break;
@@ -431,8 +629,6 @@ WIN_Opts(
SND_Patch(FX_SWEP, 127);
}
exit_opts:
SWD_SetWinDrawFunc(opt_window, NULL);
SWD_DestroyWindow(opt_window);
+1
View File
@@ -25,6 +25,7 @@ void WIN_AskExit(void);
void WIN_MainMenu(void);
void WIN_MainLoop(void);
void WIN_Pause(void);
void WIN_Opts(void);
int WIN_AskBool(const char *question);
void WIN_WinGame(int game);
void WIN_Msg(const char *msg);
+10
View File
@@ -194,3 +194,13 @@
#define OPTS_000A 0x000a // TEXT FIELD
#define OPTS_VMUSIC 0x000b // VIEW AREA
#define OPTS_VFX 0x000c // VIEW AREA
#define OPTS_FILTER 0x000d // BUTTON FIELD
#define OPTS_SCANLINES 0x000e // BUTTON FIELD
#define OPTS_RES 0x000f // BUTTON FIELD
#define OPTS_FULLSCR 0x0010 // BUTTON FIELD
#define OPTS_ASPECT 0x0011 // BUTTON FIELD
#define OPTS_PIC4 0x0012 // ICON
#define OPTS_PIC5 0x0013 // ICON
#define OPTS_PIC6 0x0014 // ICON
#define OPTS_PIC7 0x0015 // ICON
#define OPTS_PIC8 0x0016 // ICON