updating the HLE FS and FileIO

added banner support of the savegames for wii... same games 

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1031 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
fires.gc 2008-11-01 15:59:06 +00:00
parent dad9f74b09
commit 046ca53f8c
9 changed files with 391 additions and 102 deletions

View File

@ -56,11 +56,13 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
bool bkeepLooping = true;
while (bkeepLooping)
{
std::string strFilename;
BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
m_FileNames.push_back(strFilename);
{
if (findData.cFileName[0] != '.')
{
std::string strFilename;
BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
m_FileNames.push_back(strFilename);
}
bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false;
}

View File

@ -48,6 +48,10 @@ bool Exists(const char *filename)
bool IsDirectory(const char *filename)
{
#ifdef _WIN32
DWORD Attribs = GetFileAttributes(filename);
if (Attribs == INVALID_FILE_ATTRIBUTES)
return false;
return (GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY) != 0;
#else
struct stat file_info;
@ -163,11 +167,15 @@ std::string GetUserDirectory()
u64 GetSize(const char *filename)
{
FILE *f = fopen(filename, "rb");
fseek(f, 0, SEEK_END);
u64 pos = ftell(f);
fclose(f);
return pos;
FILE *pFile = fopen(filename, "rb");
if (pFile)
{
fseek(pFile, 0, SEEK_END);
u64 pos = ftell(pFile);
fclose(pFile);
return pos;
}
return 0;
}
#ifdef _WIN32
@ -236,4 +244,14 @@ u32 ScanDirectoryTree(const std::string& _Directory, FSTEntry& parentEntry)
}
#endif
bool CreateEmptyFile(const char *filename)
{
FILE* pFile = fopen(filename, "wb");
if (pFile == NULL)
return false;
fclose(pFile);
return true;
}
} // namespace

View File

@ -35,6 +35,7 @@ struct FSTEntry
std::vector<FSTEntry> children;
};
std::string SanitizePath(const char *filename);
bool Exists(const char *filename);
void Launch(const char *filename);
void Explore(const char *path);
@ -43,6 +44,7 @@ bool CreateDir(const char *filename);
bool Delete(const char *filename);
u64 GetSize(const char *filename);
std::string GetUserDirectory();
bool CreateEmptyFile(const char *filename);
u32 ScanDirectoryTree(const std::string& _Directory, FSTEntry& parentEntry);

View File

