mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
36
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a032915aa3 | ||
|
|
8c6f28b018 | ||
|
|
2e36030389 | ||
|
|
a88ca9f7e7 | ||
|
|
72d9ae85c8 | ||
|
|
b7933f6b80 | ||
|
|
fcb1680db2 | ||
|
|
7767aabdce | ||
|
|
9cb2b83db1 | ||
|
|
75ca12e07c | ||
|
|
f85e8ba67b | ||
|
|
07876ddaf9 | ||
|
|
7288f8eeb7 | ||
|
|
1a46d0f59f | ||
|
|
7c2dfa9af1 | ||
|
|
d681e7be69 | ||
|
|
8294e15d3c | ||
|
|
4278d1a1d0 | ||
|
|
b8769fded1 | ||
|
|
43d5b6028d | ||
|
|
b2675ad1ac | ||
|
|
5dafa019c9 | ||
|
|
8888fc46d6 | ||
|
|
001bdbee5c | ||
|
|
190906bb5f | ||
|
|
721e40f784 | ||
|
|
67a6119f34 | ||
|
|
aa036c574e | ||
|
|
a17d7fb7d5 | ||
|
|
8ed777ba83 | ||
|
|
ec2ecd17d9 | ||
|
|
e3437a8d0e | ||
|
|
f12babe525 | ||
|
|
cb990ac154 | ||
|
|
a3fc8d21be | ||
|
|
cc805db194 |
@@ -87,7 +87,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: os/android/app/.cxx
|
||||
key: android-cmake-v2
|
||||
key: android-cmake-v100
|
||||
|
||||
- name: Setup signing config
|
||||
if: env.KEYSTORE_FILE_BASE64 != '' && env.KEYSTORE_PROPERTIES_FILE_BASE64 != ''
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: ios-cmake-v5
|
||||
key: ios-cmake-v100
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -183,7 +183,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: linux-${{ matrix.arch }}-cmake-v3
|
||||
key: linux-${{ matrix.arch }}-cmake-v100
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -288,7 +288,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: macos-cmake-v6
|
||||
key: macos-cmake-v100
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -337,7 +337,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: windows-${{ matrix.arch }}-cmake-v3
|
||||
key: windows-${{ matrix.arch }}-cmake-v100
|
||||
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
|
||||
@@ -125,7 +125,7 @@ IFACE_BAR_SIDES_ORI=0
|
||||
;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.
|
||||
;if IFACE_BAR_WIDTH=800 - Interface bar will use 800pix wide asset from f2_res.dat.
|
||||
IFACE_BAR_WIDTH=640
|
||||
;IFACE_BAR_WIDTH=640
|
||||
```
|
||||
|
||||
Recommendations:
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@
|
||||
[Main]
|
||||
|
||||
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
|
||||
;HiResMode=1
|
||||
;EnableHighResolutionStencil=1
|
||||
|
||||
|
||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
[Misc]
|
||||
|
||||
@@ -166,7 +166,7 @@ procedure array_test_suite begin
|
||||
|
||||
display_msg("All tests finished with "+test_suite_errors+" errors.");
|
||||
|
||||
call report_test_results("Arrays");
|
||||
call report_test_results("arrays");
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "lib.arrays.h" // For arrays_equal, len_array, etc.
|
||||
#include "test_utils.h" // For assertEquals, VALTYPE_STR, report_test_results
|
||||
|
||||
// To test: copy test.ini into the game folder before running
|
||||
procedure ini_test_suite begin
|
||||
variable result_array, expected_array, key_type, value_type, count, key_val_pair;
|
||||
|
||||
display_msg("--- Testing ini functions");
|
||||
|
||||
// Test Case 1: Valid file, valid section
|
||||
result_array := get_ini_section("test.ini", "ValidSection");
|
||||
expected_array := {"Key1": "Value1", "Key2": "2"};
|
||||
call assertEquals("TC1 Size", len_array(result_array), 2);
|
||||
call assertEquals("TC1 Content", arrays_equal(result_array, expected_array), true);
|
||||
count := 0;
|
||||
foreach key_val_pair in result_array begin
|
||||
count += 1;
|
||||
call assertEquals("TC1 Key Type " + count, typeof(key_val_pair[0]), VALTYPE_STR);
|
||||
call assertEquals("TC1 Value Type " + count, typeof(key_val_pair[1]), VALTYPE_STR);
|
||||
end
|
||||
|
||||
// basic fetchers
|
||||
call assertEquals("TC2 Specific Key1 Value", result_array["Key1"], "Value1");
|
||||
call assertEquals("TC2 get_ini_setting string", get_ini_setting("test.ini|ValidSection|Key1"), 0);
|
||||
call assertEquals("TC2 get_ini_string string", get_ini_string("test.ini|ValidSection|Key1"), "Value1");
|
||||
call assertEquals("TC2 get_ini_setting int", get_ini_setting("test.ini|ValidSection|Key2"), 2);
|
||||
call assertEquals("TC2 get_ini_string int", get_ini_string("test.ini|ValidSection|Key2"), "2");
|
||||
|
||||
// INI file not found
|
||||
result_array := get_ini_section("nonexistent.ini", "AnySection");
|
||||
call assertEquals("TC3 Size", len_array(result_array), 0);
|
||||
call assertEquals("TC3 Is Map", array_key(result_array, -1), 1); // Should still be an associative array
|
||||
call assertEquals("TC3 get_ini_setting", get_ini_setting("notexist.ini|ValidSection|Key2"), 0);
|
||||
call assertEquals("TC3 get_ini_string", get_ini_string("notexist.ini|ValidSection|Key2"), "");
|
||||
|
||||
// Valid file, section not found
|
||||
result_array := get_ini_section("test.ini", "NonExistentSection");
|
||||
call assertEquals("TC4 Size", len_array(result_array), 0);
|
||||
call assertEquals("TC4 Is Map", array_key(result_array, -1), 1);
|
||||
call assertEquals("TC4 get_ini_setting", get_ini_setting("test.ini|NonExistentSection|Key2"), 0);
|
||||
call assertEquals("TC4 get_ini_string", get_ini_string("test.ini|NonExistentSection|Key2"), "");
|
||||
|
||||
|
||||
// Valid file, empty section
|
||||
result_array := get_ini_section("test.ini", "EmptySection");
|
||||
call assertEquals("TC5 Size", len_array(result_array), 0);
|
||||
call assertEquals("TC5 Is Map", array_key(result_array, -1), 1);
|
||||
call assertEquals("TC5 get_ini_setting", get_ini_setting("test.ini|EmptySection|Key2"), 0);
|
||||
call assertEquals("TC5 get_ini_string", get_ini_string("test.ini|EmptySection|Key2"), "");
|
||||
|
||||
// set ini setting
|
||||
set_ini_setting("test_set.ini|ValidSection|Key3", "OldValue");
|
||||
call assertEquals("TC6 set_ini_setting 1", get_ini_string("test_set.ini|ValidSection|Key3"), "OldValue");
|
||||
set_ini_setting("test_set.ini|ValidSection|Key3", "NewValue");
|
||||
call assertEquals("TC6 set_ini_setting 2", get_ini_string("test_set.ini|ValidSection|Key3"), "NewValue");
|
||||
set_ini_setting("test_set.ini|ValidSection|Key3", 2);
|
||||
call assertEquals("TC6 set_ini_setting int", get_ini_setting("test_set.ini|ValidSection|Key3"), 2);
|
||||
|
||||
// get_init_sections
|
||||
result_array := get_ini_sections("test.ini");
|
||||
call assertEquals("TC7 get_ini_sections size", len_array(result_array), 3);
|
||||
call assertTrue("TC7 get_ini_sections", scan_array(result_array, "TestMisc") >= 0);
|
||||
|
||||
call report_test_results("ini");
|
||||
end
|
||||
|
||||
procedure start begin
|
||||
call ini_test_suite();
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "test_utils.h"
|
||||
#include "sfall.h"
|
||||
|
||||
procedure start begin
|
||||
|
||||
display_msg("Testing math functions...");
|
||||
|
||||
call assertFloat("sin(0)", sin(0), 0.0);
|
||||
call assertFloat("sin(PI/2)", sin(1.5708), 1.0);
|
||||
call assertFloat("sin(PI)", sin(3.1416), 0.0);
|
||||
call assertFloat("sin(-PI/2)", sin(-1.5708), -1.0);
|
||||
|
||||
call assertFloat("cos(0)", cos(0), 1.0);
|
||||
call assertFloat("cos(PI/2)", cos(1.5708), 0.0);
|
||||
call assertFloat("cos(PI)", cos(3.1416), -1.0);
|
||||
call assertFloat("cos(-PI)", cos(-3.1416), -1.0);
|
||||
|
||||
call assertFloat("tan(0)", tan(0), 0.0);
|
||||
call assertFloat("tan(PI/4)", tan(0.7854), 1.0);
|
||||
call assertFloat("tan(-PI/4)", tan(-0.7854), -1.0);
|
||||
|
||||
call assertFloat("arctan(0, 1)", arctan(0, 1), 0.0);
|
||||
call assertFloat("arctan(1, 1)", arctan(1, 1), 0.7854);
|
||||
call assertFloat("arctan(-1, 1)", arctan(-1, 1), -0.7854);
|
||||
call assertFloat("arctan(1, 0)", arctan(1, 0), 1.5708);
|
||||
|
||||
call assertFloat("log(1)", log(1), 0.0);
|
||||
call assertFloat("log(e)", log(2.7183), 1.0);
|
||||
call assertFloat("log(10)", log(10), 2.3026);
|
||||
|
||||
call assertFloat("exponent(0)", exponent(0), 1.0);
|
||||
call assertFloat("exponent(1)", exponent(1), 2.7183);
|
||||
call assertFloat("exponent(2)", exponent(2), 7.3891);
|
||||
call assertFloat("exponent(-1)", exponent(-1), 0.3679);
|
||||
|
||||
call assertEquals("ceil(2.1)", ceil(2.1), 3);
|
||||
call assertEquals("ceil(2.0)", ceil(2.0), 2);
|
||||
call assertEquals("ceil(-2.1)", ceil(-2.1), -2);
|
||||
call assertEquals("ceil(-2.9)", ceil(-2.9), -2);
|
||||
|
||||
call assertEquals("floor2(2.1)", floor2(2.1), 2);
|
||||
call assertEquals("floor2(2.9)", floor2(2.9), 2);
|
||||
call assertEquals("floor2(-2.1)", floor2(-2.1), -3);
|
||||
call assertEquals("floor2(-2.9)", floor2(-2.9), -3);
|
||||
|
||||
call assertEquals("2^3", 2^3, 8);
|
||||
call assertEquals("4^2", 4^2, 16);
|
||||
call assertEquals("3^0", 3^0, 1);
|
||||
call assertFloat("2^-1", 2^-1, 0); // note: int truncation
|
||||
call assertFloat("2^-1", 2^-1.0, 0.5);
|
||||
call assertFloat("4^0.5", 4^0.5, 2.0);
|
||||
call assertFloat("8^(1/3)", 8^(1.0/3.0), 2.0);
|
||||
call assertFloat("2.5^2", 2.5^2, 6.25);
|
||||
|
||||
call assertEquals("round(2.3)", round(2.3), 2);
|
||||
call assertEquals("round(2.5)", round(2.5), 3);
|
||||
call assertEquals("round(2.7)", round(2.7), 3);
|
||||
call assertEquals("round(-2.3)", round(-2.3), -2);
|
||||
call assertEquals("round(-2.5)", round(-2.5), -3);
|
||||
call assertEquals("round(-2.7)", round(-2.7), -3);
|
||||
call assertEquals("round(0.0)", round(0.0), 0);
|
||||
call assertEquals("round(1.0)", round(1.0), 1);
|
||||
call assertEquals("round(<int>)", round(1), 1);
|
||||
|
||||
call assertFloat("sin(arctan(1, 1))", sin(arctan(1, 1)), 0.7071);
|
||||
call assertFloat("cos(arctan(1, 1))", cos(arctan(1, 1)), 0.7071);
|
||||
call assertFloat("log(ceil(2.7))", log(ceil(2.7)), 1.0986);
|
||||
call assertFloat("exponent(log(5))", exponent(log(5)), 5.0);
|
||||
|
||||
call report_test_results("math");
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "test_utils.h"
|
||||
#include "sfall.h"
|
||||
|
||||
procedure start begin
|
||||
// TODO: move this to a more suitable place, once we have more functions implemented
|
||||
// These are in the "Other" category in the sfall documentation
|
||||
display_msg("Testing misc functions...");
|
||||
variable hand := active_hand;
|
||||
toggle_active_hand;
|
||||
call assertEquals("active_hand toggled", active_hand, 1 - hand);
|
||||
toggle_active_hand;
|
||||
call assertEquals("active_hand toggled", active_hand, hand);
|
||||
|
||||
call report_test_results("misc");
|
||||
end
|
||||
@@ -154,7 +154,7 @@ procedure start begin
|
||||
call test_derived_base_stat_critter(dude_obj);
|
||||
call test_derived_base_stat_critter(closest_critter);
|
||||
|
||||
call report_test_results("Stats");
|
||||
call report_test_results("stats");
|
||||
|
||||
|
||||
// set_pc_base_stat(STAT_lu, 10);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[ValidSection]
|
||||
Key1=Value1
|
||||
Key2=2
|
||||
|
||||
[SectionWithSpaces]
|
||||
LeadingSpaceKey = LeadingSpaceValue
|
||||
TrailingSpaceKey = TrailingSpaceValue
|
||||
Both Sides Space Key = Both Sides Space Value
|
||||
SimpleKey=SimpleValue
|
||||
|
||||
[EmptySection]
|
||||
|
||||
; This is TestMisc, it's not empty but won't be directly tested for content here.
|
||||
[TestMisc]
|
||||
Alpha=Beta
|
||||
Gamma=Delta
|
||||
@@ -7,14 +7,25 @@ variable test_suite_errors := 0;
|
||||
variable test_suite_verbose := false;
|
||||
variable test_suite_assertions := 0;
|
||||
|
||||
procedure assertTrue(variable desc, variable a) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
if (not a) then begin
|
||||
display_msg("Assertion failed \""+desc+"\": is not true");
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("Assert \""+desc+"\" ok");
|
||||
end
|
||||
end
|
||||
|
||||
procedure assertEquals(variable desc, variable a, variable b) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
if (a != b or typeof(a) != typeof(b)) then begin
|
||||
display_msg("Assertion failed \""+desc+"\": "+a+" != "+b);
|
||||
display_msg("FAIL \""+desc+"\": "+a+" != "+b);
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("Assert \""+desc+"\" ok");
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,10 +33,23 @@ procedure assertNotEquals(variable desc, variable a, variable b) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
if (a == b) then begin
|
||||
display_msg("Assertion failed \""+desc+"\": "+a+" == "+b);
|
||||
display_msg("FAIL \""+desc+"\": "+a+" == "+b);
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("Assert \""+desc+"\" ok");
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
procedure assertFloat(variable desc, variable a, variable b, variable tolerance = 0.001) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
variable diff := abs(a - b);
|
||||
if (diff > tolerance) then begin
|
||||
display_msg("FAIL \""+desc+"\": "+a+" != "+b+" (diff: "+diff+")");
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,12 +59,64 @@ procedure report_test_results(variable desc) begin
|
||||
(test_suite_assertions-test_suite_errors) + "/" + test_suite_assertions + "");
|
||||
display_msg("================");
|
||||
|
||||
if (test_suite_errors == 0) then begin
|
||||
float_msg(dude_obj, desc + " tests passed " +
|
||||
(test_suite_assertions-test_suite_errors) + "/" +test_suite_assertions + "!", FLOAT_MSG_GREEN);
|
||||
|
||||
#define GL_VAR_TESTING_INFO_ARRAY_ID "TestArra"
|
||||
#define TEST_ARR_IDENTIFIER_KEY "__testing_info_array__"
|
||||
variable arr_id = get_sfall_global_int(GL_VAR_TESTING_INFO_ARRAY_ID);
|
||||
if arr_id != 0 then begin
|
||||
// Let's check that it is actually our testing array
|
||||
if array_key(arr_id, -1) == 0 then begin
|
||||
// It is not even associative array, so it is not our testing array
|
||||
arr_id = 0;
|
||||
end else begin
|
||||
if arr_id[TEST_ARR_IDENTIFIER_KEY] != 1 then begin
|
||||
// It is associative array, but it is not our testing array
|
||||
arr_id = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
if arr_id == 0 then begin
|
||||
arr_id = create_array(-1, 0);
|
||||
arr_id[TEST_ARR_IDENTIFIER_KEY] = 1;
|
||||
set_sfall_global(GL_VAR_TESTING_INFO_ARRAY_ID, arr_id);
|
||||
end
|
||||
|
||||
|
||||
#define TEST_SUITES "Test suites"
|
||||
#define TEST_ASSERTIONS_TOTAL "Tests assertings total"
|
||||
#define TEST_ASSERTIONS_FAILED "Tests assertings failed"
|
||||
|
||||
if arr_id[TEST_SUITES] == 0 then begin
|
||||
arr_id[TEST_SUITES] = create_array(-1, 0);
|
||||
end
|
||||
|
||||
//set_sfall_global("test_suite_errors", test_suite_errors);
|
||||
|
||||
arr_id[TEST_ASSERTIONS_TOTAL] += test_suite_assertions;
|
||||
arr_id[TEST_ASSERTIONS_FAILED] += test_suite_errors;
|
||||
arr_id[TEST_SUITES][desc] += 1;
|
||||
|
||||
variable total_suites_names = "";
|
||||
variable total_suites_count = 0;
|
||||
|
||||
variable key, item;
|
||||
foreach (key: item in arr_id[TEST_SUITES]) begin
|
||||
total_suites_count += item;
|
||||
if (total_suites_names != "") then begin
|
||||
total_suites_names += ", ";
|
||||
end
|
||||
total_suites_names += key;
|
||||
end
|
||||
|
||||
|
||||
variable assertions_stats_str = (arr_id[TEST_ASSERTIONS_TOTAL]-arr_id[TEST_ASSERTIONS_FAILED]) +
|
||||
"/" + arr_id[TEST_ASSERTIONS_TOTAL];
|
||||
if (arr_id[TEST_ASSERTIONS_FAILED] == 0) then begin
|
||||
float_msg(dude_obj, "Tested " + total_suites_count + " cases: " + total_suites_names + ". " +
|
||||
assertions_stats_str + " assertions passed!", FLOAT_MSG_GREEN);
|
||||
end else begin
|
||||
float_msg(dude_obj, desc + " failed " + test_suite_errors + " tests from " +
|
||||
test_suite_assertions + "!", FLOAT_MSG_RED);
|
||||
float_msg(dude_obj, "Tested " + total_suites_count + " cases: " + total_suites_names + ". " +
|
||||
assertions_stats_str + " assertions passed", FLOAT_MSG_RED);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+18
-3
@@ -6,6 +6,7 @@
|
||||
#include "color.h"
|
||||
#include "db.h"
|
||||
#include "memory_manager.h"
|
||||
#include "settings.h"
|
||||
|
||||
// The maximum number of interface fonts.
|
||||
#define INTERFACE_FONT_MAX (16)
|
||||
@@ -119,11 +120,25 @@ static int interfaceFontLoad(int font_index)
|
||||
InterfaceFontDescriptor* fontDescriptor = &(gInterfaceFontDescriptors[font_index]);
|
||||
|
||||
char path[56];
|
||||
snprintf(path, sizeof(path), "font%d.aaf", font_index);
|
||||
File* stream = nullptr;
|
||||
|
||||
File* stream = fileOpen(path, "rb");
|
||||
// Try set language path first
|
||||
snprintf(path, sizeof(path), "text/%s/font%d.aaf", settings.system.language.c_str(), font_index);
|
||||
stream = fileOpen(path, "rb");
|
||||
|
||||
// Fallback to English if needed
|
||||
if (stream == nullptr && compat_stricmp(settings.system.language.c_str(), ENGLISH) != 0) {
|
||||
snprintf(path, sizeof(path), "text/%s/font%d.aaf", ENGLISH, font_index);
|
||||
stream = fileOpen(path, "rb");
|
||||
}
|
||||
|
||||
// Fallback to original path
|
||||
if (stream == nullptr) {
|
||||
return -1;
|
||||
snprintf(path, sizeof(path), "font%d.aaf", font_index);
|
||||
stream = fileOpen(path, "rb");
|
||||
if (stream == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fileSize = fileGetSize(stream);
|
||||
|
||||
+2
-2
@@ -3241,12 +3241,12 @@ int _gdialog_barter_create_win()
|
||||
backgroundFrmImage.unlock();
|
||||
|
||||
// TRADE
|
||||
_gdialog_buttons[0] = buttonCreate(gGameDialogWindow, 40, 162, 14, 14, -1, -1, -1, KEY_LOWERCASE_M, _redButtonNormalFrmImage.getData(), _redButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
|
||||
_gdialog_buttons[0] = buttonCreate(gGameDialogWindow, 40, 163, 14, 14, -1, -1, -1, KEY_LOWERCASE_M, _redButtonNormalFrmImage.getData(), _redButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
|
||||
if (_gdialog_buttons[0] != -1) {
|
||||
buttonSetCallbacks(_gdialog_buttons[0], _gsound_med_butt_press, _gsound_med_butt_release);
|
||||
|
||||
// TALK
|
||||
_gdialog_buttons[1] = buttonCreate(gGameDialogWindow, 583, 161, 14, 14, -1, -1, -1, KEY_LOWERCASE_T, _redButtonNormalFrmImage.getData(), _redButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
|
||||
_gdialog_buttons[1] = buttonCreate(gGameDialogWindow, 583, 162, 14, 14, -1, -1, -1, KEY_LOWERCASE_T, _redButtonNormalFrmImage.getData(), _redButtonPressedFrmImage.getData(), nullptr, BUTTON_FLAG_TRANSPARENT);
|
||||
if (_gdialog_buttons[1] != -1) {
|
||||
buttonSetCallbacks(_gdialog_buttons[1], _gsound_med_butt_press, _gsound_med_butt_release);
|
||||
|
||||
|
||||
+1
-1
@@ -291,7 +291,7 @@ static FrmImage _yellowLightFrmImage;
|
||||
static FrmImage _redLightFrmImage;
|
||||
|
||||
int gInterfaceBarContentOffset = 0;
|
||||
int gInterfaceBarWidth = -1;
|
||||
int gInterfaceBarWidth = 800; // will fall back to 640 if screen width is too narrow or asset is absent
|
||||
bool gInterfaceBarIsCustom = false;
|
||||
static Art* gCustomInterfaceBarBackground = nullptr;
|
||||
|
||||
|
||||
+17
-9
@@ -3183,15 +3183,6 @@ int programStackPopInteger(Program* program)
|
||||
return programValue.integerValue;
|
||||
}
|
||||
|
||||
float programStackPopFloat(Program* program)
|
||||
{
|
||||
ProgramValue programValue = programStackPopValue(program);
|
||||
if (programValue.opcode != VALUE_TYPE_INT) {
|
||||
programFatalError("float expected, got %x", programValue.opcode);
|
||||
}
|
||||
return programValue.floatValue;
|
||||
}
|
||||
|
||||
char* programStackPopString(Program* program)
|
||||
{
|
||||
ProgramValue programValue = programStackPopValue(program);
|
||||
@@ -3355,4 +3346,21 @@ int ProgramValue::asInt() const
|
||||
}
|
||||
}
|
||||
|
||||
// CE
|
||||
ProgramValue programMakeString(Program* program, const char* str)
|
||||
{
|
||||
ProgramValue valuePv;
|
||||
valuePv.opcode = VALUE_TYPE_DYNAMIC_STRING;
|
||||
valuePv.integerValue = programPushString(program, str);
|
||||
return valuePv;
|
||||
}
|
||||
|
||||
ProgramValue programMakeInt(Program* program, int val)
|
||||
{
|
||||
ProgramValue valuePv;
|
||||
valuePv.opcode = VALUE_TYPE_INT;
|
||||
valuePv.integerValue = val;
|
||||
return valuePv;
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
+4
-1
@@ -230,7 +230,6 @@ void programStackPushPointer(Program* program, void* value);
|
||||
|
||||
ProgramValue programStackPopValue(Program* program);
|
||||
int programStackPopInteger(Program* program);
|
||||
float programStackPopFloat(Program* program);
|
||||
char* programStackPopString(Program* program);
|
||||
void* programStackPopPointer(Program* program);
|
||||
|
||||
@@ -242,6 +241,10 @@ ProgramValue programReturnStackPopValue(Program* program);
|
||||
int programReturnStackPopInteger(Program* program);
|
||||
void* programReturnStackPopPointer(Program* program);
|
||||
|
||||
// CE
|
||||
ProgramValue programMakeString(Program* program, const char* str);
|
||||
ProgramValue programMakeInt(Program* program, int val);
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
#endif /* INTERPRETER_H */
|
||||
|
||||
+26
-9
@@ -2078,34 +2078,51 @@ static void _display_body(int fid, int inventoryWindowType)
|
||||
unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow);
|
||||
int windowPitch = windowGetWidth(gInventoryWindow);
|
||||
|
||||
FrmImage backgroundFrmImage;
|
||||
int Fid = 114;
|
||||
int sourceXOffset = 0;
|
||||
|
||||
if (index == 1) {
|
||||
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) {
|
||||
rect.left = 426;
|
||||
rect.left = 426; // loot right cha window (or container)
|
||||
rect.top = 39;
|
||||
Fid = 114;
|
||||
sourceXOffset = 538;
|
||||
} else {
|
||||
rect.left = 297;
|
||||
rect.left = 297; // inventory data window? ?not used?
|
||||
rect.top = 37;
|
||||
Fid = 48;
|
||||
sourceXOffset = 229;
|
||||
}
|
||||
} else {
|
||||
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) {
|
||||
rect.left = 48;
|
||||
rect.left = 48; // loot left cha window
|
||||
rect.top = 39;
|
||||
} else {
|
||||
rect.left = 176;
|
||||
Fid = 114;
|
||||
sourceXOffset = 0;
|
||||
} else if (inventoryWindowType == INVENTORY_WINDOW_TYPE_USE_ITEM_ON) {
|
||||
rect.left = 176; // Use item cha window
|
||||
rect.top = 37;
|
||||
Fid = 113;
|
||||
sourceXOffset = 292;
|
||||
} else {
|
||||
rect.left = 176; // inventory cha window (same as use on)
|
||||
rect.top = 37;
|
||||
Fid = 48;
|
||||
sourceXOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, Fid, 0, 0, 0);
|
||||
|
||||
rect.right = rect.left + INVENTORY_BODY_VIEW_WIDTH - 1;
|
||||
rect.bottom = rect.top + INVENTORY_BODY_VIEW_HEIGHT - 1;
|
||||
|
||||
FrmImage backgroundFrmImage;
|
||||
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 114, 0, 0, 0);
|
||||
if (backgroundFrmImage.lock(backgroundFid)) {
|
||||
blitBufferToBuffer(backgroundFrmImage.getData() + INVENTORY_LOOT_WINDOW_WIDTH * rect.top + rect.left,
|
||||
blitBufferToBuffer(backgroundFrmImage.getData() + backgroundFrmImage.getWidth() * rect.top + rect.left + sourceXOffset,
|
||||
INVENTORY_BODY_VIEW_WIDTH,
|
||||
INVENTORY_BODY_VIEW_HEIGHT,
|
||||
INVENTORY_LOOT_WINDOW_WIDTH,
|
||||
backgroundFrmImage.getWidth(),
|
||||
windowBuffer + windowPitch * rect.top + rect.left,
|
||||
windowPitch);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ bool sfallConfigInit(int argc, char** argv)
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_AUTO_OPEN_DOORS, 0);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_GAPLESS_MUSIC, 0);
|
||||
|
||||
configSetBool(&gSfallConfig, SFALL_CONFIG_MAIN_KEY, SFALL_CONFIG_ENABLE_HIRES_STENCIL, true);
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
char* executable = argv[0];
|
||||
char* ch = strrchr(executable, '\\');
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace fallout {
|
||||
#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"
|
||||
|
||||
+190
-17
@@ -1,10 +1,14 @@
|
||||
#include "sfall_ini.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdio> // for snprintf
|
||||
#include <cstring> // for strncpy, strlen
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "interpreter.h"
|
||||
#include "platform_compat.h"
|
||||
#include "sfall_arrays.h"
|
||||
|
||||
namespace fallout {
|
||||
|
||||
@@ -68,6 +72,38 @@ static bool is_system_file_name(const char* fileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loads an INI file specified by 'ini_file_name' (e.g., "myconfig.ini" or "ddraw.ini")
|
||||
// into the provided 'config_out' object.
|
||||
// The 'config_out' object must be initialized by the caller (using configInit).
|
||||
// The caller is also responsible for freeing 'config_out' (using configFree).
|
||||
// Returns true if the file was successfully found and read, false otherwise.
|
||||
static bool sfall_load_named_ini_file(const char* ini_file_name, Config* config_out)
|
||||
{
|
||||
if (ini_file_name == nullptr || config_out == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
bool loaded = false;
|
||||
|
||||
if (basePath[0] != '\0' && !is_system_file_name(ini_file_name)) {
|
||||
// Attempt to load requested file in base directory.
|
||||
snprintf(path, sizeof(path), "%s\\%s", basePath, ini_file_name);
|
||||
loaded = configRead(config_out, path, false);
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
// There was no base path set, requested file is a system config, or
|
||||
// non-system config file was not found the base path - attempt to load
|
||||
// from current working directory.
|
||||
strncpy(path, ini_file_name, sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
loaded = configRead(config_out, path, false);
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void sfall_ini_set_base_path(const char* path)
|
||||
{
|
||||
if (path != nullptr) {
|
||||
@@ -111,22 +147,7 @@ bool sfall_ini_get_string(const char* triplet, char* value, size_t size)
|
||||
return false;
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
bool loaded = false;
|
||||
|
||||
if (basePath[0] != '\0' && !is_system_file_name(fileName)) {
|
||||
// Attempt to load requested file in base directory.
|
||||
snprintf(path, sizeof(path), "%s\\%s", basePath, fileName);
|
||||
loaded = configRead(&config, path, false);
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
// There was no base path set, requested file is a system config, or
|
||||
// non-system config file was not found the base path - attempt to load
|
||||
// from current working directory.
|
||||
strcpy(path, fileName);
|
||||
loaded = configRead(&config, path, false);
|
||||
}
|
||||
bool loaded = sfall_load_named_ini_file(fileName, &config);
|
||||
|
||||
// NOTE: Sfall's `GetIniSetting` returns error code (-1) only when it cannot
|
||||
// parse triplet. Otherwise the default for string settings is empty string.
|
||||
@@ -194,4 +215,156 @@ bool sfall_ini_set_string(const char* triplet, const char* value)
|
||||
return saved;
|
||||
}
|
||||
|
||||
static const ConfigSection* sfall_find_section_in_config(Config* config, const char* section_name)
|
||||
{
|
||||
if (config == nullptr || section_name == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int sectionIndex = dictionaryGetIndexByKey(config, section_name);
|
||||
if (sectionIndex == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DictionaryEntry* sectionEntry = &(config->entries[sectionIndex]);
|
||||
return static_cast<const ConfigSection*>(sectionEntry->value);
|
||||
}
|
||||
|
||||
// set_ini_setting
|
||||
void mf_set_ini_setting(Program* program, int args)
|
||||
{
|
||||
const char* triplet = programStackPopString(program);
|
||||
ProgramValue value = programStackPopValue(program);
|
||||
|
||||
if (value.isString()) {
|
||||
const char* stringValue = programGetString(program, value.opcode, value.integerValue);
|
||||
if (!sfall_ini_set_string(triplet, stringValue)) {
|
||||
debugPrint("set_ini_setting: unable to write '%s' to '%s'",
|
||||
stringValue,
|
||||
triplet);
|
||||
}
|
||||
} else {
|
||||
int integerValue = value.asInt();
|
||||
if (!sfall_ini_set_int(triplet, integerValue)) {
|
||||
debugPrint("set_ini_setting: unable to write '%d' to '%s'",
|
||||
integerValue,
|
||||
triplet);
|
||||
}
|
||||
}
|
||||
|
||||
programStackPushInteger(program, -1);
|
||||
}
|
||||
|
||||
// get_ini_section
|
||||
void mf_get_ini_section(Program* program, int args)
|
||||
{
|
||||
// Arguments: file_path (string), section_name (string)
|
||||
|
||||
const char* filePath = programStackPopString(program);
|
||||
const char* sectionName = programStackPopString(program);
|
||||
|
||||
ArrayId arrayId = CreateTempArray(-1, 0);
|
||||
|
||||
if (filePath == nullptr || sectionName == nullptr) {
|
||||
programStackPushInteger(program, arrayId);
|
||||
return;
|
||||
}
|
||||
|
||||
Config iniConfig;
|
||||
if (!configInit(&iniConfig)) {
|
||||
debugPrint("mf_get_ini_section: Failed to initialize Config structure.");
|
||||
programStackPushInteger(program, arrayId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sfall_load_named_ini_file(filePath, &iniConfig)) {
|
||||
const ConfigSection* section = sfall_find_section_in_config(&iniConfig, sectionName);
|
||||
|
||||
if (section != nullptr) {
|
||||
for (int i = 0; i < section->entriesLength; ++i) {
|
||||
DictionaryEntry* entry = &(section->entries[i]);
|
||||
const char* key = entry->key;
|
||||
const char* value = *(static_cast<char**>(entry->value));
|
||||
|
||||
if (key != nullptr && value != nullptr) {
|
||||
SetArray(arrayId, programMakeString(program, key), programMakeString(program, value), false, program);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configFree(&iniConfig);
|
||||
|
||||
programStackPushInteger(program, arrayId);
|
||||
}
|
||||
|
||||
// get_ini_sections
|
||||
void mf_get_ini_sections(Program* program, int args)
|
||||
{
|
||||
// Arguments: file_path (string)
|
||||
const char* filePath = programStackPopString(program);
|
||||
ArrayId arrayId = -1;
|
||||
|
||||
if (filePath == nullptr) {
|
||||
programStackPushInteger(program, arrayId);
|
||||
return;
|
||||
}
|
||||
|
||||
Config iniConfig;
|
||||
if (!configInit(&iniConfig)) {
|
||||
debugPrint("mf_get_ini_sections: Failed to initialize Config structure.");
|
||||
programStackPushInteger(program, arrayId);
|
||||
return;
|
||||
}
|
||||
|
||||
// note: seems to load sections in random order
|
||||
if (sfall_load_named_ini_file(filePath, &iniConfig)) {
|
||||
if (iniConfig.entriesLength > 0) {
|
||||
arrayId = CreateTempArray(iniConfig.entriesLength, 0);
|
||||
for (int i = 0; i < iniConfig.entriesLength; ++i) {
|
||||
DictionaryEntry* entry = &(iniConfig.entries[i]);
|
||||
const char* sectionName = entry->key;
|
||||
|
||||
if (sectionName != nullptr) {
|
||||
SetArray(arrayId, programMakeInt(program, i), programMakeString(program, sectionName), false, program);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configFree(&iniConfig);
|
||||
|
||||
if (arrayId == -1) {
|
||||
arrayId = CreateTempArray(0, 0);
|
||||
}
|
||||
|
||||
programStackPushInteger(program, arrayId);
|
||||
}
|
||||
|
||||
// get_ini_setting
|
||||
void op_get_ini_setting(Program* program)
|
||||
{
|
||||
const char* string = programStackPopString(program);
|
||||
|
||||
int value;
|
||||
if (sfall_ini_get_int(string, &value)) {
|
||||
programStackPushInteger(program, value);
|
||||
} else {
|
||||
programStackPushInteger(program, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// get_ini_string
|
||||
void op_get_ini_string(Program* program)
|
||||
{
|
||||
const char* string = programStackPopString(program);
|
||||
|
||||
char value[256];
|
||||
if (sfall_ini_get_string(string, value, sizeof(value))) {
|
||||
programStackPushString(program, value);
|
||||
} else {
|
||||
programStackPushInteger(program, -1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef FALLOUT_SFALL_INI_H_
|
||||
#define FALLOUT_SFALL_INI_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "dictionary.h"
|
||||
#include "interpreter.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace fallout {
|
||||
@@ -20,6 +23,13 @@ bool sfall_ini_set_int(const char* triplet, int value);
|
||||
/// Writes string key identified by "fileName|section|key" triplet.
|
||||
bool sfall_ini_set_string(const char* triplet, const char* value);
|
||||
|
||||
// metarule and opcode implementations
|
||||
void mf_set_ini_setting(Program* program, int args);
|
||||
void mf_get_ini_section(Program* program, int args);
|
||||
void mf_get_ini_sections(Program* program, int args);
|
||||
void op_get_ini_setting(Program* program);
|
||||
void op_get_ini_string(Program* program);
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
#endif /* FALLOUT_SFALL_INI_H_ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user