aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/ArchiveFile.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/ArchiveFile.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/ArchiveFile.cpp')
-rw-r--r--Minecraft.Client/ArchiveFile.cpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/Minecraft.Client/ArchiveFile.cpp b/Minecraft.Client/ArchiveFile.cpp
new file mode 100644
index 00000000..642471a4
--- /dev/null
+++ b/Minecraft.Client/ArchiveFile.cpp
@@ -0,0 +1,215 @@
+#include "stdafx.h"
+
+#include "..\Minecraft.World\StringHelpers.h"
+#include "..\Minecraft.World\compression.h"
+
+#include "ArchiveFile.h"
+
+void ArchiveFile::_readHeader(DataInputStream *dis)
+{
+ int numberOfFiles = dis->readInt();
+
+ for (int i = 0; i < numberOfFiles; i++)
+ {
+ MetaData *meta = new MetaData();
+ meta->filename = dis->readUTF();
+ meta->ptr = dis->readInt();
+ meta->filesize = dis->readInt();
+
+ // Filenames preceeded by an asterisk have been compressed.
+ if (meta->filename[0] == '*')
+ {
+ meta->filename = meta->filename.substr(1);
+ meta->isCompressed = true;
+ }
+ else meta->isCompressed = false;
+
+ m_index.insert( pair<wstring,PMetaData>(meta->filename,meta) );
+ }
+}
+
+ArchiveFile::ArchiveFile(File file)
+{
+ m_cachedData = NULL;
+ m_sourcefile = file;
+ app.DebugPrintf("Loading archive file...\n");
+#ifndef _CONTENT_PACKAGE
+ char buf[256];
+ wcstombs(buf, file.getPath().c_str(), 256);
+ app.DebugPrintf("archive file - %s\n",buf);
+#endif
+
+ if(!file.exists())
+ {
+ app.DebugPrintf("Failed to load archive file!\n");//,file.getPath());
+ app.FatalLoadError();
+ }
+
+ FileInputStream fis(file);
+
+#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64
+ byteArray readArray(file.length());
+ fis.read(readArray,0,file.length());
+
+ ByteArrayInputStream bais(readArray);
+ DataInputStream dis(&bais);
+
+ m_cachedData = readArray.data;
+#else
+ DataInputStream dis(&fis);
+#endif
+
+ _readHeader(&dis);
+
+ dis.close();
+ fis.close();
+#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64
+ bais.reset();
+#endif
+ app.DebugPrintf("Finished loading archive file\n");
+}
+
+ArchiveFile::~ArchiveFile()
+{
+ delete m_cachedData;
+}
+
+vector<wstring> *ArchiveFile::getFileList()
+{
+ vector<wstring> *out = new vector<wstring>();
+
+ for ( AUTO_VAR(it, m_index.begin());
+ it != m_index.end();
+ it++ )
+
+ out->push_back( it->first );
+
+ return out;
+}
+
+bool ArchiveFile::hasFile(const wstring &filename)
+{
+ return m_index.find(filename) != m_index.end();
+}
+
+int ArchiveFile::getFileSize(const wstring &filename)
+{
+ return hasFile(filename) ? m_index.at(filename)->filesize : -1;
+}
+
+byteArray ArchiveFile::getFile(const wstring &filename)
+{
+ byteArray out;
+ AUTO_VAR(it,m_index.find(filename));
+
+ if(it == m_index.end())
+ {
+ app.DebugPrintf("Couldn't find file in archive\n");
+ app.DebugPrintf("Failed to find file '%ls' in archive\n", filename.c_str());
+#ifndef _CONTENT_PACKAGE
+ __debugbreak();
+#endif
+ app.FatalLoadError();
+ }
+ else
+ {
+ PMetaData data = it->second;
+
+#if defined _XBOX_ONE || defined __ORBIS__ || defined _WINDOWS64
+ out = byteArray(data->filesize );
+
+ memcpy( out.data, m_cachedData + data->ptr, data->filesize );
+#else
+
+#ifdef _UNICODE
+ HANDLE hfile = CreateFile( m_sourcefile.getPath().c_str(),
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+#else
+ app.DebugPrintf("Createfile archive\n");
+ HANDLE hfile = CreateFile( wstringtofilename(m_sourcefile.getPath()),
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+#endif
+
+ if (hfile != INVALID_HANDLE_VALUE)
+ {
+ app.DebugPrintf("hfile ok\n");
+ DWORD ok = SetFilePointer( hfile,
+ data->ptr,
+ NULL,
+ FILE_BEGIN
+ );
+
+ if (ok != INVALID_SET_FILE_POINTER)
+ {
+ PBYTE pbData = new BYTE[ data->filesize ];
+
+ DWORD bytesRead = -1;
+ BOOL bSuccess = ReadFile( hfile,
+ (LPVOID) pbData,
+ data->filesize,
+ &bytesRead,
+ NULL
+ );
+
+ if(bSuccess==FALSE)
+ {
+ app.FatalLoadError();
+ }
+ assert(bytesRead == data->filesize);
+ out = byteArray(pbData, data->filesize);
+ }
+ else
+ {
+ app.FatalLoadError();
+ }
+
+ CloseHandle(hfile);
+ }
+ else
+ {
+ app.DebugPrintf("bad hfile\n");
+ app.FatalLoadError();
+ }
+#endif
+
+ // Compressed filenames are preceeded with an asterisk.
+ if ( data->isCompressed && out.data != NULL )
+ {
+ /* 4J-JEV:
+ * If a compressed file is accessed before compression object is
+ * initialized it will crash here (Compression::getCompression).
+ */
+ ///4 279 553 556
+
+ ByteArrayInputStream bais(out);
+ DataInputStream dis(&bais);
+ unsigned int decompressedSize = dis.readInt();
+ dis.close();
+
+ PBYTE uncompressedBuffer = new BYTE[decompressedSize];
+ Compression::getCompression()->Decompress(uncompressedBuffer, &decompressedSize, out.data+4, out.length-4);
+
+ delete [] out.data;
+
+ out.data = uncompressedBuffer;
+ out.length = decompressedSize;
+ }
+
+ assert(out.data != NULL); // THERE IS NO FILE WITH THIS NAME!
+
+ }
+
+ return out;
+}