1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-22 14:24:33 +01:00

convert more platform functions over to utf8 and close #1713

This commit is contained in:
IntelOrca
2015-08-04 21:41:45 +01:00
parent e0769800e7
commit be4ee45d66
8 changed files with 236 additions and 109 deletions

View File

@@ -890,10 +890,18 @@ int save_game()
void game_autosave()
{
char path[MAX_PATH];
utf8 path[MAX_PATH];
utf8 backupPath[MAX_PATH];
platform_get_user_directory(path, "save");
strcpy(backupPath, path);
strcat(path, "autosave.sv6");
strcat(backupPath, "autosave.sv6.bak");
if (platform_file_exists(path)) {
platform_file_copy(path, backupPath, true);
}
SDL_RWops* rw = platform_sdl_rwfromfile(path, "wb+");
if (rw != NULL) {

View File

@@ -158,7 +158,7 @@ void title_sequence_duplicate_preset(int duplicate, const char *name)
strncat(path, &separator, 1);
strcat(path, gConfigTitleSequences.presets[preset].saves[i]);
platform_file_copy(srcPath, path);
platform_file_copy(srcPath, path, false);
}
if (loadmm) {
@@ -237,7 +237,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName)
// Add the appropriate extension if needed
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(newPath, ".sv6");
platform_file_copy(path, newPath);
platform_file_copy(path, newPath, false);
gConfigTitleSequences.presets[preset].num_saves++;
gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves);

View File

@@ -76,5 +76,8 @@ int utf8_insert_codepoint(utf8 *dst, uint32 codepoint);
bool utf8_is_codepoint_start(utf8 *text);
void utf8_remove_format_codes(utf8 *text);
int utf8_get_codepoint_length(int codepoint);
int utf8_length(const utf8 *text);
wchar_t *utf8_to_widechar(const utf8 *src);
utf8 *widechar_to_utf8(const wchar_t *src);
#endif

View File

@@ -83,3 +83,52 @@ int utf8_get_codepoint_length(int codepoint)
return 4;
}
}
/**
* Gets the number of characters / codepoints in a UTF-8 string (not necessarily 1:1 with bytes and not including null
* terminator).
*/
int utf8_length(const utf8 *text)
{
int codepoint;
const utf8 *ch = text;
int count = 0;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
count++;
}
return count;
}
wchar_t *utf8_to_widechar(const utf8 *src)
{
wchar_t *result = malloc((utf8_length(src) + 1) * sizeof(wchar_t));
wchar_t *dst = result;
const utf8 *ch = src;
int codepoint;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
if ((uint32)codepoint > 0xFFFF) {
*dst++ = '?';
} else {
*dst++ = codepoint;
}
}
*dst = 0;
return result;
}
utf8 *widechar_to_utf8(const wchar_t *src)
{
utf8 *result = malloc((wcslen(src) * 4) + 1);
utf8 *dst = result;
for (; *src != 0; src++) {
dst = utf8_write_codepoint(dst, *src);
}
*dst++ = 0;
int size = dst - result;
return realloc(result, size);
}

View File

