diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index a4f45272..40d883be 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -1470,7 +1470,7 @@ bool CStream::Open(const char* filename, uint32 overrideSampleRate) // Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) #if !defined(_WIN32) - char *real = casepath(filename); + char *real = casepath(filename, false); if (real) { strcpy(m_aFilename, real); free(real); diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp index bd6601ef..5da6d35b 100644 --- a/src/audio/sampman_oal.cpp +++ b/src/audio/sampman_oal.cpp @@ -18,6 +18,8 @@ #include #include #include +#elif defined(__WIIU__) +extern "C" char *_getcwd (char *__buf, size_t __size); #else #define _getcwd getcwd #endif @@ -507,7 +509,7 @@ _FindMP3s(void) strcat(path, "\\MP3\\"); #if !defined(_WIN32) - char *actualPath = casepath(path); + char *actualPath = casepath(path, false); if (actualPath) { strcpy(path, actualPath); free(actualPath); diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 2ffe17c1..dee091a3 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -195,6 +195,11 @@ int _caserename(const char *old_filename, const char *new_filename) return result; } +#ifdef __WIIU__ +#define MAX_AUDIO_CACHE_ENTRIES 2000 +extern char* audioCacheEntries[MAX_AUDIO_CACHE_ENTRIES]; +#endif + // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) // Returned string should freed manually (if exists) char* casepath(char const* path, bool checkPathFirst) @@ -249,6 +254,9 @@ char* casepath(char const* path, bool checkPathFirst) rl = 1; } +#ifdef __WIIU__ + bool inAudioFolder = false; +#endif 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; char* c; @@ -274,6 +282,20 @@ char* casepath(char const* path, bool checkPathFirst) continue; } +#ifdef __WIIU__ + if (inAudioFolder) { + // this is the audio folder just look in the cache + for (int i = 0; i < MAX_AUDIO_CACHE_ENTRIES && audioCacheEntries[i]; i++) { + if (strcasecmp(audioCacheEntries[i], c) == 0) { + strcpy(out + rl, audioCacheEntries[i]); + return out; + } + } + free(out); + return nil; + } +#endif + struct dirent* e; while (e = readdir(d)) { @@ -285,6 +307,14 @@ char* casepath(char const* path, bool checkPathFirst) assert(reportedLen == strlen(c) && "casepath: This is not good at all"); closedir(d); + +#ifdef __WIIU__ + if (strcasecmp("audio", e->d_name) == 0) { + inAudioFolder = true; + break; + } +#endif + d = opendir(out); // Either it wasn't a folder, or permission error, I/O error etc. diff --git a/src/skel/wiiu/getdelim.c b/src/skel/wiiu/getdelim.c new file mode 100644 index 00000000..5f8902af --- /dev/null +++ b/src/skel/wiiu/getdelim.c @@ -0,0 +1,47 @@ +#include +#include + +ssize_t +getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) +{ + char *ptr, *eptr; + + + if (*buf == NULL || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = malloc(*bufsiz)) == NULL) + return -1; + } + + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) + return ptr == *buf ? -1 : ptr - *buf; + else + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = realloc(*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } +} + +ssize_t +getline(char **buf, size_t *bufsiz, FILE *fp) +{ + return getdelim(buf, bufsiz, '\n', fp); +} diff --git a/src/skel/wiiu/wiiu.cpp b/src/skel/wiiu/wiiu.cpp index aef7b548..bea119c9 100644 --- a/src/skel/wiiu/wiiu.cpp +++ b/src/skel/wiiu/wiiu.cpp @@ -814,6 +814,95 @@ void InitialiseLanguage() setlocale(LC_NUMERIC, "C"); } +/* + ***************************************************************************** + This is dumb, the Wii U needs ages to parse the whole audio folder with readdir + This just creates a cache file for looking those up +*/ + +// audio folder has ~1200 files, 2000 to make sure we have enough +#define MAX_AUDIO_CACHE_ENTRIES 2000 // <- when changing also change in crossplatform.cpp +char* audioCacheEntries[MAX_AUDIO_CACHE_ENTRIES] = { NULL }; + +extern "C" ssize_t getline(char **buf, size_t *bufsiz, FILE *fp); + +static void loadAudioFileCache(void) +{ + DIR* d = opendir("."); + if (!d) { + return; + } + + char audioDir[PATH_MAX]; + bool found = false; + struct dirent* ent; + + // find the audio dir with correct capitalization + while (ent = readdir(d)) { + if (strcasecmp("audio", ent->d_name) == 0) { + strcpy(audioDir, ent->d_name); + found = true; + break; + } + } + + if (!found) { + return; + } + + FILE* f = fopen("/vol/external01/wiiu/apps/reVC/audiofiles.cache", "r"); + + if (!f) { + debug("Creating audiofiles cache"); + + DIR* d = opendir(audioDir); + if (!d) { + return; + } + + f = fopen("/vol/external01/wiiu/apps/reVC/audiofiles.cache", "w"); + if (!f) { + closedir(d); + return; + } + + char** entryPtr = audioCacheEntries; + + // This will take a while on the Wii U :) + struct dirent* ent; + while (ent = readdir(d)) { + // write to cache + fprintf(f, "%s\n", ent->d_name); + + // add entry + if (audioCacheEntries - entryPtr < MAX_AUDIO_CACHE_ENTRIES) { + *entryPtr = (char*) malloc(strlen(ent->d_name) + 1); + strcpy(*entryPtr, ent->d_name); + entryPtr++; + } + } + + fclose(f); + closedir(d); + + debug("Created audiofiles cache"); + return; + } + + char** entryPtr = audioCacheEntries; + + // read entries from file + size_t size; + while (getline(entryPtr, &size, f) > 0) { + char* entry = *entryPtr; + // remove '\n' + entry[strlen(entry) - 1] = '\0'; + entryPtr++; + } + + fclose(f); +} + /* ***************************************************************************** */ @@ -874,6 +963,8 @@ main(int argc, char *argv[]) chdir("/vol/external01/wiiu/apps/reVC"); #endif + loadAudioFileCache(); + /* * Initialize the platform independent data. * This will in turn initialize the platform specific data... @@ -1361,6 +1452,12 @@ main(int argc, char *argv[]) */ RsEventHandler(rsTERMINATE, nil); +#ifdef __WIIU__ + for (int i = 0; i < MAX_AUDIO_CACHE_ENTRIES && audioCacheEntries[i]; i++) { + free(audioCacheEntries[i]); + } +#endif + #ifdef _DEBUG_BUILD_ WHBLogUdpDeinit(); #endif