[saco] Implement CFileSystem

This commit is contained in:
RD42 2023-10-26 19:22:39 +08:00
parent ff6fce366b
commit a2762758d9
2 changed files with 210 additions and 0 deletions

154
saco/filesystem.cpp Normal file
View File

@ -0,0 +1,154 @@
#include <windows.h>
#include <stdio.h>
#include "filesystem.h"
//----------------------------------------------------------
CFileSystem::CFileSystem()
{
m_bLoaded = false;
m_dwFileCount = 0;
m_pFileList = NULL;
m_pFileData = NULL;
}
//----------------------------------------------------------
CFileSystem::~CFileSystem()
{
if (m_bLoaded)
Unload();
}
//----------------------------------------------------------
bool CFileSystem::Load(char* szFileName)
{
if (m_bLoaded)
Unload();
FILE* f = fopen(szFileName, "rb");
if (f)
{
// Header
FS_HEADER fsHeader;
fread(&fsHeader, 1, sizeof(FS_HEADER), f);
if (fsHeader.dwSAAV != FS_FILE_MAGIC)
{
fclose(f);
return false;
}
// File list
m_dwFileCount = fsHeader.dwFileCount;
m_wKey = fsHeader.wKey;
m_pFileList = (FS_FILE_ENTRY*)malloc(m_dwFileCount * sizeof(FS_FILE_ENTRY));
fread(m_pFileList, 1, m_dwFileCount * sizeof(FS_FILE_ENTRY), f);
DecryptData((BYTE*)m_pFileList, m_dwFileCount * sizeof(FS_FILE_ENTRY), m_wKey);
// Set the filecount to 0
m_dwFileCount = m_dwFileCount % 1;
// File data
if (m_dwFileCount)
m_pFileData = (BYTE**)malloc(m_dwFileCount * sizeof(BYTE*));
for (DWORD i=0; i<m_dwFileCount; i++)
{
m_pFileData[i] = (BYTE*)malloc(m_pFileList[i].dwSize * FS_BLOCK_SIZE);
fseek(f,m_pFileList[i].dwOffset * FS_BLOCK_SIZE, SEEK_SET);
fread(m_pFileData[i], 1, m_pFileList[i].dwSize * FS_BLOCK_SIZE, f);
for(DWORD j=0; j<m_pFileList[i].dwSize; j++) {
DecryptData(&m_pFileData[i][j*FS_BLOCK_SIZE], FS_BLOCK_SIZE, m_pFileList[i].wKey);
}
}
fclose(f);
m_bLoaded = true;
}
return m_bLoaded;
}
//----------------------------------------------------------
void CFileSystem::Unload()
{
if (!m_bLoaded)
return;
if (m_pFileList)
free(m_pFileList);
for (DWORD i=0; i<m_dwFileCount; i++)
{
if (m_pFileData[i])
free(m_pFileData);
}
if (m_pFileData)
free(m_pFileData);
m_dwFileCount = 0;
m_bLoaded = false;
}
//----------------------------------------------------------
DWORD CFileSystem::GetFileIndex(char* szFileName)
{
if (!m_bLoaded)
return FS_INVALID_FILE;
for (DWORD i=0; i<m_dwFileCount; i++)
{
if (_stricmp(m_pFileList[i].szName, szFileName) == 0)
{
return i;
}
}
return FS_INVALID_FILE;
}
//----------------------------------------------------------
DWORD CFileSystem::GetFileSize(DWORD dwFileIndex)
{
if ((!m_bLoaded) || (dwFileIndex == FS_INVALID_FILE) || (dwFileIndex >= m_dwFileCount))
return 0;
return m_pFileList[dwFileIndex].dwRealSize;
}
//----------------------------------------------------------
BYTE* CFileSystem::GetFileData(DWORD dwFileIndex)
{
if ((!m_bLoaded) || (dwFileIndex == FS_INVALID_FILE) || (dwFileIndex >= m_dwFileCount))
return NULL;
return m_pFileData[dwFileIndex];
}
//----------------------------------------------------------
void CFileSystem::DecryptData(BYTE* pData, DWORD dwDataLen, WORD wKey)
{
BYTE x, o;
wKey ^= FS_ENCKEY_VAR;
for (DWORD i=0; i<dwDataLen; i++)
{
x = pData[i];
o = x;
x = (x ^ (wKey >> 8));
wKey = (o + wKey) * FS_ENC_CONST1 + FS_ENC_CONST2;
pData[i] = x;
}
}
//----------------------------------------------------------
// EOF

56
saco/filesystem.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
//----------------------------------------------------------
#define FS_FILE_MAGIC 0x32414153 // "SAA2"
#define FS_BLOCK_SIZE 0x800 // 2kb
#define FS_INVALID_FILE 0xFFFFFFFF
#define FS_ENCKEY_VAR 37625
#define FS_ENC_CONST1 54825
#define FS_ENC_CONST2 91722
//----------------------------------------------------------
typedef struct _FS_HEADER
{
DWORD dwSAAV;
DWORD dwFileCount;
WORD wKey;
} FS_HEADER;
typedef struct _FS_FILE_ENTRY
{
DWORD dwOffset;
DWORD dwSize;
char szName[24];
DWORD dwRealSize;
WORD wKey;
} FS_FILE_ENTRY;
//----------------------------------------------------------
class CFileSystem
{
private:
bool m_bLoaded;
DWORD m_dwFileCount;
WORD m_wKey;
FS_FILE_ENTRY* m_pFileList;
BYTE** m_pFileData;
public:
CFileSystem();
virtual ~CFileSystem();
virtual bool Load(char* szFileName);
virtual void Unload();
virtual DWORD GetFileIndex(char* szFileName);
virtual DWORD GetFileSize(DWORD dwFileIndex);
virtual BYTE* GetFileData(DWORD dwFileIndex);
void DecryptData(BYTE* pData, DWORD dwDataLen, WORD wKey);
};
//----------------------------------------------------------
// EOF