mirror of
https://gitlab.com/skmp/dca3-game.git
synced 2025-04-28 13:07:59 +03:00
Merge branch 'skmp/fix-case-streamheaderpack' into 'main'
streamheaderpack: bring in fcaseopen for case insensitive paths See merge request skmp/dca3-game!51
This commit is contained in:
commit
8eaa1c73ea
1 changed files with 139 additions and 2 deletions
|
@ -4,6 +4,9 @@
|
|||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct WavHeader {
|
||||
// RIFF Header
|
||||
char riff[4]; // RIFF Header Magic header
|
||||
|
@ -29,6 +32,140 @@ struct WavHeader {
|
|||
#define DCStreamedNameTable DCStreamedNameTable_miami
|
||||
#include "../miami/audio/sampman_dc_streams.h"
|
||||
#undef DCStreamedNameTable
|
||||
|
||||
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
|
||||
// Returned string should freed manually (if exists)
|
||||
char* casepath(char const* path, bool checkPathFirst = true)
|
||||
{
|
||||
//TODO: Implement this
|
||||
bool access_ok = false; //access(path, F_OK) != -1
|
||||
// printf("TODO: FIXME %s\n", __func__);
|
||||
|
||||
if (checkPathFirst && access_ok ) {
|
||||
// File path is correct
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t l = strlen(path);
|
||||
if (l > 2 && path[0] == '.' && (path[1] == '/' || path[1] == '\\')) {
|
||||
// remove ./ from the start of the path
|
||||
path += 2;
|
||||
}
|
||||
char* p = (char*)alloca(l + 1);
|
||||
char* out = (char*)malloc(l + 3); // for extra ./
|
||||
strcpy(p, path);
|
||||
|
||||
size_t rl = 0;
|
||||
|
||||
DIR* d;
|
||||
char* c;
|
||||
|
||||
#if defined(__SWITCH__) || defined(PSP2)
|
||||
if( (c = strstr(p, ":/")) != NULL) // scheme used by some environments, eg. switch, vita
|
||||
{
|
||||
size_t deviceNameOffset = c - p + 3;
|
||||
char* deviceNamePath = (char*)alloca(deviceNameOffset + 1);
|
||||
strlcpy(deviceNamePath, p, deviceNameOffset);
|
||||
deviceNamePath[deviceNameOffset] = 0;
|
||||
d = opendir(deviceNamePath);
|
||||
p = c + 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (p[0] == '/' || p[0] == '\\')
|
||||
{
|
||||
d = opendir("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
d = opendir(".");
|
||||
out[0] = '.';
|
||||
out[1] = 0;
|
||||
rl = 1;
|
||||
}
|
||||
|
||||
bool cantProceed = false; // just convert slashes in what's left in string, don't correct case of letters(because we can't)
|
||||
bool mayBeTrailingSlash = false;
|
||||
|
||||
while (c = strsep(&p, "/\\"))
|
||||
{
|
||||
// May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid)
|
||||
if (*c == '\0')
|
||||
{
|
||||
mayBeTrailingSlash = true;
|
||||
continue;
|
||||
} else {
|
||||
mayBeTrailingSlash = false;
|
||||
}
|
||||
|
||||
out[rl] = '/';
|
||||
rl += 1;
|
||||
out[rl] = 0;
|
||||
|
||||
if (cantProceed)
|
||||
{
|
||||
strcpy(out + rl, c);
|
||||
rl += strlen(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct dirent* e;
|
||||
while (e = readdir(d))
|
||||
{
|
||||
if (strcasecmp(c, e->d_name) == 0)
|
||||
{
|
||||
strcpy(out + rl, e->d_name);
|
||||
int reportedLen = (int)strlen(e->d_name);
|
||||
rl += reportedLen;
|
||||
assert(reportedLen == strlen(c) && "casepath: This is not good at all");
|
||||
|
||||
closedir(d);
|
||||
d = opendir(out);
|
||||
|
||||
// Either it wasn't a folder, or permission error, I/O error etc.
|
||||
if (!d) {
|
||||
cantProceed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!e)
|
||||
{
|
||||
printf("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path);
|
||||
// No match, add original name and continue converting further slashes.
|
||||
strcpy(out + rl, c);
|
||||
rl += strlen(c);
|
||||
cantProceed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (d) closedir(d);
|
||||
if (mayBeTrailingSlash) {
|
||||
out[rl] = '/'; rl += 1;
|
||||
out[rl] = '\0';
|
||||
}
|
||||
|
||||
if (rl > l + 2) {
|
||||
printf("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%zu chars)\n\tCorrected: %s (%zu chars)\n\n", path, l, out, rl);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
FILE* fcaseopen(char const* filename, char const* mode)
|
||||
{
|
||||
FILE* result;
|
||||
char* real = casepath(filename);
|
||||
if (!real)
|
||||
result = fopen(filename, mode);
|
||||
else {
|
||||
result = fopen(real, mode);
|
||||
free(real);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
|
||||
size_t table_len = 0;
|
||||
|
@ -50,7 +187,7 @@ int main(int argc, const char** argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
FILE* fout=fopen(argv[3], "wb");
|
||||
FILE* fout=fcaseopen(argv[3], "wb");
|
||||
if (!fout) {
|
||||
std::cerr << "Failed to open " << argv[3] << " for writing" << std::endl;
|
||||
return 1;
|
||||
|
@ -59,7 +196,7 @@ int main(int argc, const char** argv) {
|
|||
for (int i = 0; i < table_len; i++) {
|
||||
std::string filename = std::string(argv[2]) + "/" + table[i];
|
||||
|
||||
FILE* f = fopen(filename.c_str(), "rb");
|
||||
FILE* f = fcaseopen(filename.c_str(), "rb");
|
||||
if (!f) {
|
||||
std::cerr << "Failed to open " << filename << std::endl;
|
||||
fclose(fout);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue