Compare commits

...
Author SHA1 Message Date
cambragol 342fbdd3ae Merge branch 'main' into fallout2.cfg-enhancement 2025-06-23 17:03:07 +09:00
Mike Klaas 0adc9c9e77 Prevent pop-in by drawing city circles/names to temp buffer (#178)
* Draw city/name to a temp buffer to prevent pop-in
2025-06-22 22:48:08 -07:00
cambragol af413125bd Merge branch 'main' into fallout2.cfg-enhancement 2025-06-22 20:23:26 +09:00
cambragol afd99fa01b Merge branch 'main' into fallout2.cfg-enhancement 2025-06-19 16:26:26 +09:00
cambragol 3e469ea8e8 Update svga.cc
Removed commented out lines
2025-06-17 19:35:05 +09:00
cambragol ddefda32e7 Update ddraw.ini
Added missing features to ddraw.

-iface stuff
-worldmaptravelmarkers
-gapless music
2025-06-17 14:28:57 +09:00
cambragol 0334b8de05 Update README.md
small fix to readme to clarify.
2025-06-17 14:24:55 +09:00
cambragol 1cab275037 Update .gitignore
removed accidentally updated .gitignore entries.
2025-06-17 14:23:06 +09:00
github-actions[bot] 7eb269bab8 chore: auto-format with clang-format 2025-06-17 05:21:51 +00:00
cambragol c18d7ab25e hires_stencil
Moved hires_stencil from ddraw to fallout2.cfg
2025-06-17 09:06:18 +09:00
cambragol 59bf337583 Update README.md
Updated to reflect changes to fallout2.cfg and removal of f2_res.ini
2025-06-17 08:34:44 +09:00
cambragol 88179574e8 Making 'graphics' settings category
moved all new f2_res settings into seperate 'graphics' category - was dumped in 'system' before
2025-06-17 07:43:47 +09:00
cambragol 0733acfad7 Iface to ddraw
removed f2_res.ini res in game.cc for splash screens - replaced with settings.system.splash_size;
added game config for all f2_res setting, except iface/sidebars
Moved iface/sidebars setting to sfall -ddraw.ini
2025-06-17 07:23:26 +09:00
cambragol 1388ca1f83 First Draft
Moving f2_res.ini setting into fallout2.cfg, where appropriate

Added some setting for stretching/aspect/highquality

renamed screen_width/height to game_width/height (to later make clear that this will be the 'in game (map) size' - *not* the menu etc. Will make sense with stretching.

Added config for falloutce.dat loading.
2025-06-16 15:44:38 +09:00
12 changed files with 319 additions and 100 deletions
+26 -21
View File
@@ -96,16 +96,32 @@ The main configuration file is `fallout2.cfg`. There are several important setti
The `sound` folder (with `music` folder inside) might be located either in `data` folder, or be in the Fallout folder. Update `music_path1` setting to match your hierarchy, usually it's `data/sound/music/` or `sound/music/`. Make sure it matches your path exactly (so it might be `SOUND/MUSIC/` if you've installed Fallout from CD). Music files themselves (with `ACM` extension) should be all uppercased, regardless of `sound` and `music` folders.
The second configuration file is `f2_res.ini`. Use it to change game window size, enable/disable fullscreen mode and configure IFACE settings (the control bar at the bottom of the game screen).
Additionally, the [graphics] section provides options for fine tuning the appearence of the game. The included settings are:
```ini
[MAIN]
SCR_WIDTH=1280
SCR_HEIGHT=720
WINDOWED=1 ; 0 = fullscreen
SCALE_2X=1 ; 0 = original scale, 1 = 2x - requires increasing the minimum resolution from 640x480 to 1280x960.
```
[graphics]
fullscreen=0 ; 1 = fullscreeen, 0 = windowed
game_height=480 ; main play area height
game_width=640 ; main play area width
scale2x=0 ; 0 = original scale, 1 = 2x - requires increasing the minimum resolution from 640x480 to 1280x960.
splash_size=0 ; 0 = normal, 1 = aspect stretch, 2 = fullscreen stretch
```
[IFACE]
Recommendations:
- **Desktops**: Use any size you see fit.
- **Tablets**: Set these values to logical resolution of your device, for example iPad Pro 11 is 1668x2388 (pixels), but it's logical resolution is 834x1194 (points).
- **Mobile phones**: Set height to 480, calculate width according to your device screen (aspect) ratio, for example Samsung S21 is 20:9 device, so the width should be 480 * 20 / 9 = 1067.
In time this graphcs settings will receive an in-game interface. For the time being it must be configured manually.
The second configuration file is `ddraw.ini` (part of Sfall). There are dozens of options that adjust or override engine behaviour and gameplay mechanics. This file is intended for modders and advanced users.
For a sample ddraw.ini configuration file, containing all currently working settings use this link: [ddraw.ini](https://raw.githubusercontent.com/fallout2-ce/fallout2-ce/refs/heads/main/files/ddraw.ini)
Further, Fallout2-CE supports the following additional settings in ddraw.ini:
```
[Misc]
; if IFACE_BAR_MODE=0 - the bottom of the map view window sits at the top of the IFACE Bar.
; if IFACE_BAR_MODE=1 - the bottom of the map view window extends to the base of the screen and is overlapped by the IFACE Bar.
IFACE_BAR_MODE=0
@@ -128,22 +144,11 @@ IFACE_BAR_SIDES_ORI=0
;IFACE_BAR_WIDTH=640
```
Recommendations:
- **Desktops**: Use any size you see fit.
- **Tablets**: Set these values to logical resolution of your device, for example iPad Pro 11 is 1668x2388 (pixels), but it's logical resolution is 834x1194 (points).
- **Mobile phones**: Set height to 480, calculate width according to your device screen (aspect) ratio, for example Samsung S21 is 20:9 device, so the width should be 480 * 20 / 9 = 1067.
In time this stuff will receive in-game interface, right now you have to do it manually. For a sample f2_res.ini configuration file, containing all currently working settings use this link: [f2_res.ini](https://raw.githubusercontent.com/fallout2-ce/fallout2-ce/refs/heads/mainmenu/files/f2_res.ini)
*Note*: use of the IFACE_BAR settings requires the f2_res.dat file, which contains graphical assets. Various versions are available, but one compatible with the above f2_res.ini be found here: [f2_res.dat](https://github.com/fallout2-ce/fallout2-ce/raw/refs/heads/mainmenu/files/f2_res.dat)
The third configuration file is `ddraw.ini` (part of Sfall). There are dozens of options that adjust or override engine behaviour and gameplay mechanics. This file is intended for modders and advanced users.
For a sample ddraw.ini configuration file, containing all currently working settings use this link: [ddraw.ini](https://raw.githubusercontent.com/fallout2-ce/fallout2-ce/refs/heads/main/files/ddraw.ini)
*Note*: use of the IFACE_BAR settings requires the f2_res.dat file, which contains graphical assets. Various versions are available, but one compatible with the above settings be found here: [f2_res.dat](https://github.com/fallout2-ce/fallout2-ce/raw/refs/heads/mainmenu/files/f2_res.dat)
## Quality of life benefits over vanilla Fallout
* High resolution support
* Large game area support (through HiResMode=1 in ddraw.ini and game_height=480 and game_width=640 settings in fallout2.cfg)
* Increased pathfinding nodes 5x for more accurate pathfinding
* Ctrl-click to quickly move items when bartering, looting, or stealing
* _a_ to select "all" when selecting item quantity
+27
View File
@@ -10,6 +10,33 @@
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Misc]
; if IFACE_BAR_MODE=0 - the bottom of the map view window sits at the top of the IFACE Bar.
; if IFACE_BAR_MODE=1 - the bottom of the map view window extends to the base of the screen and is overlapped by the IFACE Bar.
IFACE_BAR_MODE=0
;if IFACE_BAR_SIDE_ART=0 - Black, No Iface-bar side art used.
;if IFACE_BAR_SIDE_ART=1 - Metal (grey) look Iface-bar side art used.
;if IFACE_BAR_SIDE_ART=2 - Leather look Iface-bar side art used.
;if IFACE_BAR_SIDE_ART=3-6 - Alternative Metal look Iface-bar side art used.
;if IFACE_BAR_SIDE_ART=7 - Alternative Leather look Iface-bar side art used.
;if IFACE_BAR_SIDE_ART=8 - Metal (brown) look Iface-bar side art used.
IFACE_BAR_SIDE_ART=5
;if IFACE_BAR_SIDES_ORI=0 - Iface-bar side graphics extend from the Iface-Bar to the Screen edges.
;if IFACE_BAR_SIDES_ORI=1 - Iface-bar side graphics extend from the Screen edges to the Iface-Bar.
IFACE_BAR_SIDES_ORI=1
;This will increase the width of the interface bar expanding the area used to display text.
;if IFACE_BAR_WIDTH=640 - Interface bar will remain at it's original width.
IFACE_BAR_WIDTH=800
;Adds Fallout 1 style travel/trail dots
WorldMapTravelMarkers=0
;Prevents pausing music between map areas with the same music
GaplessMusic=0
;Uncomment these lines to change the timers of how many days after the game starts Hakunin dream sequences will occur
;MovieTimer_artimer1=5000
;MovieTimer_artimer2=5000
+1 -11
View File
@@ -1470,17 +1470,7 @@ static void showSplash()
}
}
int size = 0;
// TODO: Move to settings.
Config config;
if (configInit(&config)) {
if (configRead(&config, "f2_res.ini", false)) {
configGetInt(&config, "STATIC_SCREENS", "SPLASH_SCRN_SIZE", &size);
}
configFree(&config);
}
int size = settings.graphics.splash_size;
int screenWidth = screenGetWidth();
int screenHeight = screenGetHeight();
+13
View File
@@ -67,6 +67,8 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, "data");
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_DAT_KEY, "critter.dat");
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY, "data");
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_DAT_KEY, "falloutce.dat");
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_PATCHES_KEY, "data");
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, ENGLISH);
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SCROLL_LOCK_KEY, 0);
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_INTERRUPT_WALK_KEY, 1);
@@ -75,6 +77,7 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_HASHING_KEY, 1);
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SPLASH_KEY, 0);
configSetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FREE_SPACE_KEY, 20480);
configSetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_GAME_DIFFICULTY_KEY, 1);
configSetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_COMBAT_DIFFICULTY_KEY, 1);
configSetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_VIOLENCE_LEVEL_KEY, 3);
@@ -113,6 +116,16 @@ bool gameConfigInit(bool isMapper, int argc, char** argv)
configSetInt(&gGameConfig, GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_SHOW_LOAD_INFO_KEY, 0);
configSetInt(&gGameConfig, GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_OUTPUT_MAP_DATA_INFO_KEY, 0);
configSetInt(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_WIDTH, 640);
configSetInt(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_HEIGHT, 480);
configSetInt(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SCALE_2X, 0);
configSetInt(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SPLASH_SIZE, 0);
configSetBool(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_FULLSCREEN, true);
configSetBool(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_STRETCH_ENABLED, true);
configSetBool(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_PRESERVE_ASPECT, true);
configSetBool(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_HIGH_QUALITY, false);
configSetBool(&gGameConfig, GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_ENABLE_HIRES_STENCIL, true);
if (isMapper) {
configSetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_EXECUTABLE_KEY, "mapper");
configSetInt(&gGameConfig, GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_OVERRIDE_LIBRARIAN_KEY, 0);
+12
View File
@@ -13,12 +13,15 @@ namespace fallout {
#define GAME_CONFIG_SOUND_KEY "sound"
#define GAME_CONFIG_MAPPER_KEY "mapper"
#define GAME_CONFIG_DEBUG_KEY "debug"
#define GAME_CONFIG_GRAPHICS_KEY "graphics"
#define GAME_CONFIG_EXECUTABLE_KEY "executable"
#define GAME_CONFIG_MASTER_DAT_KEY "master_dat"
#define GAME_CONFIG_MASTER_PATCHES_KEY "master_patches"
#define GAME_CONFIG_CRITTER_DAT_KEY "critter_dat"
#define GAME_CONFIG_CRITTER_PATCHES_KEY "critter_patches"
#define GAME_CONFIG_FALLOUTCE_DAT_KEY "falloutce_dat"
#define GAME_CONFIG_FALLOUTCE_PATCHES_KEY "falloutce_patches"
#define GAME_CONFIG_LANGUAGE_KEY "language"
#define GAME_CONFIG_SCROLL_LOCK_KEY "scroll_lock"
#define GAME_CONFIG_INTERRUPT_WALK_KEY "interrupt_walk"
@@ -28,6 +31,15 @@ namespace fallout {
#define GAME_CONFIG_HASHING_KEY "hashing"
#define GAME_CONFIG_SPLASH_KEY "splash"
#define GAME_CONFIG_FREE_SPACE_KEY "free_space"
#define GAME_CONFIG_GAME_WIDTH "game_width"
#define GAME_CONFIG_GAME_HEIGHT "game_height"
#define GAME_CONFIG_FULLSCREEN "fullscreen"
#define GAME_CONFIG_SCALE_2X "scale2x"
#define GAME_CONFIG_SPLASH_SIZE "splash_size"
#define GAME_CONFIG_STRETCH_ENABLED "stretch_enabled"
#define GAME_CONFIG_PRESERVE_ASPECT "preserve_aspect"
#define GAME_CONFIG_HIGH_QUALITY "high_quality"
#define GAME_CONFIG_ENABLE_HIRES_STENCIL "highres_stencil"
#define GAME_CONFIG_TIMES_RUN_KEY "times_run"
#define GAME_CONFIG_GAME_DIFFICULTY_KEY "game_difficulty"
#define GAME_CONFIG_RUNNING_BURNING_GUY_KEY "running_burning_guy"
+24
View File
@@ -48,6 +48,8 @@ static void settingsFromConfig()
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, settings.system.master_patches_path);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_DAT_KEY, settings.system.critter_dat_path);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY, settings.system.critter_patches_path);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_DAT_KEY, settings.system.falloutce_dat_path);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_PATCHES_KEY, settings.system.falloutce_patches_path);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, settings.system.language);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SCROLL_LOCK_KEY, settings.system.scroll_lock);
settingsRead(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_INTERRUPT_WALK_KEY, settings.system.interrupt_walk);
@@ -101,6 +103,16 @@ static void settingsFromConfig()
settingsRead(GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_SHOW_LOAD_INFO_KEY, settings.debug.show_load_info);
settingsRead(GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_OUTPUT_MAP_DATA_INFO_KEY, settings.debug.output_map_data_info);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_WIDTH, settings.graphics.game_width);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_HEIGHT, settings.graphics.game_height);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_FULLSCREEN, settings.graphics.fullscreen);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SCALE_2X, settings.graphics.scale2x);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SPLASH_SIZE, settings.graphics.splash_size);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_STRETCH_ENABLED, settings.graphics.stretch_enabled);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_PRESERVE_ASPECT, settings.graphics.preserve_aspect);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_HIGH_QUALITY, settings.graphics.high_quality);
settingsRead(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_ENABLE_HIRES_STENCIL, settings.graphics.highres_stencil);
settingsRead(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_OVERRIDE_LIBRARIAN_KEY, settings.mapper.override_librarian);
settingsRead(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_LIBRARIAN_KEY, settings.mapper.librarian);
settingsRead(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_USE_ART_NOT_PROTOS_KEY, settings.mapper.user_art_not_protos);
@@ -122,6 +134,8 @@ static void settingsToConfig()
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, settings.system.master_patches_path);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_DAT_KEY, settings.system.critter_dat_path);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_CRITTER_PATCHES_KEY, settings.system.critter_patches_path);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_DAT_KEY, settings.system.falloutce_dat_path);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_FALLOUTCE_PATCHES_KEY, settings.system.falloutce_patches_path);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_LANGUAGE_KEY, settings.system.language);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_SCROLL_LOCK_KEY, settings.system.scroll_lock);
settingsWrite(GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_INTERRUPT_WALK_KEY, settings.system.interrupt_walk);
@@ -175,6 +189,16 @@ static void settingsToConfig()
settingsWrite(GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_SHOW_LOAD_INFO_KEY, settings.debug.show_load_info);
settingsWrite(GAME_CONFIG_DEBUG_KEY, GAME_CONFIG_OUTPUT_MAP_DATA_INFO_KEY, settings.debug.output_map_data_info);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_WIDTH, settings.graphics.game_width);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_GAME_HEIGHT, settings.graphics.game_height);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_FULLSCREEN, settings.graphics.fullscreen);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SCALE_2X, settings.graphics.scale2x);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_SPLASH_SIZE, settings.graphics.splash_size);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_STRETCH_ENABLED, settings.graphics.stretch_enabled);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_PRESERVE_ASPECT, settings.graphics.preserve_aspect);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_HIGH_QUALITY, settings.graphics.high_quality);
settingsWrite(GAME_CONFIG_GRAPHICS_KEY, GAME_CONFIG_ENABLE_HIRES_STENCIL, settings.graphics.highres_stencil);
settingsWrite(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_OVERRIDE_LIBRARIAN_KEY, settings.mapper.override_librarian);
settingsWrite(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_LIBRARIAN_KEY, settings.mapper.librarian);
settingsWrite(GAME_CONFIG_MAPPER_KEY, GAME_CONFIG_USE_ART_NOT_PROTOS_KEY, settings.mapper.user_art_not_protos);
+15
View File
@@ -13,6 +13,8 @@ struct SystemSettings {
std::string master_patches_path = "data";
std::string critter_dat_path = "critter.dat";
std::string critter_patches_path = "data";
std::string falloutce_dat_path = "falloutce.dat";
std::string falloutce_patches_path = "data";
std::string language = ENGLISH;
int scroll_lock = 0;
bool interrupt_walk = true;
@@ -89,12 +91,25 @@ struct MapperSettings {
bool sort_script_list = false;
};
struct GraphicSettings {
int game_width = 640;
int game_height = 480;
int scale2x = 0;
int splash_size = 0;
bool fullscreen = true;
bool stretch_enabled = true;
bool preserve_aspect = true;
bool high_quality = false;
bool highres_stencil = true;
};
struct Settings {
SystemSettings system;
PreferencesSettings preferences;
SoundSettings sound;
DebugSettings debug;
MapperSettings mapper;
GraphicSettings graphics;
};
extern Settings settings;
+4 -1
View File
@@ -71,7 +71,10 @@ bool sfallConfigInit(int argc, char** argv)
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_GAPLESS_MUSIC, 0);
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_WORLDMAP_TRAIL_MARKERS, 0);
configSetBool(&gSfallConfig, SFALL_CONFIG_MAIN_KEY, SFALL_CONFIG_ENABLE_HIRES_STENCIL, true);
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_MODE, false);
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_WIDTH, 0);
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_SIDE_ART, 0);
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_SIDES_ORI, false);
char path[COMPAT_MAX_PATH];
char* executable = argv[0];
+6 -2
View File
@@ -76,14 +76,18 @@ namespace fallout {
#define SFALL_CONFIG_VERSION_STRING "VersionString"
#define SFALL_CONFIG_CONFIG_FILE "ConfigFile"
#define SFALL_CONFIG_PATCH_FILE "PatchFile"
#define SFALL_CONFIG_HIRES_MODE "HiResMode"
#define SFALL_CONFIG_ENABLE_HIRES_STENCIL "EnableHighResolutionStencil"
#define SFALL_CONFIG_PIPBOY_AVAILABLE_AT_GAMESTART "PipBoyAvailableAtGameStart"
#define SFALL_CONFIG_USE_WALK_DISTANCE "UseWalkDistance"
#define SFALL_CONFIG_AUTO_OPEN_DOORS "AutoOpenDoors"
#define SFALL_CONFIG_GAPLESS_MUSIC "GaplessMusic" // note: this isn't an sfall config
#define SFALL_CONFIG_WORLDMAP_TRAIL_MARKERS "WorldMapTravelMarkers"
// temp for iface bar from f2_res.ini
#define SFALL_CONFIG_IFACE_BAR_MODE "IFACE_BAR_MODE"
#define SFALL_CONFIG_IFACE_BAR_WIDTH "IFACE_BAR_WIDTH"
#define SFALL_CONFIG_IFACE_BAR_SIDE_ART "IFACE_BAR_SIDE_ART"
#define SFALL_CONFIG_IFACE_BAR_SIDES_ORI "IFACE_BAR_SIDES_ORI"
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
#define SFALL_CONFIG_BURST_MOD_DEFAULT_TARGET_MULTIPLIER 1
+18 -51
View File
@@ -11,6 +11,8 @@
#include "memory.h"
#include "mouse.h"
#include "scan_unimplemented.h"
#include "settings.h"
#include "sfall_config.h"
#include "win32.h"
#include "window_manager.h"
#include "window_manager_private.h"
@@ -105,60 +107,25 @@ int _GNW95_init_mode_ex(int width, int height, int bpp)
bool fullscreen = true;
int scale = 1;
Config resolutionConfig;
if (configInit(&resolutionConfig)) {
if (configRead(&resolutionConfig, "f2_res.ini", false)) {
int screenWidth;
if (configGetInt(&resolutionConfig, "MAIN", "SCR_WIDTH", &screenWidth)) {
width = screenWidth;
}
width = settings.graphics.game_width;
height = settings.graphics.game_height;
fullscreen = settings.graphics.fullscreen;
int scaleValue = settings.graphics.scale2x;
int screenHeight;
if (configGetInt(&resolutionConfig, "MAIN", "SCR_HEIGHT", &screenHeight)) {
height = screenHeight;
}
bool windowed;
if (configGetBool(&resolutionConfig, "MAIN", "WINDOWED", &windowed)) {
fullscreen = !windowed;
}
int scaleValue;
if (configGetInt(&resolutionConfig, "MAIN", "SCALE_2X", &scaleValue)) {
scale = scaleValue + 1; // 0 = 1x, 1 = 2x
// Only allow scaling if resulting game resolution is >= 640x480
if ((width / scale) < 640 || (height / scale) < 480) {
scale = 1;
} else {
width /= scale;
height /= scale;
}
}
configGetBool(&resolutionConfig, "IFACE", "IFACE_BAR_MODE", &gInterfaceBarMode);
configGetInt(&resolutionConfig, "IFACE", "IFACE_BAR_WIDTH", &gInterfaceBarWidth);
configGetInt(&resolutionConfig, "IFACE", "IFACE_BAR_SIDE_ART", &gInterfaceSidePanelsImageId);
configGetBool(&resolutionConfig, "IFACE", "IFACE_BAR_SIDES_ORI", &gInterfaceSidePanelsExtendFromScreenEdge);
{
ConfigMap f2_res_defaults;
f2_res_defaults["MAIN"]["SCR_WIDTH"] = "640";
f2_res_defaults["MAIN"]["SCR_HEIGHT"] = "480";
f2_res_defaults["MAIN"]["WINDOWED"] = "0";
f2_res_defaults["MAIN"]["SCALE_2X"] = "0";
f2_res_defaults["IFACE"]["IFACE_BAR_MODE"] = "0";
f2_res_defaults["IFACE"]["IFACE_BAR_WIDTH"] = "0";
f2_res_defaults["IFACE"]["IFACE_BAR_SIDE_ART"] = "0";
f2_res_defaults["IFACE"]["IFACE_BAR_SIDES_ORI"] = "0";
f2_res_defaults["STATIC_SCREENS"]["SPLASH_SCRN_SIZE"] = "0";
auto configChecker = ConfigChecker(f2_res_defaults, "f2_res.ini");
configChecker.check(resolutionConfig);
}
}
configFree(&resolutionConfig);
scale = scaleValue + 1; // 0 = 1x, 1 = 2x
// Only allow scaling if resulting game resolution is >= 640x480
if ((width / scale) < 640 || (height / scale) < 480) {
scale = 1;
} else {
width /= scale;
height /= scale;
}
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_MODE, &gInterfaceBarMode);
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_WIDTH, &gInterfaceBarWidth);
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_SIDE_ART, &gInterfaceSidePanelsImageId);
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_IFACE_BAR_SIDES_ORI, &gInterfaceSidePanelsExtendFromScreenEdge);
if (_GNW95_init_window(width, height, fullscreen, scale) == -1) {
return -1;
}
+3 -3
View File
@@ -2,7 +2,7 @@
#include "debug.h"
#include "draw.h"
#include "geometry.h"
#include "sfall_config.h"
#include "settings.h"
#include "stdio.h"
#include "tile.h"
#include <string.h>
@@ -405,7 +405,7 @@ void tile_hires_stencil_draw(Rect* rect, unsigned char* buffer, int windowWidth,
void tile_hires_stencil_init()
{
configGetBool(&gSfallConfig, SFALL_CONFIG_MAIN_KEY, SFALL_CONFIG_ENABLE_HIRES_STENCIL, &gIsTileHiresStencilEnabled);
gIsTileHiresStencilEnabled = settings.graphics.highres_stencil;
if (!gIsTileHiresStencilEnabled) {
return;
}
@@ -416,4 +416,4 @@ void tile_hires_stencil_init()
tileWindowRefresh();
}
} // namespace fallout
} // namespace fallout
+170 -11
View File
@@ -542,6 +542,7 @@ static int wmInterfaceRefresh();
static void wmInterfaceRefreshDate(bool shouldRefreshWindow);
static int wmMatchWorldPosToArea(int x, int y, int* areaIdxPtr);
static int wmInterfaceDrawCircleOverlay(CityInfo* cityInfo, CitySizeDescription* citySizeInfo, unsigned char* buffer, int x, int y);
static int wmInterfaceDrawCircleOverlaySafe(CityInfo* city, CitySizeDescription* citySizeDescription, unsigned char* dest, int x, int y);
static void wmInterfaceDrawSubTileRectFogged(unsigned char* dest, int width, int height, int pitch);
static int wmInterfaceDrawSubTileList(TileInfo* tileInfo, int column, int row, int x, int y, int a6);
static int wmDrawCursorStopped();
@@ -684,6 +685,10 @@ static int wmBkWin = -1;
// 0x51DE24
static unsigned char* wmBkWinBuf = nullptr;
// CE: Offscreen buffer for safe city overlay rendering
static unsigned char* wmOverlayOffscreenBuf = nullptr;
#define WM_OVERLAY_BUFFER_SIZE (200)
// 0x51DE2C
static int wmWorldOffsetX = 0;
@@ -3140,7 +3145,7 @@ static int wmWorldMapFunc(int a1)
}
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0 && (mouseEvent & MOUSE_EVENT_LEFT_BUTTON_REPEAT) == 0) {
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, 472, 465)) {
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, WM_VIEW_WIDTH + WM_VIEW_X, WM_VIEW_HEIGHT + WM_VIEW_Y)) {
if (!wmGenData.isWalking && !wmGenData.mousePressed && abs(wmGenData.worldPosX - worldX) < 5 && abs(wmGenData.worldPosY - worldY) < 5) {
wmGenData.mousePressed = true;
wmInterfaceRefresh();
@@ -3192,7 +3197,7 @@ static int wmWorldMapFunc(int a1)
}
}
} else {
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, 472, 465)) {
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, WM_VIEW_WIDTH + WM_VIEW_X, WM_VIEW_HEIGHT + WM_VIEW_Y)) {
wmPartyInitWalking(worldX, worldY);
}
@@ -3274,7 +3279,7 @@ static int wmWorldMapFunc(int a1)
int wheelY;
mouseGetWheel(&wheelX, &wheelY);
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, 472, 465)) {
if (mouseHitTestInWindow(wmBkWin, WM_VIEW_X, WM_VIEW_Y, WM_VIEW_WIDTH + WM_VIEW_X, WM_VIEW_HEIGHT + WM_VIEW_Y)) {
wmInterfaceScrollPixel(20, 20, wheelX, -wheelY, nullptr, true);
} else if (mouseHitTestInWindow(wmBkWin, 501, 135, 501 + 119, 135 + 178)) {
if (wheelY != 0) {
@@ -4516,6 +4521,12 @@ static int wmInterfaceInit()
return -1;
}
// CE: Allocate offscreen buffer for safe city overlay rendering
wmOverlayOffscreenBuf = (unsigned char*)internal_malloc(WM_OVERLAY_BUFFER_SIZE * WM_OVERLAY_BUFFER_SIZE);
if (wmOverlayOffscreenBuf == nullptr) {
return -1;
}
blitBufferToBuffer(_backgroundFrmImage.getData(),
_backgroundFrmImage.getWidth(),
_backgroundFrmImage.getHeight(),
@@ -4843,6 +4854,12 @@ static int wmInterfaceExit()
// NOTE: Uninline.
wmFreeTabsLabelList(&wmLabelList, &wmLabelCount);
// CE: Free offscreen buffer for safe city overlay rendering
if (wmOverlayOffscreenBuf != nullptr) {
internal_free(wmOverlayOffscreenBuf);
wmOverlayOffscreenBuf = nullptr;
}
wmInterfaceWasInitialized = 0;
scriptsEnable();
@@ -5244,10 +5261,8 @@ static int wmInterfaceRefresh()
CitySizeDescription* citySizeDescription = &(wmSphereData[cityInfo->size]);
int cityX = cityInfo->x - wmWorldOffsetX;
int cityY = cityInfo->y - wmWorldOffsetY;
if (cityX >= 0 && cityX <= 472 - citySizeDescription->frmImage.getWidth()
&& cityY >= 0 && cityY <= 465 - citySizeDescription->frmImage.getHeight()) {
wmInterfaceDrawCircleOverlay(cityInfo, citySizeDescription, wmBkWinBuf, cityX, cityY);
}
// CE: Use safe overlay drawing with proper bounds checking instead of hardcoded limits
wmInterfaceDrawCircleOverlaySafe(cityInfo, citySizeDescription, wmBkWinBuf, cityX, cityY);
}
}
@@ -5401,6 +5416,150 @@ static int wmMatchWorldPosToArea(int x, int y, int* areaIdxPtr)
return 0;
}
// CE: Safe city overlay drawing with proper bounds checking
static int wmInterfaceDrawCircleOverlaySafe(CityInfo* city, CitySizeDescription* citySizeDescription, unsigned char* dest, int xArg, int yArg)
{
MessageListItem messageListItem;
char name[CITY_NAME_SIZE];
if (wmAreaIsKnown(city->areaId)) {
wmGetAreaName(city, name);
} else {
strncpy(name, getmsg(&wmMsgFile, &messageListItem, 1004), CITY_NAME_SIZE - 1);
name[CITY_NAME_SIZE - 1] = '\0';
}
// Basic dimensions
int circleWidth = citySizeDescription->frmImage.getWidth();
int circleHeight = citySizeDescription->frmImage.getHeight();
int textWidth = fontGetStringWidth(name);
int textHeight = fontGetLineHeight();
const int spacing = 3;
// 1. Relative Ideal Positions (Origin at 0,0 for circle's top-left)
int xTextRel = (circleWidth - textWidth) / 2;
int yTextRel = circleHeight + spacing;
// 2. Content Bounding Box (Relative to circle's 0,0 origin)
int contentMinXRel = std::min(0, xTextRel);
int contentMaxXRel = std::max(circleWidth, xTextRel + textWidth);
int contentActualWidth = contentMaxXRel - contentMinXRel;
int contentActualHeight = circleHeight + spacing + textHeight;
// Viewport boundaries
int viewportLeft = WM_VIEW_X;
int viewportTop = WM_VIEW_Y;
int viewportRight = WM_VIEW_X + WM_VIEW_WIDTH;
int viewportBottom = WM_VIEW_Y + WM_VIEW_HEIGHT;
// Overall screen position for the content bounding box's top-left
int screenContentBoxX = xArg + contentMinXRel;
int screenContentBoxY = yArg; // yArg is for circle's top
// Check if the entire content box is outside the viewport
if (screenContentBoxX + contentActualWidth < viewportLeft || screenContentBoxX >= viewportRight || screenContentBoxY + contentActualHeight < viewportTop || screenContentBoxY >= viewportBottom) {
return 0; // Completely outside viewport
}
// 3. Positioning Content Bounding Box within wmOverlayOffscreenBuf
// This is the top-left of where our combined content will sit in the offscreen buffer.
int bufferContentStartX = (WM_OVERLAY_BUFFER_SIZE - contentActualWidth) / 2;
int bufferContentStartY = (WM_OVERLAY_BUFFER_SIZE - contentActualHeight) / 2;
// Clear/prepare the offscreen buffer
memset(wmOverlayOffscreenBuf, 0, WM_OVERLAY_BUFFER_SIZE * WM_OVERLAY_BUFFER_SIZE);
// Copy background from main screen buffer to offscreen buffer
// Determine the part of the screen that corresponds to our offscreen content area
int bgCopySrcXOnScreen = screenContentBoxX;
int bgCopySrcYOnScreen = screenContentBoxY;
int bgCopyClippedSrcX = std::max(bgCopySrcXOnScreen, viewportLeft);
int bgCopyClippedSrcY = std::max(bgCopySrcYOnScreen, viewportTop);
int bgCopyClippedEndX = std::min(bgCopySrcXOnScreen + contentActualWidth, viewportRight);
int bgCopyClippedEndY = std::min(bgCopySrcYOnScreen + contentActualHeight, viewportBottom);
int bgFinalCopyWidth = bgCopyClippedEndX - bgCopyClippedSrcX;
int bgFinalCopyHeight = bgCopyClippedEndY - bgCopyClippedSrcY;
if (bgFinalCopyWidth > 0 && bgFinalCopyHeight > 0) {
// Offset into the offscreen buffer where this background piece should go
int bgDstXInBuffer = bufferContentStartX + (bgCopyClippedSrcX - bgCopySrcXOnScreen);
int bgDstYInBuffer = bufferContentStartY + (bgCopyClippedSrcY - bgCopySrcYOnScreen);
if (bgDstXInBuffer >= 0 && bgDstYInBuffer >= 0 && bgDstXInBuffer + bgFinalCopyWidth <= WM_OVERLAY_BUFFER_SIZE && bgDstYInBuffer + bgFinalCopyHeight <= WM_OVERLAY_BUFFER_SIZE) {
blitBufferToBuffer(
dest + bgCopyClippedSrcY * WM_WINDOW_WIDTH + bgCopyClippedSrcX, // Source from main screen
bgFinalCopyWidth,
bgFinalCopyHeight,
WM_WINDOW_WIDTH,
wmOverlayOffscreenBuf + bgDstYInBuffer * WM_OVERLAY_BUFFER_SIZE + bgDstXInBuffer, // Dest in offscreen
WM_OVERLAY_BUFFER_SIZE);
}
}
// 4. Absolute Drawing Coordinates within wmOverlayOffscreenBuf
// (relative to top-left of wmOverlayOffscreenBuf)
int circleDrawAbsX = bufferContentStartX - contentMinXRel;
int circleDrawAbsY = bufferContentStartY; // since content_min_y_rel is 0
int textDrawAbsX = bufferContentStartX - contentMinXRel + xTextRel;
int textDrawAbsY = bufferContentStartY + yTextRel;
// Draw circle onto offscreen buffer
if (circleDrawAbsX >= 0 && circleDrawAbsY >= 0 && circleDrawAbsX + circleWidth <= WM_OVERLAY_BUFFER_SIZE && circleDrawAbsY + circleHeight <= WM_OVERLAY_BUFFER_SIZE) {
_dark_translucent_trans_buf_to_buf(
citySizeDescription->frmImage.getData(),
circleWidth, circleHeight, circleWidth,
wmOverlayOffscreenBuf,
circleDrawAbsX, circleDrawAbsY,
WM_OVERLAY_BUFFER_SIZE,
0x10000, circleBlendTable, _commonGrayTable);
}
// Draw text onto offscreen buffer
if (textDrawAbsX >= 0 && textDrawAbsY >= 0 && textDrawAbsX + textWidth <= WM_OVERLAY_BUFFER_SIZE && textDrawAbsY + textHeight <= WM_OVERLAY_BUFFER_SIZE) {
fontDrawText(
wmOverlayOffscreenBuf + textDrawAbsY * WM_OVERLAY_BUFFER_SIZE + textDrawAbsX,
name, textWidth, WM_OVERLAY_BUFFER_SIZE,
_colorTable[992] | FONT_SHADOW);
}
// 5. Final Blit to Screen (dest buffer)
// Source from offscreen buffer (top-left of our centered content)
int finalBlitSrcXOffscreen = bufferContentStartX;
int finalBlitSrcYOffscreen = bufferContentStartY;
// Destination on screen (top-left of where content box should appear)
int finalBlitDstXScreen = screenContentBoxX;
int finalBlitDstYScreen = screenContentBoxY;
// Clip the source region for blitting based on what's visible in the viewport
// relative to the screen_content_box origin.
int clippedFinalSrcXOffscreen = finalBlitSrcXOffscreen + std::max(0, viewportLeft - finalBlitDstXScreen);
int clippedFinalSrcYOffscreen = finalBlitSrcYOffscreen + std::max(0, viewportTop - finalBlitDstYScreen);
// Clipped destination on screen
int clippedFinalDstXScreen = std::max(finalBlitDstXScreen, viewportLeft);
int clippedFinalDstYScreen = std::max(finalBlitDstYScreen, viewportTop);
// Calculate width and height of the actual region to blit
int blitWidth = std::min(finalBlitDstXScreen + contentActualWidth, viewportRight) - clippedFinalDstXScreen;
int blitHeight = std::min(finalBlitDstYScreen + contentActualHeight, viewportBottom) - clippedFinalDstYScreen;
if (blitWidth > 0 && blitHeight > 0 && clippedFinalSrcXOffscreen >= 0 && clippedFinalSrcYOffscreen >= 0 && clippedFinalSrcXOffscreen + blitWidth <= WM_OVERLAY_BUFFER_SIZE && clippedFinalSrcYOffscreen + blitHeight <= WM_OVERLAY_BUFFER_SIZE && clippedFinalDstXScreen >= 0 && clippedFinalDstYScreen >= 0 && clippedFinalDstXScreen + blitWidth <= WM_WINDOW_WIDTH && clippedFinalDstYScreen + blitHeight <= WM_WINDOW_HEIGHT) {
blitBufferToBuffer(
wmOverlayOffscreenBuf + clippedFinalSrcYOffscreen * WM_OVERLAY_BUFFER_SIZE + clippedFinalSrcXOffscreen,
blitWidth, blitHeight,
WM_OVERLAY_BUFFER_SIZE,
dest + clippedFinalDstYScreen * WM_WINDOW_WIDTH + clippedFinalDstXScreen,
WM_WINDOW_WIDTH);
}
return 0;
}
// 0x4C3FA8
static int wmInterfaceDrawCircleOverlay(CityInfo* city, CitySizeDescription* citySizeDescription, unsigned char* dest, int x, int y)
{
@@ -5475,8 +5634,8 @@ static int wmInterfaceDrawSubTileList(TileInfo* tileInfo, int column, int row, i
destY = WM_VIEW_Y;
}
if (height + y > 464) {
height -= height + y - 464;
if (height + y > WM_VIEW_Y + WM_VIEW_HEIGHT) {
height -= height + y - (WM_VIEW_Y + WM_VIEW_HEIGHT);
}
int width = WM_SUBTILE_SIZE * a6;
@@ -5485,8 +5644,8 @@ static int wmInterfaceDrawSubTileList(TileInfo* tileInfo, int column, int row, i
width -= WM_VIEW_X - x;
}
if (width + x > 472) {
width -= width + x - 472;
if (width + x > WM_VIEW_X + WM_VIEW_WIDTH) {
width -= width + x - (WM_VIEW_X + WM_VIEW_WIDTH);
}
if (width > 0 && height > 0) {