1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-19 13:03:11 +01:00

add cross platform interface for enumerating files

This commit is contained in:
IntelOrca
2014-10-17 03:22:45 +01:00
parent ae85fc265e
commit 217ae84c62
5 changed files with 105 additions and 39 deletions

View File

@@ -31,5 +31,8 @@ int platform_file_exists(const char *path);
int platform_directory_exists(const char *path);
int platform_ensure_directory_exists(const char *path);
int platform_lock_single_instance();
int platform_enumerate_files_begin(const char *pattern);
int platform_enumerate_files_next(int handle, char **outFileName);
void platform_enumerate_files_end(int handle);
#endif

View File

@@ -121,6 +121,72 @@ int platform_lock_single_instance()
}
}
typedef struct {
char active;
char pattern[MAX_PATH];
HANDLE handle;
WIN32_FIND_DATAA data;
} enumerate_file_info;
static enumerate_file_info _enumerateFileInfoList[8] = { 0 };
int platform_enumerate_files_begin(const char *pattern)
{
int i;
enumerate_file_info *enumFileInfo;
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
strncpy(enumFileInfo->pattern, pattern, MAX_PATH);
enumFileInfo->handle = NULL;
enumFileInfo->active = 1;
return i;
}
}
return -1;
}
int platform_enumerate_files_next(int handle, char **outFileName)
{
int result;
enumerate_file_info *enumFileInfo;
HANDLE findFileHandle;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle == NULL) {
findFileHandle = FindFirstFile(enumFileInfo->pattern, &enumFileInfo->data);
if (findFileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = findFileHandle;
result = 1;
} else {
result = 0;
}
} else {
result = FindNextFile(enumFileInfo->handle, &enumFileInfo->data);
}
if (result) {
*outFileName = enumFileInfo->data.cFileName;
return 1;
} else {
return 0;
}
}
void platform_enumerate_files_end(int handle)
{
enumerate_file_info *enumFileInfo;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle != NULL) {
FindClose(enumFileInfo->handle);
enumFileInfo->handle = NULL;
}
enumFileInfo->active = 0;
}
/**
* http://alter.org.ua/en/docs/win/args/
*/

View File

