From c68e39d2a10fbc051e79bc84c2a5ffdc3019be70 Mon Sep 17 00:00:00 2001 From: Deorder <31899960+deorder@users.noreply.github.com> Date: Wed, 8 May 2019 23:48:46 +0200 Subject: [PATCH] Added way to add files from any source path (without using a shared/common root) bsa_add_file_from_disk is now bsa_add_file_from_disk_root Fixed issues with using libbsarch with GCC --- cpp.hint | 7 ++ libbsarch-visualstudio-test.cpp | 6 +- libbsarch.cpp | 20 ++-- libbsarch.def | 1 + libbsarch.dpr | 46 +++++---- libbsarch.dproj | 3 +- libbsarch.h | 49 +++++----- libbsarch.vcxproj | 1 + libbsarch.vcxproj.filters | 1 + wbBSArchive.pas | 163 +++++++++++++++++--------------- 10 files changed, 172 insertions(+), 125 deletions(-) create mode 100644 cpp.hint diff --git a/cpp.hint b/cpp.hint new file mode 100644 index 0000000..460536c --- /dev/null +++ b/cpp.hint @@ -0,0 +1,7 @@ +// Hint files help the Visual Studio IDE interpret Visual C++ identifiers +// such as names of functions and macros. +// For more information see https://go.microsoft.com/fwlink/?linkid=865984 +#define PACKED(datastructure) datastructure __attribute__((__packed__)) +#define PACKED(datastructure) __pragma(pack(push, 1)) datastructure __pragma(pack(pop)) +#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllexport) ReturnType __stdcall +#define BSARCH_DLL_API(ReturnType) extern "C" __declspec(dllimport) ReturnType __stdcall diff --git a/libbsarch-visualstudio-test.cpp b/libbsarch-visualstudio-test.cpp index b0c5b46..ef4e656 100644 --- a/libbsarch-visualstudio-test.cpp +++ b/libbsarch-visualstudio-test.cpp @@ -65,9 +65,13 @@ int main() { { bsa_entry_list_t entries = bsa_entry_list_create(); bsa_entry_list_add(entries, L"textures\\grass\\test.dds"); + bsa_entry_list_add(entries, L"textures\\grass\\test2.dds"); bsa_create_archive(archive, L"test_write.bsa", baSSE, entries); - bsa_add_file_from_disk(archive, L"files", L"files\\textures\\grass\\test.dds"); + bsa_add_file_from_disk_root(archive, L"", L"textures\\grass\\test.dds"); + result = bsa_add_file_from_disk(archive, L"textures\\grass\\test2.dds", L"textures\\grass\\test.dds"); + if (result.code < 0) + printf("%ls\n", result.text); bsa_save(archive); bsa_close(archive); diff --git a/libbsarch.cpp b/libbsarch.cpp index c49da6d..727f26b 100644 --- a/libbsarch.cpp +++ b/libbsarch.cpp @@ -32,11 +32,11 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_free(bsa_archive_t archive) { return { 0 }; } -BSARCH_DLL_API(bsa_result_message_t) bsa_load_from_file(bsa_archive_t archive, const wchar_t *filename) { +BSARCH_DLL_API(bsa_result_message_t) bsa_load_from_file(bsa_archive_t archive, const wchar_t *file_path) { return { 0 }; } -BSARCH_DLL_API(bsa_result_message_t) bsa_create_archive(bsa_archive_t archive, const wchar_t *filename, bsa_archive_type_t archive_type, bsa_entry_list_t entry_list) { +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) { return { 0 }; } @@ -44,15 +44,19 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_save(bsa_archive_t archive) { return { 0 }; } -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_disk(bsa_archive_t archive, const wchar_t *root_dir, const wchar_t *filename) { +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) { return { 0 }; } -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_memory(bsa_archive_t archive, const wchar_t *filename, uint32_t size, bsa_buffer_t data) { +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) { return { 0 }; } -BSARCH_DLL_API(bsa_file_record_t) bsa_find_file_record(bsa_archive_t archive, const wchar_t *filename) { +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) { + return { 0 }; +} + +BSARCH_DLL_API(bsa_file_record_t) bsa_find_file_record(bsa_archive_t archive, const wchar_t *file_path) { return NULL; } @@ -60,7 +64,7 @@ BSARCH_DLL_API(bsa_result_message_buffer_t) bsa_extract_file_data_by_record(bsa_ return { 0 }; } -BSARCH_DLL_API(bsa_result_message_buffer_t) bsa_extract_file_data_by_filename(bsa_archive_t archive, const wchar_t *filename) { +BSARCH_DLL_API(bsa_result_message_buffer_t) bsa_extract_file_data_by_filename(bsa_archive_t archive, const wchar_t *file_path) { return { 0 }; } @@ -68,7 +72,7 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_file_data_free(bsa_archive_t archive, b return { 0 }; } -BSARCH_DLL_API(bsa_result_message_t) bsa_extract_file(bsa_archive_t archive, const wchar_t *filename, const wchar_t *save_as) { +BSARCH_DLL_API(bsa_result_message_t) bsa_extract_file(bsa_archive_t archive, const wchar_t *file_path, const wchar_t *save_as) { return { 0 }; } @@ -76,7 +80,7 @@ BSARCH_DLL_API(bsa_result_message_t) bsa_iterate_files(bsa_archive_t archive, bs return { 0 }; } -BSARCH_DLL_API(bool) bsa_file_exists(bsa_archive_t archive, const wchar_t *filename) { +BSARCH_DLL_API(bool) bsa_file_exists(bsa_archive_t archive, const wchar_t *file_path) { return false; } diff --git a/libbsarch.def b/libbsarch.def index bc4c94f..3953b92 100644 --- a/libbsarch.def +++ b/libbsarch.def @@ -12,6 +12,7 @@ EXPORTS bsa_create_archive bsa_save bsa_add_file_from_disk + bsa_add_file_from_disk_root bsa_add_file_from_memory bsa_find_file_record bsa_extract_file_data_by_record diff --git a/libbsarch.dpr b/libbsarch.dpr index a79b764..5cc7e75 100644 --- a/libbsarch.dpr +++ b/libbsarch.dpr @@ -137,22 +137,22 @@ begin end; end; -function bsa_load_from_file(obj: Pointer; const aFileName: PChar): TwbBSResultMessage; stdcall; +function bsa_load_from_file(obj: Pointer; const aFilePath: PChar): TwbBSResultMessage; stdcall; begin Result.code := Ord(BSA_RESULT_NONE); try - TwbBSArchive(obj).LoadFromFile(String(aFileName)); + TwbBSArchive(obj).LoadFromFile(String(aFilePath)); except on E: Exception do exception_handler(E, Result); end; end; -function bsa_create_archive(obj: Pointer; const aFileName: PChar; aType: TBSArchiveType; aFileList: TwbBSEntryList): TwbBSResultMessage; stdcall; +function bsa_create_archive(obj: Pointer; const aFilePath: PChar; aType: TBSArchiveType; aFileList: TwbBSEntryList): TwbBSResultMessage; stdcall; begin Result.code := Ord(BSA_RESULT_NONE); try - TwbBSArchive(obj).CreateArchiveCompat(String(aFileName), aType, aFileList); + TwbBSArchive(obj).CreateArchiveCompat(String(aFilePath), aType, aFileList); except on E: Exception do exception_handler(E, Result); @@ -170,32 +170,43 @@ begin end; end; -function bsa_add_file_from_disk(obj: Pointer; const aRootDir, aFileName: PChar): TwbBSResultMessage; stdcall; +function bsa_add_file_from_disk_root(obj: Pointer; const aRootDir, aSourcePath: PChar): TwbBSResultMessage; stdcall; begin Result.code := Ord(BSA_RESULT_NONE); try - TwbBSArchive(obj).AddFile(String(aRootDir), String(aFileName)); + TwbBSArchive(obj).AddFileDiskRoot(String(aRootDir), String(aSourcePath)); except on E: Exception do exception_handler(E, Result); end; end; -function bsa_add_file_from_memory(obj: Pointer; const aFileName: PChar; const aSize: Cardinal; const aData: PByte): TwbBSResultMessage; stdcall; +function bsa_add_file_from_disk(obj: Pointer; const aFilePath, aSourcePath: PChar): TwbBSResultMessage; stdcall; begin Result.code := Ord(BSA_RESULT_NONE); try - TwbBSArchive(obj).AddFileCompat(String(aFileName), aSize, aData); + TwbBSArchive(obj).AddFileDisk(String(aFilePath), String(aSourcePath)); except on E: Exception do exception_handler(E, Result); end; end; -function bsa_find_file_record(obj: Pointer; const aFileName: PChar): Pointer; stdcall; +function bsa_add_file_from_memory(obj: Pointer; const aFilePath: PChar; const aSize: Cardinal; const aData: PByte): TwbBSResultMessage; stdcall; +begin + Result.code := Ord(BSA_RESULT_NONE); + try + TwbBSArchive(obj).AddFileDataCompat(String(aFilePath), aSize, aData); + except + on E: Exception do + exception_handler(E, Result); + end; +end; + +function bsa_find_file_record(obj: Pointer; const aFilePath: PChar): Pointer; stdcall; begin try - Result := TwbBSArchive(obj).FindFileRecord(String(aFileName)); + Result := TwbBSArchive(obj).FindFileRecord(String(aFilePath)); except Result := nil end; @@ -212,11 +223,11 @@ begin end; end; -function bsa_extract_file_data_by_filename(obj: Pointer; const aFileName: PChar): TwbBSResultMessageBuffer; stdcall; +function bsa_extract_file_data_by_filename(obj: Pointer; const aFilePath: PChar): TwbBSResultMessageBuffer; stdcall; begin Result.message.code := Ord(BSA_RESULT_NONE); try - Result.buffer := TwbBSArchive(obj).ExtractFileDataCompat(String(aFileName)); + Result.buffer := TwbBSArchive(obj).ExtractFileDataCompat(String(aFilePath)); except on E: Exception do buffer_exception_handler(E, Result); @@ -234,11 +245,11 @@ begin end; end; -function bsa_extract_file(obj: Pointer; const aFileName, aSaveAs: PChar): TwbBSResultMessage; stdcall; +function bsa_extract_file(obj: Pointer; const aFilePath, aSaveAs: PChar): TwbBSResultMessage; stdcall; begin Result.code := Ord(BSA_RESULT_NONE); try - TwbBSArchive(obj).ExtractFile(String(aFileName), String(aSaveAs)); + TwbBSArchive(obj).ExtractFile(String(aFilePath), String(aSaveAs)); except on E: Exception do exception_handler(E, Result); @@ -256,12 +267,12 @@ begin end; end; -function bsa_file_exists(obj: Pointer; const aFileName: string): Boolean; stdcall; +function bsa_file_exists(obj: Pointer; const aFilePath: string): Boolean; stdcall; begin try - Result := TwbBSArchive(obj).FileExists(aFileName); + Result := TwbBSArchive(obj).FileExists(aFilePath); except - Result := False; + Result := False; end; end; @@ -401,6 +412,7 @@ exports bsa_extract_file_data_by_record, bsa_find_file_record, bsa_add_file_from_memory, + bsa_add_file_from_disk_root, bsa_add_file_from_disk, bsa_save, bsa_create_archive, diff --git a/libbsarch.dproj b/libbsarch.dproj index 2629f0e..2b868c1 100644 --- a/libbsarch.dproj +++ b/libbsarch.dproj @@ -8,7 +8,7 @@ Library None 18.6 - Win64 + Win32 true @@ -157,6 +157,7 @@ True True + False 12 diff --git a/libbsarch.h b/libbsarch.h index df1aade..f9da4e6 100644 --- a/libbsarch.h +++ b/libbsarch.h @@ -34,32 +34,36 @@ typedef struct bsa_dds_info_s { } bsa_dds_info_t; PACKED ( -typedef struct bsa_dds_header_s { +struct bsa_dds_header_s { uint32_t magic; // DDS_MAGIC struct DirectX::DDS_HEADER header; -} bsa_dds_header_t; -) +}); + +typedef struct bsa_dds_header_s bsa_dds_header_t; PACKED ( -typedef struct bsa_result_message_s { +struct bsa_result_message_s { int8_t code; // bsa_result_code_t wchar_t text[1024]; -} bsa_result_message_t; -) +}); + +typedef struct bsa_result_message_s bsa_result_message_t; PACKED ( -typedef struct bsa_result_buffer_s { +struct bsa_result_buffer_s { uint32_t size; bsa_buffer_t data; -} bsa_result_buffer_t; -) +}); + +typedef struct bsa_result_buffer_s bsa_result_buffer_t; PACKED ( -typedef struct bsa_result_message_buffer_s { +struct bsa_result_message_buffer_s { bsa_result_buffer_t buffer; bsa_result_message_t message; -} bsa_result_message_buffer_t; -) +}); + +typedef struct bsa_result_message_buffer_s bsa_result_message_buffer_t; typedef enum bsa_archive_state_e { stReading, stWriting @@ -69,8 +73,8 @@ 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 *filename, bsa_dds_info_t dds_info); -typedef bool (*bsa_file_iteration_proc_t)(bsa_archive_t archive, const wchar_t *filename, bsa_file_record_t file_record, bsa_folder_record_t folder_record, void *context); +typedef void (*bsa_file_dds_info_proc_t)(bsa_archive_t archive, const wchar_t *file_path, bsa_dds_info_t dds_info); +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); @@ -80,18 +84,19 @@ BSARCH_DLL_API(uint32_t) bsa_entry_list_get(bsa_entry_list_t entry_list, uint32_ 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 *filename); -BSARCH_DLL_API(bsa_result_message_t) bsa_create_archive(bsa_archive_t archive, const wchar_t *filename, bsa_archive_type_t archive_type, bsa_entry_list_t entry_list); +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 *root_dir, const wchar_t *filename); -BSARCH_DLL_API(bsa_result_message_t) bsa_add_file_from_memory(bsa_archive_t archive, const wchar_t *filename, 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 *filename); +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 *filename); +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 *filename, const wchar_t *save_as); +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 *filename); +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); diff --git a/libbsarch.vcxproj b/libbsarch.vcxproj index e480e4e..e9b9ef7 100644 --- a/libbsarch.vcxproj +++ b/libbsarch.vcxproj @@ -149,6 +149,7 @@ + diff --git a/libbsarch.vcxproj.filters b/libbsarch.vcxproj.filters index 502ec7f..e57e1f7 100644 --- a/libbsarch.vcxproj.filters +++ b/libbsarch.vcxproj.filters @@ -24,6 +24,7 @@ Resource Files + diff --git a/wbBSArchive.pas b/wbBSArchive.pas index 01bab0b..6c85067 100644 --- a/wbBSArchive.pas +++ b/wbBSArchive.pas @@ -193,11 +193,11 @@ type TBSArchiveType = (baNone, baTES3, baTES4, baFO3, baSSE, baFO4, baFO4dds); TBSArchiveState = (stReading, stWriting); TBSArchiveStates = set of TBSArchiveState; - TBSFileIterationProcCompat = function(aArchive: Pointer; const aFileName: PChar; + TBSFileIterationProcCompat = function(aArchive: Pointer; const aFilePath: PChar; aFileRecord: Pointer; aFolderRecord: Pointer; aContext: Pointer): Boolean; stdcall; TDDSInfo = record Width, Height, MipMaps: Integer; end; - TBSFileDDSInfoProcCompat = procedure(aArchive: Pointer; const aFileName: PChar; + TBSFileDDSInfoProcCompat = procedure(aArchive: Pointer; const aFilePath: PChar; var aInfo: TDDSInfo); stdcall; TwbBSHeaderTES3 = packed record @@ -330,9 +330,9 @@ type function GetArchiveFormatName: string; function GetFileCount: Cardinal; procedure SetArchiveFlags(aFlags: Cardinal); - function FindFileRecordTES3(const aFileName: string; var aFileIdx: Integer): Boolean; - function FindFileRecordTES4(const aFileName: string; var aFolderIdx, aFileIdx: Integer): Boolean; - function FindFileRecordFO4(const aFileName: string; var aFileIdx: Integer): Boolean; + function FindFileRecordTES3(const aFilePath: string; var aFileIdx: Integer): Boolean; + function FindFileRecordTES4(const aFilePath: string; var aFolderIdx, aFileIdx: Integer): Boolean; + function FindFileRecordFO4(const aFilePath: string; var aFileIdx: Integer): Boolean; function GetDDSMipChunkNum(var aDDSInfo: TDDSInfo): Integer; function CalcDataHash(aData: Pointer; aLen: Cardinal): TPackedDataHash; function FindPackedData(aSize: Cardinal; aHash: TPackedDataHash; aFileRecord: Pointer): Boolean; @@ -342,19 +342,20 @@ type Sync: IReadWriteSync; constructor Create; destructor Destroy; override; - procedure LoadFromFile(const aFileName: string); - procedure CreateArchiveCompat(const aFileName: string; aType: TBSArchiveType; + procedure LoadFromFile(const aFilePath: string); + procedure CreateArchiveCompat(const aFilePath: string; aType: TBSArchiveType; aFilesList: TwbBSEntryList = nil); procedure Save; - procedure AddFile(const aRootDir, aFileName: string); overload; - procedure AddFileCompat(const aFileName: string; const aSize: Cardinal; const aData: PByte); - function FindFileRecord(const aFileName: string): Pointer; + procedure AddFileDisk(const aFilePath, aSourcePath: string); + procedure AddFileDiskRoot(const aRootDir, aSourcePath: string); + procedure AddFileDataCompat(const aFilePath: string; const aSize: Cardinal; const aData: PByte); + function FindFileRecord(const aFilePath: string): Pointer; function ExtractFileDataCompat(aFileRecord: Pointer): TwbBSResultBuffer; overload; - function ExtractFileDataCompat(const aFileName: string): TwbBSResultBuffer; overload; + function ExtractFileDataCompat(const aFilePath: string): TwbBSResultBuffer; overload; procedure ReleaseFileDataCompat(fileDataResult: TwbBSResultBuffer); - procedure ExtractFile(const aFileName, aSaveAs: string); + procedure ExtractFile(const aFilePath, aSaveAs: string); procedure IterateFilesCompat(aProc: TBSFileIterationProcCompat; aContext: Pointer = nil); - function FileExists(const aFileName: string): Boolean; + function FileExists(const aFilePath: string): Boolean; procedure ResourceListCompat(const aEntryResultList: TwbBSEntryList; aFolder: string = ''); procedure ResolveHashCompat(const aHash: UInt64; const aEntryResultList: TwbBSEntryList); procedure Close; @@ -371,11 +372,11 @@ type property DDSInfoProc: TBSFileDDSInfoProcCompat read fDDSInfoProc write fDDSInfoProc; end; -function SplitDirName(const aFileName: string; var Dir, Name: string): Integer; -function SplitNameExt(const aFileName: string; var Name, Ext: string): Integer; -function CreateHashTES3(const aFileName: string): UInt64; -function CreateHashTES4(const aFileName: string): UInt64; overload; -function CreateHashFO4(const aFileName: string): Cardinal; +function SplitDirName(const aFilePath: string; var Dir, Name: string): Integer; +function SplitNameExt(const aFilePath: string; var Name, Ext: string): Integer; +function CreateHashTES3(const aFilePath: string): UInt64; +function CreateHashTES4(const aFilePath: string): UInt64; overload; +function CreateHashFO4(const aFilePath: string): Cardinal; implementation @@ -594,35 +595,35 @@ begin end; end; -function SplitDirName(const aFileName: string; var Dir, Name: string): Integer; +function SplitDirName(const aFilePath: string; var Dir, Name: string): Integer; begin - Result := LastCharPos(aFileName, '\'); + Result := LastCharPos(aFilePath, '\'); if Result = 0 then - Result := LastCharPos(aFileName, '/'); - Dir := Copy(aFileName, 1, Pred(Result)); - Name := Copy(aFileName, Succ(Result), Length(aFileName) - Result); + Result := LastCharPos(aFilePath, '/'); + Dir := Copy(aFilePath, 1, Pred(Result)); + Name := Copy(aFilePath, Succ(Result), Length(aFilePath) - Result); end; -function SplitNameExt(const aFileName: string; var Name, Ext: string): Integer; +function SplitNameExt(const aFilePath: string; var Name, Ext: string): Integer; begin - Result := LastCharPos(aFileName, '.'); + Result := LastCharPos(aFilePath, '.'); if Result <> 0 then begin - Name := Copy(aFileName, 1, Pred(Result)); - Ext := Copy(aFileName, Result, Length(aFileName) - Result + 2); + Name := Copy(aFilePath, 1, Pred(Result)); + Ext := Copy(aFilePath, Result, Length(aFilePath) - Result + 2); end else begin - Name := aFileName; + Name := aFilePath; Ext := ''; end; end; -function CreateHashTES3(const aFileName: string): UInt64; +function CreateHashTES3(const aFilePath: string): UInt64; var s: AnsiString; i, l: integer; sum, off, temp, n: Cardinal; begin - s := AnsiString(aFileName); + s := AnsiString(aFilePath); l := Length(s) shr 1; sum := 0; off := 0; @@ -689,22 +690,22 @@ begin Result := Result + UInt64(hash) shl 32; end; -function CreateHashTES4(const aFileName: string): UInt64; overload; +function CreateHashTES4(const aFilePath: string): UInt64; overload; var fname, fext: string; begin - SplitNameExt(aFileName, fname, fext); + SplitNameExt(aFilePath, fname, fext); Result := CreateHashTES4(fname, fext); end; -function CreateHashFO4(const aFileName: string): Cardinal; +function CreateHashFO4(const aFilePath: string): Cardinal; var i: Integer; s: AnsiString; c: AnsiChar; begin Result := 0; - s := AnsiString(aFileName); + s := AnsiString(aFilePath); for i := 1 to Length(s) do begin c := s[i]; if Byte(c) > 127 then Continue; @@ -777,12 +778,12 @@ begin fHeaderTES4.Flags := fHeaderTES4.Flags or ARCHIVE_COMPRESS; end; -function TwbBSArchive.FindFileRecordTES3(const aFileName: string; var aFileIdx: Integer): Boolean; +function TwbBSArchive.FindFileRecordTES3(const aFilePath: string; var aFileIdx: Integer): Boolean; var h: UInt64; i: integer; begin - h := CreateHashTES3(aFileName); + h := CreateHashTES3(aFilePath); Result := False; for i := Low(fFilesTES3) to High(fFilesTES3) do @@ -793,13 +794,13 @@ begin end; end; -function TwbBSArchive.FindFileRecordTES4(const aFileName: string; var aFolderIdx, aFileIdx: Integer): Boolean; +function TwbBSArchive.FindFileRecordTES4(const aFilePath: string; var aFolderIdx, aFileIdx: Integer): Boolean; var fdir, fname, name, ext: string; h: UInt64; i, j: integer; begin - if SplitDirName(aFileName, fdir, fname) = 0 then + if SplitDirName(aFilePath, fdir, fname) = 0 then Exit(False); Result := False; @@ -829,14 +830,14 @@ begin end; end; -function TwbBSArchive.FindFileRecordFO4(const aFileName: string; var aFileIdx: Integer): Boolean; +function TwbBSArchive.FindFileRecordFO4(const aFilePath: string; var aFileIdx: Integer): Boolean; var fdir, fname, name, ext: string; hdir, hfile: Cardinal; hext: TMagic4; i: integer; begin - if SplitDirName(aFileName, fdir, fname) = 0 then + if SplitDirName(aFilePath, fdir, fname) = 0 then Exit(False); SplitNameExt(fname, name, ext); @@ -855,7 +856,7 @@ begin end; end; -function TwbBSArchive.FindFileRecord(const aFileName: string): Pointer; +function TwbBSArchive.FindFileRecord(const aFilePath: string): Pointer; var i, j: integer; begin @@ -863,11 +864,11 @@ begin case fType of baTES3: - if FindFileRecordTES3(aFileName, i) then Result := @fFilesTES3[i]; + if FindFileRecordTES3(aFilePath, i) then Result := @fFilesTES3[i]; baTES4, baFO3, baSSE: - if FindFileRecordTES4(aFileName, i, j) then Result := @fFoldersTES4[i].Files[j]; + if FindFileRecordTES4(aFilePath, i, j) then Result := @fFoldersTES4[i].Files[j]; baFO4, baFO4dds: - if FindFileRecordFO4(aFileName, i) then Result := @fFilesFO4[i]; + if FindFileRecordFO4(aFilePath, i) then Result := @fFilesFO4[i]; end; end; @@ -951,14 +952,14 @@ begin Inc(fPackedDataCount); end; -procedure TwbBSArchive.LoadFromFile(const aFileName: string); +procedure TwbBSArchive.LoadFromFile(const aFilePath: string); var i, j: Integer; begin if fStates * [stReading, stWriting] <> [] then Close; - fStream := TwbReadOnlyCachedFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite); + fStream := TwbReadOnlyCachedFileStream.Create(aFilePath, fmOpenRead or fmShareDenyWrite); // magic fMagic := Int2Magic(fStream.ReadCardinal); @@ -1099,7 +1100,7 @@ begin end; - fFileName := aFileName; + fFileName := aFilePath; Include(fStates, stReading); end; @@ -1131,7 +1132,7 @@ begin Result := CompareStr(List[Index1], List[Index2]); end; -procedure TwbBSArchive.CreateArchiveCompat(const aFileName: string; aType: TBSArchiveType; +procedure TwbBSArchive.CreateArchiveCompat(const aFilePath: string; aType: TBSArchiveType; aFilesList: TwbBSEntryList = nil); var HashPairs: array of THashPair; @@ -1371,8 +1372,8 @@ begin end; - fStream := TwbWriteCachedFileStream.Create(aFileName, fmCreate); - fFileName := aFileName; + fStream := TwbWriteCachedFileStream.Create(aFilePath, fmCreate); + fFileName := aFilePath; Include(fStates, stWriting); // reserve space for the header @@ -1532,7 +1533,9 @@ begin Close; end; -procedure TwbBSArchive.AddFile(const aRootDir, aFileName: string); + + +procedure TwbBSArchive.AddFileDisk(const aFilePath, aSourcePath: string); var fname: string; i: integer; @@ -1542,18 +1545,12 @@ begin if not (stWriting in fStates) then raise Exception.Create('Archive is not in writing mode'); - i := Length(aRootDir); - if (i > 1) and (aRootDir[Length(aRootDir)] <> '\') then - Inc(i); - - fname := Copy(aFileName, i + 1, Length(aFileName)); - - stream := TFileStream.Create(aFileName, fmOpenRead + fmShareDenyNone); + stream := TFileStream.Create(aSourcePath, fmOpenRead + fmShareDenyNone); try GetMem(buffer, stream.Size); try stream.Read(buffer^, stream.Size); - AddFileCompat(fname, stream.Size, buffer); + AddFileDataCompat(aFilePath, stream.Size, buffer); finally if Assigned(buffer) then FreeMem(buffer); @@ -1563,8 +1560,22 @@ begin end; end; +procedure TwbBSArchive.AddFileDiskRoot(const aRootDir, aSourcePath: string); +var + fname: string; + i: integer; +begin + i := Length(aRootDir); + if (i > 1) and (aRootDir[Length(aRootDir)] <> '\') then + Inc(i); + + fname := Copy(aSourcePath, i + 1, Length(aSourcePath)); + + AddFileDisk(fname, aSourcePath); +end; + // Modified: Version for use in non-Borland C/C++ -procedure TwbBSArchive.AddFileCompat(const aFileName: string; const aSize: Cardinal; const aData: PByte); +procedure TwbBSArchive.AddFileDataCompat(const aFilePath: string; const aSize: Cardinal; const aData: PByte); var i, j, Off, MipSize, BitsPerPixel: integer; fdir, fname, name, ext: string; @@ -1589,8 +1600,8 @@ begin try case fType of baTES3: begin - if not FindFileRecordTES3(aFileName, i) then - raise Exception.Create('File not found in files table: ' + aFileName); + if not FindFileRecordTES3(aFilePath, i) then + raise Exception.Create('File not found in files table: ' + aFilePath); if FindPackedData(aSize, DataHash, @fFilesTES3[i]) then Exit; @@ -1602,8 +1613,8 @@ begin end; baTES4, baFO3, baSSE: begin - if not FindFileRecordTES4(aFileName, i, j) then - raise Exception.Create('File not found in files table: ' + aFileName); + if not FindFileRecordTES4(aFilePath, i, j) then + raise Exception.Create('File not found in files table: ' + aFilePath); if FindPackedData(aSize, DataHash, @fFoldersTES4[i].Files[j]) then Exit; @@ -1669,8 +1680,8 @@ begin end; baFO4: begin - if SplitDirName(aFileName, fdir, fname) = 0 then - raise Exception.Create('File is missing the folder part: ' + aFileName); + if SplitDirName(aFilePath, fdir, fname) = 0 then + raise Exception.Create('File is missing the folder part: ' + aFilePath); SplitNameExt(fname, name, ext); if Length(ext) > 1 then Delete(ext, 1, 1); // no dot in extension @@ -1678,7 +1689,7 @@ begin i := fHeaderFO4.FileCount; Inc(fHeaderFO4.FileCount); // archive2.exe uses / - fFilesFO4[i].Name := StringReplace(aFileName, '\', '/', [rfReplaceAll]); + fFilesFO4[i].Name := StringReplace(aFilePath, '\', '/', [rfReplaceAll]); fFilesFO4[i].DirHash := CreateHashFO4(fdir); fFilesFO4[i].NameHash := CreateHashFO4(name); fFilesFO4[i].Ext := Int2Magic(Str2MagicInt(ext)); @@ -1711,8 +1722,8 @@ begin end; baFO4dds: begin - if SplitDirName(aFileName, fdir, fname) = 0 then - raise Exception.Create('File is missing the folder part: ' + aFileName); + if SplitDirName(aFilePath, fdir, fname) = 0 then + raise Exception.Create('File is missing the folder part: ' + aFilePath); SplitNameExt(fname, name, ext); if Length(ext) > 1 then Delete(ext, 1, 1); // no dot in extension @@ -1721,7 +1732,7 @@ begin i := fHeaderFO4.FileCount; Inc(fHeaderFO4.FileCount); // archive2.exe uses / - fFilesFO4[i].Name := StringReplace(aFileName, '\', '/', [rfReplaceAll]); + fFilesFO4[i].Name := StringReplace(aFilePath, '\', '/', [rfReplaceAll]); fFilesFO4[i].DirHash := CreateHashFO4(fdir); fFilesFO4[i].NameHash := CreateHashFO4(name); fFilesFO4[i].Ext := Int2Magic(Str2MagicInt(ext)); @@ -2197,14 +2208,14 @@ begin end; // Modified: Version for use in non-Borland C/C++ -function TwbBSArchive.ExtractFileDataCompat(const aFileName: string): TwbBSResultBuffer; +function TwbBSArchive.ExtractFileDataCompat(const aFilePath: string): TwbBSResultBuffer; var FileRecord: Pointer; begin if not (stReading in fStates) then raise Exception.Create('Archive is not loaded'); - FileRecord := FindFileRecord(aFileName); + FileRecord := FindFileRecord(aFilePath); if not Assigned(FileRecord) then raise Exception.Create('File not found in archive'); @@ -2219,7 +2230,7 @@ begin fileDataResult.size := 0; end; -procedure TwbBSArchive.ExtractFile(const aFileName, aSaveAs: string); +procedure TwbBSArchive.ExtractFile(const aFilePath, aSaveAs: string); var fs: TFileStream; fileData: TwbBSResultBuffer; @@ -2229,7 +2240,7 @@ begin fs := TFileStream.Create(aSaveAs, fmCreate); try - fileData := ExtractFileDataCompat(aFileName); + fileData := ExtractFileDataCompat(aFilePath); fs.Write(fileData.data[0], fileData.size); finally ReleaseFileDataCompat(fileData); @@ -2285,9 +2296,9 @@ begin end; end; -function TwbBSArchive.FileExists(const aFileName: string): Boolean; +function TwbBSArchive.FileExists(const aFilePath: string): Boolean; begin - Result := Assigned(FindFileRecord(aFileName)); + Result := Assigned(FindFileRecord(aFilePath)); end; procedure TwbBSArchive.Close;