From dedd0047bd8f9f73aba4defc19c429af7c987983 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Tue, 23 Aug 2022 12:32:50 +1000 Subject: [PATCH] wad: Refactor ResFindSignature to work in chunks kinda mucky but it works --- src/w_wad.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 0e39070d3..d2ea6c2ac 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -522,24 +522,49 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen */ static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos) { + //the Wii U has rather slow filesystem access, and fgetc is *unbearable* + //so I reimplemented this function to buffer 128k chunks char *s; int c; + fseek(handle, 0, SEEK_END); + size_t len = ftell(handle); + fseek(handle, startpos, SEEK_SET); + size_t remaining = len - startpos; + size_t chunkpos = startpos; + s = endPat; - while((c = fgetc(handle)) != EOF) - { - if (*s != c && s > endPat) // No match? - s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. - if (*s == c) - { - s++; - if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature. + + //128k buffers + size_t buffer_size = std::min(128 * 1024 * sizeof(char), remaining); + char* buffer = static_cast(malloc(buffer_size)); + + size_t bytes_read = 0; + while ((bytes_read = fread(buffer, 1, buffer_size, handle)) > 0) { + for (size_t i = 0; i < bytes_read; i++) { + c = (int)buffer[i]; + + if (*s != c && s > endPat) // No match? + s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. + if (*s == c) { - return true; + s++; + if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature. + { + //the original function would leave the FILE* seeked to the end of the match + size_t foundpos = chunkpos + i + 1; + fseek(handle, foundpos, SEEK_SET); + + free(buffer); + return true; + } } } + chunkpos += bytes_read; } + + free(buffer); return false; }