@@ -55,9 +55,9 @@ static struct { sint16 x, y, z; } _spritelocations1[MAX_SPRITES], _spritelocatio
static void openrct2_loop();
static void openrct2_copy_files_over(const char *originalDirectory, const char *newDirectory, const char *extension)
static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *newDirectory, const utf8 *extension)
{
char *ch, filter[MAX_PATH], oldPath[MAX_PATH], newPath[MAX_PATH];
utf8 *ch, filter[MAX_PATH], oldPath[MAX_PATH], newPath[MAX_PATH];
int fileEnumHandle;
file_info fileInfo;
@@ -86,7 +86,7 @@ static void openrct2_copy_files_over(const char *originalDirectory, const char *
strcat(oldPath, fileInfo.path);
if (!platform_file_exists(newPath))
platform_file_copy(oldPath, newPath);
platform_file_copy(oldPath, newPath, false);
}
platform_enumerate_files_end(fileEnumHandle);
@@ -110,6 +110,7 @@ static void openrct2_copy_files_over(const char *originalDirectory, const char *
platform_enumerate_directories_end(fileEnumHandle);
}
// TODO move to platform
static void openrct2_set_exe_path()
{
wchar_t exePath[MAX_PATH];
@@ -131,18 +132,18 @@ static void openrct2_set_exe_path()
*/
static void openrct2_copy_original_user_files_over()
{
char path[MAX_PATH];
utf8 path[MAX_PATH];
platform_get_user_directory(path, "save");
openrct2_copy_files_over((char*)RCT2_ADDRESS_SAVED_GAMES_PATH, path, ".sv6");
openrct2_copy_files_over((utf8*)RCT2_ADDRESS_SAVED_GAMES_PATH, path, ".sv6");
platform_get_user_directory(path, "landscape");
openrct2_copy_files_over((char*)RCT2_ADDRESS_LANDSCAPES_PATH, path, ".sc6");
openrct2_copy_files_over((utf8*)RCT2_ADDRESS_LANDSCAPES_PATH, path, ".sc6");
}
bool openrct2_initialise()
{
char userPath[MAX_PATH];
utf8 userPath[MAX_PATH];
platform_get_user_directory(userPath, NULL);
if (!platform_ensure_directory_exists(userPath)) {

View File

@@ -81,46 +81,46 @@ void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, i
void platform_init();
void platform_draw();
void platform_free();
void platform_update_palette(char* colours, int start_index, int num_colours);
void platform_update_palette(char *colours, int start_index, int num_colours);
void platform_set_fullscreen_mode(int mode);
void platform_set_cursor(char cursor);
void platform_refresh_video();
void platform_process_messages();
int platform_scancode_to_rct_keycode(int sdl_key);
void platform_start_text_input(char* buffer, int max_length);
void platform_start_text_input(utf8 *buffer, int max_length);
void platform_stop_text_input();
SDL_RWops* platform_sdl_rwfromfile(const char* filename, const char* mode);
SDL_RWops* platform_sdl_rwfromfile(const utf8* filename, const char* mode);
// Platform specific definitions
char platform_get_path_separator();
int platform_file_exists(const char *path);
int platform_directory_exists(const char *path);
int platform_original_game_data_exists(const char *path);
time_t platform_file_get_modified_time(char* path);
int platform_ensure_directory_exists(const char *path);
int platform_directory_delete(const char *path);
int platform_lock_single_instance();
int platform_enumerate_files_begin(const char *pattern);
int platform_enumerate_files_next(int handle, file_info *outFileInfo);
bool platform_file_exists(const utf8 *path);
bool platform_directory_exists(const utf8 *path);
bool platform_original_game_data_exists(const utf8 *path);
time_t platform_file_get_modified_time(const utf8* path);
bool platform_ensure_directory_exists(const utf8 *path);
bool platform_directory_delete(const utf8 *path);
bool platform_lock_single_instance();
int platform_enumerate_files_begin(const utf8 *pattern);
bool platform_enumerate_files_next(int handle, file_info *outFileInfo);
void platform_enumerate_files_end(int handle);
int platform_enumerate_directories_begin(const char *directory);
int platform_enumerate_directories_next(int handle, char *path);
int platform_enumerate_directories_begin(const utf8 *directory);
bool platform_enumerate_directories_next(int handle, utf8 *path);
void platform_enumerate_directories_end(int handle);
// Returns the bitmask of the GetLogicalDrives function for windows, 0 for other systems
int platform_get_drives();
int platform_file_copy(const char *srcPath, const char *dstPath);
int platform_file_move(const char *srcPath, const char *dstPath);
int platform_file_delete(const char *path);
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite);
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath);
bool platform_file_delete(const utf8 *path);
void platform_hide_cursor();
void platform_show_cursor();
void platform_get_cursor_position(int *x, int *y);
void platform_set_cursor_position(int x, int y);
unsigned int platform_get_ticks();
void platform_get_user_directory(char *outPath, const char *subDirectory);
void platform_show_messagebox(char *message);
int platform_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory);
void platform_show_messagebox(utf8 *message);
int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName);
utf8 *platform_open_directory_browser(utf8 *title);
uint8 platform_get_locale_currency();
uint16 platform_get_locale_language();

View File