@@ -40,28 +40,26 @@
* Loads only the basic information from a scenario.
* rct2: 0x006761D6
*/
int scenario_load_basic(const char *path)
int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info)
{
FILE *file;
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
file = fopen(path, "rb");
if (file != NULL) {
// Read first chunk
sawyercoding_read_chunk(file, (uint8*)s6Header);
if (s6Header->type == S6_TYPE_SCENARIO) {
sawyercoding_read_chunk(file, (uint8*)header);
if (header->type == S6_TYPE_SCENARIO) {
// Read second chunk
sawyercoding_read_chunk(file, (uint8*)s6Info);
sawyercoding_read_chunk(file, (uint8*)info);
fclose(file);
RCT2_GLOBAL(0x009AA00C, uint8) = 0;
// Checks for a scenario string object (possibly for localisation)
if ((s6Info->entry.flags & 0xFF) != 255) {
if (object_get_scenario_text(&s6Info->entry)) {
if ((info->entry.flags & 0xFF) != 255) {
if (object_get_scenario_text(&info->entry)) {
int ebp = RCT2_GLOBAL(0x009ADAF8, uint32);
format_string(s6Info->name, RCT2_GLOBAL(ebp, sint16), NULL);
format_string(s6Info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL);
format_string(info->name, RCT2_GLOBAL(ebp, sint16), NULL);
format_string(info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL);
RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8);
object_free_scenario_text();
}

View File

@@ -402,7 +402,7 @@ extern rct_scenario_basic *gScenarioList;
int scenario_scores_save();
void scenario_load_list();
int scenario_load_basic(const char *path);
int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info);
int scenario_load(const char *path);
int scenario_load_and_play(const rct_scenario_basic *scenario);
int scenario_load_and_play_from_path(const char *path);

View File

@@ -18,9 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <windows.h>
#include "addresses.h"
#include "rct2.h"
#include "platform/platform.h"
#include "scenario.h"
// Scenario list
@@ -49,9 +48,8 @@ static rct_scenario_basic *get_scenario_by_filename(const char *filename)
*/
void scenario_load_list()
{
int i;
HANDLE hFindFile;
WIN32_FIND_DATAA findFileData;
int i, enumFileHandle;
char *enumFileName;
// Load scores
scenario_scores_load();
@@ -61,12 +59,12 @@ void scenario_load_list()
gScenarioList[i].flags &= ~SCENARIO_FLAGS_VISIBLE;
// Enumerate through each scenario in the directory
hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), &findFileData);
if (hFindFile != INVALID_HANDLE_VALUE) {
do {
scenario_list_add(findFileData.cFileName);
} while (FindNextFile(hFindFile, &findFileData));
FindClose(hFindFile);
enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char));
if (enumFileHandle >= 0) {
while (platform_enumerate_files_next(enumFileHandle, &enumFileName)) {
scenario_list_add(enumFileName);
}
platform_enumerate_files_end(enumFileHandle);
}
// Sort alphabetically
@@ -80,17 +78,18 @@ static void scenario_list_add(const char *path)
{
char scenarioPath[MAX_PATH];
rct_scenario_basic *scenario;
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
rct_s6_header s6Header;
rct_s6_info s6Info;
// Get absolute path
subsitute_path(scenarioPath, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), path);
// Load the basic scenario information
if (!scenario_load_basic(scenarioPath))
if (!scenario_load_basic(scenarioPath, &s6Header, &s6Info))
return;
// Ignore scenarios where first header byte is not 255
if (s6Info->var_000 != 255)
if (s6Info.var_000 != 255)
return;
// Check if scenario already exists in list, likely if in scores
@@ -98,13 +97,13 @@ static void scenario_list_add(const char *path)
if (scenario != NULL) {
// Update the scenario information
scenario->flags |= SCENARIO_FLAGS_VISIBLE;
scenario->category = s6Info->category;
scenario->objective_type = s6Info->objective_type;
scenario->objective_arg_1 = s6Info->objective_arg_1;
scenario->objective_arg_2 = s6Info->objective_arg_2;
scenario->objective_arg_3 = s6Info->objective_arg_3;
strcpy(scenario->name, s6Info->name);
strcpy(scenario->details, s6Info->details);
scenario->category = s6Info.category;
scenario->objective_type = s6Info.objective_type;
scenario->objective_arg_1 = s6Info.objective_arg_1;
scenario->objective_arg_2 = s6Info.objective_arg_2;
scenario->objective_arg_3 = s6Info.objective_arg_3;
strcpy(scenario->name, s6Info.name);
strcpy(scenario->details, s6Info.details);
} else {
// Check if the scenario list buffer has room for another scenario
if (gScenarioListCount >= gScenarioListCapacity) {
@@ -122,13 +121,13 @@ static void scenario_list_add(const char *path)
scenario->flags = SCENARIO_FLAGS_VISIBLE;
if (RCT2_GLOBAL(0x009AA00C, uint8) & 1)
scenario->flags |= SCENARIO_FLAGS_SIXFLAGS;
scenario->category = s6Info->category;
scenario->objective_type = s6Info->objective_type;
scenario->objective_arg_1 = s6Info->objective_arg_1;
scenario->objective_arg_2 = s6Info->objective_arg_2;
scenario->objective_arg_3 = s6Info->objective_arg_3;
strcpy(scenario->name, s6Info->name);
strcpy(scenario->details, s6Info->details);
scenario->category = s6Info.category;
scenario->objective_type = s6Info.objective_type;
scenario->objective_arg_1 = s6Info.objective_arg_1;
scenario->objective_arg_2 = s6Info.objective_arg_2;
scenario->objective_arg_3 = s6Info.objective_arg_3;
strcpy(scenario->name, s6Info.name);
strcpy(scenario->details, s6Info.details);
}
}