diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fd6364c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,121 @@ +cmake_minimum_required(VERSION 3.28) + +# Define the project +project(SZS C) + +# Dependencies +find_package(Curses REQUIRED) +find_package(OpenSSL REQUIRED) +find_package(PNG REQUIRED) + +# Create the library +add_library(SZS SHARED + external/project/dclib/dclib-basics.c + external/project/dclib/dclib-tables.c + external/project/dclib/dclib-numeric.c + external/project/dclib/dclib-color.c + external/project/dclib/dclib-file.c + external/project/dclib/dclib-debug.c + external/project/dclib/dclib-xdump.c + external/project/dclib/dclib-utf8.c + external/project/dclib/lib-dol.c + external/project/dclib/dclib-ui.c + + external/project/src/lib-std.c + external/project/src/db-file.c + external/project/src/db-mkw.c + external/project/src/lib-szs.c + external/project/src/file-type.c + external/project/src/lib-pack.c + external/project/src/lib-file.c + external/project/src/lib-breff.c + external/project/src/lib-rarc.c + external/project/src/lib-brres.c + external/project/src/lib-checksum.c + external/project/src/lib-rkc.c + external/project/src/lib-bzip2.c + external/project/src/lib-lzma.c + external/project/src/libbz2/bzlib.c + external/project/src/libbz2/crctable.c + external/project/src/libbz2/randtable.c + external/project/src/liblzma/LzmaEnc.c + external/project/src/liblzma/LzmaDec.c + external/project/dclib/dclib-parser.c + external/project/dclib/lib-bmg.c + external/project/dclib/dclib-regex.c + external/project/dclib/dclib-shift-jis.c + external/project/src/liblzma/LzFind.c + external/project/src/liblzma/CpuArch.c + external/project/src/lib-object.c + external/project/src/db-object.c + external/project/src/libbz2/decompress.c + external/project/src/libbz2/huffman.c + external/project/src/lib-numeric.c + external/project/src/lib-objflow.c + external/project/src/lib-parser.c + external/project/src/lib-parser-func.c + external/project/dclib/lib-mkw.c + external/project/dclib/dclib-vector.c + external/project/src/lib-common.c + external/project/src/libbz2/compress.c + external/project/src/libbz2/blocksort.c + external/project/src/lib-geohit.c + external/project/src/crypto/sha1_one.c + external/project/src/lib-lecode.c + external/project/src/lib-ledis.c + external/project/src/lib-ctcode.c + external/project/src/db-ctcode.c + external/project/src/lib-xbmg.c + external/project/src/lib-analyze.c + external/project/src/lib-lex.c + external/project/src/lib-szs-create.c + external/project/src/lib-kcl.c + external/project/src/lib-transform.c + external/project/src/lib-kmp.c + external/project/src/db-kcl.c + external/project/src/lib-pat.c + external/project/src/lib-mdl.c + external/project/src/lib-image3.c + external/project/src/lib-image2.c + external/project/src/lib-image1.c + external/project/src/lib-kmp-pflags.c + external/project/src/lib-kmp-text.c + external/project/src/lib-kmp-draw.c + external/project/src/analyze.c + + source/szs/szs.c + source/bmg/bmg.c + source/bmg/bmg.h +) +# Include additional directories +target_include_directories(SZS PRIVATE + # Libraries + ${CURSES_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIR} + ${PNG_INCLUDE_DIRS} + + # Local + external/project + external/project/dclib + external/project/src + external/project/src/libbz2 + external/project/src/liblzma + external/project/src/ui + external/project/src/crypto +) +# Link with additional libraries +target_link_libraries(SZS PRIVATE + # External Libraries + ${CURSES_LIBRARIES} + ${OPENSSL_LIBRARIES} + ${PNG_LIBRARY} +) +target_compile_definitions(SZS PRIVATE + # Library arguments + BUILD_SZS + + # Original Wiimm's arguments + Z7_ST=1 + USE_SHA_LIB=1 + DCLIB_DEBUG_C +) \ No newline at end of file diff --git a/source/bmg/bmg.c b/source/bmg/bmg.c new file mode 100644 index 0000000..09fa70d --- /dev/null +++ b/source/bmg/bmg.c @@ -0,0 +1,75 @@ +#include "bmg.h" + + +BmgFile* bmgFileNew() { + // allocate the memory for the object + BmgFile* file = (BmgFile*)malloc(sizeof(BmgFile)); + file->_internal = (bmg_t*)malloc(sizeof(bmg_t)); + + // initialize the internal structure + InitializeBMG(file->_internal); + + return file; +} + +void bmgFileFree(BmgFile* file) { + // deallocate the memory of the object + free(file->_internal); + free(file); +} + +BmgFile* bmgFileLoad(const char* path) { + // create a new bmg file + BmgFile* file = bmgFileNew(); + + // load the bmg file + LoadBMG( + file->_internal, + false, + NULL, + path, + FM_MODIFY + ); + + return file; +} + +BmgRecord* bmgRecordNew(bmg_item_t* internal_record) { + // allocate memory for the record + BmgRecord* record = (BmgRecord*)malloc(sizeof(BmgRecord)); + record->_internal = internal_record; + + return record; +} + +void bmgRecordFree(BmgRecord* record) { + // free the memory used for the record + free(record); +} + +BmgRecord* bmgRecordGet(BmgFile* file, u32 id) { + // find the corresponding bmg record + bmg_item_t* internal_record = FindItemBMG(file->_internal, id); + // wrap it with our structure + BmgRecord* record = bmgRecordNew(internal_record); + + return record; +} + +BmgRecord* bmgRecordInsert(BmgFile* file, u32 id, const char* text) { + // insert the data into the bmg file + bmg_item_t* internal_record = InsertItemBMG( + file->_internal, + id, + NULL, + 0, + NULL + ); + + // internal_record->text = strdup(text); + + // wrap it with our structure + BmgRecord* record = bmgRecordNew(internal_record); + + return record; +} \ No newline at end of file diff --git a/source/bmg/bmg.h b/source/bmg/bmg.h new file mode 100644 index 0000000..2219ee4 --- /dev/null +++ b/source/bmg/bmg.h @@ -0,0 +1,25 @@ +#pragma once + + +#ifdef BUILD_SZS +// if we are building the library, use the base Wiimm's types. +#include "lib-bmg.h" +#else +#define bmg_t void +#endif + + +typedef struct { + bmg_t* _internal; +} BmgFile; + +typedef struct { + bmg_item_t* _internal; +} BmgRecord; + + +BmgFile* bmgFileNew(); + +void bmgFileFree(BmgFile* file); + +BmgFile* bmgFileLoad(const char* path); diff --git a/source/szs/szs.c b/source/szs/szs.c new file mode 100644 index 0000000..f2e6724 --- /dev/null +++ b/source/szs/szs.c @@ -0,0 +1,135 @@ +#include "szs.h" + + +SzsFile* szsFileNew() { + // allocate the memory for the wrapper and the internal file + SzsFile* file = (SzsFile*)malloc(sizeof(SzsFile)); + file->_internal = (szs_file_t*)malloc(sizeof(szs_file_t)); + + // initialize the internal structure + InitializeSZS(file->_internal); + + return file; +} + +void szsFileFree(SzsFile* file) { + // reset the SZS file + ResetSZS(file->_internal); + + // free the memory + free(file->_internal); + free(file); +} + +SzsFile* szsFileLoad(const char* path) { + // create a new empty SZS file + SzsFile* file = szsFileNew(); + + // load the file + if (LoadSZS( + file->_internal, + path, + true, + false, + false + ) > ERR_WARNING) { + // if an error occurred, cancel the file allocation and return NULL + szsFileFree(file); + return NULL; + } + + return file; +} + +SzsFile* szsFileCreate(const char* path) { + // create a new empty SZS file + SzsFile* file = szsFileNew(); + + // create the file from a directory + if (CreateSZS( + file->_internal, + NULL, + path, + NULL, + NULL, + -1, + -1, + false + ) > ERR_WARNING) { + // if an error occurred, cancel the file allocation and return NULL + szsFileFree(file); + return NULL; + } + + return file; +} + +void szsFileExtract(SzsFile* file, const char* path) { + // TODO(Faraphel): don't seem to work + + // set the destination of the base archive + // TODO(Faraphel): the output directory name is the filename with a .d extension instead of .szs + // for customizability, the extraction should instead be implemented manually. + file->_internal->fname = strdup(path); + + ExtractFilesSZS( + file->_internal, + -1, + false, + NULL, + path + ); +} + +SzsSubfile* szsSubfileNew(szs_subfile_t* internal_subfile) { + // allocate memory for our subfile wrapper + SzsSubfile* subfile = (SzsSubfile*)malloc(sizeof(SzsSubfile)); + + // save the base subfile + subfile->_internal = internal_subfile; + subfile->path_p = &subfile->_internal->path; + subfile->name_p = &subfile->_internal->name; + subfile->size_p = &subfile->_internal->size; + subfile->data_p = &subfile->_internal->data; + subfile->is_directory_p = (bool*)&subfile->_internal->is_dir; + + return subfile; +} + +void szsSubfileFree(SzsSubfile* subfile) { + free(subfile); +} + +void szsFileDiscover(SzsFile* file, bool force) { + // if the subfiles are already loaded and force is disabled, directly exit + if (file->_internal->subfile.used != 0 && !force) + return; + + // reset the list of subfiles and reload it + CollectFilesSZS(file->_internal, true, 0, -1, SORT_NONE); +} + +SzsSubfileIterator* szsSubfileIterateNew(SzsFile* file) { + szsFileDiscover(file, false); + SzsSubfileIterator* iterator = malloc(sizeof(SzsSubfileIterator)); + + iterator->_internal_current = &file->_internal->subfile.list[0]; + iterator->_internal_final = &file->_internal->subfile.list[file->_internal->subfile.size]; + + return iterator; +} + +void szsSubfileIterateFree(SzsSubfileIterator* iterator) { + free(iterator); +} + +SzsSubfile* szsSubfileIterateNext(SzsSubfileIterator* iterator) { + // if we went over the last file in the list, return NULL + if (iterator->_internal_current > iterator->_internal_final) + return NULL; + + // get the next subfile + SzsSubfile* subfile = szsSubfileNew(iterator->_internal_current++); + + return subfile; +} diff --git a/source/szs/szs.h b/source/szs/szs.h new file mode 100644 index 0000000..dd26be4 --- /dev/null +++ b/source/szs/szs.h @@ -0,0 +1,127 @@ +#pragma once + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef BUILD_SZS +// if we are building the library, use the base Wiimm's types. +#include "lib-szs.h" +#else +// if we are importing the library, do not import the types directly to avoid potential incompatibilities +// provoced by non-standard C code. +#define szs_file_t void +#define szs_subfile_t void +#endif + +#include +#include +#include + + +/** + * A structure representing a SZS subfile. + * Wrapper around Wiimm's szs_subfile_t. + */ +typedef struct { + szs_subfile_t* _internal; // this reference the original szs_subfile_t. + + const char** path_p; // pointer to the path of the subfile. + const char** name_p; // pointer to the name of the subfile. + uint32_t* size_p; // pointer to the size of the subfile. + uint8_t** data_p; // pointer to the array of data. + bool* is_directory_p; // pointer to a boolean indicating if the file is a directory. +} SzsSubfile; + +/** + * A structure representing an SZS file. + * Wrapper around Wiimm's szs_file_t. + */ +typedef struct { + szs_file_t* _internal; // this reference the original szs_file_t. Type not used for the linking when used as a library. +} SzsFile; + +typedef struct { + szs_subfile_t* _internal_current; // this reference the current object in the list. + szs_subfile_t* _internal_final; // this reference the last object in the list. +} SzsSubfileIterator; + +// File + +/** + * Initialize a new empty SZS file. + * @return an empty SZS file + */ +SzsFile* szsFileNew(); + +/** + * Free the memory from an SZS file. + * @param file the file to free + */ +void szsFileFree(SzsFile *file); + +/** + * Load an SZS file. + * @param path the path to the file + * @return the SZS instance + */ +SzsFile* szsFileLoad(const char* path); + +/** + * Create an SZS file from a directory. + * @param path the path of the directory + * @return the SZS instance + */ +SzsFile* szsFileCreate(const char* path); + +void szsFileExtract(SzsFile* file, const char* path); + +// Subfile + +/** + * Create a new subfile. + * @param internal_subfile the base Wiimm's szs_subfile_t structure + * @return a wrapper for this subfile + */ +SzsSubfile* szsSubfileNew(szs_subfile_t* internal_subfile); + +/** + * Free the memory from an SZS subfile. + * @param subfile the subfile to free + */ +void szsSubfileFree(SzsSubfile* subfile); + +/** + * Refresh the list of subfiles inside a SZS file. + * @param file the file to refresh the subfiles from + * @param force ignore the cache system and refresh the subfiles no matter what + */ +void szsFileDiscover(SzsFile* file, bool force); + +/** + * Create an iterator to iterate through the subfiles of a SZS file. + * @param file the file to iterate + * @return an iterator + */ +SzsSubfileIterator* szsSubfileIterateNew(SzsFile* file); + +/** + * Free from the memory a SZS subfile iterator. + * @param iterator the iterator + */ +void szsSubfileIterateFree(SzsSubfileIterator* iterator); + +/** + * Return the next subfile in the iterator + * @param iterator the iterator to the subfiles + * @return the next subfile + * @warning you need to manually free the returned SzsSubfile with `szsSubfileFree` after usage. + */ +SzsSubfile* szsSubfileIterateNext(SzsSubfileIterator* iterator); + + +#ifdef __cplusplus +} +#endif