mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
342fbdd3ae | ||
|
|
0adc9c9e77 | ||
|
|
af413125bd | ||
|
|
afd99fa01b | ||
|
|
3e469ea8e8 | ||
|
|
ddefda32e7 | ||
|
|
0334b8de05 | ||
|
|
1cab275037 | ||
|
|
7eb269bab8 | ||
|
|
c18d7ab25e | ||
|
|
59bf337583 | ||
|
|
88179574e8 | ||
|
|
0733acfad7 | ||
|
|
1388ca1f83 |
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user