@ -16,10 +16,31 @@
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FileUtil.h"
#include "WII_IPC_HLE_Device_FileIO.h"
std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size)
{
char Buffer[128];
memcpy(Buffer, _pFilename, _size);
std::string Filename("WII");
if (Buffer[1] == '0')
Filename += std::string("/title"); // this looks and feel like an hack...
Filename += File::SanitizePath(Buffer);
return Filename;
}
/// ----------------------------------------------------------------
CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName )
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
, m_pFileHandle(NULL)
@ -43,16 +64,6 @@ CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress)
return true;
}
std::string HLE_IPC_BuildFilename(const char* _pFilename)
{
std::string Filename("WII");
if (_pFilename[1] == '0')
Filename += std::string("/title"); // this looks and feel like an hack...
Filename += std::string (_pFilename);
return Filename;
}
bool
CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
{
@ -60,7 +71,7 @@ CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
LOG(WII_IPC_FILEIO, "FileIO: Open (Device=%s)", GetDeviceName().c_str());
m_Filename = (HLE_IPC_BuildFilename(GetDeviceName().c_str()));
m_Filename = std::string(HLE_IPC_BuildFilename(GetDeviceName().c_str(), 64));
switch(_Mode)
{
@ -175,7 +186,7 @@ CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
{
case ISFS_IOCTL_GETFILESTATS:
{
u32 Position = ftell(m_pFileHandle);
u32 Position = (u32)ftell(m_pFileHandle);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS");

View File

@ -18,6 +18,7 @@
#include "Common.h"
#include "StringUtil.h"
#include "FileSearch.h"
#include "FileUtil.h"
#include "WII_IPC_HLE_Device_fs.h"
@ -26,12 +27,16 @@
extern std::string HLE_IPC_BuildFilename(const char* _pFilename);
extern std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size);
#define FS_RESULT_OK (0)
#define FS_FILE_EXIST (-105)
#define FS_FILE_NOT_EXIST (-106)
#define FS_RESULT_FATAL (-128)
#define MAX_NAME (12)
CWII_IPC_HLE_Device_fs::CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
{}
@ -85,18 +90,60 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
{
case IOCTL_READ_DIR:
{
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address)));
// the wii uses this function to define the type (dir or file)
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address), CommandBuffer.InBuffer[0].m_Size));
LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", Filename.c_str());
// check if this is really a directory
if (!File::IsDirectory(Filename.c_str()))
{
LOG(WII_IPC_FILEIO, " Not a directory - return -6 (dunno if this is a correct return value)", Filename.c_str());
ReturnValue = -6;
break;
}
// make a file search
CFileSearch::XStringVector Directories;
Directories.push_back(Filename);
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.*");
CFileSearch FileSearch(Extensions, Directories);
// it is one
if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
{
LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s (dunno what i should return, number of FiLES?)", Filename.c_str());
size_t numFile = FileSearch.GetFileNames().size();
LOG(WII_IPC_FILEIO, " Files in directory: %i", numFile);
Memory::Write_U32(0, CommandBuffer.PayloadBuffer[0].m_Address);
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
}
else
{
PanicAlert("IOCTL_READ_DIR with a lot of parameters");
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size);
size_t numFile = FileSearch.GetFileNames().size();
for (size_t i=0; i<numFile; i++)
{
char* pDest = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address + i * MAX_NAME));
std::string filename, ext;
SplitPath(FileSearch.GetFileNames()[i], NULL, &filename, &ext);
memcpy(pDest, (filename + ext).c_str(), MAX_NAME);
pDest[MAX_NAME-1] = 0x00;
LOG(WII_IPC_FILEIO, " %s", pDest);
}
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[1].m_Address);
}
ReturnValue = 0;
}
break;
@ -106,12 +153,14 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
// fsBlocks and inodes
// we answer nothing is used, but if a program uses it to check
// how much memory has been used we are doomed...
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address)));
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address), CommandBuffer.InBuffer[0].m_Size));
LOG(WII_IPC_FILEIO, "FS: IOCTL_GETUSAGE %s", Filename.c_str());
Memory::Write_U32(0, CommandBuffer.PayloadBuffer[0].m_Address);
Memory::Write_U32(0, CommandBuffer.PayloadBuffer[1].m_Address);
ReturnValue = 0;
}
break;
@ -131,13 +180,64 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
{
switch(_Parameter)
{
case DELETE_FILE:
case CREATE_DIR:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
u32 Addr = _BufferIn;
u32 OwnerID = Memory::Read_U32(Addr); Addr += 4;
u16 GroupID = Memory::Read_U16(Addr); Addr += 2;
std::string DirName(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(Addr), 64));
Addr += 64;
Addr += 9; // owner attribs, permission
u8 Attribs = Memory::Read_U8(Addr);
if (File::IsDirectory(DirName.c_str()))
{
bool Result = File::CreateDir(DirName.c_str());
LOG(WII_IPC_FILEIO, "FS: CREATE_DIR %s (%s)", DirName.c_str(), Result ? "success" : "failed");
_dbg_assert_msg_(WII_IPC_FILEIO, Result, "FS: CREATE_DIR %s failed", DirName.c_str());
}
return FS_RESULT_OK;
}
break;
case GET_ATTR:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
int Offset = 0;
std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset));
std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64);
Offset += 64;
if (remove(Filename.c_str()) == 0)
if (File::IsDirectory(Filename.c_str()))
{
LOG(WII_IPC_FILEIO, "FS: GET_ATTR Directory %s - ni", Filename.c_str());
}
else
{
if (File::Exists(Filename.c_str()))
{
LOG(WII_IPC_FILEIO, "FS: GET_ATTR %s - ni", Filename.c_str());
}
}
return FS_RESULT_OK;
}
break;
case DELETE_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
int Offset = 0;
std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64);
Offset += 64;
if (File::Delete(Filename.c_str()))
{
LOG(WII_IPC_FILEIO, "FS: DeleteFile %s", Filename.c_str());
}
@ -152,14 +252,17 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case RENAME_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
int Offset = 0;
std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset));
std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64);
Offset += 64;
std::string FilenameRename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset));
std::string FilenameRename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn+Offset), 64);
Offset += 64;
CreateDirectoryStruct(FilenameRename);
if (rename(Filename.c_str(), FilenameRename.c_str()) == 0)
{
LOG(WII_IPC_FILEIO, "FS: Rename %s to %s", Filename.c_str(), FilenameRename.c_str());
@ -176,40 +279,36 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case CREATE_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
u32 Addr = _BufferIn;
u32 OwnerID = Memory::Read_U32(Addr); Addr += 4;
u16 GroupID = Memory::Read_U16(Addr); Addr += 2;
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(Addr)));
std::string Filename(HLE_IPC_BuildFilename((const char*)Memory::GetPointer(Addr), 64));
Addr += 64;
Addr += 9; // unk memory;
u8 Attribs = Memory::Read_U8(Addr);
LOG(WII_IPC_FILEIO, "FS: CreateFile %s (attrib: 0x%02x)", Filename.c_str(), Attribs);
FILE* pFileHandle = fopen(Filename.c_str(), "r+b");
if (pFileHandle != NULL)
// check if the file allready exist
if (File::Exists(Filename.c_str()))
{
fclose(pFileHandle);
pFileHandle = NULL;
LOG(WII_IPC_FILEIO, " result = FS_RESULT_EXISTS", Filename.c_str(), Attribs);
LOG(WII_IPC_FILEIO, " result = FS_RESULT_EXISTS", Filename.c_str());
return FS_FILE_EXIST;
}
else
{
CreateDirectoryStruct(Filename);
FILE* pFileHandle = fopen(Filename.c_str(), "w+b");
if (!pFileHandle)
{
PanicAlert("CWII_IPC_HLE_Device_fs: couldn't create new file");
return FS_RESULT_FATAL;
}
fclose(pFileHandle);
LOG(WII_IPC_FILEIO, " result = FS_RESULT_OK", Filename.c_str(), Attribs);
return FS_RESULT_OK;
// create the file
CreateDirectoryStruct(Filename);
bool Result = File::CreateEmptyFile(Filename.c_str());
if (!Result)
{
PanicAlert("CWII_IPC_HLE_Device_fs: couldn't create new file");
return FS_RESULT_FATAL;
}
LOG(WII_IPC_FILEIO, " result = FS_RESULT_OK", Filename.c_str(), Attribs);
return FS_RESULT_OK;
}
break;
@ -228,18 +327,31 @@ void CWII_IPC_HLE_Device_fs::CreateDirectoryStruct(const std::string& _rFullPath
size_t Position = 0;
while(true)
{
Position = _rFullPath.find('/', Position);
if (Position == std::string::npos)
break;
// find next sub path
{
size_t nextPosition = _rFullPath.find('/', Position);
if (nextPosition == std::string::npos)
nextPosition = _rFullPath.find('\\', Position);
Position = nextPosition;
Position++;
if (Position == std::string::npos)
break;
Position++;
}
// create next sub path
std::string SubPath = _rFullPath.substr(0, Position);
if (!SubPath.empty())
_mkdir(SubPath.c_str());
LOG(WII_IPC_FILEIO, " CreateSubDir %s", SubPath.c_str());
{
if (!File::IsDirectory(SubPath.c_str()))
{
File::CreateDir(SubPath.c_str());
LOG(WII_IPC_FILEIO, " CreateSubDir %s", SubPath.c_str());
}
}
// just a safty check...
PanicCounter--;
if (PanicCounter <= 0)
{
@ -247,4 +359,4 @@ void CWII_IPC_HLE_Device_fs::CreateDirectoryStruct(const std::string& _rFullPath
break;
}
}
}
}

