From 36e8104dbb004b27dbe42a08327e68cee608ba1b Mon Sep 17 00:00:00 2001 From: Alex Taber Date: Tue, 16 Jun 2020 18:45:59 -0400 Subject: [PATCH] Automatically set BGM flag to enabled when doing a BGM install --- include/fs.h | 2 ++ include/search.h | 7 ------- source/fs.c | 53 ++++++++++++++++++++++++++++++++++++++++++----- source/search.c | 54 ------------------------------------------------ source/themes.c | 21 +++++++++++++++---- 5 files changed, 67 insertions(+), 70 deletions(-) delete mode 100644 include/search.h delete mode 100644 source/search.c diff --git a/include/fs.h b/include/fs.h index b9f5012..161ada4 100644 --- a/include/fs.h +++ b/include/fs.h @@ -39,6 +39,8 @@ Result close_archives(void); u32 file_to_buf(FS_Path path, FS_Archive archive, char** buf); u32 zip_memory_to_buf(char *file_name, void * zip_memory, size_t zip_size, char ** buf); u32 zip_file_to_buf(char *file_name, u16 *zip_path, char **buf); +u32 decompress_lz_file(FS_Path file_name, FS_Archive archive, char **buf); +u32 compress_lz_file_fast(FS_Path path, FS_Archive archive, char *in_buf, u32 size); Result buf_to_file(u32 size, FS_Path path, FS_Archive archive, char *buf); void remake_file(FS_Path path, FS_Archive archive, u32 size); diff --git a/include/search.h b/include/search.h deleted file mode 100644 index b2307b7..0000000 --- a/include/search.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef SEARCH_H -#define SEARCH_H - -int BM_search(char *txt, int n, char *pat, int m); - -#endif - diff --git a/source/fs.c b/source/fs.c index 5d76cd9..3b15a24 100644 --- a/source/fs.c +++ b/source/fs.c @@ -28,7 +28,6 @@ #include "fs.h" #include "unicode.h" -#include "search.h" #include #include @@ -197,11 +196,11 @@ Result buf_to_file(u32 size, FS_Path path, FS_Archive archive, char *buf) return 0; } -u32 decompress_lz_file(FS_Path file_name, char **buf) +u32 decompress_lz_file(FS_Path file_name, FS_Archive archive, char **buf) { Handle handle; Result res = 0; - if (R_FAILED(res = FSUSER_OpenFile(&handle, ArchiveSD, file_name, FS_OPEN_READ, 0))) { + if (R_FAILED(res = FSUSER_OpenFile(&handle, archive, file_name, FS_OPEN_READ, 0))) { DEBUG("%lu\n", res); return 0; } @@ -218,6 +217,7 @@ u32 decompress_lz_file(FS_Path file_name, char **buf) FSFILE_Close(handle); if (temp_buf[0] != 0x11) { + free(temp_buf); return 0; } @@ -290,9 +290,52 @@ u32 decompress_lz_file(FS_Path file_name, char **buf) return cur_written; } -u32 compress_lz_file(FS_Path path, char *buf, u32 len) +// This is an awful algorithm to "compress" LZ11 data. +// We do this instead of actual LZ11 compression because of time - +// LZ11 requires a lot of mem searching which is painfully slow on 3DS. +// This process is nearly instant but means the resulting file is actually larger +// than the input file. I don't think this is a problem as the only file we compress like this +// is the theme data installed to extdata in some rare cases, which means only 1 file at most +// is ever compressed like this. I don't think 400 KB is that big a sacrifice for probably +// half a minute or so of time save - I may change my mind on this in the future, especially +// if i figure out a dynamic programming algorithm which ends up being significantly +// faster. Otherwise, I think this is probably a fine implementation. + +u32 compress_lz_file_fast(FS_Path path, FS_Archive archive, char *in_buf, u32 size) { - + char *output_buf = calloc(1, size * 2); + u32 output_size = 0; + u32 mask_pos = 0; + u32 bytes_processed = 0; + u8 counter = 0; + + if (output_buf == NULL) return 0; + + // Set header data for the LZ11 file - 0x11 is version (LZ11), next 3 bytes are size + output_buf[0] = 0x11; + output_buf[3] = (size & 0xFF0000) >> 16; + output_buf[2] = (size & 0xFF00) >> 8; + output_buf[1] = (size & 0xFF); + + output_size += 4; + + while (bytes_processed < size) + { + if (counter == 0) + { + mask_pos = output_size++; + output_buf[mask_pos] = 0; + } + + output_buf[output_size++] = in_buf[bytes_processed++]; + + if (++counter == 8) counter = 0; + } + + buf_to_file(output_size, path, archive, output_buf); + free(output_buf); + + return output_size; } void remake_file(FS_Path path, FS_Archive archive, u32 size) diff --git a/source/search.c b/source/search.c deleted file mode 100644 index 0492a37..0000000 --- a/source/search.c +++ /dev/null @@ -1,54 +0,0 @@ -/* C implementation of Boyer-Moore Pattern Searching taken from https://www.geeksforgeeks.org/boyer-moore-algorithm-for-pattern-searching/ */ - -# include -# include -# include - -# define NO_OF_CHARS 256 - -int max (int a, int b) { return (a > b)? a: b; } - - -void badCharHeuristic( char *str, int size, - int badchar[NO_OF_CHARS]) -{ - int i; - - for (i = 0; i < NO_OF_CHARS; i++) - badchar[i] = -1; - - for (i = 0; i < size; i++) - badchar[(int) str[i]] = i; -} - - -int BM_search(char *txt, int n, char *pat, int m) -{ - - int badchar[NO_OF_CHARS]; - - badCharHeuristic(pat, m, badchar); - - int s = 0; - - while(s <= (n - m)) - { - int j = m-1; - - while(j >= 0 && pat[j] == txt[s+j]) - j--; - - if (j < 0) - { - return s; - - s += (s+m < n)? m-badchar[txt[s+m]] : 1; - - } - - else - s += max(1, j - badchar[txt[s+j]]); - } - - return -1; -} diff --git a/source/themes.c b/source/themes.c index ca477c6..4787087 100644 --- a/source/themes.c +++ b/source/themes.c @@ -184,16 +184,29 @@ static Result install_theme_internal(Entry_List_s themes, int installmode) if(installmode & THEME_INSTALL_BGM) { music_size = load_data("/bgm.bcstm", current_theme, &music); - if(music_size > BGM_MAX_SIZE) + if (music_size > BGM_MAX_SIZE) { free(music); DEBUG("bgm too big\n"); return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE); } - remake_file(fsMakePath(PATH_ASCII, "/BgmCache.bin"), ArchiveThemeExt, BGM_MAX_SIZE); - res = buf_to_file(music_size, fsMakePath(PATH_ASCII, "/BgmCache.bin"), ArchiveThemeExt, music); - free(music); + if (music_size != 0) + { + remake_file(fsMakePath(PATH_ASCII, "/BgmCache.bin"), ArchiveThemeExt, BGM_MAX_SIZE); + res = buf_to_file(music_size, fsMakePath(PATH_ASCII, "/BgmCache.bin"), ArchiveThemeExt, music); + free(music); + + char *body_buf = NULL; + body_size = decompress_lz_file(fsMakePath(PATH_ASCII, "/BodyCache.bin"), ArchiveThemeExt, &body_buf); + if (body_buf[5] != 1) + { + installmode |= THEME_INSTALL_BODY; + body_buf[5] = 1; + body_size = compress_lz_file_fast(fsMakePath(PATH_ASCII, "/BodyCache.bin"), ArchiveThemeExt, body_buf, body_size); + } + free(body_buf); + } if(R_FAILED(res)) return res; } else