@@ -90,55 +90,68 @@ char platform_get_path_separator()
return '\\';
}
int platform_file_exists(const char *path)
bool platform_file_exists(const utf8 *path)
{
return !(GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND));
wchar_t *wPath = utf8_to_widechar(path);
DWORD result = GetFileAttributesW(wPath);
DWORD error = GetLastError();
free(wPath);
return !(result == INVALID_FILE_ATTRIBUTES && (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND));
}
int platform_directory_exists(const char *path)
bool platform_directory_exists(const utf8 *path)
{
DWORD dwAttrib = GetFileAttributes(path);
wchar_t *wPath = utf8_to_widechar(path);
DWORD dwAttrib = GetFileAttributesW(wPath);
free(wPath);
return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
}
int platform_original_game_data_exists(const char *path)
bool platform_original_game_data_exists(const utf8 *path)
{
char checkPath[MAX_PATH];
utf8 checkPath[MAX_PATH];
sprintf(checkPath, "%s%c%s%c%s", path, platform_get_path_separator(), "data", platform_get_path_separator(), "g1.dat");
return platform_file_exists(checkPath);
}
int platform_ensure_directory_exists(const char *path)
bool platform_ensure_directory_exists(const utf8 *path)
{
if (platform_directory_exists(path))
return 1;
return CreateDirectory(path, NULL);
wchar_t *wPath = utf8_to_widechar(path);
BOOL success = CreateDirectoryW(wPath, NULL);
free(wPath);
return success == TRUE;
}
int platform_directory_delete(const char *path)
bool platform_directory_delete(const utf8 *path)
{
char pszFrom[MAX_PATH];
strcpy(pszFrom, path);
wchar_t pszFrom[MAX_PATH];
wchar_t *wPath = utf8_to_widechar(path);
wcsncpy(pszFrom, wPath, MAX_PATH);
free(wPath);
// Needs to be double-null terminated for some weird reason
pszFrom[strlen(path) + 1] = 0;
SHFILEOPSTRUCTA fileop;
pszFrom[wcslen(wPath) + 1] = 0;
SHFILEOPSTRUCTW fileop;
fileop.hwnd = NULL; // no status display
fileop.wFunc = FO_DELETE; // delete operation
fileop.pFrom = pszFrom; // source file name as double null terminated string
fileop.pTo = NULL; // no destination needed
fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; // do not prompt the user
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user
fileop.fAnyOperationsAborted = FALSE;
fileop.lpszProgressTitle = NULL;
fileop.hNameMappings = NULL;
int ret = SHFileOperationA(&fileop);
int ret = SHFileOperationW(&fileop);
return (ret == 0);
}
int platform_lock_single_instance()
bool platform_lock_single_instance()
{
HANDLE mutex, status;
@@ -150,67 +163,74 @@ int platform_lock_single_instance()
if (status == NULL)
log_error("unable to create mutex\n");
return 1;
return true;
} else {
// Already running
CloseHandle(mutex);
return 0;
return false;
}
}
typedef struct {
char active;
char pattern[MAX_PATH];
bool active;
wchar_t pattern[MAX_PATH];
HANDLE handle;
WIN32_FIND_DATAA data;
WIN32_FIND_DATAW data;
utf8 *outFilename;
} enumerate_file_info;
static enumerate_file_info _enumerateFileInfoList[8] = { 0 };
int platform_enumerate_files_begin(const char *pattern)
int platform_enumerate_files_begin(const utf8 *pattern)
{
int i;
enumerate_file_info *enumFileInfo;
wchar_t *wPattern = utf8_to_widechar(pattern);
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
strncpy(enumFileInfo->pattern, pattern, MAX_PATH);
wcsncpy(enumFileInfo->pattern, wPattern, MAX_PATH);
enumFileInfo->handle = NULL;
enumFileInfo->active = 1;
enumFileInfo->active = true;
enumFileInfo->outFilename = NULL;
free(wPattern);
return i;
}
}
free(wPattern);
return INVALID_HANDLE;
}
int platform_enumerate_files_next(int handle, file_info *outFileInfo)
bool platform_enumerate_files_next(int handle, file_info *outFileInfo)
{
int result;
bool result;
enumerate_file_info *enumFileInfo;
HANDLE findFileHandle;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle == NULL) {
findFileHandle = FindFirstFile(enumFileInfo->pattern, &enumFileInfo->data);
findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (findFileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = findFileHandle;
result = 1;
result = true;
} else {
result = 0;
result = false;
}
} else {
result = FindNextFile(enumFileInfo->handle, &enumFileInfo->data);
result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data);
}
if (result) {
outFileInfo->path = enumFileInfo->data.cFileName;
outFileInfo->path = enumFileInfo->outFilename = widechar_to_utf8(enumFileInfo->data.cFileName);
outFileInfo->size = ((uint64)enumFileInfo->data.nFileSizeHigh << 32ULL) | (uint64)enumFileInfo->data.nFileSizeLow;
outFileInfo->last_modified = ((uint64)enumFileInfo->data.ftLastWriteTime.dwHighDateTime << 32ULL) | (uint64)enumFileInfo->data.ftLastWriteTime.dwLowDateTime;
return 1;
return true;
} else {
return 0;
return false;
}
}
@@ -223,32 +243,39 @@ void platform_enumerate_files_end(int handle)
FindClose(enumFileInfo->handle);
enumFileInfo->handle = NULL;
}
enumFileInfo->active = 0;
enumFileInfo->active = false;
SafeFree(enumFileInfo->outFilename);
}
int platform_enumerate_directories_begin(const char *directory)
int platform_enumerate_directories_begin(const utf8 *directory)
{
int i;
enumerate_file_info *enumFileInfo;
if (strlen(directory) + 3 >= MAX_PATH)
wchar_t *wDirectory = utf8_to_widechar(directory);
if (wcslen(wDirectory) + 3 >= MAX_PATH)
return INVALID_HANDLE;
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
strncpy(enumFileInfo->pattern, directory, MAX_PATH);
strncat(enumFileInfo->pattern, "*", MAX_PATH);
wcsncpy(enumFileInfo->pattern, wDirectory, MAX_PATH);
wcsncat(enumFileInfo->pattern, L"*", MAX_PATH);
enumFileInfo->handle = NULL;
enumFileInfo->active = 1;
enumFileInfo->active = true;
enumFileInfo->outFilename = NULL;
free(wDirectory);
return i;
}
}
free(wDirectory);
return INVALID_HANDLE;
}
int platform_enumerate_directories_next(int handle, char *path)
bool platform_enumerate_directories_next(int handle, utf8 *path)
{
enumerate_file_info *enumFileInfo;
HANDLE fileHandle;
@@ -256,31 +283,32 @@ int platform_enumerate_directories_next(int handle, char *path)
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle == NULL) {
fileHandle = FindFirstFile(enumFileInfo->pattern, &enumFileInfo->data);
fileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (fileHandle != 0) {
enumFileInfo->handle = fileHandle;
} else {
return 0;
return false;
}
} else {
if (!FindNextFile(enumFileInfo->handle, &enumFileInfo->data)) {
return 0;
if (!FindNextFileW(enumFileInfo->handle, &enumFileInfo->data)) {
return false;
}
}
while (
(enumFileInfo->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0
|| strchr(enumFileInfo->data.cFileName, '.') != NULL
(enumFileInfo->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ||
wcschr(enumFileInfo->data.cFileName, '.') != NULL
) {
if (!FindNextFile(enumFileInfo->handle, &enumFileInfo->data)) {
return 0;
if (!FindNextFileW(enumFileInfo->handle, &enumFileInfo->data)) {
return false;
}
}
memset(path, '\0', MAX_PATH);
strncpy(path, enumFileInfo->data.cFileName, MAX_PATH);
utf8 *filename = widechar_to_utf8(enumFileInfo->data.cFileName);
strncpy(path, filename, MAX_PATH);
strncat(path, "\\", MAX_PATH);
return 1;
free(filename);
return true;
}
void platform_enumerate_directories_end(int handle)
@@ -292,26 +320,40 @@ void platform_enumerate_directories_end(int handle)
FindClose(enumFileInfo->handle);
enumFileInfo->handle = NULL;
}
enumFileInfo->active = 0;
enumFileInfo->active = false;
}
int platform_get_drives(){
int platform_get_drives()
{
return GetLogicalDrives();
}
int platform_file_copy(const char *srcPath, const char *dstPath)
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
{
return CopyFileA(srcPath, dstPath, TRUE);
wchar_t *wSrcPath = utf8_to_widechar(srcPath);
wchar_t *wDstPath = utf8_to_widechar(dstPath);
BOOL success = CopyFileW(wSrcPath, wDstPath, overwrite ? FALSE : TRUE);
free(wSrcPath);
free(wDstPath);
return success == TRUE;
}
int platform_file_move(const char *srcPath, const char *dstPath)
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
{
return MoveFileA(srcPath, dstPath);
wchar_t *wSrcPath = utf8_to_widechar(srcPath);
wchar_t *wDstPath = utf8_to_widechar(dstPath);
BOOL success = MoveFileW(wSrcPath, wDstPath);
free(wSrcPath);
free(wDstPath);
return success == TRUE;
}
int platform_file_delete(const char *path)
bool platform_file_delete(const utf8 *path)
{
return DeleteFileA(path);
wchar_t *wPath = utf8_to_widechar(path);
BOOL success = DeleteFileW(wPath);
free(wPath);
return success == TRUE;
}
void platform_hide_cursor()
@@ -347,11 +389,16 @@ unsigned int platform_get_ticks()
return GetTickCount();
}
void platform_get_user_directory(char *outPath, const char *subDirectory)
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
{
wchar_t wOutPath[MAX_PATH];
char separator[2] = { platform_get_path_separator(), 0 };
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, outPath))) {
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wOutPath))) {
utf8 *outPathTemp = widechar_to_utf8(wOutPath);
strcpy(outPath, outPathTemp);
free(outPathTemp);
strcat(outPath, separator);
strcat(outPath, "OpenRCT2");
strcat(outPath, separator);
@@ -362,6 +409,8 @@ void platform_get_user_directory(char *outPath, const char *subDirectory)
} else {
outPath[0] = 0;
}
free(wOutPath);
}
void platform_show_messagebox(char *message)
@@ -643,7 +692,8 @@ PCHAR *CommandLineToArgvA(PCHAR CmdLine, int *_argc)
return argv;
}
uint16 platform_get_locale_language(){
uint16 platform_get_locale_language()
{
CHAR langCode[4];
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
@@ -689,23 +739,33 @@ uint16 platform_get_locale_language(){
return LANGUAGE_UNDEFINED;
}
time_t platform_file_get_modified_time(char* path){
time_t platform_file_get_modified_time(const utf8* path)
{
WIN32_FILE_ATTRIBUTE_DATA data;
if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data))
wchar_t *wPath = utf8_to_widechar(path);
BOOL result = GetFileAttributesExW(wPath, GetFileExInfoStandard, &data);
free(wPath);
if (result) {
ULARGE_INTEGER ull;
ull.LowPart = data.ftLastWriteTime.dwLowDateTime;
ull.HighPart = data.ftLastWriteTime.dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL;
} else {
return 0;
ULARGE_INTEGER ull;
ull.LowPart = data.ftLastWriteTime.dwLowDateTime;
ull.HighPart = data.ftLastWriteTime.dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL;
}
}
uint8 platform_get_locale_currency(){
uint8 platform_get_locale_currency()
{
CHAR currCode[4];
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SINTLSYMBOL,
(LPSTR)&currCode,
sizeof(currCode)) == 0){
sizeof(currCode)) == 0
) {
return CURRENCY_POUNDS;
}
if (strcmp(currCode, "GBP") == 0){
@@ -741,15 +801,18 @@ uint8 platform_get_locale_currency(){
return CURRENCY_POUNDS;
}
uint8 platform_get_locale_measurement_format(){
uint8 platform_get_locale_measurement_format()
{
UINT measurement_system;
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
(LPSTR)&measurement_system,
sizeof(measurement_system)) == 0){
sizeof(measurement_system)) == 0
) {
return MEASUREMENT_FORMAT_IMPERIAL;
}
switch (measurement_system){
switch (measurement_system) {
case 0:
return MEASUREMENT_FORMAT_METRIC;
case 1:
@@ -758,16 +821,19 @@ uint8 platform_get_locale_measurement_format(){
}
}
uint8 platform_get_locale_temperature_format(){
uint8 platform_get_locale_temperature_format()
{
// There does not seem to be a function to obtain this, just check the countries
UINT country;
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
(LPSTR)&country,
sizeof(country)) == 0){
sizeof(country)) == 0
) {
return TEMPERATURE_FORMAT_C;
}
switch (country){
switch (country) {
case CTRY_UNITED_STATES:
case CTRY_BELIZE:
return TEMPERATURE_FORMAT_F;

View File

@@ -3171,7 +3171,7 @@ int install_track(char* source_path, char* dest_name){
// Set path for actual copy
subsitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), dest_name);
return platform_file_copy(source_path, dest_path);
return platform_file_copy(source_path, dest_path, false);
}
/* rct2: 0x006D13FE */