View File

@ -43,7 +43,9 @@ private:
enum
{
CREATE_DIR = 0x03,
IOCTL_READ_DIR = 0x04,
GET_ATTR = 0x06,
DELETE_FILE = 0x07,
RENAME_FILE = 0x08,
CREATE_FILE = 0x09,
@ -53,6 +55,7 @@ private:
s32 ExecuteCommand(u32 Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize);
void CreateDirectoryStruct(const std::string& _rFullPath);
};
#endif

View File

@ -21,6 +21,7 @@
#include "BannerLoaderGC.h"
#include "VolumeCreator.h"
#include "FileUtil.h"
namespace DiscIO
{

View File

@ -21,77 +21,110 @@
#include "Common.h"
#include "BannerLoaderWii.h"
#include "FileHandlerARC.h"
// #include "FileHandlerLZ77.h"
#include "FileUtil.h"
namespace DiscIO
{
CBannerLoaderWii::CBannerLoaderWii(DiscIO::IFileSystem& _rFileSystem)
: m_pBuffer(NULL)
CBannerLoaderWii::CBannerLoaderWii(DiscIO::IFileSystem& _rFileSystem)
: m_pBannerFile(NULL)
, m_IsValid(false)
{
FILE* pFile = fopen("e:\\opening.bnr", "rb");
InitLUTTable();
char Filename[260];
char TitleID[4];
_rFileSystem.GetVolume()->Read(0, 4, (u8*)TitleID);
sprintf(Filename, "Wii/title/00010000/%02x%02x%02x%02x/data/banner.bin", (u8)TitleID[0], (u8)TitleID[1], (u8)TitleID[2], (u8)TitleID[3]);
if (pFile)
// load the opening.bnr
size_t FileSize = File::GetSize(Filename);
if (FileSize > 0)
{
fseek(pFile, 0, SEEK_END);
int insize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
m_pBuffer = new u8[insize];
fread(m_pBuffer, 1, insize, pFile);
fclose(pFile);
CARCFile ArcFile(m_pBuffer + 0x600, insize - 0x600);
size_t BannerSize = ArcFile.GetFileSize("meta\\banner.bin");
if (BannerSize > 0)
m_pBannerFile = new u8[FileSize];
FILE* pFile = fopen(Filename, "rb");
if (pFile != NULL)
{
u8* TempBuffer = new u8[BannerSize];
ArcFile.ReadFile("meta\\banner.bin", TempBuffer, BannerSize);
// CLZ77File File(TempBuffer + 0x20 + 4, BannerSize - 0x20 - 4);
delete[] TempBuffer;
// CARCFile IconFile(File.GetBuffer(), File.GetSize());
// IconFile.ExportFile("arc\\anim\\banner_loop.brlan", "e:\\banner_loop.brlan");
//IconFile.ReadFile("meta\\icon.bin", TempBuffer, BannerSize);
fread(m_pBannerFile, FileSize, 1, pFile);
fclose(pFile);
m_IsValid = true;
}
}
m_Name = std::string("Wii: ") + _rFileSystem.GetVolume()->GetName();
}
CBannerLoaderWii::~CBannerLoaderWii()
{
delete [] m_pBuffer;
m_pBuffer = NULL;
if (m_pBannerFile)
{
delete [] m_pBannerFile;
m_pBannerFile = NULL;
}
}
bool
CBannerLoaderWii::IsValid()
{
return(true);
return (m_IsValid);
}
bool
CBannerLoaderWii::GetBanner(u32* _pBannerImage)
{
return(false);
if (!IsValid())
{
return(false);
}
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
static u32 Buffer[192 * 64];
decode5A3image(Buffer, (u16*)pBanner->m_BannerTexture, 192, 64);
for (int y=0; y<32; y++)
{
for (int x=0; x<96; x++)
{
_pBannerImage[y*96+x] = Buffer[(y*2)*96+(x*2)];
}
}
return(true);
}
std::string
CBannerLoaderWii::StupidWideCharToString(u16* _pSrc, size_t _max)
{
std::string temp;
int offset = 0;
while (_pSrc[offset] != 0x0000)
{
temp += (char)(_pSrc[offset] >> 8);
offset ++;
if (offset >= _max)
break;
}
return temp;
}
bool
CBannerLoaderWii::GetName(std::string& _rName, int language)
{
if (IsValid())
{
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
// very stupid
_rName = StupidWideCharToString(pBanner->m_Comment[0], WII_BANNER_COMMENT_SIZE);
return true;
}
_rName = m_Name;
return(true);
}
@ -107,7 +140,84 @@ CBannerLoaderWii::GetCompany(std::string& _rCompany)
bool
CBannerLoaderWii::GetDescription(std::string& _rDescription)
{
if (IsValid())
{
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
// very stupid
_rDescription = StupidWideCharToString(pBanner->m_Comment[1], WII_BANNER_COMMENT_SIZE);
return true;
}
return(false);
}
void
CBannerLoaderWii::InitLUTTable()
{
// build LUT Table
for (int i = 0; i < 8; i++)
{
lut3to8[i] = (i * 255) / 7;
}
for (int i = 0; i < 16; i++)
{
lut4to8[i] = (i * 255) / 15;
}
for (int i = 0; i < 32; i++)
{
lut5to8[i] = (i * 255) / 31;
}
}
u32
CBannerLoaderWii::decode5A3(u16 val)
{
u32 bannerBGColor = 0x00000000;
int r, g, b, a;
if ((val & 0x8000))
{
r = lut5to8[(val >> 10) & 0x1f];
g = lut5to8[(val >> 5) & 0x1f];
b = lut5to8[(val) & 0x1f];
a = 0xFF;
}
else
{
a = lut3to8[(val >> 12) & 0x7];
r = (lut4to8[(val >> 8) & 0xf] * a + (bannerBGColor & 0xFF) * (255 - a)) / 255;
g = (lut4to8[(val >> 4) & 0xf] * a + ((bannerBGColor >> 8) & 0xFF) * (255 - a)) / 255;
b = (lut4to8[(val) & 0xf] * a + ((bannerBGColor >> 16) & 0xFF) * (255 - a)) / 255;
a = 0xFF;
}
return((a << 24) | (r << 16) | (g << 8) | b);
}
void
CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height)
{
for (int y = 0; y < height; y += 4)
{
for (int x = 0; x < width; x += 4)
{
for (int iy = 0; iy < 4; iy++, src += 4)
{
for (int ix = 0; ix < 4; ix++)
{
u32 RGBA = decode5A3(Common::swap16(src[ix]));
dst[(y + iy) * width + (x + ix)] = RGBA;
}
}
}
}
}
} // namespace

View File

@ -43,10 +43,40 @@ class CBannerLoaderWii
private:
#define WII_BANNER_TEXTURE_SIZE (192 * 64 * 2)
#define WII_BANNER_ICON_SIZE ( 48 * 48 * 2)
#define WII_BANNER_COMMENT_SIZE 32
struct SWiiBanner
{
u32 ID;
u32 m_Flag;
u16 m_Speed;
u8 m_Unknown[22];
u16 m_Comment[2][WII_BANNER_COMMENT_SIZE];
u8 m_BannerTexture[WII_BANNER_TEXTURE_SIZE];
u8 m_IconTexture[8][WII_BANNER_ICON_SIZE];
} ;
// for banner decoding
int lut3to8[8];
int lut4to8[16];
int lut5to8[32];
std::string m_Name;
u8* m_pBuffer;
u8* m_pBannerFile;
bool m_IsValid;
void InitLUTTable();
u32 decode5A3(u16 val);
void decode5A3image(u32* dst, u16* src, int width, int height);
std::string StupidWideCharToString(u16* _pSrc, size_t _max);
};
} // namespace