diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt
index 1115d0a7..cdeb0439 100644
--- a/artifacts/scripting/sfall function notes.txt
+++ b/artifacts/scripting/sfall function notes.txt
@@ -394,6 +394,11 @@ Some utility/math functions are available:
- take control of a given critter
- passing 0 will reset control back to "real" dude
+> array sfall_func1("get_ini_sections", string fileName)
+- returns an array of names of all sections in a given INI file
+
+> array sfall_func2("get_ini_section", string fileName, string section)
+- returns an associative array of keys and values for a given INI file and section
------------------------
------ MORE INFO -------
diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp
index f3587b62..94dfed3c 100644
--- a/sfall/Modules/Scripting/Handlers/Metarule.cpp
+++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp
@@ -125,6 +125,8 @@ static const SfallMetarule metaruleArray[] = {
{"intface_is_hidden", sf_intface_is_hidden, 0, 0},
{"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}},
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
+ {"get_ini_sections", sf_get_ini_sections, 1, 1, {ARG_STRING}},
+ {"get_ini_section", sf_get_ini_section, 2, 2, {ARG_STRING, ARG_STRING}},
{"set_outline", sf_set_outline, 2, 2, {ARG_OBJECT, ARG_INT}},
{"get_outline", sf_get_outline, 1, 1, {ARG_OBJECT}},
{"set_flags", sf_set_flags, 2, 2, {ARG_OBJECT, ARG_INT}},
diff --git a/sfall/Modules/Scripting/Handlers/Misc.cpp b/sfall/Modules/Scripting/Handlers/Misc.cpp
index 6a765da6..66b185ff 100644
--- a/sfall/Modules/Scripting/Handlers/Misc.cpp
+++ b/sfall/Modules/Scripting/Handlers/Misc.cpp
@@ -16,6 +16,8 @@
* along with this program. If not, see .
*/
+#include
+
#include "..\..\..\FalloutEngine\Fallout2.h"
#include "..\..\AI.h"
#include "..\..\Criticals.h"
@@ -28,6 +30,7 @@
#include "..\..\PlayerModel.h"
#include "..\..\ScriptExtender.h"
#include "..\..\Stats.h"
+#include "..\Arrays.h"
#include "..\OpcodeContext.h"
#include "Misc.h"
@@ -47,6 +50,10 @@ static void _stdcall strcpy_p(char* to, const char* from) {
strcpy_s(to, 64, from);
}
+/************************************************************************/
+/* TODO: Rewrite these raw handlers using OpcodeContext */
+/************************************************************************/
+
void __declspec(naked) op_set_dm_model() {
__asm {
push ebx;
@@ -1714,5 +1721,47 @@ void sf_exec_map_update_scripts(OpcodeContext& ctx) {
__asm call fo::funcoffs::scr_exec_map_update_scripts_
}
+char getIniSectionBuf[512];
+void sf_get_ini_sections(OpcodeContext& ctx) {
+ auto fileName = std::string(".\\") + ctx.arg(0).asString();
+ GetPrivateProfileSectionNamesA(getIniSectionBuf, 512, fileName.data());
+ std::vector sections;
+ char* section = getIniSectionBuf;
+ while (*section != 0) {
+ sections.push_back(section);
+ section += std::strlen(section) + 1;
+ }
+ int arrayId = TempArray(sections.size(), 0);
+ auto& arr = arrays[arrayId];
+
+ for (size_t i = 0; i < sections.size(); ++i) {
+ arr.val[i].set(sections[i]);
+ }
+ ctx.setReturn(arrayId);
+}
+
+void sf_get_ini_section(OpcodeContext& ctx) {
+ auto fileName = std::string(".\\") + ctx.arg(0).asString();
+ auto section = ctx.arg(1).asString();
+ GetPrivateProfileSectionA(section, getIniSectionBuf, 512, fileName.data());
+ int arrayId = TempArray(-1, 0); // associative
+ auto& arr = arrays[arrayId];
+ char *key = getIniSectionBuf, *val = nullptr;
+ while (*key != 0) {
+ char* val = std::strpbrk(key, "=");
+ if (val != nullptr) {
+ *val = '\0';
+ val += 1;
+
+ SetArray(arrayId, ScriptValue(key), ScriptValue(val), false);
+
+ key = val + std::strlen(val) + 1;
+ } else {
+ key += std::strlen(key) + 1;
+ }
+ }
+ ctx.setReturn(arrayId);
+}
+
}
}
diff --git a/sfall/Modules/Scripting/Handlers/Misc.h b/sfall/Modules/Scripting/Handlers/Misc.h
index 378b4711..5319b9dd 100644
--- a/sfall/Modules/Scripting/Handlers/Misc.h
+++ b/sfall/Modules/Scripting/Handlers/Misc.h
@@ -157,5 +157,9 @@ void sf_tile_light(OpcodeContext& ctx);
void sf_exec_map_update_scripts(OpcodeContext&);
+void sf_get_ini_sections(OpcodeContext&);
+
+void sf_get_ini_section(OpcodeContext&);
+
}
}