mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
Merge pull request #591 from winterheart/ddio-update
Update DDIO and related to it's code OSIRIS
This commit is contained in:
commit
0e228aa9db
@ -40,7 +40,7 @@
|
||||
// input_channels (default 1)
|
||||
// input_factor (compression factor) (default 4 for 22K, 8 for 44K)
|
||||
// input_volscale (Volume scaling) (slightly <= 1.0, default ,97)
|
||||
bool aenc_Compress(char *input_filename, char *output_filename, const int *input_levels = nullptr,
|
||||
bool aenc_Compress(const char *input_filename, const char *output_filename, const int *input_levels = nullptr,
|
||||
const int *input_samples = nullptr, const int *input_rate = nullptr,
|
||||
const int *input_channels = nullptr, const float *input_factor = nullptr,
|
||||
const float *input_volscale = nullptr);
|
||||
|
@ -36,7 +36,7 @@ int32_t aenc_ReadSamp(void *data) {
|
||||
return (b << 8) | a;
|
||||
}
|
||||
|
||||
bool aenc_Compress(char *input_filename, char *output_filename, const int *input_levels, const int *input_samples,
|
||||
bool aenc_Compress(const char *input_filename, const char *output_filename, const int *input_levels, const int *input_samples,
|
||||
const int *input_rate, const int *input_channels, const float *input_factor,
|
||||
const float *input_volscale) {
|
||||
FILE *in, *out;
|
||||
|
@ -645,10 +645,10 @@ void ForceEffectsInit(void) {
|
||||
int lowid;
|
||||
Force_time_since_last_shake = 0;
|
||||
FORCEPROJECT prj;
|
||||
char path[_MAX_PATH];
|
||||
std::filesystem::path path;
|
||||
|
||||
if (cfexist("D3Force.ifr")) {
|
||||
ddio_MakePath(path, Descent3_temp_directory, "D3Force.ifr", NULL);
|
||||
path = Descent3_temp_directory / "D3Force.ifr";
|
||||
cf_CopyFile(path, "D3Force.ifr", 0);
|
||||
prj = ddio_ForceLoadProject(IGNORE_TABLE(path), kJoy1);
|
||||
} else {
|
||||
@ -708,6 +708,6 @@ void ForceEffectsInit(void) {
|
||||
|
||||
ddio_ForceUnloadProject(prj);
|
||||
if (cfexist(path)) {
|
||||
ddio_DeleteFile(path);
|
||||
std::filesystem::remove(path);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ DLLGameClose_fp DLLGameClose = NULL;
|
||||
DLLGetGameInfo_fp DLLGetGameInfo = NULL;
|
||||
dllinfo DLLInfo;
|
||||
tOSIRISModuleInit Multi_d3m_osiris_funcs;
|
||||
char Multi_game_dll_name[_MAX_PATH * 2];
|
||||
std::filesystem::path Multi_game_dll_name;
|
||||
|
||||
static void DUMMYrend_DrawScaledBitmap(int x1, int y1, int x2, int y2, int bm, float u0, float v0, float u1, float v1,
|
||||
float zval, int color, float *alphas) {
|
||||
@ -551,9 +551,9 @@ void CloseGameModule(module *mod) {
|
||||
// Clear out error queue
|
||||
mod_GetLastError();
|
||||
mod_FreeModule(mod);
|
||||
if (Multi_game_dll_name[0] != '\0') {
|
||||
if (Multi_game_dll_name.empty()) {
|
||||
// Try deleting the file now!
|
||||
if (!ddio_DeleteFile(Multi_game_dll_name)) {
|
||||
if (!std::filesystem::remove(Multi_game_dll_name)) {
|
||||
LOG_WARNING << "Couldn't delete the tmp dll";
|
||||
}
|
||||
}
|
||||
@ -561,30 +561,26 @@ void CloseGameModule(module *mod) {
|
||||
}
|
||||
// this function will load up the DLL, but not get any symbols
|
||||
bool InitGameModule(const char *name, module *mod) {
|
||||
char lib_name[_MAX_PATH * 2];
|
||||
char dll_name[_MAX_PATH * 2];
|
||||
char tmp_dll_name[_MAX_PATH * 2];
|
||||
std::filesystem::path lib_name;
|
||||
std::filesystem::path dll_name;
|
||||
std::filesystem::path tmp_dll_name;
|
||||
// Make the hog filename
|
||||
ddio_MakePath(lib_name, Base_directory, "netgames", name, NULL);
|
||||
strcat(lib_name, ".d3m");
|
||||
// Make the dll filename
|
||||
#if defined(WIN32)
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.dll", name);
|
||||
#elif defined(MACOSX)
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.dylib", name);
|
||||
#else
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.so", name);
|
||||
#endif
|
||||
lib_name = std::filesystem::path(Base_directory) / "netgames" / name;
|
||||
lib_name.replace_extension(".d3m");
|
||||
// Make the dll filename
|
||||
dll_name = name;
|
||||
dll_name.replace_extension(MODULE_EXT);
|
||||
|
||||
// Open the hog file
|
||||
if (!cf_OpenLibrary(lib_name)) {
|
||||
ddio_MakePath(tmp_dll_name, Base_directory, "netgames", name, NULL);
|
||||
strcat(tmp_dll_name, ".d3m");
|
||||
Multi_game_dll_name[0] = '\0';
|
||||
tmp_dll_name = std::filesystem::path(Base_directory) / "netgames" / name;
|
||||
tmp_dll_name.replace_extension(".d3m");
|
||||
Multi_game_dll_name.clear();
|
||||
goto loaddll;
|
||||
}
|
||||
// get a temp file name
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3m", tmp_dll_name)) {
|
||||
tmp_dll_name = ddio_GetTmpFileName(Descent3_temp_directory, "d3m");
|
||||
if (tmp_dll_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
// Copy the DLL
|
||||
@ -592,7 +588,7 @@ bool InitGameModule(const char *name, module *mod) {
|
||||
LOG_WARNING << "DLL copy failed!";
|
||||
return false;
|
||||
}
|
||||
strcpy(Multi_game_dll_name, tmp_dll_name);
|
||||
Multi_game_dll_name = tmp_dll_name;
|
||||
loaddll:
|
||||
// Clear out error queue
|
||||
mod_GetLastError();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Descent 3
|
||||
* Descent 3
|
||||
* Copyright (C) 2024 Parallax Software
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -400,6 +400,8 @@
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
|
||||
#include "osiris_dll.h"
|
||||
#include "pserror.h"
|
||||
@ -425,7 +427,6 @@
|
||||
#define OSIRISDEBUG
|
||||
#endif
|
||||
|
||||
|
||||
bool Show_osiris_debug = false;
|
||||
|
||||
#define MAX_LOADED_MODULES 96 // maximum number of dlls that can be loaded at a time
|
||||
@ -510,13 +511,14 @@ struct {
|
||||
|
||||
#define OESF_USED 0x0001
|
||||
#define OESF_MISSION 0x0002 // mission dlls
|
||||
|
||||
struct tExtractedScriptInfo {
|
||||
uint8_t flags;
|
||||
char *temp_filename;
|
||||
char *real_filename;
|
||||
uint8_t flags = 0;
|
||||
std::filesystem::path temp_filename;
|
||||
};
|
||||
static tExtractedScriptInfo OSIRIS_Extracted_scripts[MAX_LOADED_MODULES];
|
||||
static char *OSIRIS_Extracted_script_dir = NULL;
|
||||
|
||||
static std::map<std::filesystem::path, tExtractedScriptInfo> OSIRIS_Extracted_scripts;
|
||||
static std::filesystem::path OSIRIS_Extracted_script_dir;
|
||||
|
||||
// Osiris_CreateModuleInitStruct
|
||||
// Purpose:
|
||||
@ -619,7 +621,7 @@ void Osiris_InitModuleLoader(void) {
|
||||
Osiris_InitMemoryManager();
|
||||
Osiris_InitOMMS();
|
||||
|
||||
OSIRIS_Extracted_script_dir = NULL;
|
||||
OSIRIS_Extracted_script_dir.clear();
|
||||
|
||||
atexit(Osiris_ShutdownModuleLoader);
|
||||
}
|
||||
@ -769,16 +771,15 @@ void Osiris_DumpLoadedObjects(char *file) {
|
||||
// Osiris_FindLoadedModule
|
||||
// Purpose:
|
||||
// Given the name of a module, it returns the id of a loaded OSIRIS module. -1 if it isn't loaded.
|
||||
int Osiris_FindLoadedModule(char *module_name) {
|
||||
int Osiris_FindLoadedModule(const std::filesystem::path &module_name) {
|
||||
// search through the list of loaded modules and see if we can find a match
|
||||
// strip off the extension
|
||||
char real_name[_MAX_PATH];
|
||||
ddio_SplitPath(module_name, NULL, real_name, NULL);
|
||||
std::filesystem::path real_name = module_name.stem();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_LOADED_MODULES; i++) {
|
||||
for (int i = 0; i < MAX_LOADED_MODULES; i++) {
|
||||
if (OSIRIS_loaded_modules[i].flags & OSIMF_INUSE) {
|
||||
if (OSIRIS_loaded_modules[i].module_name && (!stricmp(OSIRIS_loaded_modules[i].module_name, real_name))) {
|
||||
if (OSIRIS_loaded_modules[i].module_name &&
|
||||
(stricmp(OSIRIS_loaded_modules[i].module_name, real_name.u8string().c_str()) == 0)) {
|
||||
// we found a match
|
||||
return i;
|
||||
}
|
||||
@ -797,8 +798,8 @@ void Osiris_UnloadModule(int module_id) {
|
||||
return;
|
||||
if (OSIRIS_loaded_modules[module_id].flags & OSIMF_INUSE) {
|
||||
// the module is in use
|
||||
LOG_DEBUG_IF(Show_osiris_debug).printf("OSIRIS: Decrementing reference count for module (%s)",
|
||||
OSIRIS_loaded_modules[module_id].module_name);
|
||||
LOG_DEBUG_IF(Show_osiris_debug)
|
||||
.printf("OSIRIS: Decrementing reference count for module (%s)", OSIRIS_loaded_modules[module_id].module_name);
|
||||
OSIRIS_loaded_modules[module_id].reference_count--;
|
||||
|
||||
ASSERT(OSIRIS_loaded_modules[module_id].reference_count >= 0);
|
||||
@ -815,8 +816,9 @@ void Osiris_UnloadModule(int module_id) {
|
||||
OSIRIS_loaded_modules[module_id].module_name);
|
||||
} else {
|
||||
// time to unload this module
|
||||
LOG_DEBUG_IF(Show_osiris_debug).printf("OSIRIS: Module (%s) reference count is at 0, unloading",
|
||||
OSIRIS_loaded_modules[module_id].module_name);
|
||||
LOG_DEBUG_IF(Show_osiris_debug)
|
||||
.printf("OSIRIS: Module (%s) reference count is at 0, unloading",
|
||||
OSIRIS_loaded_modules[module_id].module_name);
|
||||
Osiris_FreeModule(module_id);
|
||||
}
|
||||
}
|
||||
@ -880,31 +882,25 @@ void Osiris_UnloadLevelModule(void) {
|
||||
// returns: -2 if not found
|
||||
// -1 if it is in data\scripts
|
||||
// 0-x which extracted script id it is
|
||||
int _get_full_path_to_module(char *module_name, char *fullpath, char *basename) {
|
||||
char ppath[_MAX_PATH], pext[256];
|
||||
char adjusted_name[_MAX_PATH], adjusted_fname[_MAX_PATH];
|
||||
char *p;
|
||||
int get_full_path_to_module(const std::filesystem::path &module_name, std::filesystem::path &fullpath,
|
||||
std::filesystem::path &basename) {
|
||||
std::filesystem::path ppath;
|
||||
std::filesystem::path adjusted_name, adjusted_fname;
|
||||
|
||||
ddio_SplitPath(module_name, ppath, basename, pext);
|
||||
ppath = module_name.parent_path();
|
||||
adjusted_fname = module_name.filename();
|
||||
|
||||
// make sure filename/ext is all lowercase, requirement for Linux, doesn't hurt Windows
|
||||
p = basename;
|
||||
while (p && *p) {
|
||||
*p = tolower(*p);
|
||||
p++;
|
||||
}
|
||||
p = pext;
|
||||
while (p && *p) {
|
||||
*p = tolower(*p);
|
||||
p++;
|
||||
}
|
||||
strcpy(adjusted_fname, basename);
|
||||
strcat(adjusted_fname, pext);
|
||||
std::string p = adjusted_fname.u8string();
|
||||
std::transform(p.begin(), p.end(), p.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
adjusted_fname = p;
|
||||
|
||||
if (strlen(ppath) > 0) {
|
||||
ddio_MakePath(adjusted_name, ppath, adjusted_fname, NULL);
|
||||
basename = adjusted_fname.stem();
|
||||
|
||||
if (ppath.empty()) {
|
||||
adjusted_name = adjusted_fname;
|
||||
} else {
|
||||
strcpy(adjusted_name, adjusted_fname);
|
||||
adjusted_name = ppath / adjusted_fname;
|
||||
}
|
||||
|
||||
// determine real name of script
|
||||
@ -913,28 +909,23 @@ int _get_full_path_to_module(char *module_name, char *fullpath, char *basename)
|
||||
int exist = cfexist(modfilename);
|
||||
switch (exist) {
|
||||
case CFES_ON_DISK:
|
||||
ddio_MakePath(fullpath, LocalScriptDir, modfilename.u8string().c_str(), NULL);
|
||||
fullpath = std::filesystem::path(LocalScriptDir) / modfilename;
|
||||
return -1;
|
||||
break;
|
||||
case CFES_IN_LIBRARY: {
|
||||
ASSERT(OSIRIS_Extracted_script_dir);
|
||||
if (!OSIRIS_Extracted_script_dir)
|
||||
ASSERT(!OSIRIS_Extracted_script_dir.empty());
|
||||
if (OSIRIS_Extracted_script_dir.empty())
|
||||
return -2;
|
||||
|
||||
// search through our list of extracted files to find it...
|
||||
for (int i = 0; i < MAX_LOADED_MODULES; i++) {
|
||||
if (OSIRIS_Extracted_scripts[i].flags & OESF_USED) {
|
||||
if (!stricmp(basename, OSIRIS_Extracted_scripts[i].real_filename)) {
|
||||
// this is it
|
||||
ddio_MakePath(fullpath, OSIRIS_Extracted_script_dir, OSIRIS_Extracted_scripts[i].temp_filename, NULL);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (OSIRIS_Extracted_scripts.find(std::filesystem::path(basename)) != OSIRIS_Extracted_scripts.end()) {
|
||||
fullpath = OSIRIS_Extracted_script_dir / OSIRIS_Extracted_scripts[basename].temp_filename;
|
||||
return 0;
|
||||
}
|
||||
Int3(); // this file was supposed to exist
|
||||
} break;
|
||||
default:
|
||||
*fullpath = '\0';
|
||||
fullpath.clear();
|
||||
return -2;
|
||||
};
|
||||
return -2;
|
||||
@ -947,7 +938,7 @@ int _get_full_path_to_module(char *module_name, char *fullpath, char *basename)
|
||||
// before calling this function, it will return the id to where the module is, and will not reload
|
||||
// the module. Returns -1 if the module does not exist. Returns -2 if the module couldn't initialize.
|
||||
// Returns -3 if the module is not a level module. Returns -4 if no module slots are available.
|
||||
int Osiris_LoadLevelModule(char *module_name) {
|
||||
int Osiris_LoadLevelModule(const std::filesystem::path &module_name) {
|
||||
if ((Game_mode & GM_MULTI) && (Netgame.local_role != LR_SERVER)) {
|
||||
// no scripts for a client!
|
||||
return -2;
|
||||
@ -964,8 +955,9 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
if (loaded_id != -1) {
|
||||
// the module is already loaded
|
||||
OSIRIS_loaded_modules[loaded_id].reference_count++;
|
||||
LOG_DEBUG_IF(Show_osiris_debug).printf("OSIRIS: Level Module (%s) reference count increased to %d",
|
||||
module_name, OSIRIS_loaded_modules[loaded_id].reference_count);
|
||||
LOG_DEBUG_IF(Show_osiris_debug)
|
||||
.printf("OSIRIS: Level Module (%s) reference count increased to %d", module_name.u8string().c_str(),
|
||||
OSIRIS_loaded_modules[loaded_id].reference_count);
|
||||
return loaded_id;
|
||||
}
|
||||
|
||||
@ -979,19 +971,19 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
|
||||
if (loaded_id >= MAX_LOADED_MODULES) {
|
||||
// no slots available
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadLevelModule(%s): No available slots\n", module_name);
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadLevelModule(%s): No available slots\n", module_name.u8string().c_str());
|
||||
Int3();
|
||||
return -4;
|
||||
}
|
||||
|
||||
OSIRIS_loaded_modules[loaded_id].flags = 0; // set this to 0 as we fill in the data
|
||||
|
||||
char fullpath[_MAX_PATH], basename[_MAX_PATH];
|
||||
int ret_val = _get_full_path_to_module(module_name, fullpath, basename);
|
||||
std::filesystem::path fullpath, basename;
|
||||
int ret_val = get_full_path_to_module(module_name, fullpath, basename);
|
||||
switch (ret_val) {
|
||||
case -2:
|
||||
// the module does not exist
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s): Module doesn't exist", module_name);
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s): Module doesn't exist", module_name.u8string().c_str());
|
||||
return -1;
|
||||
break;
|
||||
case -1:
|
||||
@ -999,7 +991,8 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
break;
|
||||
default:
|
||||
// the module was an extracted file
|
||||
LOG_DEBUG.printf("OSIRIS: Found module (%s) in a temp file", basename);
|
||||
LOG_DEBUG.printf("OSIRIS: Found module (%s) in a temp file (%s)", basename.u8string().c_str(),
|
||||
fullpath.u8string().c_str());
|
||||
OSIRIS_loaded_modules[loaded_id].flags |= OSIMF_INTEMPDIR;
|
||||
OSIRIS_loaded_modules[loaded_id].extracted_id = ret_val;
|
||||
break;
|
||||
@ -1008,7 +1001,7 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
// the module exists, now attempt to load it
|
||||
if (!mod_LoadModule(&OSIRIS_loaded_modules[loaded_id].mod, fullpath)) {
|
||||
// there was an error trying to load the module
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadLevelModule(%s): Unable to load module", module_name);
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadLevelModule(%s): Unable to load module", module_name.u8string().c_str());
|
||||
Int3();
|
||||
return -3;
|
||||
}
|
||||
@ -1039,7 +1032,7 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
osm->SaveRestoreState = (SaveRestoreState_fp)mod_GetSymbol(mod, "SaveRestoreState", 8);
|
||||
|
||||
osm->flags |= OSIMF_INUSE | OSIMF_LEVEL;
|
||||
osm->module_name = mem_strdup(basename);
|
||||
osm->module_name = mem_strdup(basename.u8string().c_str());
|
||||
osm->reference_count = 1;
|
||||
|
||||
#ifdef OSIRISDEBUG
|
||||
@ -1052,7 +1045,7 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
!osm->GetCOScriptList || !osm->CreateInstance || !osm->DestroyInstance || !osm->SaveRestoreState ||
|
||||
!osm->CallInstanceEvent) {
|
||||
// there was an error importing a function
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s) couldn't import function.", module_name);
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s) couldn't import function.", module_name.u8string().c_str());
|
||||
Int3();
|
||||
osm->flags = 0;
|
||||
if (osm->module_name)
|
||||
@ -1064,14 +1057,15 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
|
||||
// check to see if there is a corresponding string table to load
|
||||
char stringtablename[_MAX_PATH];
|
||||
strcpy(stringtablename, basename);
|
||||
strcpy(stringtablename, basename.u8string().c_str());
|
||||
strcat(stringtablename, ".str");
|
||||
|
||||
if (cfexist(stringtablename)) {
|
||||
// there is a string table, load it up
|
||||
bool ret = CreateStringTable(stringtablename, &osm->string_table, &osm->strings_loaded);
|
||||
if (!ret) {
|
||||
LOG_ERROR.printf("OSIRIS: Unable to load string table (%s) for (%s)\n", stringtablename, basename);
|
||||
LOG_ERROR.printf("OSIRIS: Unable to load string table (%s) for (%s)", stringtablename,
|
||||
basename.u8string().c_str());
|
||||
Int3();
|
||||
osm->string_table = NULL;
|
||||
osm->strings_loaded = 0;
|
||||
@ -1090,7 +1084,7 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
// when we get to this point we nearly have a loaded module, we just need to initialize it
|
||||
if (!osm->InitializeDLL(&Osiris_module_init)) {
|
||||
// there was an error initializing the module
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s) error initializing module.", basename);
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadLevelModule(%s) error initializing module.", basename.u8string().c_str());
|
||||
if (osm->string_table) {
|
||||
DestroyStringTable(osm->string_table, osm->strings_loaded);
|
||||
}
|
||||
@ -1133,8 +1127,8 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
tOSIRISCurrentLevel.instance =
|
||||
OSIRIS_loaded_modules[loaded_id].CreateInstance(0); // level scripts always have id of 0 in a level dll
|
||||
|
||||
LOG_INFO.printf("OSIRIS: Level Module (%s) loaded successfully (%d custom handles)", basename,
|
||||
tOSIRISCurrentLevel.num_customs);
|
||||
LOG_INFO.printf("OSIRIS: Level Module (%s) loaded successfully (%d custom handles)", basename.u8string().c_str(),
|
||||
tOSIRISCurrentLevel.num_customs);
|
||||
Osiris_level_script_loaded = true;
|
||||
return loaded_id;
|
||||
}
|
||||
@ -1146,8 +1140,8 @@ int Osiris_LoadLevelModule(char *module_name) {
|
||||
// before calling this function, it will return the id to where the module is, and will not reload
|
||||
// the module. Returns -1 if the module does not exist. Returns -2 if the module couldn't initialize.
|
||||
// Returns -3 if the module is not a game module. Returns -4 if no module slots are available.
|
||||
int Osiris_LoadGameModule(char *module_name) {
|
||||
if (module_name[0] == '\0') {
|
||||
int Osiris_LoadGameModule(const std::filesystem::path &module_name) {
|
||||
if (module_name.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1157,8 +1151,8 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
// the module is already loaded
|
||||
OSIRIS_loaded_modules[loaded_id].reference_count++;
|
||||
if (Show_osiris_debug) {
|
||||
LOG_DEBUG.printf("OSIRIS: Game Module (%s) reference count increased to %d", module_name,
|
||||
OSIRIS_loaded_modules[loaded_id].reference_count);
|
||||
LOG_DEBUG.printf("OSIRIS: Game Module (%s) reference count increased to %d", module_name.u8string().c_str(),
|
||||
OSIRIS_loaded_modules[loaded_id].reference_count);
|
||||
}
|
||||
return loaded_id;
|
||||
}
|
||||
@ -1173,19 +1167,19 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
|
||||
if (loaded_id >= MAX_LOADED_MODULES) {
|
||||
// no slots available
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadGameModule(%s): No available slots", module_name);
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadGameModule(%s): No available slots", module_name.u8string().c_str());
|
||||
Int3();
|
||||
return -4;
|
||||
}
|
||||
|
||||
OSIRIS_loaded_modules[loaded_id].flags = 0; // set this to 0 as we fill in the data
|
||||
|
||||
char fullpath[_MAX_PATH], basename[_MAX_PATH];
|
||||
int ret_val = _get_full_path_to_module(module_name, fullpath, basename);
|
||||
std::filesystem::path fullpath, basename;
|
||||
int ret_val = get_full_path_to_module(module_name, fullpath, basename);
|
||||
switch (ret_val) {
|
||||
case -2:
|
||||
// the module does not exist
|
||||
LOG_WARNING.printf("OSIRIS: Osiris_LoadLevelModule(%s): Module doesn't exist", module_name);
|
||||
LOG_WARNING.printf("OSIRIS: Osiris_LoadLevelModule(%s): Module doesn't exist", module_name.u8string().c_str());
|
||||
return -1;
|
||||
break;
|
||||
case -1:
|
||||
@ -1193,7 +1187,7 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
break;
|
||||
default:
|
||||
// the module was an extracted file
|
||||
LOG_INFO.printf("OSIRIS: Found module (%s) in a temp file", basename);
|
||||
LOG_INFO.printf("OSIRIS: Found module (%s) in a temp file", basename.u8string().c_str());
|
||||
OSIRIS_loaded_modules[loaded_id].flags |= OSIMF_INTEMPDIR;
|
||||
OSIRIS_loaded_modules[loaded_id].extracted_id = ret_val;
|
||||
break;
|
||||
@ -1202,7 +1196,7 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
// the module exists, now attempt to load it
|
||||
if (!mod_LoadModule(&OSIRIS_loaded_modules[loaded_id].mod, fullpath)) {
|
||||
// there was an error trying to load the module
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadGameModule(%s): Unable to load module", module_name);
|
||||
LOG_FATAL.printf("OSIRIS: Osiris_LoadGameModule(%s): Unable to load module", module_name.u8string().c_str());
|
||||
Int3();
|
||||
return -3;
|
||||
}
|
||||
@ -1223,52 +1217,53 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
osm->InitializeDLL = (InitializeDLL_fp)mod_GetSymbol(mod, "InitializeDLL", 4);
|
||||
osm->ShutdownDLL = (ShutdownDLL_fp)mod_GetSymbol(mod, "ShutdownDLL", 0);
|
||||
osm->GetGOScriptID = (GetGOScriptID_fp)mod_GetSymbol(mod, "GetGOScriptID", 8);
|
||||
osm->GetTriggerScriptID = NULL;
|
||||
osm->GetCOScriptList = NULL;
|
||||
osm->GetTriggerScriptID = nullptr;
|
||||
osm->GetCOScriptList = nullptr;
|
||||
osm->CreateInstance = (CreateInstance_fp)mod_GetSymbol(mod, "CreateInstance", 4);
|
||||
osm->DestroyInstance = (DestroyInstance_fp)mod_GetSymbol(mod, "DestroyInstance", 8);
|
||||
osm->CallInstanceEvent = (CallInstanceEvent_fp)mod_GetSymbol(mod, "CallInstanceEvent", 16);
|
||||
osm->SaveRestoreState = (SaveRestoreState_fp)mod_GetSymbol(mod, "SaveRestoreState", 8);
|
||||
|
||||
osm->flags |= OSIMF_INUSE;
|
||||
osm->module_name = mem_strdup(basename);
|
||||
osm->module_name = mem_strdup(basename.u8string().c_str());
|
||||
osm->reference_count = 1;
|
||||
|
||||
#ifdef OSIRISDEBUG
|
||||
ASSERT(osm->RefRoot == NULL);
|
||||
osm->RefRoot = NULL;
|
||||
ASSERT(osm->RefRoot == nullptr);
|
||||
osm->RefRoot = nullptr;
|
||||
#endif
|
||||
|
||||
// make sure all of the functions imported ok
|
||||
if (!osm->InitializeDLL || !osm->ShutdownDLL || !osm->GetGOScriptID || !osm->CreateInstance ||
|
||||
!osm->DestroyInstance || !osm->SaveRestoreState || !osm->CallInstanceEvent) {
|
||||
// there was an error importing a function
|
||||
LOG_WARNING.printf("OSIRIS: Osiris_LoadGameModule(%s) couldn't import function.", basename);
|
||||
LOG_WARNING.printf("OSIRIS: Osiris_LoadGameModule(%s) couldn't import function.", basename.u8string().c_str());
|
||||
Int3();
|
||||
osm->flags = 0;
|
||||
if (osm->module_name)
|
||||
mem_free(osm->module_name);
|
||||
osm->module_name = NULL;
|
||||
osm->module_name = nullptr;
|
||||
mod_FreeModule(mod);
|
||||
return -3;
|
||||
}
|
||||
|
||||
// check to see if there is a corresponding string table to load
|
||||
char stringtablename[_MAX_PATH];
|
||||
strcpy(stringtablename, basename);
|
||||
strcpy(stringtablename, basename.u8string().c_str());
|
||||
strcat(stringtablename, ".str");
|
||||
|
||||
if (cfexist(stringtablename)) {
|
||||
// there is a string table, load it up
|
||||
bool ret = CreateStringTable(stringtablename, &osm->string_table, &osm->strings_loaded);
|
||||
if (!ret) {
|
||||
LOG_FATAL.printf("OSIRIS: Unable to load string table (%s) for (%s)", stringtablename, basename);
|
||||
LOG_FATAL.printf("OSIRIS: Unable to load string table (%s) for (%s)", stringtablename,
|
||||
basename.u8string().c_str());
|
||||
Int3();
|
||||
osm->string_table = NULL;
|
||||
osm->string_table = nullptr;
|
||||
osm->strings_loaded = 0;
|
||||
}
|
||||
} else {
|
||||
osm->string_table = NULL;
|
||||
osm->string_table = nullptr;
|
||||
osm->strings_loaded = 0;
|
||||
}
|
||||
Osiris_module_init.string_count = osm->strings_loaded;
|
||||
@ -1280,7 +1275,7 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
// when we get to this point we nearly have a loaded module, we just need to initialize it
|
||||
if (!osm->InitializeDLL(&Osiris_module_init)) {
|
||||
// there was an error initializing the module
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadGameModule(%s) error initializing module.", basename);
|
||||
LOG_ERROR.printf("OSIRIS: Osiris_LoadGameModule(%s) error initializing module.", basename.u8string().c_str());
|
||||
if (osm->string_table) {
|
||||
DestroyStringTable(osm->string_table, osm->strings_loaded);
|
||||
}
|
||||
@ -1301,7 +1296,7 @@ int Osiris_LoadGameModule(char *module_name) {
|
||||
}
|
||||
|
||||
// we have a successful module load
|
||||
LOG_INFO.printf("OSIRIS: Game Module (%s) loaded successfully", basename);
|
||||
LOG_INFO.printf("OSIRIS: Game Module (%s) loaded successfully", basename.u8string().c_str());
|
||||
return loaded_id;
|
||||
}
|
||||
|
||||
@ -1376,8 +1371,8 @@ int Osiris_LoadMissionModule(module *module_handle, const char *filename) {
|
||||
osm->reference_count = 1;
|
||||
|
||||
#ifdef OSIRISDEBUG
|
||||
ASSERT(osm->RefRoot == NULL);
|
||||
osm->RefRoot = NULL;
|
||||
ASSERT(osm->RefRoot == nullptr);
|
||||
osm->RefRoot = nullptr;
|
||||
#endif
|
||||
|
||||
// make sure all of the functions imported ok
|
||||
@ -1653,7 +1648,7 @@ bool Osiris_BindScriptsToObject(object *obj) {
|
||||
if (!gos_instance) {
|
||||
// we had an error obtaining the instance of the COS...doh!
|
||||
LOG_FATAL.printf("OSIRIS: Unable to create COS instance from level dll for (%s)",
|
||||
(page_name) ? (page_name) : "<No Name>");
|
||||
(page_name) ? (page_name) : "<No Name>");
|
||||
Int3();
|
||||
} else {
|
||||
// ok, everything is valid
|
||||
@ -2740,9 +2735,9 @@ bool Osiris_RestoreSystemState(CFILE *file) {
|
||||
// when the state was saved. This means that things are not going to be restored exactly for
|
||||
// sure. We'll skip over those that are not loaded. We're int3 here because I want to know
|
||||
// when this happens.
|
||||
LOG_ERROR.printf(
|
||||
"OSIRIS: Restoring global state, the number of loaded modules is not the same as the restored count (%d vs. %d)",
|
||||
loaded_module_count, read_module_count);
|
||||
LOG_ERROR.printf("OSIRIS: Restoring global state, the number of loaded modules is not the same as the restored "
|
||||
"count (%d vs. %d)",
|
||||
loaded_module_count, read_module_count);
|
||||
if (Demo_flags != DF_PLAYBACK) {
|
||||
Int3();
|
||||
}
|
||||
@ -3098,18 +3093,6 @@ void Osiris_RestoreMemoryChunks(CFILE *file) {
|
||||
}
|
||||
}
|
||||
|
||||
void _extractscript(char *script, char *tempfilename) { cf_CopyFile(tempfilename, script); }
|
||||
|
||||
int _getfreeextractslot(void) {
|
||||
// find a free slot
|
||||
for (int q = 0; q < MAX_LOADED_MODULES; q++) {
|
||||
if (!(OSIRIS_Extracted_scripts[q].flags & OESF_USED)) {
|
||||
return q;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _clearextractedall(void) { Osiris_ClearExtractedScripts(false); }
|
||||
|
||||
int Osiris_ExtractScriptsFromHog(int library_handle, bool is_mission_hog) {
|
||||
@ -3118,17 +3101,18 @@ int Osiris_ExtractScriptsFromHog(int library_handle, bool is_mission_hog) {
|
||||
|
||||
LOG_INFO << "OSIRIS: Extracting Scripts From Hog";
|
||||
|
||||
char filename[_MAX_PATH], temp_filename[_MAX_PATH];
|
||||
char tempdir[_MAX_PATH], temp_file[_MAX_PATH], temp_fileext[_MAX_EXT];
|
||||
char temp_realname[_MAX_PATH];
|
||||
char filename[_MAX_PATH];
|
||||
std::filesystem::path temp_filename;
|
||||
std::filesystem::path tempdir;
|
||||
std::filesystem::path temp_file;
|
||||
std::string temp_realname;
|
||||
tExtractedScriptInfo t;
|
||||
|
||||
if (!OSIRIS_Extracted_script_dir) {
|
||||
strcpy(tempdir, Descent3_temp_directory);
|
||||
OSIRIS_Extracted_script_dir = mem_strdup(tempdir);
|
||||
if (!OSIRIS_Extracted_script_dir)
|
||||
Error("Out of memory");
|
||||
if (OSIRIS_Extracted_script_dir.empty()) {
|
||||
tempdir = Descent3_temp_directory;
|
||||
OSIRIS_Extracted_script_dir = Descent3_temp_directory;
|
||||
} else {
|
||||
strcpy(tempdir, OSIRIS_Extracted_script_dir);
|
||||
tempdir = OSIRIS_Extracted_script_dir;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
@ -3141,69 +3125,58 @@ int Osiris_ExtractScriptsFromHog(int library_handle, bool is_mission_hog) {
|
||||
#elif defined(WIN32)
|
||||
script_extension = "*.dll";
|
||||
#else
|
||||
#error Unsupported platform!
|
||||
#error Unsupported platform!
|
||||
#endif
|
||||
|
||||
int index;
|
||||
index = _getfreeextractslot();
|
||||
if (index == -1) {
|
||||
LOG_FATAL << "OSIRIS: Out of slots extracting scripts!";
|
||||
Int3();
|
||||
goto ex_error;
|
||||
}
|
||||
|
||||
LOG_DEBUG << "Search started";
|
||||
if (cf_LibraryFindFirst(library_handle, script_extension, filename)) {
|
||||
if (!ddio_GetTempFileName(tempdir, "d3s", temp_filename))
|
||||
temp_filename = ddio_GetTmpFileName(tempdir, "d3s");
|
||||
if (temp_filename.empty())
|
||||
Int3();
|
||||
else {
|
||||
ddio_SplitPath(temp_filename, NULL, temp_file, temp_fileext);
|
||||
strcat(temp_file, temp_fileext);
|
||||
// extract it out
|
||||
cf_CopyFile(temp_filename, filename);
|
||||
|
||||
OSIRIS_Extracted_scripts[index].flags = OESF_USED;
|
||||
OSIRIS_Extracted_scripts[index].temp_filename = mem_strdup(temp_file);
|
||||
|
||||
ddio_SplitPath(filename, NULL, temp_realname, NULL);
|
||||
OSIRIS_Extracted_scripts[index].real_filename = mem_strdup(temp_realname);
|
||||
temp_file = temp_filename.filename();
|
||||
temp_realname = std::filesystem::path(filename).stem().u8string();
|
||||
// Lowercase for optimized search
|
||||
std::transform(temp_realname.begin(), temp_realname.end(), temp_realname.begin(), [](unsigned char c) {
|
||||
return std::tolower(c);
|
||||
});
|
||||
|
||||
if (is_mission_hog) {
|
||||
OSIRIS_Extracted_scripts[index].flags |= OESF_MISSION;
|
||||
t.flags = OESF_MISSION;
|
||||
}
|
||||
t.temp_filename = temp_file;
|
||||
OSIRIS_Extracted_scripts.insert_or_assign(temp_realname, t);
|
||||
|
||||
// extract it out
|
||||
_extractscript(filename, temp_filename);
|
||||
LOG_DEBUG.printf("Extracted %s as %s", filename, temp_filename);
|
||||
LOG_DEBUG.printf("Extracted %s as %s", temp_realname.c_str(), temp_filename.u8string().c_str());
|
||||
|
||||
count++;
|
||||
|
||||
while (cf_LibraryFindNext(filename)) {
|
||||
index = _getfreeextractslot();
|
||||
if (index == -1) {
|
||||
LOG_FATAL << "OSIRIS: Out of slots extracting scripts!";
|
||||
Int3();
|
||||
goto ex_error;
|
||||
}
|
||||
|
||||
// generate temp filename
|
||||
if (!ddio_GetTempFileName(tempdir, "d3s", temp_filename))
|
||||
temp_filename = ddio_GetTmpFileName(tempdir, "d3s");
|
||||
if (temp_filename.empty())
|
||||
Int3();
|
||||
else {
|
||||
ddio_SplitPath(temp_filename, NULL, temp_file, temp_fileext);
|
||||
strcat(temp_file, temp_fileext);
|
||||
// extract it out
|
||||
cf_CopyFile(temp_filename, filename);
|
||||
|
||||
OSIRIS_Extracted_scripts[index].flags = OESF_USED;
|
||||
OSIRIS_Extracted_scripts[index].temp_filename = mem_strdup(temp_file);
|
||||
|
||||
ddio_SplitPath(filename, NULL, temp_realname, NULL);
|
||||
OSIRIS_Extracted_scripts[index].real_filename = mem_strdup(temp_realname);
|
||||
temp_file = temp_filename.filename();
|
||||
temp_realname = std::filesystem::path(filename).stem().u8string();
|
||||
// Lowercase for optimized search
|
||||
std::transform(temp_realname.begin(), temp_realname.end(), temp_realname.begin(), [](unsigned char c) {
|
||||
return std::tolower(c);
|
||||
});
|
||||
|
||||
if (is_mission_hog) {
|
||||
OSIRIS_Extracted_scripts[index].flags |= OESF_MISSION;
|
||||
t.flags = OESF_MISSION;
|
||||
}
|
||||
t.temp_filename = temp_file;
|
||||
OSIRIS_Extracted_scripts.insert_or_assign(temp_realname, t);
|
||||
|
||||
// extract it out
|
||||
_extractscript(filename, temp_filename);
|
||||
LOG_DEBUG.printf("Extracted %s as %s", filename, temp_filename);
|
||||
LOG_DEBUG.printf("Extracted %s as %s", temp_realname.c_str(), temp_filename.u8string().c_str());
|
||||
|
||||
count++;
|
||||
}
|
||||
@ -3211,17 +3184,11 @@ int Osiris_ExtractScriptsFromHog(int library_handle, bool is_mission_hog) {
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG << "Done Extracting";
|
||||
LOG_DEBUG.printf("Extracted %d scripts", count);
|
||||
|
||||
ex_error:
|
||||
cf_LibraryFindClose();
|
||||
|
||||
static bool atex = false;
|
||||
|
||||
if (!atex) {
|
||||
atexit(_clearextractedall);
|
||||
atex = true;
|
||||
}
|
||||
atexit(_clearextractedall);
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -3229,35 +3196,20 @@ ex_error:
|
||||
void Osiris_ClearExtractedScripts(bool mission_only) {
|
||||
LOG_DEBUG << "OSIRIS: Removing Extracted DLLs";
|
||||
|
||||
char fullpath[_MAX_PATH];
|
||||
if (!OSIRIS_Extracted_script_dir) {
|
||||
if (OSIRIS_Extracted_script_dir.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_LOADED_MODULES; i++) {
|
||||
if (OSIRIS_Extracted_scripts[i].flags & OESF_USED) {
|
||||
if (mission_only && (!(OSIRIS_Extracted_scripts[i].flags & OESF_MISSION)))
|
||||
continue;
|
||||
for (auto it = OSIRIS_Extracted_scripts.begin(); it != OSIRIS_Extracted_scripts.end(); ++it) {
|
||||
if (mission_only && (!(it->second.flags & OESF_MISSION)))
|
||||
continue;
|
||||
|
||||
ASSERT(OSIRIS_Extracted_scripts[i].temp_filename);
|
||||
ASSERT(OSIRIS_Extracted_scripts[i].real_filename);
|
||||
if (!(OSIRIS_Extracted_scripts[i].temp_filename && OSIRIS_Extracted_scripts[i].real_filename))
|
||||
continue;
|
||||
|
||||
ddio_MakePath(fullpath, OSIRIS_Extracted_script_dir, OSIRIS_Extracted_scripts[i].temp_filename, NULL);
|
||||
ddio_DeleteFile(fullpath);
|
||||
|
||||
mem_free(OSIRIS_Extracted_scripts[i].temp_filename);
|
||||
mem_free(OSIRIS_Extracted_scripts[i].real_filename);
|
||||
OSIRIS_Extracted_scripts[i].temp_filename = NULL;
|
||||
OSIRIS_Extracted_scripts[i].real_filename = NULL;
|
||||
OSIRIS_Extracted_scripts[i].flags &= ~OESF_USED;
|
||||
}
|
||||
std::filesystem::remove(OSIRIS_Extracted_script_dir / it->second.temp_filename);
|
||||
OSIRIS_Extracted_scripts.erase(it);
|
||||
}
|
||||
|
||||
if (!mission_only) {
|
||||
mem_free(OSIRIS_Extracted_script_dir);
|
||||
OSIRIS_Extracted_script_dir = NULL;
|
||||
OSIRIS_Extracted_script_dir.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3313,7 +3265,8 @@ OMMSHANDLE OMMS_Find(uint32_t unique_identifier,char *script_identifier);
|
||||
// Returns information about the OMMS memory given its handle returned from the OMMS_Find() or
|
||||
// OMMS_Malloc(). Returns 0 if the handle was invalid, 1 if the information has been filled in;
|
||||
// Pass NULL in for those parameters you don't need information about.
|
||||
char OMMS_GetInfo(OMMSHANDLE handle,uint32_t *mem_size,uint32_t *uid,uint16_t *reference_count,uint8_t *has_free_been_called);
|
||||
char OMMS_GetInfo(OMMSHANDLE handle,uint32_t *mem_size,uint32_t *uid,uint16_t *reference_count,uint8_t
|
||||
*has_free_been_called);
|
||||
|
||||
|
||||
******************************************************************************
|
||||
@ -3537,7 +3490,7 @@ void Osiris_RestoreOMMS(CFILE *file) {
|
||||
cf_ReadBytes((uint8_t *)node->memory_ptr, node->size_of_memory, file);
|
||||
}
|
||||
} // end reading nodes
|
||||
} // end reading hash nodes
|
||||
} // end reading hash nodes
|
||||
}
|
||||
|
||||
// Searches through the hash nodes and looks for the one associated with
|
||||
|
@ -221,10 +221,9 @@ bool taunt_ImportWave(const char *wave_filename, const char *outputfilename) {
|
||||
int amount_to_flush;
|
||||
tWaveFile wavdata;
|
||||
int samples, rate, chan;
|
||||
char temp_filename[_MAX_PATH];
|
||||
char osftemp_filename[_MAX_PATH];
|
||||
std::filesystem::path temp_filename;
|
||||
std::filesystem::path osftemp_filename;
|
||||
uint8_t *StaticFileBuffer = NULL;
|
||||
*temp_filename = *osftemp_filename = '\0';
|
||||
OSFArchive osf;
|
||||
CFILE *fpin = NULL;
|
||||
bool osfopened;
|
||||
@ -291,7 +290,8 @@ bool taunt_ImportWave(const char *wave_filename, const char *outputfilename) {
|
||||
// now we need to compress it, first it must be written as raw data to a temp
|
||||
// file.
|
||||
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3o", temp_filename)) {
|
||||
temp_filename = ddio_GetTmpFileName(Descent3_temp_directory, "d3o");
|
||||
if (temp_filename.empty()) {
|
||||
LOG_WARNING << "TAUNT: Unable to create temp filename";
|
||||
ret = false;
|
||||
TauntLastError = TAUNTIMPERR_INTERNALERR;
|
||||
@ -346,14 +346,15 @@ bool taunt_ImportWave(const char *wave_filename, const char *outputfilename) {
|
||||
rate = wavdata.samples_per_second;
|
||||
chan = wavdata.number_channels;
|
||||
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3o", osftemp_filename)) {
|
||||
osftemp_filename = ddio_GetTmpFileName(Descent3_temp_directory, "d3o");
|
||||
if (osftemp_filename.empty()) {
|
||||
LOG_WARNING << "TAUNT: Unable to create osftemp filename";
|
||||
TauntLastError = TAUNTIMPERR_INTERNALERR;
|
||||
ret = false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!aenc_Compress(temp_filename, osftemp_filename, NULL, &samples, &rate, &chan, NULL, NULL)) {
|
||||
if (!aenc_Compress(temp_filename.u8string().c_str(), osftemp_filename.u8string().c_str(), NULL, &samples, &rate, &chan, NULL, NULL)) {
|
||||
// unable to compress
|
||||
LOG_WARNING << "Unable to compress";
|
||||
ret = false;
|
||||
@ -467,11 +468,11 @@ error:
|
||||
}
|
||||
|
||||
if (cfexist(osftemp_filename)) {
|
||||
ddio_DeleteFile(osftemp_filename);
|
||||
std::filesystem::remove(osftemp_filename);
|
||||
}
|
||||
|
||||
if (cfexist(temp_filename)) {
|
||||
ddio_DeleteFile(temp_filename);
|
||||
std::filesystem::remove(temp_filename);
|
||||
}
|
||||
|
||||
if (StaticFileBuffer) {
|
||||
|
@ -427,7 +427,7 @@ bool Descent_overrided_intro = false;
|
||||
|
||||
bool Katmai = true;
|
||||
|
||||
char Descent3_temp_directory[_MAX_PATH]; // temp directory to put temp files
|
||||
std::filesystem::path Descent3_temp_directory; // temp directory to put temp files
|
||||
// ---------------------------------------------------------------------------
|
||||
// Descent3: Choke 1
|
||||
// Initializes game elements and invokes the MainLoop
|
||||
|
@ -193,7 +193,7 @@ extern std::filesystem::path orig_pwd;
|
||||
extern grScreen *Game_screen; // The Descent 3 screen.
|
||||
extern oeApplication *Descent; // The Descent object
|
||||
extern oeAppDatabase *Database; // The Database
|
||||
extern char Descent3_temp_directory[_MAX_PATH]; // temp directory to put temp files
|
||||
extern std::filesystem::path Descent3_temp_directory; // temp directory to put temp files
|
||||
extern bool Katmai; // whether or not katmai is detected
|
||||
// ---------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
@ -1468,7 +1468,7 @@ void InitIOSystems(bool editor) {
|
||||
|
||||
// Init hogfiles
|
||||
INIT_MESSAGE(("Checking for HOG files."));
|
||||
int d3_hid = -1, extra_hid = -1, sys_hid = -1, extra13_hid = -1;
|
||||
int d3_hid, extra_hid, sys_hid, extra13_hid;
|
||||
char fullname[_MAX_PATH];
|
||||
|
||||
#ifdef DEMO
|
||||
@ -1536,14 +1536,10 @@ void InitIOSystems(bool editor) {
|
||||
// extract from extra.hog first, so its DLL files are listed ahead of d3.hog's
|
||||
INIT_MESSAGE(("Initializing OSIRIS."));
|
||||
Osiris_InitModuleLoader();
|
||||
if (extra13_hid != -1)
|
||||
Osiris_ExtractScriptsFromHog(extra13_hid, false);
|
||||
if (extra_hid != -1)
|
||||
Osiris_ExtractScriptsFromHog(extra_hid, false);
|
||||
if (merc_hid != -1)
|
||||
Osiris_ExtractScriptsFromHog(merc_hid, false);
|
||||
if (sys_hid != -1)
|
||||
Osiris_ExtractScriptsFromHog(sys_hid, false);
|
||||
Osiris_ExtractScriptsFromHog(extra13_hid, false);
|
||||
Osiris_ExtractScriptsFromHog(extra_hid, false);
|
||||
Osiris_ExtractScriptsFromHog(merc_hid, false);
|
||||
Osiris_ExtractScriptsFromHog(sys_hid, false);
|
||||
Osiris_ExtractScriptsFromHog(d3_hid, false);
|
||||
}
|
||||
|
||||
@ -1958,7 +1954,7 @@ void SetupTempDirectory(void) {
|
||||
|
||||
int t_arg = FindArg("-tempdir");
|
||||
if (t_arg) {
|
||||
strcpy(Descent3_temp_directory, GameArgs[t_arg + 1]);
|
||||
Descent3_temp_directory = GameArgs[t_arg + 1];
|
||||
} else {
|
||||
std::error_code ec;
|
||||
std::filesystem::path tempPath = std::filesystem::temp_directory_path(ec);
|
||||
@ -1966,29 +1962,22 @@ void SetupTempDirectory(void) {
|
||||
Error("Could not find temporary directory: \"%s\"", ec.message().c_str() );
|
||||
exit(1);
|
||||
}
|
||||
ddio_MakePath(Descent3_temp_directory, tempPath.u8string().c_str(), "Descent3",
|
||||
"cache", NULL);
|
||||
Descent3_temp_directory = tempPath / "Descent3" / "cache";
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(Descent3_temp_directory, ec);
|
||||
if (ec) {
|
||||
Error("Could not create temporary directory: \"%s\"", Descent3_temp_directory);
|
||||
Error("Could not create temporary directory: \"%s\"", Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// verify that temp directory exists
|
||||
if (!ddio_SetWorkingDir(Descent3_temp_directory)) {
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char tempfilename[_MAX_PATH];
|
||||
std::filesystem::path tempfilename = ddio_GetTmpFileName(Descent3_temp_directory, "d3t");
|
||||
|
||||
// verify that we can write to the temp directory
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3t", tempfilename)) {
|
||||
if (tempfilename.empty()) {
|
||||
LOG_WARNING << "Unable to get temp file name";
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1997,7 +1986,7 @@ void SetupTempDirectory(void) {
|
||||
if (!file) {
|
||||
// unable to open file for writing
|
||||
LOG_WARNING << "Unable to open temp file name for writing";
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -2009,8 +1998,8 @@ void SetupTempDirectory(void) {
|
||||
if (!file) {
|
||||
// unable to open file for reading
|
||||
LOG_WARNING << "Unable to open temp file name for reading";
|
||||
ddio_DeleteFile(tempfilename);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory);
|
||||
std::filesystem::remove(tempfilename);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -2018,22 +2007,23 @@ void SetupTempDirectory(void) {
|
||||
// verify failed
|
||||
LOG_WARNING << "Temp file verify failed";
|
||||
cfclose(file);
|
||||
ddio_DeleteFile(tempfilename);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory);
|
||||
std::filesystem::remove(tempfilename);
|
||||
Error("Unable to set temporary directory to: \"%s\"", Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cfclose(file);
|
||||
|
||||
// temp directory is valid!
|
||||
ddio_DeleteFile(tempfilename);
|
||||
std::filesystem::remove(tempfilename);
|
||||
|
||||
LOG_INFO << "Temp directory set to: " << Descent3_temp_directory;
|
||||
|
||||
// Lock the directory
|
||||
if (!ddio_CreateLockFile(std::filesystem::path(Descent3_temp_directory))) {
|
||||
LOG_WARNING << "Lock file NOT created in temp dir " << Descent3_temp_directory;
|
||||
Error("Unable to set temporary directory to: \"%s\"\nUnable to create lock file", Descent3_temp_directory);
|
||||
Error("Unable to set temporary directory to: \"%s\"\nUnable to create lock file",
|
||||
Descent3_temp_directory.u8string().c_str());
|
||||
exit(1);
|
||||
}
|
||||
// restore working dir
|
||||
|
@ -277,6 +277,8 @@
|
||||
* $NoKeywords: $
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "chrono_timer.h"
|
||||
#include "ui.h"
|
||||
#include "newui.h"
|
||||
@ -370,7 +372,7 @@ char Auto_login_name[MAX_AUTO_LOGIN_STUFF_LEN];
|
||||
char Auto_login_pass[MAX_AUTO_LOGIN_STUFF_LEN];
|
||||
char Auto_login_addr[MAX_AUTO_LOGIN_STUFF_LEN];
|
||||
char Auto_login_port[MAX_AUTO_LOGIN_STUFF_LEN];
|
||||
char Multi_conn_dll_name[_MAX_PATH * 2] = "";
|
||||
std::filesystem::path Multi_conn_dll_name;
|
||||
char PXO_hosted_lobby_name[100] = "global";
|
||||
bool Supports_score_api = false;
|
||||
#ifdef USE_DIRECTPLAY
|
||||
@ -576,19 +578,20 @@ void FreeMultiDLL() {
|
||||
DLLMultiClose();
|
||||
mod_FreeModule(&MultiDLLHandle);
|
||||
// Try deleting the file now!
|
||||
if (!ddio_DeleteFile(Multi_conn_dll_name)) {
|
||||
if (!std::filesystem::remove(Multi_conn_dll_name)) {
|
||||
LOG_WARNING << "Couldn't delete the tmp dll";
|
||||
}
|
||||
DLLMultiCall = NULL;
|
||||
DLLMultiInit = NULL;
|
||||
DLLMultiClose = NULL;
|
||||
}
|
||||
|
||||
// Loads the Multi dll. Returns 1 on success, else 0 on failure
|
||||
int LoadMultiDLL(const char *name) {
|
||||
static int first = 1;
|
||||
char lib_name[_MAX_PATH * 2];
|
||||
char dll_name[_MAX_PATH * 2];
|
||||
char tmp_dll_name[_MAX_PATH * 2];
|
||||
std::filesystem::path lib_name;
|
||||
std::filesystem::path dll_name;
|
||||
std::filesystem::path tmp_dll_name;
|
||||
MultiFlushAllIncomingBuffers();
|
||||
|
||||
// Delete old dlls
|
||||
@ -605,35 +608,30 @@ int LoadMultiDLL(const char *name) {
|
||||
});
|
||||
|
||||
// Make the hog filename
|
||||
ddio_MakePath(lib_name, Base_directory, "online", name, NULL);
|
||||
strcat(lib_name, ".d3c");
|
||||
// Make the dll filename
|
||||
#if defined(WIN32)
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.dll", name);
|
||||
#elif defined(MACOSX)
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.dylib", name);
|
||||
#else
|
||||
snprintf(dll_name, sizeof(dll_name), "%s.so", name);
|
||||
#endif
|
||||
lib_name = std::filesystem::path(Base_directory) / "online" / name;
|
||||
lib_name.replace_extension(".d3c");
|
||||
// Make the dll filename
|
||||
dll_name = name;
|
||||
dll_name.replace_extension(MODULE_EXT);
|
||||
|
||||
// Open the hog file
|
||||
if (!cf_OpenLibrary(lib_name)) {
|
||||
ddio_MakePath(tmp_dll_name, Base_directory, "online", name, NULL);
|
||||
strcat(tmp_dll_name, ".d3c");
|
||||
Multi_conn_dll_name[0] = 0;
|
||||
tmp_dll_name = std::filesystem::path(Base_directory) / "online" / name;
|
||||
tmp_dll_name.replace_extension(".d3c");
|
||||
Multi_conn_dll_name.clear();
|
||||
goto loaddll;
|
||||
}
|
||||
// get a temp file name
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3c", tmp_dll_name)) {
|
||||
tmp_dll_name = ddio_GetTmpFileName(Descent3_temp_directory, "d3c");
|
||||
if (tmp_dll_name.empty()) {
|
||||
return 0;
|
||||
}
|
||||
// Copy the DLL
|
||||
// ddio_MakePath(dll_path_name,Base_directory,"online",tmp_dll_name,NULL);
|
||||
if (!cf_CopyFile(tmp_dll_name, dll_name)) {
|
||||
LOG_WARNING << "DLL copy failed!";
|
||||
return 0;
|
||||
}
|
||||
strcpy(Multi_conn_dll_name, tmp_dll_name);
|
||||
Multi_conn_dll_name = tmp_dll_name;
|
||||
loaddll:
|
||||
|
||||
if (!mod_LoadModule(&MultiDLLHandle, tmp_dll_name)) {
|
||||
@ -700,6 +698,7 @@ loaddll:
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The chokepoint function to call the dll function
|
||||
void CallMultiDLL(int eventnum) {
|
||||
if (MultiDLLHandle.handle && DLLMultiCall)
|
||||
|
@ -138,7 +138,7 @@ extern void Osiris_ShutdownModuleLoader(void);
|
||||
// Osiris_FindLoadedModule
|
||||
// Purpose:
|
||||
// Given the name of a module, it returns the id of a loaded OSIRIS module. -1 if it isn't loaded.
|
||||
extern int Osiris_FindLoadedModule(char *filename);
|
||||
extern int Osiris_FindLoadedModule(const std::filesystem::path &module_name);
|
||||
|
||||
// Osiris_LoadLevelModule
|
||||
// Purpose:
|
||||
@ -147,7 +147,7 @@ extern int Osiris_FindLoadedModule(char *filename);
|
||||
// before calling this function, it will return the id to where the module is, and will not reload
|
||||
// the module. Returns -1 if the module does not exist. Returns -2 if the module couldn't initialize.
|
||||
// Returns -3 if the module is not a level module. Returns -4 if no module slots are available.
|
||||
extern int Osiris_LoadLevelModule(char *module_name);
|
||||
extern int Osiris_LoadLevelModule(const std::filesystem::path &module_name);
|
||||
|
||||
// Osiris_UnloadLevelModule
|
||||
// Purpose:
|
||||
@ -163,7 +163,7 @@ extern void Osiris_UnloadLevelModule(void);
|
||||
// before calling this function, it will return the id to where the module is, and will not reload
|
||||
// the module. Returns -1 if the module does not exist. Returns -2 if the module couldn't initialize.
|
||||
// Returns -3 if the module is not a game module. Returns -4 if no module slots are available.
|
||||
extern int Osiris_LoadGameModule(char *module_name);
|
||||
extern int Osiris_LoadGameModule(const std::filesystem::path &module_name);
|
||||
|
||||
// Osiris_UnloadModule
|
||||
// Purpose:
|
||||
|
@ -1965,10 +1965,10 @@ bool ImportGraphic(const char *pathname, char *newfile) {
|
||||
|
||||
bm_ChangeSize(bm_handle, 64, 64);
|
||||
|
||||
char tempfilename[_MAX_PATH];
|
||||
std::filesystem::path tempfilename = ddio_GetTmpFileName(Descent3_temp_directory, "d3i");
|
||||
|
||||
// Create a temporary filename, so that we can temporarily save the graphic to this file
|
||||
if (!ddio_GetTempFileName(Descent3_temp_directory, "d3i", tempfilename)) {
|
||||
if (tempfilename.empty()) {
|
||||
// there was an error trying to create a temporary filename
|
||||
bm_FreeBitmap(bm_handle);
|
||||
LOG_WARNING << "Error creating temp filename";
|
||||
@ -2004,7 +2004,7 @@ bool ImportGraphic(const char *pathname, char *newfile) {
|
||||
|
||||
// p contains the real filename
|
||||
// tempfilename contains old filename
|
||||
bm_handle = bm_AllocLoadFileBitmap(IGNORE_TABLE(tempfilename), 0);
|
||||
bm_handle = bm_AllocLoadFileBitmap(IGNORE_TABLE(tempfilename.u8string().c_str()), 0);
|
||||
if (bm_handle <= BAD_BITMAP_HANDLE) {
|
||||
LOG_WARNING << "Error reloading bitmap for rename";
|
||||
std::filesystem::remove(tempfilename, ec);
|
||||
|
@ -39,3 +39,7 @@ target_include_directories(ddio PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/ddio
|
||||
>
|
||||
)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
31
ddio/ddio.h
31
ddio/ddio.h
@ -374,27 +374,14 @@ void ddio_MakePath(char *newPath, const char *absolutePathHeader, const char *su
|
||||
void ddio_DoForeachFile(const std::filesystem::path &search_path, const std::regex ®ex,
|
||||
const std::function<void(std::filesystem::path)> &func);
|
||||
|
||||
// given a path (with no filename), it will return the parent path
|
||||
// srcPath is the source given path
|
||||
// dest is where the parent path will be placed
|
||||
// returns true on success
|
||||
// dest should be at least _MAX_PATH in length
|
||||
bool ddio_GetParentPath(char *dest, const char *srcPath);
|
||||
|
||||
// given a path, it cleans it up (if the path is c:\windows\..\dos it would make it c:\dos)
|
||||
// srcPath is the original path
|
||||
// dest is the finished cleaned path.
|
||||
// dest should be at least _MAX_PATH in size
|
||||
void ddio_CleanPath(char *dest, const char *srcPath);
|
||||
|
||||
// Generates a temporary filename based on the prefix, and basedir
|
||||
// Parameters:
|
||||
// basedir - directory to put the files
|
||||
// prefix - prefix for the temp filename
|
||||
// filename - buffer to hold generated filename (must be at least _MAX_PATH in length)
|
||||
//
|
||||
// Returns TRUE if successful, FALSE if an error
|
||||
bool ddio_GetTempFileName(const char *basedir, const char *prefix, char *filename);
|
||||
/**
|
||||
* Generates a temporary filename based on the prefix in basedir. Function ensures that generated
|
||||
* filename does not exists in basedir directory.
|
||||
* @param basedir directory to put the files
|
||||
* @param prefix prefix for the temp filename
|
||||
* @return generated filename with ".tmp" extension in basedir directory or empty path on failure
|
||||
*/
|
||||
std::filesystem::path ddio_GetTmpFileName(const std::filesystem::path &basedir, const char *prefix);
|
||||
|
||||
/**
|
||||
* Check process existence by PID
|
||||
@ -425,4 +412,4 @@ bool ddio_CreateLockFile(const std::filesystem::path &dir);
|
||||
*/
|
||||
bool ddio_DeleteLockFile(const std::filesystem::path &dir);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -17,13 +17,16 @@
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <regex>
|
||||
|
||||
#include "IOOps.h"
|
||||
#include "chrono_timer.h"
|
||||
#include "ddio.h"
|
||||
#include "mem.h"
|
||||
#include "pserror.h"
|
||||
|
||||
const std::array<char, 4> LOCK_TAG = {'L', 'O', 'C', 'K'};
|
||||
@ -156,3 +159,36 @@ void ddio_DoForeachFile(const std::filesystem::path &search_path, const std::reg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path ddio_GetTmpFileName(const std::filesystem::path &basedir, const char *prefix) {
|
||||
static const char alphanum[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
// size of random part
|
||||
const int len = 10;
|
||||
const char *ext = ".tmp";
|
||||
std::filesystem::path result;
|
||||
size_t len_result = strlen((basedir / prefix).u8string().c_str());
|
||||
char *random_name = (char *)mem_malloc(len_result + len + strlen(ext) + 1);
|
||||
strncpy(random_name, (basedir / prefix).u8string().c_str(), len_result);
|
||||
|
||||
srand(D3::ChronoTimer::GetTimeMS());
|
||||
|
||||
int tries = 20;
|
||||
while (tries > 0) {
|
||||
for (size_t i = len_result; i < len_result + len; i++) {
|
||||
random_name[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
random_name[len_result + len] = '\0';
|
||||
strcat(random_name, ext);
|
||||
if (!std::filesystem::exists(random_name)) {
|
||||
// Found unique name, break the loop
|
||||
result = random_name;
|
||||
break;
|
||||
}
|
||||
tries--;
|
||||
}
|
||||
mem_free(random_name);
|
||||
return result;
|
||||
}
|
||||
|
210
ddio/lnxfile.cpp
210
ddio/lnxfile.cpp
@ -266,216 +266,6 @@ int ddio_GetFileSysRoots(char **roots, int max_roots) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// given a path, it cleans it up (if the path is /usr/lib/../src it would make it /usr/src)
|
||||
// srcPath is the original path
|
||||
// dest is the finished cleaned path.
|
||||
// dest should be at least _MAX_PATH in size
|
||||
void ddio_CleanPath(char *dest, const char *srcPath) {
|
||||
// NOTE: we may want to use getcwd() here if we don't want symbolic links
|
||||
// but I think we do
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
strcpy(dest, srcPath);
|
||||
|
||||
// break the path into directories
|
||||
char **directories;
|
||||
int dirs;
|
||||
int path_length;
|
||||
|
||||
// make sure the path ends with a / for sanity
|
||||
path_length = strlen(dest);
|
||||
|
||||
if (dest[path_length - 1] != '/') {
|
||||
dest[path_length] = '/';
|
||||
dest[path_length + 1] = '\0';
|
||||
path_length++;
|
||||
}
|
||||
|
||||
// now divide the full path into separate NULL terminated strings,counting the number
|
||||
// of directories in the process
|
||||
dirs = 0;
|
||||
char *strptr;
|
||||
if (dest[0] == '/')
|
||||
strptr = dest + 1; // skip first / of root dir
|
||||
else
|
||||
strptr = dest;
|
||||
|
||||
while (*strptr != '\0') {
|
||||
if (*strptr == '/') {
|
||||
*strptr = '\0';
|
||||
dirs++;
|
||||
}
|
||||
strptr++;
|
||||
}
|
||||
|
||||
// check to make sure we have a directory, if we don't then return the original path given
|
||||
if (dirs == 0) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate the memory needed for the separate strings of each directory
|
||||
directories = mem_rmalloc<char *>(dirs);
|
||||
if (!directories) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// now get all the directories, and place into the individual strings
|
||||
strptr = dest;
|
||||
int count = 0;
|
||||
while (count < dirs) {
|
||||
directories[count] = mem_strdup(strptr);
|
||||
strptr += strlen(strptr) + 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
// now the fun part, figure out the correct order of the directories
|
||||
int *dir_order;
|
||||
|
||||
dir_order = mem_rmalloc<int>(dirs);
|
||||
if (!dir_order) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
for (count = 0; count < dirs; count++)
|
||||
dir_order[count] = -1; // a -1 means the end of the sequence
|
||||
|
||||
// now build the order based on the indicies
|
||||
int curr_index = 0;
|
||||
for (count = 0; count < dirs; count++) {
|
||||
|
||||
if (!stricmp(directories[count], "..")) {
|
||||
// we have to back up a directory
|
||||
curr_index--; // back up
|
||||
if (curr_index < 0)
|
||||
curr_index = 0; // can't go further than root
|
||||
dir_order[curr_index] = -1; // invalidate current slot
|
||||
} else if (stricmp(directories[count], ".")) {
|
||||
// we have a normal directory, add its index
|
||||
dir_order[curr_index] = count;
|
||||
curr_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// now rebuild the correct path for use, when we hit -1, we're done
|
||||
dest[0] = '\0';
|
||||
for (count = 0; count < dirs; count++) {
|
||||
if (dir_order[count] == -1)
|
||||
break;
|
||||
else {
|
||||
strcat(dest, directories[dir_order[count]]);
|
||||
strcat(dest, "/");
|
||||
}
|
||||
}
|
||||
|
||||
// now remove trailing / char
|
||||
path_length = strlen(dest);
|
||||
if ((path_length > 0) && (dest[path_length - 1] == '/'))
|
||||
dest[path_length - 1] = '\0';
|
||||
|
||||
// free up all the allocated memory and we're done
|
||||
for (count = 0; count < dirs; count++) {
|
||||
if (directories[count])
|
||||
mem_free(directories[count]);
|
||||
}
|
||||
if (directories)
|
||||
mem_free(directories);
|
||||
if (dir_order)
|
||||
mem_free(dir_order);
|
||||
}
|
||||
|
||||
// given a path (with no filename), it will return the parent path
|
||||
// srcPath is the source given path
|
||||
// dest is where the parent path will be placed
|
||||
// returns true on success
|
||||
// dest should be at least _MAX_PATH in length
|
||||
bool ddio_GetParentPath(char *dest, const char *srcPath) {
|
||||
assert(srcPath);
|
||||
assert(dest);
|
||||
|
||||
#define PARENT_DELIM ".."
|
||||
int spath_len = strlen(srcPath);
|
||||
char *temp;
|
||||
|
||||
temp = (char *)mem_malloc(spath_len + strlen(PARENT_DELIM) + 3);
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ddio_MakePath(temp, srcPath, PARENT_DELIM, NULL);
|
||||
ddio_CleanPath(dest, temp);
|
||||
mem_free(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Generates a temporary filename based on the prefix, and basedir
|
||||
// Parameters:
|
||||
// basedir - directory to put the files
|
||||
// prefix - prefix for the temp filename
|
||||
// filename - buffer to hold generated filename (must be at least _MAX_PATH in length)
|
||||
//
|
||||
// Returns TRUE if successful, FALSE if an error
|
||||
bool ddio_GetTempFileName(const char *basedir, const char *prefix, char *filename) {
|
||||
char old_workdir[_MAX_PATH];
|
||||
bool success = false;
|
||||
|
||||
if (strlen(prefix) > 64)
|
||||
return false;
|
||||
|
||||
ddio_GetWorkingDir(old_workdir, _MAX_PATH);
|
||||
|
||||
if (!ddio_SetWorkingDir(basedir)) {
|
||||
return false; // invalid base directory
|
||||
}
|
||||
|
||||
char randname[10];
|
||||
int index;
|
||||
int tries = 0;
|
||||
char rc;
|
||||
|
||||
bool created = false;
|
||||
|
||||
index = 0;
|
||||
|
||||
while (!success && tries < 20) {
|
||||
// generate a bunch of random characters
|
||||
rc = (rand() % 128);
|
||||
if ((rc >= 'a' && rc <= 'z') || (rc >= 'A' && rc <= 'Z') || (rc >= '0' && rc <= '9')) {
|
||||
// valid character
|
||||
randname[index] = rc;
|
||||
index++;
|
||||
|
||||
if (index == 10) {
|
||||
// we hit the size of our max, see if we generated a unique filename
|
||||
char t[_MAX_PATH];
|
||||
randname[9] = '\0';
|
||||
snprintf(t, sizeof(t), "%s%s.tmp", prefix, randname);
|
||||
|
||||
// see if we can find this file
|
||||
FILE *fd = fopen(t, "rb");
|
||||
if (!fd) {
|
||||
// we found a good file!
|
||||
ddio_MakePath(filename, basedir, t, NULL);
|
||||
success = true;
|
||||
created = true;
|
||||
} else {
|
||||
// already taken
|
||||
fclose(fd);
|
||||
tries++;
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue; // try again
|
||||
}
|
||||
}
|
||||
|
||||
ddio_SetWorkingDir(old_workdir);
|
||||
return created;
|
||||
}
|
||||
|
||||
bool ddio_CheckProcess(int pid) {
|
||||
if (kill(pid, 0) == -1) {
|
||||
/* some other error, log it */
|
||||
|
@ -40,6 +40,7 @@
|
||||
* $NoKeywords: $
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
#include "pstring.h"
|
||||
#include "forcefeedback.h"
|
||||
|
||||
@ -286,7 +287,7 @@ bool ddio_ffjoy_SupportAutoCenter(tDevice) { return false; }
|
||||
// for it. It returns a handle to that resource.
|
||||
// If it returns NULL, then it couldn't load the project.
|
||||
// Make sure device is aquired before calling.
|
||||
FORCEPROJECT ddio_ForceLoadProject(char *filename, tDevice dev) { return NULL; }
|
||||
FORCEPROJECT ddio_ForceLoadProject(std::filesystem::path &filename, tDevice dev) { return NULL; }
|
||||
|
||||
// Unloads a FORCEPROJECT file
|
||||
void ddio_ForceUnloadProject(FORCEPROJECT prj) {}
|
||||
|
10
ddio/tests/CMakeLists.txt
Normal file
10
ddio/tests/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
set(CMAKE_FOLDER "tests")
|
||||
|
||||
add_executable(ddio_tests
|
||||
ddio_tests.cpp
|
||||
)
|
||||
target_link_libraries(ddio_tests PRIVATE
|
||||
GTest::gtest_main
|
||||
ddio
|
||||
)
|
||||
gtest_discover_tests(ddio_tests)
|
30
ddio/tests/ddio_tests.cpp
Normal file
30
ddio/tests/ddio_tests.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Descent 3
|
||||
* Copyright (C) 2024 Descent Developers
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ddio.h"
|
||||
|
||||
TEST(D3, DDIO_GetTmpFileName) {
|
||||
std::filesystem::path temp_dir = std::filesystem::temp_directory_path();
|
||||
std::filesystem::path result = ddio_GetTmpFileName(temp_dir, "prefix_");
|
||||
EXPECT_FALSE(result.empty());
|
||||
EXPECT_EQ(result.extension(), ".tmp");
|
||||
EXPECT_TRUE(canonical(result.parent_path()) == canonical(temp_dir));
|
||||
}
|
143
ddio/winfile.cpp
143
ddio/winfile.cpp
@ -271,14 +271,6 @@ void ddio_MakePath(char *newPath, const char *absolutePathHeader, const char *su
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool ddio_GetTempFileName(const char *basedir, const char *prefix, char *filename) {
|
||||
|
||||
if (!GetTempFileName(basedir, prefix, 0, filename))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// retrieve root names, free up roots array (allocated with malloc) after use
|
||||
int ddio_GetFileSysRoots(char **roots, int max_roots) {
|
||||
char buffer[100];
|
||||
@ -354,141 +346,6 @@ std::vector<std::filesystem::path> ddio_GetSysRoots() {
|
||||
return result;
|
||||
};
|
||||
|
||||
// given a path, it cleans it up (if the path is c:\windows\..\dos it would make it c:\dos)
|
||||
// srcPath is the original path
|
||||
// dest is the finished cleaned path.
|
||||
// dest should be at least _MAX_PATH in size
|
||||
void ddio_CleanPath(char *dest, const char *srcPath) {
|
||||
strcpy(dest, srcPath);
|
||||
|
||||
// break the path into directories
|
||||
char **directories;
|
||||
int dirs;
|
||||
int path_length;
|
||||
|
||||
// make sure the path ends with a \ for sanity
|
||||
path_length = strlen(dest);
|
||||
|
||||
if (dest[path_length - 1] != '\\') {
|
||||
dest[path_length] = '\\';
|
||||
dest[path_length + 1] = '\0';
|
||||
path_length++;
|
||||
}
|
||||
|
||||
// now divide the full path into separate NULL terminated strings,counting the number
|
||||
// of directories in the process
|
||||
dirs = 0;
|
||||
char *strptr = dest;
|
||||
while (*strptr != '\0') {
|
||||
if (*strptr == '\\') {
|
||||
*strptr = '\0';
|
||||
dirs++;
|
||||
}
|
||||
strptr++;
|
||||
}
|
||||
|
||||
// check to make sure we have a directory, if we don't then return the original path given
|
||||
if (dirs == 0) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate the memory needed for the separate strings of each directory
|
||||
directories = mem_rmalloc<char *>(dirs);
|
||||
if (!directories) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// now get all the directories, and place into the individual strings
|
||||
strptr = dest;
|
||||
int count = 0;
|
||||
while (count < dirs) {
|
||||
directories[count] = mem_strdup(strptr);
|
||||
strptr += strlen(strptr) + 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
// now the fun part, figure out the correct order of the directories
|
||||
int *dir_order;
|
||||
|
||||
dir_order = mem_rmalloc<int>(dirs);
|
||||
if (!dir_order) {
|
||||
strcpy(dest, srcPath);
|
||||
return;
|
||||
}
|
||||
|
||||
for (count = 0; count < dirs; count++)
|
||||
dir_order[count] = -1; // a -1 means the end of the sequence
|
||||
|
||||
// now build the order based on the indicies
|
||||
int curr_index = 0;
|
||||
for (count = 0; count < dirs; count++) {
|
||||
|
||||
if (!stricmp(directories[count], "..")) {
|
||||
// we have to back up a directory
|
||||
curr_index--; // back up
|
||||
if (curr_index < 0)
|
||||
curr_index = 0; // can't go further than root
|
||||
dir_order[curr_index] = -1; // invalidate current slot
|
||||
} else if (stricmp(directories[count], ".")) {
|
||||
// we have a normal directory, add its index
|
||||
dir_order[curr_index] = count;
|
||||
curr_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// now rebuild the correct path for use, when we hit -1, we're done
|
||||
dest[0] = '\0';
|
||||
for (count = 0; count < dirs; count++) {
|
||||
if (dir_order[count] == -1)
|
||||
break;
|
||||
else {
|
||||
strcat(dest, directories[dir_order[count]]);
|
||||
strcat(dest, "\\");
|
||||
}
|
||||
}
|
||||
|
||||
// now remove trailing \ char
|
||||
path_length = strlen(dest);
|
||||
if ((path_length > 0) && (dest[path_length - 1] == '\\'))
|
||||
dest[path_length - 1] = '\0';
|
||||
|
||||
// free up all the allocated memory and we're done
|
||||
for (count = 0; count < dirs; count++) {
|
||||
if (directories[count])
|
||||
mem_free(directories[count]);
|
||||
}
|
||||
if (directories)
|
||||
mem_free(directories);
|
||||
if (dir_order)
|
||||
mem_free(dir_order);
|
||||
}
|
||||
|
||||
// given a path (with no filename), it will return the parent path
|
||||
// srcPath is the source given path
|
||||
// dest is where the parent path will be placed
|
||||
// returns true on success
|
||||
// dest should be at least _MAX_PATH in length
|
||||
bool ddio_GetParentPath(char *dest, const char *srcPath) {
|
||||
assert(srcPath);
|
||||
assert(dest);
|
||||
|
||||
#define PARENT_DELIM ".."
|
||||
int spath_len = strlen(srcPath);
|
||||
char *temp;
|
||||
|
||||
temp = (char *)mem_malloc(spath_len + strlen(PARENT_DELIM) + 3);
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ddio_MakePath(temp, srcPath, PARENT_DELIM, NULL);
|
||||
ddio_CleanPath(dest, temp);
|
||||
mem_free(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ddio_CheckProcess(int pid) {
|
||||
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
|
||||
if (proc) {
|
||||
|
@ -287,7 +287,6 @@ inline void CFileList::setPath(CString path) {
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
// ddio_CleanPath(buffer,temp.GetBuffer(0));
|
||||
strcpy(buffer, temp.GetBuffer(0));
|
||||
|
||||
m_csPath = buffer;
|
||||
|
@ -73,6 +73,7 @@
|
||||
#ifndef __DDIO_FORCEFEEDBACK_H_
|
||||
#define __DDIO_FORCEFEEDBACK_H_
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include "pstypes.h"
|
||||
#include "string.h"
|
||||
#define kMAX_Str 80
|
||||
@ -430,7 +431,7 @@ bool ddio_ffjoy_SupportAutoCenter(tDevice dev);
|
||||
// for it. It returns a handle to that resource.
|
||||
// If it returns NULL, then it couldn't load the project.
|
||||
// Make sure device is aquired before calling.
|
||||
FORCEPROJECT ddio_ForceLoadProject(char *filename, tDevice dev);
|
||||
FORCEPROJECT ddio_ForceLoadProject(std::filesystem::path &filename, tDevice dev);
|
||||
// Unloads a FORCEPROJECT file
|
||||
void ddio_ForceUnloadProject(FORCEPROJECT prj);
|
||||
// Given a handle to a resource, and the name of the effect to load
|
||||
|
Loading…
Reference in New Issue
Block a user