From 046ca53f8c0827d37f5f7e009e0c3e2dfec74a10 Mon Sep 17 00:00:00 2001 From: "fires.gc" Date: Sat, 1 Nov 2008 15:59:06 +0000 Subject: [PATCH] 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 --- Source/Core/Common/Src/FileSearch.cpp | 12 +- Source/Core/Common/Src/FileUtil.cpp | 28 ++- Source/Core/Common/Src/FileUtil.h | 2 + .../Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp | 35 ++-- .../Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp | 190 ++++++++++++++---- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.h | 3 + Source/Core/DiscIO/Src/BannerLoader.cpp | 1 + Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 190 ++++++++++++++---- Source/Core/DiscIO/Src/BannerLoaderWii.h | 32 ++- 9 files changed, 391 insertions(+), 102 deletions(-) diff --git a/Source/Core/Common/Src/FileSearch.cpp b/Source/Core/Common/Src/FileSearch.cpp index 6ada69d79b..95df8a0ba8 100644 --- a/Source/Core/Common/Src/FileSearch.cpp +++ b/Source/Core/Common/Src/FileSearch.cpp @@ -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; } diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 742ec097ee..bc141a5517 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -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 diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index fac0486251..42fd731b37 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -35,6 +35,7 @@ struct FSTEntry std::vector 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); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index 587f8aaf13..c5337c9304 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -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"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index 2d9a78e214..2b833dca0d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -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; iRead(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 diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index 9ed9f21fdc..d0f253bcfe 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -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