mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-21 00:00:29 +02:00
Maps folder: Halo PC maps there are explained, not a blue screen
A maps folder holding Halo PC's maps (one pointed at a Halo PC install's, say) had its ui.map, a Custom Edition or retail Halo PC cache file, loaded as the Xbox's: game_load() failed, and the player got a blue screen. Before the window opens the desktop builds now read ui.map's header: when it is Halo PC's, or there is no ui.map, the game says where the Xbox maps go (the data root's maps folder, named in full) and that Custom Edition maps go in custom_maps beside it, and quits. Halo PC maps in maps/ itself, which play only from custom_maps, are named in a warning. Runs with no window log it instead. The README's game data section says so. (cherry picked from commit 223c4aaf16b2819c57cd31d470d5dd04c9daa4f7, made again for OpenCE's custom_maps folder in place of that fork's maps/ce and md_maps, and not on the web build)
This commit is contained in:
1 parent
76984235b7
commit
e075fffa28
4 files changed
+199
-1
No files matched your search
@@ -58,6 +58,10 @@ so players of the two versions can play together.
|
||||
says to put the disc image next to the executable, and stops.
|
||||
3. The game extracts the `maps/` folder. Then the game starts.
|
||||
|
||||
The `maps/` folder holds the Xbox maps only. If it holds Halo PC's maps
|
||||
instead (a Halo PC or Custom Edition install's `maps` folder), the game says
|
||||
so and stops: Custom Edition maps go in `custom_maps/`, beside `maps/`.
|
||||
|
||||
On Linux and Windows, the game puts `maps/` next to the executable. On
|
||||
Android, copy the disc image to the phone first. The app puts `maps/` in its
|
||||
data folder. Refer to [port/android/README.md](port/android/README.md). On
|
||||
|
||||
@@ -105,6 +105,30 @@ const char *platform_custom_edition_root(void);
|
||||
out of an Xbox disc image into destination (sdl_platform.c), and quits if
|
||||
the player declines; nonzero once destination has one */
|
||||
BOOL platform_offer_game_data(const char *destination);
|
||||
/* what the data root's maps folder holds, which should be the Xbox maps
|
||||
(sdl_platform.c tells the player when it is not, rather than the game
|
||||
failing on Halo PC's ui.map) */
|
||||
enum
|
||||
{
|
||||
_maps_folder_xbox,
|
||||
/* its ui.map is Halo PC's (retail's, version 7, or Custom Edition's, 609) */
|
||||
_maps_folder_halo_pc,
|
||||
/* it has no ui.map (or one that is not a map) */
|
||||
_maps_folder_no_ui,
|
||||
};
|
||||
#define PLATFORM_MAPS_FOLDER_NAMED 4
|
||||
struct platform_maps_folder
|
||||
{
|
||||
int state;
|
||||
/* the data root, whole */
|
||||
char root[1024];
|
||||
long ui_version;
|
||||
/* Halo PC maps in maps/ itself, which play only from custom_maps: how
|
||||
many, and the first PLATFORM_MAPS_FOLDER_NAMED's names */
|
||||
long stray_pc_maps;
|
||||
char stray_names[256];
|
||||
};
|
||||
void platform_maps_folder_check(struct platform_maps_folder *maps);
|
||||
/* asks the player, in a box of its own that waits for the answer (before
|
||||
the window opens, or between frames), with `count` buttons (3 at most: Android's),
|
||||
`default_index` Enter's and Escape's: the index of the one chosen, or -1
|
||||
|
||||
@@ -112,6 +112,61 @@ extern const unsigned long platform_window_icon_size;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(HALO_ANDROID) && !defined(HALO_WEB)
|
||||
/* the maps folder checked to hold the Xbox maps (platform_maps_folder_check).
|
||||
When it holds Halo PC's instead, or no ui.map, the player is told where each
|
||||
kind goes and the game quits, rather than failing to load Halo PC's ui.map
|
||||
as the Xbox's (game_load). Halo PC maps in maps/ itself, which play only from
|
||||
custom_maps, are warned of */
|
||||
static void data_check_maps(void)
|
||||
{
|
||||
struct platform_maps_folder maps;
|
||||
char message[2048];
|
||||
char where[1200];
|
||||
BOOL quiet = config_boolean("debug.hidden_window") || config_real("debug.exit_after") > 0.0 ||
|
||||
config_string("debug.network_test")[0];
|
||||
|
||||
platform_maps_folder_check(&maps);
|
||||
snprintf(where, sizeof(where),
|
||||
"Put the Xbox maps from your Halo: Combat Evolved disc image in %s/maps. Halo Custom Edition "
|
||||
"maps go in a custom_maps folder beside it.",
|
||||
maps.root);
|
||||
switch (maps.state)
|
||||
{
|
||||
case _maps_folder_xbox:
|
||||
if (!maps.stray_pc_maps)
|
||||
return;
|
||||
snprintf(message, sizeof(message),
|
||||
"These maps in the maps folder are Halo PC maps, which play only from custom_maps: %s%s.\n\n%s",
|
||||
maps.stray_names, maps.stray_pc_maps > PLATFORM_MAPS_FOLDER_NAMED ? " and more" : "", where);
|
||||
platform_log("maps folder: %ld Halo PC maps in %s/maps (%s)", maps.stray_pc_maps, maps.root,
|
||||
maps.stray_names);
|
||||
if (!quiet)
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Halo", message, NULL);
|
||||
return;
|
||||
case _maps_folder_halo_pc:
|
||||
snprintf(message, sizeof(message),
|
||||
"The maps folder holds Halo PC maps, not the Xbox maps: its ui.map is from %s.\n\n%s\n\n"
|
||||
"To copy the Xbox maps out of your disc image again, move this maps folder aside and "
|
||||
"start the game.",
|
||||
maps.ui_version == 609 ? "Halo PC (Custom Edition)" : "Halo PC", where);
|
||||
break;
|
||||
default:
|
||||
snprintf(message, sizeof(message),
|
||||
"Halo's Xbox maps were not found: %s/maps has no ui.map.\n\n%s\n\n"
|
||||
"To copy the Xbox maps out of your disc image, move the maps folder aside and start the game.",
|
||||
maps.root, where);
|
||||
break;
|
||||
}
|
||||
platform_log("maps folder: %s/maps is not the Xbox maps (ui.map version %ld): quitting", maps.root,
|
||||
maps.ui_version);
|
||||
platform_log("%s", message);
|
||||
if (!quiet)
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Halo", message, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL platform_sdl_initialize(void)
|
||||
{
|
||||
if (platform_sdl_started)
|
||||
@@ -159,8 +214,11 @@ BOOL platform_sdl_initialize(void)
|
||||
platform_sdl_started = TRUE;
|
||||
#ifndef HALO_ANDROID
|
||||
/* found (or offered to the player, platform_offer_game_data) before the
|
||||
game's window opens */
|
||||
game's window opens, and checked to be the Xbox maps */
|
||||
platform_data_root();
|
||||
#ifndef HALO_WEB
|
||||
data_check_maps();
|
||||
#endif
|
||||
/* (a new version looked for meanwhile, updater_poll asking about it) */
|
||||
updater_start();
|
||||
#endif
|
||||
|
||||
@@ -268,6 +268,118 @@ void platform_translate_path(const char *xbox_path, char *host_path, unsigned lo
|
||||
snprintf(host_path, host_path_size, "%s", resolved);
|
||||
}
|
||||
|
||||
/* ---------- the maps folder's maps */
|
||||
|
||||
enum
|
||||
{
|
||||
/* a cache file's header: 'head' and its version */
|
||||
MAP_HEADER_SIGNATURE = 0x68656164,
|
||||
/* (Halo PC's: retail's, and Custom Edition's) */
|
||||
HALO_PC_MAP_VERSION = 7,
|
||||
CUSTOM_EDITION_MAP_VERSION = 609,
|
||||
};
|
||||
|
||||
/* a map file's cache version, by its header; 0 if it is not a cache file */
|
||||
static long map_file_version(const char *path)
|
||||
{
|
||||
unsigned char header[8];
|
||||
FILE *file = fopen(path, "rb");
|
||||
long version = 0;
|
||||
|
||||
if (!file)
|
||||
return 0;
|
||||
if (fread(header, 1, sizeof(header), file) == sizeof(header) &&
|
||||
(header[0] | header[1] << 8 | header[2] << 16 | (unsigned long)header[3] << 24) == MAP_HEADER_SIGNATURE)
|
||||
{
|
||||
version = (long)(header[4] | header[5] << 8 | header[6] << 16 | (unsigned long)header[7] << 24);
|
||||
}
|
||||
fclose(file);
|
||||
return version;
|
||||
}
|
||||
|
||||
static BOOL map_version_is_pc(long version)
|
||||
{
|
||||
return version == HALO_PC_MAP_VERSION || version == CUSTOM_EDITION_MAP_VERSION;
|
||||
}
|
||||
|
||||
static BOOL name_ends_with(const char *name, const char *ending)
|
||||
{
|
||||
size_t length = strlen(name);
|
||||
size_t ending_length = strlen(ending);
|
||||
size_t index;
|
||||
|
||||
if (length < ending_length)
|
||||
return FALSE;
|
||||
for (index = 0; index < ending_length; index++)
|
||||
{
|
||||
if (tolower((unsigned char)name[length - ending_length + index]) != tolower((unsigned char)ending[index]))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* the Halo PC maps in the maps folder, which play only from custom_maps:
|
||||
how many, and the first PLATFORM_MAPS_FOLDER_NAMED's names */
|
||||
static long pc_maps_in_maps(char *names, unsigned long names_size)
|
||||
{
|
||||
char folder[1024];
|
||||
char name[256];
|
||||
long count = 0;
|
||||
void *directory;
|
||||
|
||||
platform_translate_path("d:\\maps", folder, sizeof(folder));
|
||||
directory = posix_directory_open(folder);
|
||||
if (!directory)
|
||||
return 0;
|
||||
while (posix_directory_next(directory, name, sizeof(name)))
|
||||
{
|
||||
char path[1300];
|
||||
|
||||
if (!name_ends_with(name, ".map"))
|
||||
continue;
|
||||
snprintf(path, sizeof(path), "%s/%s", folder, name);
|
||||
if (!map_version_is_pc(map_file_version(path)))
|
||||
continue;
|
||||
if (count < PLATFORM_MAPS_FOLDER_NAMED)
|
||||
{
|
||||
size_t length = strlen(names);
|
||||
|
||||
snprintf(names + length, names_size - length, "%s%s", length ? ", " : "", name);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
posix_directory_close(directory);
|
||||
return count;
|
||||
}
|
||||
|
||||
void platform_maps_folder_check(struct platform_maps_folder *maps)
|
||||
{
|
||||
const char *root = platform_data_root();
|
||||
char path[1024];
|
||||
|
||||
memset(maps, 0, sizeof(*maps));
|
||||
/* the data root as the player finds it (whole: Windows' is the
|
||||
executable's folder's, or paths.data's) */
|
||||
#ifndef _WIN32
|
||||
if (root[0] != '/' && getcwd(maps->root, sizeof(maps->root)))
|
||||
{
|
||||
size_t length = strlen(maps->root);
|
||||
|
||||
if (strcmp(root, "."))
|
||||
snprintf(maps->root + length, sizeof(maps->root) - length, "/%s", root);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
snprintf(maps->root, sizeof(maps->root), "%s", root);
|
||||
}
|
||||
platform_translate_path("d:\\maps\\ui.map", path, sizeof(path));
|
||||
maps->ui_version = map_file_version(path);
|
||||
maps->state = map_version_is_pc(maps->ui_version) ? _maps_folder_halo_pc :
|
||||
!maps->ui_version ? _maps_folder_no_ui : _maps_folder_xbox;
|
||||
maps->stray_pc_maps = pc_maps_in_maps(maps->stray_names, sizeof(maps->stray_names));
|
||||
}
|
||||
|
||||
/* ---------- file handles */
|
||||
|
||||
struct platform_file
|
||||
|
||||
Reference in new issue
Block a user