diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..5f6e9a2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,117 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - forever + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^(static_cast(ch0)) \ - | (static_cast(static_cast(ch1)) << 8) \ - | (static_cast(static_cast(ch2)) << 16) \ - | (static_cast(static_cast(ch3)) << 24)) -#endif /* defined(MAKEFOURCC) */ - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = - { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = - { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = - { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 = - { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 = - { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 = - { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = - { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = - { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 = - { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 = - { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 = - { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 = - { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8_ALT = - { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 8, 0x00ff, 0x0000, 0x0000, 0xff00 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 = - { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V8U8 = - { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 = - { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; - -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V16U16 = - { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; - -// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue - -// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) -extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 = - { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; - -#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT -#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT -#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH -#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH -#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE - -#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT -#define DDS_WIDTH 0x00000004 // DDSD_WIDTH - -#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE -#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP -#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX - -#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX -#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX -#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY -#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY -#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ -#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ - -#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ - DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ - DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) - -#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP - -#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME - -// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION -enum DDS_RESOURCE_DIMENSION -{ - DDS_DIMENSION_TEXTURE1D = 2, - DDS_DIMENSION_TEXTURE2D = 3, - DDS_DIMENSION_TEXTURE3D = 4, -}; - -// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG -enum DDS_RESOURCE_MISC_FLAG -{ - DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, -}; - -enum DDS_MISC_FLAGS2 -{ - DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, -}; - -enum DDS_ALPHA_MODE -{ - DDS_ALPHA_MODE_UNKNOWN = 0, - DDS_ALPHA_MODE_STRAIGHT = 1, - DDS_ALPHA_MODE_PREMULTIPLIED = 2, - DDS_ALPHA_MODE_OPAQUE = 3, - DDS_ALPHA_MODE_CUSTOM = 4, -}; - -struct DDS_HEADER -{ - uint32_t size; - uint32_t flags; - uint32_t height; - uint32_t width; - uint32_t pitchOrLinearSize; - uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags - uint32_t mipMapCount; - uint32_t reserved1[11]; - DDS_PIXELFORMAT ddspf; - uint32_t caps; - uint32_t caps2; - uint32_t caps3; - uint32_t caps4; - uint32_t reserved2; -}; - -struct DDS_HEADER_DXT10 -{ - DXGI_FORMAT dxgiFormat; - uint32_t resourceDimension; - uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG - uint32_t arraySize; - uint32_t miscFlags2; // see DDS_MISC_FLAGS2 -}; - -#pragma pack(pop) - -static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); -static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); - -} // namespace diff --git a/delphi/lib/libbsarch.dll b/delphi/lib/libbsarch.dll new file mode 100644 index 0000000..c60183f Binary files /dev/null and b/delphi/lib/libbsarch.dll differ diff --git a/delphi/lib/libbsarchd.dll b/delphi/lib/libbsarchd.dll new file mode 100644 index 0000000..3b6b094 Binary files /dev/null and b/delphi/lib/libbsarchd.dll differ diff --git a/delphi/lib64/libbsarch.dll b/delphi/lib64/libbsarch.dll new file mode 100644 index 0000000..dae0d2d Binary files /dev/null and b/delphi/lib64/libbsarch.dll differ diff --git a/delphi/lib64/libbsarchd.dll b/delphi/lib64/libbsarchd.dll new file mode 100644 index 0000000..f034e75 Binary files /dev/null and b/delphi/lib64/libbsarchd.dll differ diff --git a/libbsarch.dpr b/delphi/libbsarch.dpr similarity index 100% rename from libbsarch.dpr rename to delphi/libbsarch.dpr diff --git a/libbsarch.dproj b/delphi/libbsarch.dproj similarity index 100% rename from libbsarch.dproj rename to delphi/libbsarch.dproj diff --git a/wbBSArchive.pas b/delphi/wbBSArchive.pas similarity index 100% rename from wbBSArchive.pas rename to delphi/wbBSArchive.pas diff --git a/libbsarch-visualstudio-test.cpp b/examples/libbsarch-visualstudio-test.cpp similarity index 100% rename from libbsarch-visualstudio-test.cpp rename to examples/libbsarch-visualstudio-test.cpp diff --git a/libbsarch-visualstudio-test.sln b/examples/libbsarch-visualstudio-test.sln similarity index 100% rename from libbsarch-visualstudio-test.sln rename to examples/libbsarch-visualstudio-test.sln diff --git a/libbsarch-visualstudio-test.vcxproj b/libbsarch-visualstudio-test.vcxproj deleted file mode 100644 index 8957bfc..0000000 --- a/libbsarch-visualstudio-test.vcxproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - {8F73F848-939D-4862-B58B-26572CF20A5F} - Win32Proj - libbsarchvisualstudiotest - 10.0 - libbsarch-visualstudio-test - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(OutDir);$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(OutDir);$(ReferencePath) - - - true - $(OutDir);$(LibraryPath) - $(OutDir);$(ReferencePath) - - - false - $(OutDir);$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(OutDir);$(ReferencePath) - - - false - $(OutDir);$(LibraryPath) - $(OutDir);$(ReferencePath) - - - - - - Level3 - Disabled - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - $(OutDir) - - - - - - - Level3 - Disabled - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - $(OutDir) - - - - - - - Level3 - MaxSpeed - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - $(OutDir) - - - - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - $(OutDir) - - - - - - - - - \ No newline at end of file diff --git a/libbsarch-visualstudio-test.vcxproj.filters b/libbsarch-visualstudio-test.vcxproj.filters deleted file mode 100644 index 47af292..0000000 --- a/libbsarch-visualstudio-test.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/libbsarch.h b/libbsarch.h deleted file mode 100644 index e079690..0000000 --- a/libbsarch.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include - -#include - -#include "DDS.h" - -#ifdef BSARCH_DLL_EXPORT -#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllexport) ReturnType __stdcall -#else -#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllimport) ReturnType __stdcall -#endif - -#ifdef __GNUC__ -#define PACKED(datastructure) datastructure __attribute__((__packed__)) -#else -#define PACKED(datastructure) __pragma(pack(push, 1)) datastructure __pragma(pack(pop)) -#endif - -typedef enum bsa_result_code_e { - BSA_RESULT_NONE = 0, - BSA_RESULT_EXCEPTION = -1 -} bsa_result_code_t; - -typedef void* bsa_buffer_t; -typedef void* bsa_archive_t; -typedef void* bsa_entry_list_t; -typedef void* bsa_file_record_t; -typedef void* bsa_folder_record_t; - -typedef struct bsa_dds_info_s { - uint32_t width, height, mipmaps; -} bsa_dds_info_t; - -PACKED ( -struct bsa_dds_header_s { - uint32_t magic; // DDS_MAGIC - struct DirectX::DDS_HEADER header; -}); - -typedef struct bsa_dds_header_s bsa_dds_header_t; - -PACKED ( -struct bsa_result_message_s { - int8_t code; // bsa_result_code_t - wchar_t text[1024]; -}); - -typedef struct bsa_result_message_s bsa_result_message_t; - -PACKED ( -struct bsa_result_buffer_s { - uint32_t size; - bsa_buffer_t data; -}); - -typedef struct bsa_result_buffer_s bsa_result_buffer_t; - -PACKED ( -struct bsa_result_message_buffer_s { - bsa_result_buffer_t buffer; - bsa_result_message_t message; -}); - -typedef struct bsa_result_message_buffer_s bsa_result_message_buffer_t; - -typedef enum bsa_archive_state_e { - stReading, stWriting -} bsa_archive_state_t; - -typedef enum bsa_archive_type_e { - baNone, baTES3, baTES4, baFO3, baSSE, baFO4, baFO4dds -} bsa_archive_type_t; - -typedef void (*bsa_file_dds_info_proc_t)(bsa_archive_t archive, const wchar_t *file_path, bsa_dds_info_t *dds_info, void *context); -typedef bool (*bsa_file_iteration_proc_t)(bsa_archive_t archive, const wchar_t *file_path, bsa_file_record_t file_record, bsa_folder_record_t folder_record, void *context); - -BSARCH_DLL_API(bsa_entry_list_t) bsa_entry_list_create(); -BSARCH_DLL_API(bsa_result_message_t) bsa_entry_list_free(bsa_entry_list_t entry_list); -BSARCH_DLL_API(uint32_t) bsa_entry_list_count(bsa_entry_list_t entry_list); -BSARCH_DLL_API(bsa_result_message_t) bsa_entry_list_add(bsa_entry_list_t entry_list, const wchar_t *entry_string); -BSARCH_DLL_API(uint32_t) bsa_entry_list_get(bsa_entry_list_t entry_list, uint32_t index, uint32_t string_buffer_size, const wchar_t *string_buffer); - -BSARCH_DLL_API(bsa_archive_t) bsa_create(); -BSARCH_DLL_API(bsa_result_message_t) bsa_free(bsa_archive_t archive); -BSARCH_DLL_API(bsa_result_message_t) bsa_load_from_file(bsa_archive_t archive, const wchar_t *file_path); -BSARCH_DLL_API(bsa_result_message_t) bsa_create_archive(bsa_archive_t archive, const wchar_t *file_path, bsa_archive_type_t archive_type, bsa_entry_list_t entry_list); -BSARCH_DLL_API(bsa_result_message_t) bsa_save(bsa_archive_t archive); -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_disk(bsa_archive_t archive, const wchar_t *file_path, const wchar_t *source_path); -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_disk_root(bsa_archive_t archive, const wchar_t *root_dir, const wchar_t *source_path); -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_memory(bsa_archive_t archive, const wchar_t *file_path, uint32_t size, bsa_buffer_t data); -BSARCH_DLL_API(bsa_file_record_t) bsa_find_file_record(bsa_archive_t archive, const wchar_t *file_path); -BSARCH_DLL_API(bsa_result_message_buffer_t) bsa_extract_file_data_by_record(bsa_archive_t archive, bsa_file_record_t file_record); -BSARCH_DLL_API(bsa_result_message_buffer_t) bsa_extract_file_data_by_filename(bsa_archive_t archive, const wchar_t *file_path); -BSARCH_DLL_API(bsa_result_message_t) bsa_file_data_free(bsa_archive_t archive, bsa_result_buffer_t file_data_result); -BSARCH_DLL_API(bsa_result_message_t) bsa_extract_file(bsa_archive_t archive, const wchar_t *file_path, const wchar_t *save_as); -BSARCH_DLL_API(bsa_result_message_t) bsa_iterate_files(bsa_archive_t archive, bsa_file_iteration_proc_t file_iteration_proc, void *context); -BSARCH_DLL_API(bool) bsa_file_exists(bsa_archive_t archive, const wchar_t *file_path); -BSARCH_DLL_API(bsa_result_message_t) bsa_get_resource_list(bsa_archive_t archive, bsa_entry_list_t entry_result_list, const wchar_t *folder); -BSARCH_DLL_API(bsa_result_message_t) bsa_resolve_hash(bsa_archive_t archive, uint64_t hash, bsa_entry_list_t entry_result_list); -BSARCH_DLL_API(bsa_result_message_t) bsa_close(bsa_archive_t archive); - -BSARCH_DLL_API(uint32_t) bsa_filename_get(bsa_archive_t archive, uint32_t string_buffer_size, const wchar_t *string_buffer); -BSARCH_DLL_API(bsa_archive_type_t) bsa_archive_type_get(bsa_archive_t archive); -BSARCH_DLL_API(uint32_t) bsa_version_get(bsa_archive_t archive); -BSARCH_DLL_API(uint32_t) bsa_format_name_get(bsa_archive_t archive, uint32_t string_buffer_size, const wchar_t *string_buffer); -BSARCH_DLL_API(uint32_t) bsa_file_count_get(bsa_archive_t archive); -BSARCH_DLL_API(uint32_t) bsa_archive_flags_get(bsa_archive_t archive); -BSARCH_DLL_API(void) bsa_archive_flags_set(bsa_archive_t archive, uint32_t flags); -BSARCH_DLL_API(uint32_t) bsa_file_flags_get(bsa_archive_t archive); -BSARCH_DLL_API(void) bsa_file_flags_set(bsa_archive_t archive, uint32_t flags); -BSARCH_DLL_API(bool) bsa_compress_get(bsa_archive_t archive); -BSARCH_DLL_API(void) bsa_compress_set(bsa_archive_t archive, bool flags); -BSARCH_DLL_API(bool) bsa_share_data_get(bsa_archive_t archive); -BSARCH_DLL_API(void) bsa_share_data_set(bsa_archive_t archive, bool flags); - -BSARCH_DLL_API(void) bsa_file_dds_info_callback_set(bsa_archive_t archive, bsa_file_dds_info_proc_t file_dds_info_proc, void *context); diff --git a/libbsarch.sln b/libbsarch.sln deleted file mode 100644 index 59cc737..0000000 --- a/libbsarch.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.572 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbsarch", "libbsarch.vcxproj", "{537F42AD-5B15-4671-B99E-2D1818999A98}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {537F42AD-5B15-4671-B99E-2D1818999A98}.Debug|x64.ActiveCfg = Debug|x64 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Debug|x64.Build.0 = Debug|x64 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Debug|x86.ActiveCfg = Debug|Win32 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Debug|x86.Build.0 = Debug|Win32 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Release|x64.ActiveCfg = Release|x64 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Release|x64.Build.0 = Release|x64 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Release|x86.ActiveCfg = Release|Win32 - {537F42AD-5B15-4671-B99E-2D1818999A98}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {274A40A7-F42F-40A4-A8BD-2DA20258DB0A} - EndGlobalSection -EndGlobal diff --git a/libbsarch.vcxproj b/libbsarch.vcxproj deleted file mode 100644 index e9b9ef7..0000000 --- a/libbsarch.vcxproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {537F42AD-5B15-4671-B99E-2D1818999A98} - Win32Proj - 10.0 - - - - DynamicLibrary - true - v142 - - - DynamicLibrary - false - v142 - - - DynamicLibrary - true - v142 - - - DynamicLibrary - false - v142 - - - - - - - - - - - - - - - - - - - - - true - $(DirectXTexPath)\DirectXTex;$(IncludePath) - $(ProjectName) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - true - $(DirectXTexPath)\DirectXTex;$(IncludePath) - $(ProjectName) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - $(DirectXTexPath)\DirectXTex;$(IncludePath) - $(ProjectName) - - - $(DirectXTexPath)\DirectXTex;$(IncludePath) - $(ProjectName) - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBBSARCH_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - false - Windows - libbsarch.def - - - xcopy /y "$(ProjectDir)libbsarch.h" "$(OutDir)" - Copying header file - $(OutDir)libbsarch.h - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBBSARCH_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Windows - true - true - libbsarch.def - - - xcopy /y "$(ProjectDir)libbsarch.h" "$(OutDir)" - Copying header file - $(OutDir)libbsarch.h - - - - - false - libbsarch.def - - - xcopy /y "$(ProjectDir)libbsarch.h" "$(OutDir)" - Copying header file - $(OutDir)libbsarch.h - - - - - libbsarch.def - - - xcopy /y "$(ProjectDir)libbsarch.h" "$(OutDir)" - Copying header file - $(OutDir)libbsarch.h - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libbsarch.vcxproj.filters b/libbsarch.vcxproj.filters deleted file mode 100644 index e57e1f7..0000000 --- a/libbsarch.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Header Files - - - Resource Files - - - - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/src/base_types.hpp b/src/base_types.hpp new file mode 100644 index 0000000..2baf4be --- /dev/null +++ b/src/base_types.hpp @@ -0,0 +1,66 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#pragma once + +#include "libbsarch.h" +#include "utils/convertible_string.hpp" +#include + +namespace libbsarch { +struct memory_blob : public bsa_result_buffer_t +{ + memory_blob(uint32_t buffer_size, bsa_buffer_t buffer_data, bsa_archive_t parent) + : bsa_result_buffer_t{buffer_size, buffer_data} + , parent_(parent) + {} + + memory_blob(bsa_result_buffer_t buffer, bsa_archive_t parent) + : bsa_result_buffer_t(buffer) + , parent_(parent) + {} + + bsa_archive_t parent_; + + memory_blob(memory_blob const &) = default; + ~memory_blob() { bsa_file_data_free(parent_, *this); } +}; + +struct disk_blob +{ + disk_blob(const convertible_string &root_dir, const convertible_string &absolute_path) + : path_in_archive(absolute_path) + , path_on_disk(absolute_path) + { + path_in_archive.remove_substring(root_dir); + } + + disk_blob(const convertible_string &path_in_archive, + const convertible_string &absolute_path, + [[maybe_unused]] bool decoy_parameter) + : path_in_archive(path_in_archive) + , path_on_disk(absolute_path) + {} + + convertible_string path_in_archive; + convertible_string path_on_disk; +}; + +struct bs_packed_file +{ + bs_packed_file(const disk_blob &blob) + : path_in_archive(blob.path_in_archive) + , data(blob.path_on_disk) + {} + + bs_packed_file(convertible_string path_in_archive, memory_blob blob) + : path_in_archive(std::move(path_in_archive)) + , data(blob) + {} + + convertible_string path_in_archive; + std::variant data; +}; + +} // namespace libbsarch diff --git a/src/bs_archive.cpp b/src/bs_archive.cpp new file mode 100644 index 0000000..b50ef5b --- /dev/null +++ b/src/bs_archive.cpp @@ -0,0 +1,185 @@ +#include "bs_archive.h" + +namespace libbsarch { + +bs_archive::bs_archive() + : archive_(bsa_create()) +{} + +bs_archive::bs_archive(const bsa_archive_type_t &type) + : archive_(bsa_create()) + , type_(type) +{} + +bs_archive::~bs_archive() +{ + bsa_close(archive_); + bsa_free(archive_); +} + +/* Properties */ +convertible_string bs_archive::get_filename() +{ + wchar_t name[max_string_buffer_size]; + bsa_filename_get(archive_, max_string_buffer_size, name); + return name; +} + +bsa_archive_type_t bs_archive::get_type() +{ + return bsa_archive_type_get(archive_); +} + +uint32_t bs_archive::get_version() +{ + return bsa_version_get(archive_); +} + +convertible_string bs_archive::get_format_name() +{ + wchar_t format_name[max_string_buffer_size]; + bsa_format_name_get(archive_, max_string_buffer_size, format_name); + return format_name; +} + +uint32_t bs_archive::get_file_count() +{ + return bsa_file_count_get(archive_); +} + +uint32_t bs_archive::get_archive_flags() +{ + return bsa_archive_flags_get(archive_); +} + +void bs_archive::set_archive_flags(uint32_t flags) +{ + bsa_archive_flags_set(archive_, flags); +} + +uint32_t bs_archive::get_file_flags() +{ + return bsa_file_flags_get(archive_); +} + +void bs_archive::set_file_flags(uint32_t flags) +{ + bsa_file_flags_set(archive_, flags); +} + +void bs_archive::set_compressed(bool value) +{ + bsa_compress_set(archive_, value); +} + +void bs_archive::set_share_data(bool value) +{ + bsa_share_data_set(archive_, value); +} + +bool bs_archive::get_compressed() +{ + return bsa_compress_get(archive_); +} + +bool bs_archive::get_share_data() +{ + return bsa_share_data_get(archive_); +} + +void bs_archive::load_from_disk(const convertible_string &archive_path) +{ + debug_log() << "Opening archive: " << archive_path; + const std::wstring str = archive_path; + const auto &result = bsa_load_from_file(archive_, str.c_str()); + libbsarch::checkResult(result); +} + +void bs_archive::create(const convertible_string &archiveName, const bs_archive_entries &entries) +{ + create(archiveName, entries, type_); +} + +void bs_archive::create(const convertible_string &archiveName, + const bs_archive_entries &entries, + const bsa_archive_type_t type) +{ + debug_log() << "Creating archive. Archive name: " << archiveName << '\n' + << "type: " << type_ << '\n' + << "entries: " << entries.getEntries(); + bsa_create_archive(archive_, archiveName, type, entries.getEntries()); +} + +void bs_archive::save() const +{ + debug_log() << "Saving archive: " << archive_; + + const auto &result = bsa_save(archive_); + + libbsarch::checkResult(result); +} + +void bs_archive::add_file_from_disk(const disk_blob &blob) +{ + debug_log() << "Adding file from disk root. Path in archive: " << blob.path_in_archive << '\n' + << "Filepath: " << blob.path_on_disk << '\n' + << "Archive: " << archive_; + + const auto &result = bsa_add_file_from_disk(archive_, blob.path_in_archive, blob.path_on_disk); + + libbsarch::checkResult(result); +} + +void bs_archive::add_file_from_memory(const convertible_string &path_in_archive, + const memory_blob &memory_data) //NOTE UNTESTED +{ + debug_log() << "Adding file from memory. Filename: " << path_in_archive << '\n' + << "Data size: " << memory_data.size; + const auto &result = bsa_add_file_from_memory(archive_, path_in_archive, memory_data.size, memory_data.data); + libbsarch::checkResult(result); +} + +bsa_file_record_t bs_archive::find_file_record(const convertible_string &filename) +{ + debug_log() << "Finding file record of: " << filename; + const auto &result = bsa_find_file_record(archive_, filename); + return result; +} + +memory_blob bs_archive::extract_to_memory(bsa_file_record_t record) +{ + const auto &result = bsa_extract_file_data_by_record(archive_, record); + libbsarch::checkResult(result); + return memory_blob(result.buffer, archive_); +} + +memory_blob bs_archive::extract_to_memory(const convertible_string &filename) +{ + const auto &result = bsa_extract_file_data_by_filename(archive_, filename); + libbsarch::checkResult(result); + return memory_blob(result.buffer, archive_); +} + +void bs_archive::extract_to_disk(const convertible_string &filename, const convertible_string &save_as) const +{ + debug_log() << "Extracting: " << filename << " saved as " << save_as; + const auto &result = bsa_extract_file(archive_, filename, save_as); + + libbsarch::checkResult(result); +} + +std::vector bs_archive::list_files() const +{ + bsa_entry_list_t list = bsa_entry_list_create(); + const auto &result = bsa_get_resource_list(archive_, list, L""); + + libbsarch::checkResult(result); + + return bs_archive_entries(list).list(); +} + +bsa_archive_t bs_archive::get_archive() const +{ + return archive_; +} +} // namespace libbsarch diff --git a/src/bs_archive.h b/src/bs_archive.h new file mode 100644 index 0000000..af08366 --- /dev/null +++ b/src/bs_archive.h @@ -0,0 +1,100 @@ +#pragma once + +#include "bs_archive_entries.h" +#include "libbsarch.hpp" + +namespace libbsarch { +class bs_archive +{ +public: + bs_archive(); + bs_archive(const bsa_archive_type_t &type); + virtual ~bs_archive(); + + /* Properties */ + convertible_string get_filename(); + bsa_archive_type_t get_type(); + uint32_t get_version(); + convertible_string get_format_name(); + uint32_t get_file_count(); + + uint32_t get_archive_flags(); + void set_archive_flags(uint32_t flags); + + uint32_t get_file_flags(); + void set_file_flags(uint32_t flags); + + void set_compressed(bool value); + bool get_compressed(); + + void set_share_data(bool value); + bool get_share_data(); + + /* Input-Output */ + virtual void load_from_disk(const convertible_string &archive_path); + virtual void create(const convertible_string &archiveName, const bs_archive_entries &entries); + virtual void create(const convertible_string &archiveName, + const bs_archive_entries &entries, + const bsa_archive_type_t type); + void save() const; + + /* Add to archive */ + virtual void add_file_from_disk(const disk_blob &blob); + virtual void add_file_from_memory(const convertible_string &path_in_archive, const memory_blob &memory_data); + + /* Extract */ + memory_blob extract_to_memory(bsa_file_record_t record); + memory_blob extract_to_memory(const convertible_string &filename); + void extract_to_disk(const convertible_string &filename, const convertible_string &save_as) const; + + /* Selectors */ + bsa_file_record_t find_file_record(const convertible_string &filename); + std::vector list_files() const; + + /* Other */ + + /*! \brief Sets the DDS callback. It is required to use Fallout 4 DDS archives. You do not have + * to manage the lifetime of the provided context + * \example + void dds_callback([[maybe_unused]] bsa_archive_t archive, + const wchar_t *file_path, + bsa_dds_info_t *dds_info, + void *context) + { + const auto &path = *static_cast(context) + '/' + convertible_string(file_path); + + auto image = std::make_unique(); + DirectX::TexMetadata info; + + const auto hr = LoadFromDDSFile(PREPARE_PATH_LIBBSARCH(path), DirectX::DDS_FLAGS_BAD_DXTN_TAILS, &info, *image); + if (FAILED(hr)) + { + //Do not throw here. Exceptions will be ignored + return; + } + + dds_info->width = info.width; + dds_info->height = info.height; + dds_info->mipmaps = info.mipLevels; + } + */ + template + void set_dds_callback(bsa_file_dds_info_proc_t dds_function, const context_type &context) + { + debug_log() << "Setting DDS callback for archive: " << archive_ << "\nCallback adress: " << &dds_function; + + auto heap_context = new context_type(context); + callback_contexts_.emplace_back(heap_context); + bsa_file_dds_info_callback_set(archive_, dds_function, callback_contexts_.back()); + } + + bsa_archive_t get_archive() const; + +protected: + bsa_archive_t archive_; + bsa_archive_type_t type_; + +private: + std::vector callback_contexts_; +}; +} // namespace libbsarch diff --git a/src/bs_archive_auto.cpp b/src/bs_archive_auto.cpp new file mode 100644 index 0000000..4a996f0 --- /dev/null +++ b/src/bs_archive_auto.cpp @@ -0,0 +1,89 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "bs_archive_auto.hpp" +#include +namespace libbsarch { +bs_archive_auto::bs_archive_auto(const bsa_archive_type_t &type) + : bs_archive(type) +{} + +void bs_archive_auto::add_file_from_disk(const disk_blob &blob) +{ + files_.emplace_back(blob); +} + +void bs_archive_auto::add_file_from_disk(const std::vector &blobs) +{ + files_.reserve(blobs.size()); + files_.insert(files_.end(), blobs.cbegin(), blobs.cend()); +} + +void bs_archive_auto::add_file_from_memory(const convertible_string &path_in_archive, const memory_blob &memory_data) +{ + files_.emplace_back(bs_packed_file(path_in_archive, memory_data)); +} + +void bs_archive_auto::add_file(const bs_packed_file &file) +{ + files_.emplace_back(file); +} + +void bs_archive_auto::extract_all(const convertible_string &directory, bool overwrite_current_files) +{ + namespace fs = std::filesystem; + for (const auto &file : list_files()) + { + convertible_string path_string = std::string(directory) + "/" + std::string(file); + fs::path current_file(path_string); + fs::path current_path = fs::path(current_file).remove_filename(); + + fs::create_directories(current_path); + if (fs::exists(current_file) && overwrite_current_files) + { + fs::remove(current_file); + extract_to_disk(file, current_file.string()); + } + else if (!fs::exists(current_file)) + extract_to_disk(file, current_file.string()); + } +} + +void bs_archive_auto::load_from_disk(const convertible_string &archive_path) +{ + bs_archive::load_from_disk(archive_path); + for (const auto &file : list_files()) + entries_.add(file); +} + +void bs_archive_auto::save_to_disk(const convertible_string &archive_path) +{ + for (const auto &file : files_) + entries_.add(file.path_in_archive); + + bs_archive::create(archive_path, entries_); + + for (const auto &file : files_) + { + switch (file.data.index()) + { + case 0: + { + const auto &blob = std::get(file.data); + bs_archive::add_file_from_memory(file.path_in_archive, blob); + break; + } + case 1: + { + const auto &file_path = std::get(file.data); + const auto &blob = disk_blob(file.path_in_archive, file_path, bool()); + bs_archive::add_file_from_disk(blob); + } + } + } + bs_archive::save(); +} + +} // namespace libbsarch diff --git a/src/bs_archive_auto.hpp b/src/bs_archive_auto.hpp new file mode 100644 index 0000000..5825f68 --- /dev/null +++ b/src/bs_archive_auto.hpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#pragma once + +#include "bs_archive.h" + +namespace libbsarch { +/*! + * \brief The bs_archive_auto class is a convenience class. It manages both bs_archive and bs_archive_entries. + * It is recommended when packing from disk/extracting to disk + * Otherwise, if using memory, the use of these two separate classes is recommended + */ +class bs_archive_auto : public bs_archive +{ +protected: + bs_archive_entries entries_; + +public: + bs_archive_auto() = default; + bs_archive_auto(const bsa_archive_type_t &type); + + void add_file_from_disk(const disk_blob &blob) override; + void add_file_from_disk(const std::vector &blobs); + void add_file_from_memory(const convertible_string &path_in_archive, const memory_blob &memory_data) override; + void add_file(const bs_packed_file &file); + + void extract_all(const convertible_string &directory, bool overwrite_current_files); + + void load_from_disk(const convertible_string &archive_path) override; + void save_to_disk(const convertible_string &archive_path); + +private: + using bs_archive::create; //Use save_to_disk instead + using bs_archive::save; //Use save_to_disk instead + std::vector files_; +}; +} // namespace libbsarch diff --git a/src/bs_archive_entries.cpp b/src/bs_archive_entries.cpp new file mode 100644 index 0000000..1fb1114 --- /dev/null +++ b/src/bs_archive_entries.cpp @@ -0,0 +1,54 @@ +#include "bs_archive_entries.h" + +namespace libbsarch { +bs_archive_entries::bs_archive_entries() + : _entries(bsa_entry_list_create()) +{ +} + +bs_archive_entries::bs_archive_entries(const std::vector &entries) + : _entries(bsa_entry_list_create()) +{ + for (const auto &entry : entries) + add(entry); +} + +bs_archive_entries::bs_archive_entries(const bsa_entry_list_t &entries) + : _entries(entries) +{ +} + +bs_archive_entries::~bs_archive_entries() +{ + bsa_entry_list_free(_entries); +} + +void bs_archive_entries::add(const convertible_string &filepath) +{ + debug_log() << "Adding to entries: " << filepath; + const auto &result = bsa_entry_list_add(_entries, filepath); + libbsarch::checkResult(result); +} + +uint32_t bs_archive_entries::count() +{ + return bsa_entry_list_count(_entries); +} + +std::vector bs_archive_entries::list() +{ + std::vector list; + for (uint32_t i = 0; i < count(); ++i) + { + wchar_t buffer[max_string_buffer_size]; + bsa_entry_list_get(_entries, i, max_string_buffer_size, buffer); + list.push_back(buffer); + } + return list; +} + +bsa_entry_list_t bs_archive_entries::getEntries() const +{ + return _entries; +} +} // namespace libbsarch diff --git a/src/bs_archive_entries.h b/src/bs_archive_entries.h new file mode 100644 index 0000000..7df2f40 --- /dev/null +++ b/src/bs_archive_entries.h @@ -0,0 +1,24 @@ +#pragma once + +#include "libbsarch.hpp" +#include + +namespace libbsarch { +class bs_archive_entries +{ +public: + bs_archive_entries(); + explicit bs_archive_entries(const std::vector &entries); + explicit bs_archive_entries(const bsa_entry_list_t &entries); + ~bs_archive_entries(); + + void add(const convertible_string &filepath); + uint32_t count(); + std::vector list(); + + bsa_entry_list_t getEntries() const; + +protected: + bsa_entry_list_t _entries; +}; +} // namespace libbsarch diff --git a/src/dds.h b/src/dds.h new file mode 100644 index 0000000..a37183d --- /dev/null +++ b/src/dds.h @@ -0,0 +1,240 @@ +//-------------------------------------------------------------------------------------- +// dds.h +// +// This header defines constants and structures that are useful when parsing +// DDS files. DDS files were originally designed to use several structures +// and constants that are native to DirectDraw and are defined in ddraw.h, +// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar +// (compatible) constants and structures so that one can use DDS files +// without needing to include ddraw.h. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +// http://go.microsoft.com/fwlink/?LinkID=615561 +//-------------------------------------------------------------------------------------- + +#pragma once + +#include +#include + +namespace DirectX { +#pragma pack(push, 1) + +const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +struct DDS_PIXELFORMAT +{ + uint32_t size; + uint32_t flags; + uint32_t fourCC; + uint32_t RGBBitCount; + uint32_t RBitMask; + uint32_t GBitMask; + uint32_t BBitMask; + uint32_t ABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHAPIXELS 0x00000001 // DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 +#define DDS_PAL8A 0x00000021 // DDPF_PALETTEINDEXED8 | DDPF_ALPHAPIXELS +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + (static_cast(static_cast(ch0)) | (static_cast(static_cast(ch1)) << 8) \ + | (static_cast(static_cast(ch2)) << 16) \ + | (static_cast(static_cast(ch3)) << 24)) +#endif /* defined(MAKEFOURCC) */ + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DXT1 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DXT2 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DXT3 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DXT4 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DXT5 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_BC4_UNORM = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_BC4_SNORM = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_BC5_UNORM = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_BC5_SNORM = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_R8G8_B8G8 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_G8R8_G8B8 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_YUY2 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'), 0, 0, 0, 0, 0}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A8R8G8B8 = {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_X8R8G8B8 = {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A8B8G8R8 = {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_X8B8G8R8 = {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_G16R16 = {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_R5G6B5 = {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A1R5G5B5 = {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A4R4G4B4 = {sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_R8G8B8 = {sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}; + +extern __declspec(selectany) const + DDS_PIXELFORMAT DDSPF_L8 = {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00}; + +extern __declspec(selectany) const + DDS_PIXELFORMAT DDSPF_L16 = {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A8L8 = {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_A8L8_ALT = {sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 8, 0x00ff, 0x0000, 0x0000, 0xff00}; + +extern __declspec(selectany) const + DDS_PIXELFORMAT DDSPF_A8 = {sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_V8U8 = {sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_Q8W8V8U8 = {sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}; + +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_V16U16 = {sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000}; + +// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +extern __declspec(selectany) const DDS_PIXELFORMAT + DDSPF_DX10 = {sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0}; + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES \ + (DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX | DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY \ + | DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION +enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +}; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +enum DDS_ALPHA_MODE +{ + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, +}; + +struct DDS_HEADER +{ + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t pitchOrLinearSize; + uint32_t depth; // only if DDS_HEADER_FLAGS_VOLUME is set in flags + uint32_t mipMapCount; + uint32_t reserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t caps; + uint32_t caps2; + uint32_t caps3; + uint32_t caps4; + uint32_t reserved2; +}; + +struct DDS_HEADER_DXT10 +{ + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see D3D11_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 +}; + +#pragma pack(pop) + +static_assert(sizeof(DDS_HEADER) == 124, "DDS Header size mismatch"); +static_assert(sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + +} // namespace DirectX diff --git a/libbsarch.cpp b/src/libbsarch.cpp similarity index 94% rename from libbsarch.cpp rename to src/libbsarch.cpp index 9cab580..ed8f984 100644 --- a/libbsarch.cpp +++ b/src/libbsarch.cpp @@ -1,9 +1,8 @@ -#ifndef BSARCH_DLL_EXPORT -#define BSARCH_DLL_EXPORT 1 -#endif - +#ifdef BSARCH_DLL_EXPORT #include "libbsarch.h" +namespace libbsarch { + BSARCH_DLL_API(bsa_entry_list_t) bsa_entry_list_create() { return NULL; } @@ -20,7 +19,7 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_entry_list_add(bsa_entry_list_t entry_l return { 0 }; } -BSARCH_DLL_API(uint32_t) bsa_entry_list_get(bsa_entry_list_t entry_list, uint32_t index, uint32_t string_buffer_size, const wchar_t *string_buffer) { +BSARCH_DLL_API(uint32_t) bsa_entry_list_get(bsa_entry_list_t entry_list, uint32_t index, uint32_t string_buffer_size, wchar_t *string_buffer) { return 0; } @@ -96,7 +95,7 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_close(bsa_archive_t archive) { return { 0 }; } -BSARCH_DLL_API(uint32_t) bsa_filename_get(bsa_archive_t archive, uint32_t string_buffer_size, const wchar_t *string_buffer) { +BSARCH_DLL_API(uint32_t) bsa_filename_get(bsa_archive_t archive, uint32_t string_buffer_size, wchar_t *string_buffer) { return 0; } @@ -108,7 +107,7 @@ BSARCH_DLL_API(uint32_t) bsa_version_get(bsa_archive_t archive) { return 0; } -BSARCH_DLL_API(uint32_t) bsa_format_name_get(bsa_archive_t archive, uint32_t string_buffer_size, const wchar_t *string_buffer) { +BSARCH_DLL_API(uint32_t) bsa_format_name_get(bsa_archive_t archive, uint32_t string_buffer_size, wchar_t *string_buffer) { return 0; } @@ -151,3 +150,5 @@ BSARCH_DLL_API(void) bsa_share_data_set(bsa_archive_t archive, bool flags) { BSARCH_DLL_API(void) bsa_file_dds_info_callback_set(bsa_archive_t archive, bsa_file_dds_info_proc_t file_dds_info_proc, void *context) { return; } +} +#endif diff --git a/libbsarch.def b/src/libbsarch.def similarity index 100% rename from libbsarch.def rename to src/libbsarch.def diff --git a/src/libbsarch.h b/src/libbsarch.h new file mode 100644 index 0000000..03a9edc --- /dev/null +++ b/src/libbsarch.h @@ -0,0 +1,151 @@ +#pragma once + +#include "dds.h" +#include +#include + +#ifdef BSARCH_DLL_EXPORT +#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllexport) ReturnType __stdcall +#else +#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllimport) ReturnType __stdcall +#endif + +#ifdef __GNUC__ +#define PACKED(datastructure) datastructure __attribute__((__packed__)) +#else +#define PACKED(datastructure) __pragma(pack(push, 1)) datastructure __pragma(pack(pop)) +#endif + +namespace libbsarch { + +typedef enum bsa_result_code_e +{ + BSA_RESULT_NONE = 0, + BSA_RESULT_EXCEPTION = -1 +} bsa_result_code_t; + +typedef void *bsa_buffer_t; +typedef void *bsa_archive_t; +typedef void *bsa_entry_list_t; +typedef void *bsa_file_record_t; +typedef void *bsa_folder_record_t; + +typedef struct bsa_dds_info_s +{ + uint32_t width, height, mipmaps; +} bsa_dds_info_t; + +PACKED(struct bsa_dds_header_s { + uint32_t magic; // DDS_MAGIC + struct DirectX::DDS_HEADER header; +}); + +typedef struct bsa_dds_header_s bsa_dds_header_t; + +PACKED(struct bsa_result_message_s { + int8_t code; // bsa_result_code_t + wchar_t text[1024]; +}); + +typedef struct bsa_result_message_s bsa_result_message_t; + +PACKED(struct bsa_result_buffer_s { + uint32_t size; + bsa_buffer_t data; +}); + +typedef struct bsa_result_buffer_s bsa_result_buffer_t; + +PACKED(struct bsa_result_message_buffer_s { + bsa_result_buffer_t buffer; + bsa_result_message_t message; +}); + +typedef struct bsa_result_message_buffer_s bsa_result_message_buffer_t; + +typedef enum bsa_archive_state_e +{ + stReading, + stWriting +} bsa_archive_state_t; + +typedef enum bsa_archive_type_e +{ + baNone, + baTES3, + baTES4, + baFO3, + baSSE, + baFO4, + baFO4dds +} bsa_archive_type_t; + +typedef void (*bsa_file_dds_info_proc_t)(bsa_archive_t archive, + const wchar_t *file_path, + bsa_dds_info_t *dds_info, + void *context); +typedef bool (*bsa_file_iteration_proc_t)(bsa_archive_t archive, + const wchar_t *file_path, + bsa_file_record_t file_record, + bsa_folder_record_t folder_record, + void *context); + +BSARCH_DLL_API(bsa_entry_list_t) bsa_entry_list_create(); +BSARCH_DLL_API(bsa_result_message_t) bsa_entry_list_free(bsa_entry_list_t entry_list); +BSARCH_DLL_API(uint32_t) bsa_entry_list_count(bsa_entry_list_t entry_list); +BSARCH_DLL_API(bsa_result_message_t) bsa_entry_list_add(bsa_entry_list_t entry_list, const wchar_t *entry_string); +BSARCH_DLL_API(uint32_t) +bsa_entry_list_get(bsa_entry_list_t entry_list, uint32_t index, uint32_t string_buffer_size, wchar_t *string_buffer); + +BSARCH_DLL_API(bsa_archive_t) bsa_create(); +BSARCH_DLL_API(bsa_result_message_t) bsa_free(bsa_archive_t archive); +BSARCH_DLL_API(bsa_result_message_t) bsa_load_from_file(bsa_archive_t archive, const wchar_t *file_path); +BSARCH_DLL_API(bsa_result_message_t) +bsa_create_archive(bsa_archive_t archive, + const wchar_t *file_path, + bsa_archive_type_t _archivetype, + bsa_entry_list_t entry_list); +BSARCH_DLL_API(bsa_result_message_t) bsa_save(bsa_archive_t archive); +BSARCH_DLL_API(bsa_result_message_t) +bsa_add_file_from_disk(bsa_archive_t archive, const wchar_t *file_path, const wchar_t *source_path); +BSARCH_DLL_API(bsa_result_message_t) +bsa_add_file_from_disk_root(bsa_archive_t archive, const wchar_t *root_dir, const wchar_t *source_path); +BSARCH_DLL_API(bsa_result_message_t) +bsa_add_file_from_memory(bsa_archive_t archive, const wchar_t *file_path, uint32_t size, bsa_buffer_t data); +BSARCH_DLL_API(bsa_file_record_t) bsa_find_file_record(bsa_archive_t archive, const wchar_t *file_path); +BSARCH_DLL_API(bsa_result_message_buffer_t) +bsa_extract_file_data_by_record(bsa_archive_t archive, bsa_file_record_t file_record); +BSARCH_DLL_API(bsa_result_message_buffer_t) +bsa_extract_file_data_by_filename(bsa_archive_t archive, const wchar_t *file_path); +BSARCH_DLL_API(bsa_result_message_t) bsa_file_data_free(bsa_archive_t archive, bsa_result_buffer_t file_data_result); +BSARCH_DLL_API(bsa_result_message_t) +bsa_extract_file(bsa_archive_t archive, const wchar_t *file_path, const wchar_t *save_as); +BSARCH_DLL_API(bsa_result_message_t) +bsa_iterate_files(bsa_archive_t archive, bsa_file_iteration_proc_t file_iteration_proc, void *context); +BSARCH_DLL_API(bool) bsa_file_exists(bsa_archive_t archive, const wchar_t *file_path); +BSARCH_DLL_API(bsa_result_message_t) +bsa_get_resource_list(bsa_archive_t archive, bsa_entry_list_t entry_result_list, const wchar_t *folder); +BSARCH_DLL_API(bsa_result_message_t) +bsa_resolve_hash(bsa_archive_t archive, uint64_t hash, bsa_entry_list_t entry_result_list); +BSARCH_DLL_API(bsa_result_message_t) bsa_close(bsa_archive_t archive); + +BSARCH_DLL_API(uint32_t) +bsa_filename_get(bsa_archive_t archive, uint32_t string_buffer_size, wchar_t *string_buffer); +BSARCH_DLL_API(bsa_archive_type_t) bsa_archive_type_get(bsa_archive_t archive); +BSARCH_DLL_API(uint32_t) bsa_version_get(bsa_archive_t archive); +BSARCH_DLL_API(uint32_t) +bsa_format_name_get(bsa_archive_t archive, uint32_t string_buffer_size, wchar_t *string_buffer); +BSARCH_DLL_API(uint32_t) bsa_file_count_get(bsa_archive_t archive); +BSARCH_DLL_API(uint32_t) bsa_archive_flags_get(bsa_archive_t archive); +BSARCH_DLL_API(void) bsa_archive_flags_set(bsa_archive_t archive, uint32_t flags); +BSARCH_DLL_API(uint32_t) bsa_file_flags_get(bsa_archive_t archive); +BSARCH_DLL_API(void) bsa_file_flags_set(bsa_archive_t archive, uint32_t flags); +BSARCH_DLL_API(bool) bsa_compress_get(bsa_archive_t archive); +BSARCH_DLL_API(void) bsa_compress_set(bsa_archive_t archive, bool flags); +BSARCH_DLL_API(bool) bsa_share_data_get(bsa_archive_t archive); +BSARCH_DLL_API(void) bsa_share_data_set(bsa_archive_t archive, bool flags); + +BSARCH_DLL_API(void) +bsa_file_dds_info_callback_set(bsa_archive_t archive, bsa_file_dds_info_proc_t file_dds_info_proc, void *context); + +} diff --git a/src/libbsarch.hpp b/src/libbsarch.hpp new file mode 100644 index 0000000..61ae1db --- /dev/null +++ b/src/libbsarch.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "base_types.hpp" +#include "utils/convertible_ostream.hpp" +#include "utils/convertible_string.hpp" + +namespace libbsarch { +constexpr bool enable_debug_log = true; +[[maybe_unused]] constexpr int max_string_buffer_size = 1024; + +inline convertible_ostream &debug_log() +{ + static convertible_ostream ostr; + if constexpr (enable_debug_log) + return ostr << "[libbsarch] " << __FUNCTION__ << ' '; +} + +inline void checkResult(const bsa_result_message_s &result) +{ + if (result.code == BSA_RESULT_EXCEPTION) + { + const std::string &error = to_string(result.text); + debug_log() << error; + throw std::runtime_error(error); + } +} + +inline void checkResult(const bsa_result_message_buffer_s &result) +{ + checkResult(result.message); +} +} // namespace libbsarch diff --git a/src/utils/convertible_ostream.cpp b/src/utils/convertible_ostream.cpp new file mode 100644 index 0000000..38fa6a4 --- /dev/null +++ b/src/utils/convertible_ostream.cpp @@ -0,0 +1,58 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "convertible_ostream.hpp" + +namespace libbsarch { +convertible_ostream &convertible_ostream::operator<<(const std::string &rh) +{ + std::cout << rh; + return *this; +} +convertible_ostream &convertible_ostream::operator<<(const char *rh) +{ + std::cout << rh; + return *this; +} +convertible_ostream &convertible_ostream::operator<<(const char rh) +{ + std::cout << rh; + return *this; +} +convertible_ostream &convertible_ostream::operator<<(const std::wstring &rh) +{ + std::wcout << rh; + return *this; +} +convertible_ostream &convertible_ostream::operator<<(const void *rh) +{ + std::cout << rh; + return *this; +} +convertible_ostream &convertible_ostream::operator<<(const convertible_string &rh) +{ + return *this << std::string(rh); +} + +convertible_ostream::operator std::ostream &() +{ + return std::cout; +} +convertible_ostream::operator std::wostream &() +{ + return std::wcout; +} + +#ifdef QT +convertible_ostream::operator QDebug() +{ + return qDebug(); +} +convertible_ostream &convertible_ostream::operator<<(const QString &rh) +{ + qDebug() << rh; + return *this; +} +#endif +} // namespace libbsarch diff --git a/src/utils/convertible_ostream.hpp b/src/utils/convertible_ostream.hpp new file mode 100644 index 0000000..919ca7a --- /dev/null +++ b/src/utils/convertible_ostream.hpp @@ -0,0 +1,37 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#pragma once + +#include "convertible_string.hpp" +#include + +namespace libbsarch { +class convertible_ostream +{ +public: + convertible_ostream &operator<<(const std::string &rh); + convertible_ostream &operator<<(const char *rh); + convertible_ostream &operator<<(const char rh); + convertible_ostream &operator<<(const std::wstring &rh); + convertible_ostream &operator<<(const void *rh); + convertible_ostream &operator<<(const convertible_string &rh); + + template::value, number>::type> + convertible_ostream &operator<<(const number &num) + { + std::cout << num; + return *this; + } + + operator std::ostream &(); + operator std::wostream &(); + +#ifdef QT + operator QDebug(); + convertible_ostream &operator<<(const QString &rh); +#endif +}; +} // namespace libbsarch diff --git a/src/utils/convertible_string.cpp b/src/utils/convertible_string.cpp new file mode 100644 index 0000000..d9947d9 --- /dev/null +++ b/src/utils/convertible_string.cpp @@ -0,0 +1,128 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "convertible_string.hpp" +#include + +namespace libbsarch { +/* conversion ctors */ +convertible_string::convertible_string(std::string value, bool to_native_path) + : str_(std::move(value)) + , auto_convert_to_native_path(to_native_path) +{ + if (auto_convert_to_native_path) + this->to_native_path(); +} + +convertible_string::convertible_string(const char *const val_array, bool to_native_path) + : str_(std::string(val_array)) + , auto_convert_to_native_path(to_native_path) + +{ + if (auto_convert_to_native_path) + this->to_native_path(); +} +convertible_string::convertible_string(const std::wstring &wvalue, bool to_native_path) + : str_(to_string(wvalue)) + , auto_convert_to_native_path(to_native_path) + +{ + if (auto_convert_to_native_path) + this->to_native_path(); +} +convertible_string::convertible_string(wchar_t const *wval_array, bool to_native_path) + : str_(to_string(std::wstring(wval_array))) + , auto_convert_to_native_path(to_native_path) +{ + if (auto_convert_to_native_path) + this->to_native_path(); +} + +#ifdef QT +convertible_string::convertible_string(const QString &qsvalue, bool to_native_path) + : str_(to_string(qsvalue)) + , auto_convert_to_native_path(to_native_path) +{ + if (auto_convert_to_native_path) + this->to_native_path(); +} +#endif + +/* assignment operators */ +convertible_string &convertible_string::operator=(const std::string &value) +{ + str_ = value; + if (auto_convert_to_native_path) + this->to_native_path(); + return *this; +} +convertible_string &convertible_string::operator=(const std::wstring &wvalue) +{ + str_ = to_string(wvalue); + if (auto_convert_to_native_path) + this->to_native_path(); + return *this; +} + +convertible_string &convertible_string::operator=(const wchar_t *wvalue) +{ + str_ = to_string(std::wstring(wvalue)); + if (auto_convert_to_native_path) + this->to_native_path(); + return *this; +} + +#ifdef QT +convertible_string &convertible_string::operator=(const QString &qsvalue) +{ + str_ = to_string(qsvalue); + if (auto_convert_to_native_path) + this->to_native_path(); + return *this; +} +#endif + +/* implicit conversion operators */ +convertible_string::operator std::string() const +{ + return str_; +} +convertible_string::operator std::wstring() const +{ + return to_wstring(str_); +} +convertible_string::operator const wchar_t *() const +{ + const std::wstring wstr = to_wstring(str_); + wchar_t *wchar_array = new wchar_t[wstr.length() + 1]; + wcscpy_s(wchar_array, wstr.length() + 1, wstr.c_str()); + return wchar_array; +} +#ifdef QT +convertible_string::operator QString() const +{ + return to_qstring(str_); +} +#endif + +/* Util */ +bool convertible_string::remove_substring(const convertible_string &sub_str) +{ + size_t pos = str_.find(sub_str); + if (pos != std::string::npos) + { + str_.erase(pos, std::string(sub_str).length()); + return true; + } + return false; +} + +convertible_string &convertible_string::to_native_path() +{ + std::filesystem::path path(str_); + str_ = path.make_preferred().string(); + return *this; +} +} // namespace libbsarch diff --git a/src/utils/convertible_string.hpp b/src/utils/convertible_string.hpp new file mode 100644 index 0000000..468f77f --- /dev/null +++ b/src/utils/convertible_string.hpp @@ -0,0 +1,54 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#pragma once + +//See https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string + +#include "string_convert.hpp" +#ifdef QT +#include +#endif + +namespace libbsarch { +class convertible_string +{ +public: + // default ctor + convertible_string() = default; + + /* conversion ctors */ + convertible_string(std::string value, bool to_native_path = true); + convertible_string(const char *const val_array, bool to_native_path = true); + convertible_string(const std::wstring &wvalue, bool to_native_path = true); + convertible_string(const wchar_t *const wval_array, bool to_native_path = true); +#ifdef QT + convertible_string(const QString &qsvalue, bool to_native_path = true); +#endif + + /* assignment operators */ + convertible_string &operator=(const std::string &value); + convertible_string &operator=(const std::wstring &wvalue); + convertible_string &operator=(const wchar_t *wvalue); +#ifdef QT + convertible_string &operator=(const QString &qsvalue); +#endif + + /* implicit conversion operators */ + operator std::string() const; + operator std::wstring() const; + operator const wchar_t *() const; +#ifdef QT + operator QString() const; +#endif + + /* Util */ + bool remove_substring(const convertible_string &sub_str); + convertible_string &to_native_path(); + +private: + std::string str_; + bool auto_convert_to_native_path = true; +}; +} // namespace libbsarch diff --git a/src/utils/string_convert.cpp b/src/utils/string_convert.cpp new file mode 100644 index 0000000..9ba129d --- /dev/null +++ b/src/utils/string_convert.cpp @@ -0,0 +1,49 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include "string_convert.hpp" + +namespace libbsarch { +#ifdef QT +std::wstring to_wstring(const QString &str) +{ +#ifdef _MSC_VER + return std::wstring(reinterpret_cast(str.utf16())); +#else + return str.toStdWString(); +#endif +} + +std::string to_string(const QString &str) +{ + return str.toStdString(); +} + +QString to_qstring(const std::string &str) +{ + return QString::fromStdString(str); +} + +QString to_qstring(const std::wstring &str) +{ +#ifdef _MSC_VER + return QString::fromUtf16(reinterpret_cast(str.c_str())); +#else + return QString::fromStdWString(str); +#endif +} +#endif + +static std::wstring_convert> s_converter; +std::string to_string(const std::wstring &str) +{ + return s_converter.to_bytes(str); +} + +std::wstring to_wstring(const std::string &str) +{ + auto ws = s_converter.from_bytes(str); + return ws; +} +} // namespace libbsarch diff --git a/src/utils/string_convert.hpp b/src/utils/string_convert.hpp new file mode 100644 index 0000000..0b1d685 --- /dev/null +++ b/src/utils/string_convert.hpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2019 G'k + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#pragma once + +#ifdef QT +#include +#endif +#include +#include +#include + +namespace libbsarch { +#ifdef QT +std::wstring to_wstring(const QString &str); +std::string to_string(const QString &str); +QString to_qstring(const std::string &str); +QString to_qstring(const std::wstring &str); +#endif + +std::string to_string(const std::wstring &str); +std::wstring to_wstring(const std::string &str); +} // namespace libbsarch