From 54eaa5de61f51553fb9202c902d732afef9d21a7 Mon Sep 17 00:00:00 2001 From: Aetias Date: Thu, 22 Feb 2024 18:20:12 +0100 Subject: [PATCH] Add MSYS support in `rom` tools --- tools/rom/build.c | 76 ++++++++++++--------------------------------- tools/rom/extract.c | 34 ++++---------------- tools/rom/util.h | 57 +++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 95 deletions(-) diff --git a/tools/rom/build.c b/tools/rom/build.c index f5b28e10..819f09cf 100644 --- a/tools/rom/build.c +++ b/tools/rom/build.c @@ -367,7 +367,7 @@ bool WriteArm9OverlayFiles( size_t address = *pAddress; char fileName[32]; - if (chdir(OVERLAYS_SUBDIR) != 0) FATAL("Failed to enter overlays directory '" OVERLAYS_SUBDIR "'\n"); + if (!ChangeDir(OVERLAYS_SUBDIR)) return false; for (size_t ovNum = 0; ovNum < numOverlays; ++ovNum) { sprintf(fileName, "ov%02ld.lz", ovNum); @@ -383,7 +383,7 @@ bool WriteArm9OverlayFiles( fatEntries[fileId].endOffset = address; } - if (chdir("..") != 0) FATAL("Failed to leave overlays directory '" OVERLAYS_SUBDIR "'\n"); + if (!ChangeDir("..")) return false; *pAddress = address; return true; @@ -674,9 +674,9 @@ bool TraverseAndAppendAssets(FILE *fpRom, size_t *pAddress, const FileTree *tree entries[child->firstFileId].endOffset = address; continue; } - if (chdir(name) != 0) FATAL("Failed to enter assets directory '%s'\n", name); + if (!ChangeDir(name)) return false; if (!TraverseAndAppendAssets(fpRom, &address, child, entries, child->firstFileId)) return false; - if (chdir("..") != 0) FATAL("Failed to leave assets directory '%s'\n", name); + if (!ChangeDir("..")) return false; } *pAddress = address; @@ -711,7 +711,7 @@ bool AppendAssets( assetsList[listSize] = '\0'; char assetsDir[256]; - if (getcwd(assetsDir, sizeof(assetsDir)) == NULL) FATAL("Failed to get assets directory\n"); + if (!GetCurrentDir(assetsDir, sizeof(assetsDir))) FATAL("Failed to get assets directory\n"); char *const listEnd = assetsList + listSize; for (char *path = assetsList, *next; path < listEnd; path = next) { @@ -723,9 +723,9 @@ bool AppendAssets( // First file ID of root directory is given from number of overlays uint16_t firstFileId = subTree->entry == NULL ? numOverlays : subTree->firstFileId; - if (path[1] != '\0' && chdir(&path[1]) != 0) FATAL("Failed to enter assets directory '%s'\n", path); + if (path[1] != '\0' && !ChangeDir(&path[1])) return false; if (!TraverseAndAppendAssets(fpRom, &address, subTree, entries, firstFileId)) return false; - if (chdir(assetsDir) != 0) FATAL("Failed to leave assets directory '%s'\n", path); + if (!ChangeDir(assetsDir)) return false; subTree->addedToFat = true; } @@ -884,7 +884,7 @@ int main(int argc, char **argv) { // --------------------- Set up --------------------- char rootDir[256]; - if (getcwd(rootDir, sizeof(rootDir)) == NULL) { + if (!GetCurrentDir(rootDir, sizeof(rootDir))) { fprintf(stderr, "Failed to get root directory\n"); return 1; } @@ -921,23 +921,14 @@ int main(int argc, char **argv) { // --------------------- Get canonical file paths --------------------- if (assetsListFile != NULL && !AllocFullPath(assetsListFile, &assetsListFile)) return 1; - if (chdir(baseDir) != 0) { - fprintf(stderr, "Failed to enter base directory '%s'\n", baseDir); - return 1; - } + if (!ChangeDir(baseDir)) return 1; char *arm9overlayDataFile = NULL; if (!AllocFullPath(ARM9_OVERLAY_DATA_FILE, &arm9overlayDataFile)) return 1; - if (chdir(rootDir) != 0) { - fprintf(stderr, "Failed to leave base directory '%s'\n", baseDir); - return 1; - } + if (!ChangeDir(rootDir)) return 1; // --------------------- Write ARM9 program --------------------- - if (chdir(buildDir) != 0) { - fprintf(stderr, "Failed to enter build directory '%s'\n", buildDir); - return 1; - } + if (!ChangeDir(buildDir)) return 1; if (!Align(512, fpRom, &address)) return 1; header.arm9.offset = address; @@ -957,15 +948,9 @@ int main(int argc, char **argv) { if (!WriteArm9Overlays(fpRom, &address, &header, arm9overlayDataFile, overlayEntries, &numOverlays)) return 1; FreeFullPath(&arm9overlayDataFile); - if (chdir(rootDir) != 0) { - fprintf(stderr, "Failed to leave build directory '%s'\n", buildDir); - return 1; - } + if (!ChangeDir(rootDir)) return 1; - if (chdir(baseDir) != 0) { - fprintf(stderr, "Failed to enter base directory '%s'\n", baseDir); - return 1; - } + if (!ChangeDir(baseDir)) return 1; // --------------------- Write ARM7 program --------------------- @@ -973,10 +958,7 @@ int main(int argc, char **argv) { header.arm7.offset = address; if (!AppendFile(fpRom, ARM7_PROGRAM_FILE, &address, &header.arm7.size)) return 1; - if (chdir(ASSETS_SUBDIR) != 0) { - fprintf(stderr, "Failed to enter assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir(ASSETS_SUBDIR)) return 1; // --------------------- Write file name table (FNT) --------------------- @@ -999,10 +981,7 @@ int main(int argc, char **argv) { FatEntry *fatEntries = malloc(numFiles * sizeof(FatEntry)); memcpy(fatEntries, overlayEntries, numOverlays * sizeof(*fatEntries)); - if (chdir("..") != 0) { - fprintf(stderr, "Failed to leave assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir("..")) return 1; // --------------------- Write banner --------------------- @@ -1010,10 +989,7 @@ int main(int argc, char **argv) { header.bannerOffset = address; if (!WriteBanner(fpRom, &address)) return false; - if (chdir(ASSETS_SUBDIR) != 0) { - fprintf(stderr, "Failed to enter assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir(ASSETS_SUBDIR)) return 1; // --------------------- Write assets --------------------- @@ -1027,15 +1003,9 @@ int main(int argc, char **argv) { if (!FreeFileTree(&root)) return false; - if (chdir("..") != 0) { - fprintf(stderr, "Failed to leave assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir("..")) return 1; - if (chdir(rootDir) != 0) { - fprintf(stderr, "Failed to leave base directory '%s'\n", baseDir); - return 1; - } + if (!ChangeDir(rootDir)) return 1; // --------------------- Write padding --------------------- @@ -1049,18 +1019,12 @@ int main(int argc, char **argv) { char *arm7bios = NULL; if (arm7biosFile != NULL && !AllocFullPath(arm7biosFile, &arm7bios)) return 1; - if (chdir(buildDir) != 0) { - fprintf(stderr, "Failed to enter build directory '%s'\n", buildDir); - return 1; - } + if (!ChangeDir(buildDir)) return 1; if (!FinalizeHeader(fpRom, &header, arm7bios, secureArea, &metadata)) return false; FreeFullPath(&arm7bios); - if (chdir(rootDir) != 0) { - fprintf(stderr, "Failed to leave build directory '%s'\n", buildDir); - return 1; - } + if (!ChangeDir(rootDir)) return 1; free(readBuffer); fclose(fpRom); diff --git a/tools/rom/extract.c b/tools/rom/extract.c index 5ce4a293..c236b5f8 100644 --- a/tools/rom/extract.c +++ b/tools/rom/extract.c @@ -24,16 +24,6 @@ void Indent(size_t depth) { } } -bool MakeDir(const char *dir) { - struct stat dirStat; - if (stat(dir, &dirStat) != 0) { - if (mkdir(dir, 0777) != 0) FATAL("Failed to make directory '%s'\n", dir); - return true; - } - if (!S_ISDIR(dirStat.st_mode)) FATAL("Could not make directory '%s' due to a file with the same name\n", dir); - return true; -} - bool CheckRegion(const Header *pHeader, BuildInfo *pInfo) { Region region = pHeader->gamecode[3]; if ( @@ -181,7 +171,7 @@ bool ExtractSubtable( printf("%s {\n", name); } if (!MakeDir(name)) return false; - if (chdir(name) != 0) FATAL("Failed to enter assets subdirectory '%s'\n", name); + if (!ChangeDir(name)) return false; uint16_t subdirId = READ_SUBDIR_ID(pSubEntry); uint16_t subdirIndex = subdirId & 0xfff; @@ -205,7 +195,7 @@ bool ExtractSubtable( printf("}\n"); } - if (chdir("..") != 0) FATAL("Failed to leave assets subdirectory '%s'\n", name); + if (!ChangeDir("..")) return false; subEntryAddr += sizeof(FntSubEntry) + pSubEntry->length + sizeof(subdirId); pSubEntry = (const FntSubEntry*) subEntryAddr; } @@ -378,10 +368,7 @@ int main(int argc, const char **argv) { BuildInfo info; if (!CheckRegion(pHeader, &info)) return 1; if (!MakeDir(outDir)) return 1; - if (chdir(outDir) != 0) { - fprintf(stderr, "Failed to enter output directory '%s'\n", outDir); - return 1; - } + if (!ChangeDir(outDir)) return 1; // --------------------- Extract ARM7 program --------------------- @@ -395,26 +382,17 @@ int main(int argc, const char **argv) { // --------------------- Extract assets --------------------- if (!MakeDir(ASSETS_SUBDIR)) return 1; - if (chdir(ASSETS_SUBDIR) != 0) { - fprintf(stderr, "Failed to enter assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir(ASSETS_SUBDIR)) return 1; const uint8_t *fntStart = rom + pHeader->fileNames.offset; const uint8_t *fatStart = rom + pHeader->fileAllocs.offset; if (!ExtractAssets(rom, fatStart, fntStart)) return 1; - if (chdir("..") != 0) { - fprintf(stderr, "Failed to leave assets directory '" ASSETS_SUBDIR "'\n"); - return 1; - } + if (!ChangeDir("..")) return 1; // --------------------- Extract overlay data --------------------- if (!ExtractOverlayData(rom, pHeader)) return 1; - if (chdir("..") != 0) { - fprintf(stderr, "Failed to leave output directory '%s'\n", outDir); - return 1; - } + if (!ChangeDir("..")) return 1; free(rom); } diff --git a/tools/rom/util.h b/tools/rom/util.h index a1dbf3b7..a757278a 100644 --- a/tools/rom/util.h +++ b/tools/rom/util.h @@ -1,5 +1,5 @@ -#ifndef __FS_H -#define __FS_H +#ifndef __UTIL_H +#define __UTIL_H #include #include @@ -16,11 +16,11 @@ #define READ32(buf) (((uint8_t*) buf)[0] | (((uint8_t*) buf)[1] << 8) | (((uint8_t*) buf)[2] << 16) | (((uint8_t*) buf)[3] << 24)) #define REVERSE32(val) ((val >> 24) | ((val & 0xff0000) >> 8) | ((val & 0xff00) << 8) | ((val & 0xff) << 24)) -#ifdef _WIN32 +#if defined(_WIN32) || defined(__MSYS__) +# define __UTIL_WINDOWS # include -# include -# define mkdir(path, mode) mkdir(path) #elif __linux__ +# define __UTIL_LINUX # include # include # include @@ -30,13 +30,48 @@ # error "Target platform not supported" #endif +bool MakeDir(const char *dir) { +#ifdef __UTIL_WINDOWS + if (CreateDirectoryA(dir, NULL)) return true; + if (GetLastError() == ERROR_ALREADY_EXISTS) return true; + FATAL("Failed to make directory '%s'\n", dir); +#elif defined(__UTIL_LINUX) + struct stat dirStat; + if (stat(dir, &dirStat) != 0) { + if (mkdir(dir, 0777) != 0) FATAL("Failed to make directory '%s'\n", dir); + return true; + } + if (!S_ISDIR(dirStat.st_mode)) FATAL("Could not make directory '%s' due to a file with the same name\n", dir); + return true; +#endif +} + +bool GetCurrentDir(char *dir, size_t dirSize) { +#ifdef __UTIL_WINDOWS + return GetCurrentDirectory(dirSize, dir) > 0; +#elif defined(__UTIL_LINUX) + return getcwd(dir, dirSize) != NULL; +#endif +} + +bool ChangeDir(const char *dir) { +#ifdef __UTIL_WINDOWS + if (SetCurrentDirectory(dir)) return true; +#elif defined(__UTIL_LINUX) + if (chdir(dir) == 0) return true; +#endif + char cwd[256]; + if (!GetCurrentDir(cwd, sizeof(cwd))) strcpy(cwd, "[unknown]"); + FATAL("Failed to enter directory '%s' from current directory '%s'\n", dir, cwd); +} + bool WcharToUtf8(wchar_t *in, size_t inSize, char *out, size_t outSize, size_t *pResultSize) { -#ifdef _WIN32 +#ifdef __UTIL_WINDOWS size_t resultSize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, in, inSize / sizeof(wchar_t), out, outSize, NULL, NULL); if (resultSize == 0) FATAL("Failed to convert to UTF-8\n"); *pResultSize = resultSize; return true; -#elif __linux__ +#elif defined(__UTIL_LINUX) iconv_t convDesc = iconv_open("UTF-8", "UTF-16"); if (convDesc == (iconv_t) -1) FATAL("Failed to get conversion description to UTF-8\n"); size_t remainingBytes = outSize; @@ -50,11 +85,11 @@ bool WcharToUtf8(wchar_t *in, size_t inSize, char *out, size_t outSize, size_t * } bool Utf8ToWchar(char *in, size_t inSize, wchar_t *out, size_t outSize) { -#ifdef _WIN32 +#ifdef __UTIL_WINDOWS size_t resultSize = MultiByteToWideChar(CP_UTF8, 0, in, inSize, out, outSize / sizeof(wchar_t)); if (resultSize == 0) FATAL("Failed to convert from UTF-8: %d\n", GetLastError()); return true; -#elif __linux__ +#elif defined(__UTIL_LINUX) iconv_t convDesc = iconv_open("UTF-16", "UTF-8"); if (convDesc == (iconv_t) -1) FATAL("Failed to get conversion description from UTF-8\n"); size_t remainingBytes = outSize; @@ -74,7 +109,7 @@ bool Utf8ToWchar(char *in, size_t inSize, wchar_t *out, size_t outSize) { } bool AllocFullPath(const char *path, char **pFullPath) { -#ifdef _WIN32 +#ifdef __UTIL_WINDOWS if (path[0] == '/') { // Remove drive letter, e.g. /c/Projects/ph/ -> /Projects/ph/ const char *root = strchr(path + 1, '/'); @@ -86,7 +121,7 @@ bool AllocFullPath(const char *path, char **pFullPath) { if (resultSize == 0 || resultSize > size) FATAL("Failed to get full path for '%s'\n", path); *pFullPath = fullPath; return true; -#elif __linux__ +#elif defined(__UTIL_LINUX) char *fullPath = realpath(path, NULL); if (fullPath == NULL) FATAL("Failed to get full path for '%s'\n", path); *pFullPath = fullPath;