Compare commits
18 Commits
v1.3.0
...
fix-macos-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c983a6307 | ||
|
|
6a8950c4f2 | ||
|
|
f9af163495 | ||
|
|
9d6f4d9686 | ||
|
|
2e14e4620e | ||
|
|
95d92d8bd0 | ||
|
|
d586e81827 | ||
|
|
67375a5857 | ||
|
|
3dbea2e400 | ||
|
|
bd7321b128 | ||
|
|
ad7b0e56ab | ||
|
|
e770e64a48 | ||
|
|
5956227dcb | ||
|
|
f443e365cc | ||
|
|
b443e21c6e | ||
|
|
19ed168d42 | ||
|
|
939211d640 | ||
|
|
0a9aaab4d1 |
14
.github/workflows/ci-build.yml
vendored
14
.github/workflows/ci-build.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: os/android/app/.cxx
|
||||
key: android-cmake-v1
|
||||
key: android-cmake-v2
|
||||
|
||||
- name: Setup signing config
|
||||
if: env.KEYSTORE_FILE_BASE64 != '' && env.KEYSTORE_PROPERTIES_FILE_BASE64 != ''
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
ios:
|
||||
name: iOS
|
||||
|
||||
runs-on: macos-12
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build
|
||||
key: ios-cmake-v2
|
||||
key: ios-cmake-v4
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build
|
||||
key: linux-${{ matrix.arch }}-cmake-v1
|
||||
key: linux-${{ matrix.arch }}-cmake-v3
|
||||
|
||||
- name: Configure (x86)
|
||||
if: matrix.arch == 'x86'
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
macos:
|
||||
name: macOS
|
||||
|
||||
runs-on: macos-11
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build
|
||||
key: macos-cmake-v4
|
||||
key: macos-cmake-v6
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -265,7 +265,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build
|
||||
key: windows-${{ matrix.arch }}-cmake-v1
|
||||
key: windows-${{ matrix.arch }}-cmake-v2
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
|
||||
@@ -6,10 +6,10 @@ set(EXECUTABLE_NAME fallout2-ce)
|
||||
|
||||
if(APPLE)
|
||||
if(IOS)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11" CACHE STRING "")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "")
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "")
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "")
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
|
||||
endif()
|
||||
endif()
|
||||
@@ -361,8 +361,7 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
add_subdirectory("third_party/fpattern")
|
||||
target_link_libraries(${EXECUTABLE_NAME} ${FPATTERN_LIBRARY})
|
||||
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${FPATTERN_INCLUDE_DIR})
|
||||
target_link_libraries(${EXECUTABLE_NAME} fpattern::fpattern)
|
||||
|
||||
if((NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD"))
|
||||
add_subdirectory("third_party/zlib")
|
||||
|
||||
@@ -8,7 +8,7 @@ There is also [Fallout Community Edition](https://github.com/alexbatalov/fallout
|
||||
|
||||
## Installation
|
||||
|
||||
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2) or [Steam](https://store.steampowered.com/app/38410). Download latest [release](https://github.com/alexbatalov/fallout2-ce/releases) or build from source. You can also check latest [debug](https://github.com/alexbatalov/fallout2-ce/actions) build intended for testers.
|
||||
You must own the game to play. Purchase your copy on [GOG](https://www.gog.com/game/fallout_2), [Epic Games](https://store.epicgames.com/p/fallout-2) or [Steam](https://store.steampowered.com/app/38410). Download latest [release](https://github.com/alexbatalov/fallout2-ce/releases) or build from source. You can also check latest [debug](https://github.com/alexbatalov/fallout2-ce/actions) build intended for testers.
|
||||
|
||||
### Windows
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ typedef enum AnimationType {
|
||||
LAST_SF_DEATH_ANIM = ANIM_FALL_FRONT_BLOOD_SF,
|
||||
} AnimationType;
|
||||
|
||||
#define FID_ANIM_TYPE(value) ((value)&0xFF0000) >> 16
|
||||
#define FID_ANIM_TYPE(value) ((value) & 0xFF0000) >> 16
|
||||
|
||||
// Signature of animation callback accepting 2 parameters.
|
||||
typedef int(AnimationCallback)(void* a1, void* a2);
|
||||
|
||||
@@ -525,7 +525,7 @@ int artCopyFileName(int objectType, int id, char* dest)
|
||||
{
|
||||
ArtListDescription* ptr;
|
||||
|
||||
if (objectType < OBJ_TYPE_ITEM && objectType >= OBJ_TYPE_COUNT) {
|
||||
if (objectType < OBJ_TYPE_ITEM || objectType >= OBJ_TYPE_COUNT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -633,11 +633,11 @@ char* artBuildFilePath(int fid)
|
||||
v5 = (v2 & 0xF000) >> 12;
|
||||
type = FID_TYPE(v2);
|
||||
|
||||
if (v3 >= gArtListDescriptions[type].fileNamesLength) {
|
||||
if (type < OBJ_TYPE_ITEM || type >= OBJ_TYPE_COUNT) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (type < OBJ_TYPE_ITEM || type >= OBJ_TYPE_COUNT) {
|
||||
if (v3 >= gArtListDescriptions[type].fileNamesLength) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -995,7 +995,7 @@ int characterEditorShow(bool isCreationMode)
|
||||
}
|
||||
} else if (characterEditorSelectedItem >= 61 && characterEditorSelectedItem < 79) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
_win_button_press_and_release(gCharacterEditorTagSkillBtns[gCharacterEditorIsCreationMode - 61]);
|
||||
_win_button_press_and_release(gCharacterEditorTagSkillBtns[characterEditorSelectedItem - 61]);
|
||||
windowRefresh(gCharacterEditorWindow);
|
||||
} else {
|
||||
characterEditorHandleAdjustSkillButtonPressed(keyCode);
|
||||
@@ -1003,7 +1003,7 @@ int characterEditorShow(bool isCreationMode)
|
||||
}
|
||||
} else if (characterEditorSelectedItem >= 82 && characterEditorSelectedItem < 98) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
_win_button_press_and_release(gCharacterEditorOptionalTraitBtns[gCharacterEditorIsCreationMode - 82]);
|
||||
_win_button_press_and_release(gCharacterEditorOptionalTraitBtns[characterEditorSelectedItem - 82]);
|
||||
windowRefresh(gCharacterEditorWindow);
|
||||
}
|
||||
}
|
||||
@@ -1018,7 +1018,7 @@ int characterEditorShow(bool isCreationMode)
|
||||
}
|
||||
} else if (characterEditorSelectedItem >= 61 && characterEditorSelectedItem < 79) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
_win_button_press_and_release(gCharacterEditorTagSkillBtns[gCharacterEditorIsCreationMode - 61]);
|
||||
_win_button_press_and_release(gCharacterEditorTagSkillBtns[characterEditorSelectedItem - 61]);
|
||||
windowRefresh(gCharacterEditorWindow);
|
||||
} else {
|
||||
characterEditorHandleAdjustSkillButtonPressed(keyCode);
|
||||
@@ -1026,7 +1026,7 @@ int characterEditorShow(bool isCreationMode)
|
||||
}
|
||||
} else if (characterEditorSelectedItem >= 82 && characterEditorSelectedItem < 98) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
_win_button_press_and_release(gCharacterEditorOptionalTraitBtns[gCharacterEditorIsCreationMode - 82]);
|
||||
_win_button_press_and_release(gCharacterEditorOptionalTraitBtns[characterEditorSelectedItem - 82]);
|
||||
windowRefresh(gCharacterEditorWindow);
|
||||
}
|
||||
}
|
||||
@@ -1877,7 +1877,7 @@ static void characterEditorWindowFree()
|
||||
|
||||
fontSetCurrent(gCharacterEditorOldFont);
|
||||
|
||||
if (gCharacterEditorIsCreationMode == 1) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
skillsSetTagged(gCharacterEditorTempTaggedSkills, 3);
|
||||
traitsSetSelected(gCharacterEditorTempTraits[0], gCharacterEditorTempTraits[1]);
|
||||
characterEditorSelectedItem = 0;
|
||||
@@ -2366,7 +2366,7 @@ static void characterEditorDrawPcStats()
|
||||
char formattedValueBuffer[16];
|
||||
char stringBuffer[128];
|
||||
|
||||
if (gCharacterEditorIsCreationMode == 1) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2930,7 +2930,7 @@ static void characterEditorDrawSkills(int a1)
|
||||
selectedSkill = characterEditorSelectedItem - EDITOR_FIRST_SKILL;
|
||||
}
|
||||
|
||||
if (gCharacterEditorIsCreationMode == 0 && a1 == 0) {
|
||||
if (!gCharacterEditorIsCreationMode && a1 == 0) {
|
||||
buttonDestroy(gCharacterEditorSliderPlusBtn);
|
||||
buttonDestroy(gCharacterEditorSliderMinusBtn);
|
||||
gCharacterEditorSliderMinusBtn = -1;
|
||||
@@ -4868,7 +4868,7 @@ static void characterEditorRestorePlayer()
|
||||
}
|
||||
}
|
||||
|
||||
if (gCharacterEditorIsCreationMode == 1) {
|
||||
if (gCharacterEditorIsCreationMode) {
|
||||
v3 -= gCharacterEditorIsCreationMode;
|
||||
}
|
||||
|
||||
@@ -5373,7 +5373,7 @@ static void characterEditorDrawOptionalTraits()
|
||||
double step;
|
||||
double y;
|
||||
|
||||
if (gCharacterEditorIsCreationMode != 1) {
|
||||
if (!gCharacterEditorIsCreationMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7250,7 +7250,7 @@ static int customKarmaFolderGetFrmId()
|
||||
return entry.frmId;
|
||||
}
|
||||
}
|
||||
return gCustomKarmaFolderDescriptions.end()->frmId;
|
||||
return gCustomKarmaFolderDescriptions.back().frmId;
|
||||
}
|
||||
|
||||
static void customTownReputationInit()
|
||||
|
||||
@@ -5475,11 +5475,13 @@ static void _draw_loc_(int eventCode, int color)
|
||||
// 0x426218
|
||||
static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hitMode)
|
||||
{
|
||||
*hitLocation = HIT_LOCATION_TORSO;
|
||||
|
||||
if (critter == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (critter->pid >> 24 != OBJ_TYPE_CRITTER) {
|
||||
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ int debugPrint(const char* format, ...)
|
||||
|
||||
rc = gDebugPrintProc(string);
|
||||
} else {
|
||||
#ifdef _DEBUG
|
||||
#ifndef NDEBUG
|
||||
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, format, args);
|
||||
#endif
|
||||
rc = -1;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <fpattern.h>
|
||||
#include <fpattern/fpattern.h>
|
||||
|
||||
#include "platform_compat.h"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fpattern.h>
|
||||
#include <fpattern/fpattern.h>
|
||||
|
||||
namespace fallout {
|
||||
|
||||
@@ -30,6 +30,7 @@ bool fileFindFirst(const char* path, DirectoryFileFindData* findData)
|
||||
|
||||
char basePath[COMPAT_MAX_PATH];
|
||||
compat_makepath(basePath, drive, dir, nullptr, nullptr);
|
||||
compat_resolve_path(basePath);
|
||||
|
||||
findData->dir = opendir(basePath);
|
||||
if (findData->dir == nullptr) {
|
||||
|
||||
@@ -107,10 +107,10 @@ static int _background_loop_requested = -1;
|
||||
static char* _sound_sfx_path = _aSoundSfx;
|
||||
|
||||
// 0x518E78
|
||||
static char* _sound_music_path1 = _aSoundMusic_0;
|
||||
static char* _sound_music_path1 = nullptr;
|
||||
|
||||
// 0x518E7C
|
||||
static char* _sound_music_path2 = _aSoundMusic_0;
|
||||
static char* _sound_music_path2 = nullptr;
|
||||
|
||||
// 0x518E80
|
||||
static char* _sound_speech_path = _aSoundSpeech_0;
|
||||
@@ -391,6 +391,9 @@ int gameSoundExit()
|
||||
audioFileExit();
|
||||
audioExit();
|
||||
|
||||
internal_free(_sound_music_path1);
|
||||
internal_free(_sound_music_path2);
|
||||
|
||||
gGameSoundInitialized = false;
|
||||
|
||||
return 0;
|
||||
@@ -1957,12 +1960,15 @@ int _gsound_get_music_path(char** out_value, const char* key)
|
||||
char* copy;
|
||||
char* value;
|
||||
|
||||
configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, out_value);
|
||||
if (!configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, &value)) {
|
||||
*out_value = internal_strdup(_aSoundMusic_0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = *out_value;
|
||||
len = strlen(value);
|
||||
|
||||
if (value[len - 1] == '\\' || value[len - 1] == '/') {
|
||||
*out_value = internal_strdup(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1978,7 +1984,9 @@ int _gsound_get_music_path(char** out_value, const char* key)
|
||||
copy[len] = '\\';
|
||||
copy[len + 1] = '\0';
|
||||
|
||||
if (configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, copy) != 1) {
|
||||
if (!configSetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, copy)) {
|
||||
internal_free(copy);
|
||||
|
||||
if (gGameSoundDebugEnabled) {
|
||||
debugPrint("config_set_string failed in gsound_music_path.\n");
|
||||
}
|
||||
@@ -1986,16 +1994,20 @@ int _gsound_get_music_path(char** out_value, const char* key)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, out_value)) {
|
||||
if (!configGetString(&gGameConfig, GAME_CONFIG_SOUND_KEY, key, &value)) {
|
||||
internal_free(copy);
|
||||
return 0;
|
||||
|
||||
if (gGameSoundDebugEnabled) {
|
||||
debugPrint("config_get_string failed in gsound_music_path.\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gGameSoundDebugEnabled) {
|
||||
debugPrint("config_get_string failed in gsound_music_path.\n");
|
||||
}
|
||||
internal_free(copy);
|
||||
|
||||
return -1;
|
||||
*out_value = internal_strdup(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 0x452378
|
||||
|
||||
31
src/lips.cc
31
src/lips.cc
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace fallout {
|
||||
|
||||
static char* _lips_fix_string(const char* fileName, size_t length);
|
||||
static char* lips_fix_string(const char* fileName, size_t length);
|
||||
static int lipsReadV1(LipsData* a1, File* stream);
|
||||
static int _lips_make_speech();
|
||||
|
||||
@@ -65,14 +65,15 @@ static int _speechStartTime = 0;
|
||||
// 0x613CA0
|
||||
static char _lips_subdir_name[14];
|
||||
|
||||
// 0x613CAE
|
||||
static char _tmp_str[50];
|
||||
|
||||
// 0x47AAC0
|
||||
static char* _lips_fix_string(const char* fileName, size_t length)
|
||||
static char* lips_fix_string(const char* fileName, size_t length)
|
||||
{
|
||||
strncpy(_tmp_str, fileName, length);
|
||||
return _tmp_str;
|
||||
// 0x613CAE
|
||||
static char tmp_str[50];
|
||||
|
||||
strncpy(tmp_str, fileName, length);
|
||||
tmp_str[length] = '\0';
|
||||
return tmp_str;
|
||||
}
|
||||
|
||||
// 0x47AAD8
|
||||
@@ -212,7 +213,7 @@ static int lipsReadV1(LipsData* lipsData, File* stream)
|
||||
if (fileReadInt32(stream, &(lipsData->field_44)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_48)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_4C)) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_50, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->file_name, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_58, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_5C, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_60, 4) == -1) return -1;
|
||||
@@ -235,7 +236,7 @@ int lipsLoad(const char* audioFileName, const char* headFileName)
|
||||
{
|
||||
char* sep;
|
||||
int i;
|
||||
char v60[16];
|
||||
char audioBaseName[16];
|
||||
|
||||
SpeechMarker* speech_marker;
|
||||
SpeechMarker* prev_speech_marker;
|
||||
@@ -254,16 +255,16 @@ int lipsLoad(const char* audioFileName, const char* headFileName)
|
||||
*sep = '\0';
|
||||
}
|
||||
|
||||
strcpy(v60, audioFileName);
|
||||
strcpy(audioBaseName, audioFileName);
|
||||
|
||||
sep = strchr(v60, '.');
|
||||
sep = strchr(audioBaseName, '.');
|
||||
if (sep != nullptr) {
|
||||
*sep = '\0';
|
||||
}
|
||||
|
||||
strcpy(gLipsData.field_50, v60);
|
||||
strncpy(gLipsData.file_name, audioBaseName, sizeof(gLipsData.file_name));
|
||||
|
||||
strcat(path, _lips_fix_string(gLipsData.field_50, sizeof(gLipsData.field_50)));
|
||||
strcat(path, lips_fix_string(gLipsData.file_name, sizeof(gLipsData.file_name)));
|
||||
strcat(path, ".");
|
||||
strcat(path, gLipsData.field_60);
|
||||
|
||||
@@ -296,7 +297,7 @@ int lipsLoad(const char* audioFileName, const char* headFileName)
|
||||
if (fileReadInt32(stream, &(gLipsData.field_24)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(gLipsData.field_28)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(gLipsData.field_2C)) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, gLipsData.field_50, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, gLipsData.file_name, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, gLipsData.field_58, 4) == -1) return -1;
|
||||
} else {
|
||||
debugPrint("\nError: Lips file WRONG version: %s!", path);
|
||||
@@ -405,7 +406,7 @@ static int _lips_make_speech()
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
char* v1 = _lips_fix_string(gLipsData.field_50, sizeof(gLipsData.field_50));
|
||||
char* v1 = lips_fix_string(gLipsData.file_name, sizeof(gLipsData.file_name));
|
||||
snprintf(path, sizeof(path), "%s%s\\%s.%s", "SOUND\\SPEECH\\", _lips_subdir_name, v1, "ACM");
|
||||
|
||||
if (gLipsData.sound != nullptr) {
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef struct LipsData {
|
||||
int field_44;
|
||||
int field_48;
|
||||
int field_4C;
|
||||
char field_50[8];
|
||||
char file_name[8];
|
||||
char field_58[4];
|
||||
char field_5C[4];
|
||||
char field_60[4];
|
||||
|
||||
@@ -390,6 +390,16 @@ int lsgSaveGame(int mode)
|
||||
fileClose(_flptr);
|
||||
}
|
||||
|
||||
if (!messageListInit(&gLoadSaveMessageList)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "LSGAME.MSG");
|
||||
if (!messageListLoad(&gLoadSaveMessageList, path)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_snapshotBuf = nullptr;
|
||||
int v6 = _QuickSnapShot();
|
||||
if (v6 == 1) {
|
||||
@@ -409,16 +419,6 @@ int lsgSaveGame(int mode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!messageListInit(&gLoadSaveMessageList)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
snprintf(path, sizeof(path), "%s%s", asc_5186C8, "LSGAME.MSG");
|
||||
if (!messageListLoad(&gLoadSaveMessageList, path)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
soundPlayFile("iisxxxx1");
|
||||
|
||||
// Error saving game!
|
||||
|
||||
@@ -1255,6 +1255,9 @@ int mapHandleTransition()
|
||||
} else {
|
||||
if (!isInCombat()) {
|
||||
if (gMapTransition.map != gMapHeader.field_34 || gElevation == gMapTransition.elevation) {
|
||||
// SFALL: Remove text floaters after moving to another map.
|
||||
textObjectsReset();
|
||||
|
||||
mapLoadById(gMapTransition.map);
|
||||
}
|
||||
|
||||
|
||||
@@ -700,7 +700,7 @@ void _mouse_get_raw_state(int* out_x, int* out_y, int* out_buttons)
|
||||
// 0x4CAC3C
|
||||
void mouseSetSensitivity(double value)
|
||||
{
|
||||
if (value > 0 && value < 2.0) {
|
||||
if (value >= 1.0 && value <= 2.5) {
|
||||
gMouseSensitivity = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ enum {
|
||||
OBJ_TYPE_COUNT,
|
||||
};
|
||||
|
||||
#define FID_TYPE(value) ((value)&0xF000000) >> 24
|
||||
#define FID_TYPE(value) ((value) & 0xF000000) >> 24
|
||||
#define PID_TYPE(value) (value) >> 24
|
||||
#define SID_TYPE(value) (value) >> 24
|
||||
|
||||
|
||||
@@ -449,6 +449,12 @@ int objectRead(Object* obj, File* stream)
|
||||
if (PID_TYPE(obj->pid) == 0 && !(gMapHeader.flags & 0x01)) {
|
||||
_object_fix_weapon_ammo(obj);
|
||||
}
|
||||
|
||||
if (PID_TYPE(obj->pid) == OBJ_TYPE_ITEM
|
||||
&& itemGetType(obj) == ITEM_TYPE_WEAPON
|
||||
&& obj->data.item.weapon.ammoQuantity < 0) {
|
||||
obj->data.item.weapon.ammoQuantity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1476,6 +1482,9 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
|
||||
}
|
||||
|
||||
if (elevation != oldElevation) {
|
||||
// SFALL: Remove text floaters after moving to another elevation.
|
||||
textObjectsReset();
|
||||
|
||||
mapSetElevation(elevation);
|
||||
tileSetCenter(tile, TILE_SET_CENTER_REFRESH_WINDOW | TILE_SET_CENTER_FLAG_IGNORE_SCROLL_RESTRICTIONS);
|
||||
if (isInCombat()) {
|
||||
|
||||
@@ -150,6 +150,15 @@ int _GNW95_init_mode_ex(int width, int height, int bpp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// macOS seems to require dequeuing NSApp events in order for window to
|
||||
// become visible. There is no concrete number of calls required to make
|
||||
// it happen. Sadly there is no particular event to watch for because SDL
|
||||
// marks window as shown immediately after creation (see
|
||||
// `SDL_FinishWindowCreation`).
|
||||
for (int i = 0; i < 10; i++) {
|
||||
SDL_PumpEvents();
|
||||
}
|
||||
|
||||
_scr_size.left = 0;
|
||||
_scr_size.top = 0;
|
||||
_scr_size.right = width - 1;
|
||||
|
||||
@@ -1294,12 +1294,9 @@ int win_get_num_i(int* value, int min, int max, bool clear, const char* title, i
|
||||
"Cancel",
|
||||
0);
|
||||
|
||||
char* hint = (char*)internal_malloc(80);
|
||||
if (hint == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
char hint[80];
|
||||
|
||||
sprintf(hint, "Please enter a number between %d and %d.", min, max);
|
||||
snprintf(hint, sizeof(hint), "Please enter a number between %d and %d.", min, max);
|
||||
windowRefresh(win);
|
||||
|
||||
int rc;
|
||||
@@ -1317,7 +1314,6 @@ int win_get_num_i(int* value, int min, int max, bool clear, const char* title, i
|
||||
*value = original;
|
||||
}
|
||||
|
||||
internal_free(hint);
|
||||
windowDestroy(win);
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -4380,14 +4380,10 @@ static void wmPartyWalkingStep()
|
||||
// 0x4C219C
|
||||
static void wmInterfaceScrollTabsStart(int delta)
|
||||
{
|
||||
for (int index = 0; index < 7; index++) {
|
||||
buttonDisable(wmTownMapSubButtonIds[index]);
|
||||
}
|
||||
|
||||
wmGenData.oldTabsOffsetY = wmGenData.tabsOffsetY;
|
||||
|
||||
// SFALL: Fix world map cities list scrolling bug that might leave buttons
|
||||
// in the disabled state.
|
||||
if (delta >= 0) {
|
||||
if (wmGenData.oldTabsOffsetY < wmGenData.tabsBackgroundFrmImage.getHeight() - 230) {
|
||||
if (wmGenData.tabsOffsetY < wmGenData.tabsBackgroundFrmImage.getHeight() - 230) {
|
||||
wmGenData.oldTabsOffsetY = std::min(wmGenData.tabsOffsetY + 7 * delta, wmGenData.tabsBackgroundFrmImage.getHeight() - 230);
|
||||
wmGenData.tabsScrollingDelta = delta;
|
||||
}
|
||||
@@ -4398,7 +4394,14 @@ static void wmInterfaceScrollTabsStart(int delta)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Uninline.
|
||||
if (wmGenData.tabsScrollingDelta == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int index = 0; index < 7; index++) {
|
||||
buttonDisable(wmTownMapSubButtonIds[index]);
|
||||
}
|
||||
|
||||
wmInterfaceScrollTabsUpdate();
|
||||
}
|
||||
|
||||
@@ -6247,7 +6250,10 @@ static int wmRefreshTabs()
|
||||
unsigned char* v13;
|
||||
FrmImage labelFrm;
|
||||
|
||||
blitBufferToBufferTrans(wmGenData.tabsBackgroundFrmImage.getData() + wmGenData.tabsBackgroundFrmImage.getWidth() * wmGenData.tabsOffsetY + 9,
|
||||
// CE: Skip first empty tab (original code does this in the
|
||||
// `wmInterfaceInit`).
|
||||
unsigned char* src = wmGenData.tabsBackgroundFrmImage.getData() + wmGenData.tabsBackgroundFrmImage.getWidth() * 27;
|
||||
blitBufferToBufferTrans(src + wmGenData.tabsBackgroundFrmImage.getWidth() * wmGenData.tabsOffsetY + 9,
|
||||
119,
|
||||
178,
|
||||
wmGenData.tabsBackgroundFrmImage.getWidth(),
|
||||
|
||||
30
third_party/fpattern/CMakeLists.txt
vendored
30
third_party/fpattern/CMakeLists.txt
vendored
@@ -1,30 +1,10 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(fpattern
|
||||
GIT_REPOSITORY "https://github.com/Loadmaster/fpattern"
|
||||
GIT_TAG "v1.9"
|
||||
GIT_REPOSITORY "https://github.com/alexbatalov/fpattern"
|
||||
GIT_TAG 8523173ec252c3b796fcdfca0fcc6329642fbbe3 # v1.9
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(fpattern)
|
||||
if (NOT fpattern_POPULATED)
|
||||
FetchContent_Populate(fpattern)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
endif()
|
||||
|
||||
add_library(fpattern STATIC
|
||||
"${fpattern_SOURCE_DIR}/debug.h"
|
||||
"${fpattern_SOURCE_DIR}/fpattern.c"
|
||||
"${fpattern_SOURCE_DIR}/fpattern.h"
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
target_compile_definitions(fpattern PRIVATE
|
||||
"-Dunix"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(FPATTERN_LIBRARY "fpattern" PARENT_SCOPE)
|
||||
set(FPATTERN_INCLUDE_DIR "${fpattern_SOURCE_DIR}" PARENT_SCOPE)
|
||||
FetchContent_MakeAvailable(fpattern)
|
||||
|
||||
Reference in New Issue
Block a user