diff options
Diffstat (limited to 'Source/Core/DiscIO')
| -rw-r--r-- | Source/Core/DiscIO/Src/BannerLoader.cpp | 206 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/BannerLoaderGC.cpp | 386 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 448 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/Blob.cpp | 220 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/CompressedBlob.cpp | 684 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/DriveBlob.cpp | 50 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/FileBlob.cpp | 220 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/FileHandlerARC.cpp | 474 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/FileSystemGCWii.cpp | 498 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/Filesystem.cpp | 100 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/VolumeCreator.cpp | 524 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/VolumeDirectory.cpp | 932 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/VolumeGC.cpp | 338 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp | 508 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Src/stdafx.cpp | 42 |
15 files changed, 2815 insertions, 2815 deletions
diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index a0ec090973..60cee599b0 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -1,103 +1,103 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-#include "stdafx.h"
-
-#include "BannerLoader.h"
-#include "BannerLoaderWii.h"
-#include "BannerLoaderGC.h"
-
-#include "VolumeCreator.h"
-#include "FileUtil.h"
-
-namespace DiscIO
-{
-bool IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src)
-{
- static bool bValidChars[256];
- static bool bInitialized = false;
-
- if (!bInitialized)
- {
- for (int i = 0; i < 256; i++)
- {
- bValidChars[i] = false;
- }
-
- // generate valid chars
- for (unsigned char c = 0x20; c <= 0x80; c++)
- {
- bValidChars[c] = true;
- }
-
- bValidChars[0x0a] = true;
- bValidChars[0xa9] = true;
- bValidChars[0xe9] = true;
-
- bInitialized = true;
- }
-
- bool bResult = true;
- char destBuffer[2048];
- char* dest = destBuffer;
- const char* src = _src;
-
- // copy the string and check for "unknown" characters
- while (*src != 0x00)
- {
- u8 c = *src;
-
- if (c == 0x0a){c = 0x20;}
-
- if (bValidChars[c] == false)
- {
- bResult = false;
- break;
- }
-
- *dest = c;
- dest++;
- src++;
- }
-
- // finalize the string
- if (bResult)
- {
- *dest = 0x00;
- }
- else
- {
- dest[0] = ' ';
- dest[1] = 0x00;
- }
-
- _rDestination = destBuffer;
-
- return(bResult);
-}
-
-
-IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem)
-{
- if (IsVolumeWiiDisc(_rFileSystem.GetVolume()))
- {
- return(new CBannerLoaderWii(_rFileSystem));
- }
-
- return(new CBannerLoaderGC(_rFileSystem));
-}
-} // namespace
-
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "stdafx.h" + +#include "BannerLoader.h" +#include "BannerLoaderWii.h" +#include "BannerLoaderGC.h" + +#include "VolumeCreator.h" +#include "FileUtil.h" + +namespace DiscIO +{ +bool IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src) +{ + static bool bValidChars[256]; + static bool bInitialized = false; + + if (!bInitialized) + { + for (int i = 0; i < 256; i++) + { + bValidChars[i] = false; + } + + // generate valid chars + for (unsigned char c = 0x20; c <= 0x80; c++) + { + bValidChars[c] = true; + } + + bValidChars[0x0a] = true; + bValidChars[0xa9] = true; + bValidChars[0xe9] = true; + + bInitialized = true; + } + + bool bResult = true; + char destBuffer[2048]; + char* dest = destBuffer; + const char* src = _src; + + // copy the string and check for "unknown" characters + while (*src != 0x00) + { + u8 c = *src; + + if (c == 0x0a){c = 0x20;} + + if (bValidChars[c] == false) + { + bResult = false; + break; + } + + *dest = c; + dest++; + src++; + } + + // finalize the string + if (bResult) + { + *dest = 0x00; + } + else + { + dest[0] = ' '; + dest[1] = 0x00; + } + + _rDestination = destBuffer; + + return(bResult); +} + + +IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem) +{ + if (IsVolumeWiiDisc(_rFileSystem.GetVolume())) + { + return(new CBannerLoaderWii(_rFileSystem)); + } + + return(new CBannerLoaderGC(_rFileSystem)); +} +} // namespace + diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp index 9e897c22d8..2480739979 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp @@ -1,193 +1,193 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include "BannerLoaderGC.h"
-
-namespace DiscIO
-{
-CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem)
- : m_pBannerFile(NULL),
- m_IsValid(false)
-{
- // 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;
- }
-
- // load the opening.bnr
- size_t FileSize = _rFileSystem.GetFileSize("opening.bnr");
-
- if (FileSize > 0)
- {
- m_pBannerFile = new u8[FileSize];
- _rFileSystem.ReadFile("opening.bnr", m_pBannerFile, FileSize);
- m_IsValid = true;
- }
-}
-
-
-CBannerLoaderGC::~CBannerLoaderGC()
-{
- delete [] m_pBannerFile;
- m_pBannerFile = NULL;
-}
-
-
-bool
-CBannerLoaderGC::IsValid()
-{
- return(m_IsValid);
-}
-
-
-bool
-CBannerLoaderGC::GetBanner(u32* _pBannerImage)
-{
- if (!IsValid())
- {
- return(false);
- }
-
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
- decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT);
-
- return(true);
-}
-
-
-bool
-CBannerLoaderGC::GetName(std::string& _rName, int language)
-{
- _rName = "invalid image";
-
- if (!IsValid())
- {
- return(false);
- }
-
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
-
- if (!CopyToStringAndCheck(_rName, language != 0 ? pBanner->comment[0].shortTitle : pBanner->comment[0].longTitle))
- {
- return(false);
- }
-
- return(true);
-}
-
-
-bool
-CBannerLoaderGC::GetCompany(std::string& _rCompany)
-{
- _rCompany = "invalid images";
-
- if (!IsValid())
- {
- return(false);
- }
-
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
-
- if (!CopyToStringAndCheck(_rCompany, pBanner->comment[0].shortMaker))
- {
- return(false);
- }
-
- return(true);
-}
-
-
-bool
-CBannerLoaderGC::GetDescription(std::string& _rDescription)
-{
- _rDescription = "invalid images";
-
- if (!IsValid())
- {
- return(false);
- }
-
- DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile;
-
- if (!CopyToStringAndCheck(_rDescription, pBanner->comment[0].comment))
- {
- _rDescription = "";
- }
-
- return(true);
-}
-
-
-u32
-CBannerLoaderGC::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
-CBannerLoaderGC::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
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include "BannerLoaderGC.h" + +namespace DiscIO +{ +CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem) + : m_pBannerFile(NULL), + m_IsValid(false) +{ + // 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; + } + + // load the opening.bnr + size_t FileSize = _rFileSystem.GetFileSize("opening.bnr"); + + if (FileSize > 0) + { + m_pBannerFile = new u8[FileSize]; + _rFileSystem.ReadFile("opening.bnr", m_pBannerFile, FileSize); + m_IsValid = true; + } +} + + +CBannerLoaderGC::~CBannerLoaderGC() +{ + delete [] m_pBannerFile; + m_pBannerFile = NULL; +} + + +bool +CBannerLoaderGC::IsValid() +{ + return(m_IsValid); +} + + +bool +CBannerLoaderGC::GetBanner(u32* _pBannerImage) +{ + if (!IsValid()) + { + return(false); + } + + DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); + + return(true); +} + + +bool +CBannerLoaderGC::GetName(std::string& _rName, int language) +{ + _rName = "invalid image"; + + if (!IsValid()) + { + return(false); + } + + DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + + if (!CopyToStringAndCheck(_rName, language != 0 ? pBanner->comment[0].shortTitle : pBanner->comment[0].longTitle)) + { + return(false); + } + + return(true); +} + + +bool +CBannerLoaderGC::GetCompany(std::string& _rCompany) +{ + _rCompany = "invalid images"; + + if (!IsValid()) + { + return(false); + } + + DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + + if (!CopyToStringAndCheck(_rCompany, pBanner->comment[0].shortMaker)) + { + return(false); + } + + return(true); +} + + +bool +CBannerLoaderGC::GetDescription(std::string& _rDescription) +{ + _rDescription = "invalid images"; + + if (!IsValid()) + { + return(false); + } + + DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + + if (!CopyToStringAndCheck(_rDescription, pBanner->comment[0].comment)) + { + _rDescription = ""; + } + + return(true); +} + + +u32 +CBannerLoaderGC::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 +CBannerLoaderGC::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.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index 204c1fe771..e9048fc41d 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -1,224 +1,224 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include <stdio.h>
-
-#include "Common.h"
-#include "BannerLoaderWii.h"
-#include "FileUtil.h"
-
-namespace DiscIO
-{
-CBannerLoaderWii::CBannerLoaderWii(DiscIO::IFileSystem& _rFileSystem)
- : m_pBannerFile(NULL)
- , m_IsValid(false)
-{
- InitLUTTable();
-
- char Filename[260];
- char TitleID[4];
-
- _rFileSystem.GetVolume()->Read(0, 4, (u8*)TitleID);
- sprintf(Filename, FULL_WII_USER_DIR "title/00010000/%02x%02x%02x%02x/data/banner.bin", (u8)TitleID[0], (u8)TitleID[1], (u8)TitleID[2], (u8)TitleID[3]);
-
- // load the opening.bnr
- size_t FileSize = File::GetSize(Filename);
-
- if (FileSize > 0)
- {
- m_pBannerFile = new u8[FileSize];
- FILE* pFile = fopen(Filename, "rb");
- if (pFile != NULL)
- {
- fread(m_pBannerFile, FileSize, 1, pFile);
- fclose(pFile);
- m_IsValid = true;
- }
- }
-}
-
-CBannerLoaderWii::~CBannerLoaderWii()
-{
- if (m_pBannerFile)
- {
- delete [] m_pBannerFile;
- m_pBannerFile = NULL;
- }
-}
-
-
-bool
-CBannerLoaderWii::IsValid()
-{
- return (m_IsValid);
-}
-
-
-bool
-CBannerLoaderWii::GetBanner(u32* _pBannerImage)
-{
- if (!IsValid())
- {
- return false;
- }
-
- SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
-
- static u32 Buffer[192 * 64];
- decode5A3image(Buffer, (u16*)pBanner->m_BannerTexture, 192, 64);
-
- // ugly scaling :)
- for (int y=0; y<32; y++)
- {
- for (int x=0; x<96; x++)
- {
- _pBannerImage[y*96+x] = Buffer[(y*192*2)+(x*2)];
- }
- }
-
-
- return true;
-}
-
-std::string
-CBannerLoaderWii::StupidWideCharToString(u16* _pSrc, size_t _max)
-{
- std::string temp;
-
- u32 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;
- }
-
- return true;
-}
-
-
-bool
-CBannerLoaderWii::GetCompany(std::string& _rCompany)
-{
- _rCompany = "N/A";
- return true;
-}
-
-
-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
-
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include <stdio.h> + +#include "Common.h" +#include "BannerLoaderWii.h" +#include "FileUtil.h" + +namespace DiscIO +{ +CBannerLoaderWii::CBannerLoaderWii(DiscIO::IFileSystem& _rFileSystem) + : m_pBannerFile(NULL) + , m_IsValid(false) +{ + InitLUTTable(); + + char Filename[260]; + char TitleID[4]; + + _rFileSystem.GetVolume()->Read(0, 4, (u8*)TitleID); + sprintf(Filename, FULL_WII_USER_DIR "title/00010000/%02x%02x%02x%02x/data/banner.bin", (u8)TitleID[0], (u8)TitleID[1], (u8)TitleID[2], (u8)TitleID[3]); + + // load the opening.bnr + size_t FileSize = File::GetSize(Filename); + + if (FileSize > 0) + { + m_pBannerFile = new u8[FileSize]; + FILE* pFile = fopen(Filename, "rb"); + if (pFile != NULL) + { + fread(m_pBannerFile, FileSize, 1, pFile); + fclose(pFile); + m_IsValid = true; + } + } +} + +CBannerLoaderWii::~CBannerLoaderWii() +{ + if (m_pBannerFile) + { + delete [] m_pBannerFile; + m_pBannerFile = NULL; + } +} + + +bool +CBannerLoaderWii::IsValid() +{ + return (m_IsValid); +} + + +bool +CBannerLoaderWii::GetBanner(u32* _pBannerImage) +{ + if (!IsValid()) + { + return false; + } + + SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; + + static u32 Buffer[192 * 64]; + decode5A3image(Buffer, (u16*)pBanner->m_BannerTexture, 192, 64); + + // ugly scaling :) + for (int y=0; y<32; y++) + { + for (int x=0; x<96; x++) + { + _pBannerImage[y*96+x] = Buffer[(y*192*2)+(x*2)]; + } + } + + + return true; +} + +std::string +CBannerLoaderWii::StupidWideCharToString(u16* _pSrc, size_t _max) +{ + std::string temp; + + u32 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; + } + + return true; +} + + +bool +CBannerLoaderWii::GetCompany(std::string& _rCompany) +{ + _rCompany = "N/A"; + return true; +} + + +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/Blob.cpp b/Source/Core/DiscIO/Src/Blob.cpp index f26c53ef90..c592c61c33 100644 --- a/Source/Core/DiscIO/Src/Blob.cpp +++ b/Source/Core/DiscIO/Src/Blob.cpp @@ -1,110 +1,110 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "Common.h"
-#include "FileUtil.h"
-#include "Blob.h"
-#include "CompressedBlob.h"
-#include "FileBlob.h"
-#include "DriveBlob.h"
-#include "MappedFile.h"
-
-namespace DiscIO
-{
-
-// Provides caching and split-operation-to-block-operations facilities.
-// Used for compressed blob reading and direct drive reading.
-
-void SectorReader::SetSectorSize(int blocksize)
-{
- for (int i = 0; i < CACHE_SIZE; i++)
- {
- cache[i] = new u8[blocksize];
- cache_tags[i] = (u64)(s64) - 1;
- }
- m_blocksize = blocksize;
-}
-
-SectorReader::~SectorReader() {
- for (int i = 0; i < CACHE_SIZE; i++)
- delete[] cache[i];
-}
-
-const u8 *SectorReader::GetBlockData(u64 block_num)
-{
- if (cache_tags[0] == block_num)
- {
- return cache[0];
- }
- else
- {
- GetBlock(block_num, cache[0]);
- cache_tags[0] = block_num;
- return cache[0];
- }
-}
-
-bool SectorReader::Read(u64 offset, u64 size, u8* out_ptr)
-{
- u64 startingBlock = offset / m_blocksize;
- u64 remain = size;
-
- int positionInBlock = (int)(offset % m_blocksize);
- u64 block = startingBlock;
-
- while (remain > 0)
- {
- const u8* data = GetBlockData(block);
- if (!data)
- return false;
-
- u32 toCopy = m_blocksize - positionInBlock;
- if (toCopy >= remain)
- {
- // yay, we are done!
- memcpy(out_ptr, data + positionInBlock, (size_t)remain);
- return true;
- }
- else
- {
- memcpy(out_ptr, data + positionInBlock, toCopy);
- out_ptr += toCopy;
- remain -= toCopy;
- positionInBlock = 0;
- block++;
- }
- }
- return true;
-}
-
-
-IBlobReader* CreateBlobReader(const char* filename)
-{
- //if (strlen(filename) < 4 && filename[1] == ':') // Drive, for sure.
- // return DriveReader::Create(filename);
-
- if (!File::Exists(filename))
- return 0;
-
- if (IsCompressedBlob(filename))
- return CompressedBlobReader::Create(filename);
-
- // Still here? Assume plain file.
- return PlainFileReader::Create(filename);
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "FileUtil.h" +#include "Blob.h" +#include "CompressedBlob.h" +#include "FileBlob.h" +#include "DriveBlob.h" +#include "MappedFile.h" + +namespace DiscIO +{ + +// Provides caching and split-operation-to-block-operations facilities. +// Used for compressed blob reading and direct drive reading. + +void SectorReader::SetSectorSize(int blocksize) +{ + for (int i = 0; i < CACHE_SIZE; i++) + { + cache[i] = new u8[blocksize]; + cache_tags[i] = (u64)(s64) - 1; + } + m_blocksize = blocksize; +} + +SectorReader::~SectorReader() { + for (int i = 0; i < CACHE_SIZE; i++) + delete[] cache[i]; +} + +const u8 *SectorReader::GetBlockData(u64 block_num) +{ + if (cache_tags[0] == block_num) + { + return cache[0]; + } + else + { + GetBlock(block_num, cache[0]); + cache_tags[0] = block_num; + return cache[0]; + } +} + +bool SectorReader::Read(u64 offset, u64 size, u8* out_ptr) +{ + u64 startingBlock = offset / m_blocksize; + u64 remain = size; + + int positionInBlock = (int)(offset % m_blocksize); + u64 block = startingBlock; + + while (remain > 0) + { + const u8* data = GetBlockData(block); + if (!data) + return false; + + u32 toCopy = m_blocksize - positionInBlock; + if (toCopy >= remain) + { + // yay, we are done! + memcpy(out_ptr, data + positionInBlock, (size_t)remain); + return true; + } + else + { + memcpy(out_ptr, data + positionInBlock, toCopy); + out_ptr += toCopy; + remain -= toCopy; + positionInBlock = 0; + block++; + } + } + return true; +} + + +IBlobReader* CreateBlobReader(const char* filename) +{ + //if (strlen(filename) < 4 && filename[1] == ':') // Drive, for sure. + // return DriveReader::Create(filename); + + if (!File::Exists(filename)) + return 0; + + if (IsCompressedBlob(filename)) + return CompressedBlobReader::Create(filename); + + // Still here? Assume plain file. + return PlainFileReader::Create(filename); +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/CompressedBlob.cpp b/Source/Core/DiscIO/Src/CompressedBlob.cpp index 370c8b8ede..f424b2c465 100644 --- a/Source/Core/DiscIO/Src/CompressedBlob.cpp +++ b/Source/Core/DiscIO/Src/CompressedBlob.cpp @@ -1,342 +1,342 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#ifdef _WIN32
-#include <io.h>
-#include <windows.h>
-#else
-#include <unistd.h>
-#endif
-
-#include "Common.h"
-#include "CompressedBlob.h"
-#include "FileUtil.h"
-#include "Hash.h"
-
-#ifdef _WIN32
-#include "../../../../Externals/zlib/zlib.h"
-#else
-// TODO: Include generic zlib.h
-#include "../../../../Externals/zlib/zlib.h"
-#endif
-
-namespace DiscIO
-{
-
-CompressedBlobReader::CompressedBlobReader(const char *filename)
-{
- file = fopen(filename, "rb");
- fseek(file, 0, SEEK_END);
- file_size = ftell(file);
- fseek(file, 0, SEEK_SET);
- fread(&header, sizeof(CompressedBlobHeader), 1, file);
-
- SetSectorSize(header.block_size);
-
- // cache block pointers and hashes
- block_pointers = new u64[header.num_blocks];
- fread(block_pointers, sizeof(u64), header.num_blocks, file);
- hashes = new u32[header.num_blocks];
- fread(hashes, sizeof(u32), header.num_blocks, file);
-
- data_offset = (sizeof(CompressedBlobHeader))
- + (sizeof(u64)) * header.num_blocks // skip block pointers
- + (sizeof(u32)) * header.num_blocks; // skip hashes
-
- // A compressed block is never ever longer than a decompressed block, so just header.block_size should be fine.
- // I still add some safety margin.
- zlib_buffer_size = header.block_size + 64;
- zlib_buffer = new u8[zlib_buffer_size];
- memset(zlib_buffer, 0, zlib_buffer_size);
-}
-
-CompressedBlobReader* CompressedBlobReader::Create(const char* filename)
-{
- if (IsCompressedBlob(filename))
- return new CompressedBlobReader(filename);
- else
- return 0;
-}
-
-CompressedBlobReader::~CompressedBlobReader()
-{
- delete [] zlib_buffer;
- delete [] block_pointers;
- delete [] hashes;
- fclose(file);
- file = 0;
-}
-
-// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function.
-u64 CompressedBlobReader::GetBlockCompressedSize(u64 block_num) const
-{
- u64 start = block_pointers[block_num];
- if (block_num < header.num_blocks - 1)
- return block_pointers[block_num + 1] - start;
- else if (block_num == header.num_blocks - 1)
- return header.compressed_data_size - start;
- else
- PanicAlert("GetBlockCompressedSize - illegal block number %i", (int)block_num);
- return 0;
-}
-
-void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr)
-{
- bool uncompressed = false;
- u32 comp_block_size = (u32)GetBlockCompressedSize(block_num);
- u64 offset = block_pointers[block_num] + data_offset;
-
- if (offset & (1ULL << 63))
- {
- if (comp_block_size != header.block_size)
- PanicAlert("Uncompressed block with wrong size");
- uncompressed = true;
- offset &= ~(1ULL << 63);
- }
-
- // clear unused part of zlib buffer. maybe this can be deleted when it works fully.
- memset(zlib_buffer + comp_block_size, 0, zlib_buffer_size - comp_block_size);
-
- fseek(file, offset, SEEK_SET);
- fread(zlib_buffer, 1, comp_block_size, file);
-
- u8* source = zlib_buffer;
- u8* dest = out_ptr;
-
- // First, check hash.
- u32 block_hash = HashAdler32(source, comp_block_size);
- if (block_hash != hashes[block_num])
- PanicAlert("Hash of block %i is %08x instead of %08x. Your ISO is corrupt.",
- block_num, block_hash, hashes[block_num]);
-
- if (uncompressed)
- {
- memcpy(dest, source, comp_block_size);
- }
- else
- {
- z_stream z;
- memset(&z, 0, sizeof(z));
- z.next_in = source;
- z.avail_in = comp_block_size;
- if (z.avail_in > header.block_size)
- {
- PanicAlert("We have a problem");
- }
- z.next_out = dest;
- z.avail_out = header.block_size;
- inflateInit(&z);
- int status = inflate(&z, Z_FULL_FLUSH);
- u32 uncomp_size = header.block_size - z.avail_out;
- if (status != Z_STREAM_END)
- {
- // this seem to fire wrongly from time to time
- // to be sure, don't use compressed isos :P
- PanicAlert("Failure reading block %i - out of data and not at end.", block_num);
- }
- inflateEnd(&z);
- if (uncomp_size != header.block_size)
- PanicAlert("Wrong block size");
- }
-}
-
-bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
- int block_size, CompressCB callback, void* arg)
-{
- if (File::GetSize(infile) > 2000000000ULL) {
- PanicAlert("Sorry - compressing Wii games not yet supported.");
- return false;
- }
-
- if (IsCompressedBlob(infile))
- {
- PanicAlert("%s is already compressed! Cannot compress it further.", infile);
- return false;
- }
-
- FILE* inf = fopen(infile, "rb");
- if (!inf)
- return false;
-
- FILE* f = fopen(outfile, "wb");
- if (!f)
- return false;
-
- callback("Files opened, ready to compress.", 0, arg);
-
- fseek(inf, 0, SEEK_END);
- s64 insize = ftell(inf);
- fseek(inf, 0, SEEK_SET);
- CompressedBlobHeader header;
- header.magic_cookie = kBlobCookie;
- header.sub_type = sub_type;
- header.block_size = block_size;
- header.data_size = insize;
-
- // round upwards!
- header.num_blocks = (u32)((header.data_size + (block_size - 1)) / block_size);
-
- u64* offsets = new u64[header.num_blocks];
- u32* hashes = new u32[header.num_blocks];
- u8* out_buf = new u8[block_size];
- u8* in_buf = new u8[block_size];
-
- // seek past the header (we will write it at the end)
- fseek(f, sizeof(CompressedBlobHeader), SEEK_CUR);
- // seek past the offset and hash tables (we will write them at the end)
- fseek(f, (sizeof(u64) + sizeof(u32)) * header.num_blocks, SEEK_CUR);
-
- // Now we are ready to write compressed data!
- u64 position = 0;
- int num_compressed = 0;
- int num_stored = 0;
- for (u32 i = 0; i < header.num_blocks; i++)
- {
- if (i % (header.num_blocks / 1000) == 0)
- {
- u64 inpos = ftell(inf);
- int ratio = 0;
- if (inpos != 0)
- ratio = (int)(100 * position / inpos);
- char temp[512];
- sprintf(temp, "%i of %i blocks. compression ratio %i%%", i, header.num_blocks, ratio);
- callback(temp, (float)i / (float)header.num_blocks, arg);
- }
-
- offsets[i] = position;
- // u64 start = i * header.block_size;
- // u64 size = header.block_size;
- memset(in_buf, 0, header.block_size);
- fread(in_buf, header.block_size, 1, inf);
- z_stream z;
- memset(&z, 0, sizeof(z));
- z.zalloc = Z_NULL;
- z.zfree = Z_NULL;
- z.opaque = Z_NULL;
- z.next_in = in_buf;
- z.avail_in = header.block_size;
- z.next_out = out_buf;
- z.avail_out = block_size;
- int retval = deflateInit(&z, 9);
-
- if (retval != Z_OK)
- {
- PanicAlert("Deflate failed");
- goto cleanup;
- }
-
- int status = deflate(&z, Z_FINISH);
- int comp_size = block_size - z.avail_out;
- if ((status != Z_STREAM_END) || (z.avail_out < 10))
- {
- //PanicAlert("%i %i Store %i", i*block_size, position, comp_size);
- // let's store uncompressed
- offsets[i] |= 0x8000000000000000ULL;
- fwrite(in_buf, block_size, 1, f);
- hashes[i] = HashAdler32(in_buf, block_size);
- position += block_size;
- num_stored++;
- }
- else
- {
- // let's store compressed
- //PanicAlert("Comp %i to %i", block_size, comp_size);
- fwrite(out_buf, comp_size, 1, f);
- hashes[i] = HashAdler32(out_buf, comp_size);
- position += comp_size;
- num_compressed++;
- }
-
- deflateEnd(&z);
- }
-
- header.compressed_data_size = position;
-
- // Okay, go back and fill in headers
- fseek(f, 0, SEEK_SET);
- fwrite(&header, sizeof(header), 1, f);
- fwrite(offsets, sizeof(u64), header.num_blocks, f);
- fwrite(hashes, sizeof(u32), header.num_blocks, f);
-
-cleanup:
- // Cleanup
- delete[] in_buf;
- delete[] out_buf;
- delete[] offsets;
- fclose(f);
- fclose(inf);
- callback("Done compressing disc image.", 1.0f, arg);
- return true;
-}
-
-bool DecompressBlobToFile(const char* infile, const char* outfile, CompressCB callback, void* arg)
-{
- if (!IsCompressedBlob(infile))
- {
- PanicAlert("File not compressed");
- return false;
- }
-
- CompressedBlobReader* reader = CompressedBlobReader::Create(infile);
- if (!reader) return false;
-
- FILE* f = fopen(outfile, "wb");
- const CompressedBlobHeader &header = reader->GetHeader();
- u8* buffer = new u8[header.block_size];
-
- for (u64 i = 0; i < header.num_blocks; i++)
- {
- if (i % (header.num_blocks / 100) == 0)
- {
- callback("Unpacking", (float)i / (float)header.num_blocks, arg);
- }
- reader->Read(i * header.block_size, header.block_size, buffer);
- fwrite(buffer, header.block_size, 1, f);
- }
-
- delete[] buffer;
-
-#ifdef _WIN32
- // ector: _chsize sucks, not 64-bit safe
- // F|RES: changed to _chsize_s. i think it is 64-bit safe
- _chsize_s(_fileno(f), (long)header.data_size);
-#else
- ftruncate(fileno(f), header.data_size);
-#endif
- fclose(f);
-
- delete reader;
-
- return true;
-}
-
-bool IsCompressedBlob(const char* filename)
-{
- FILE* f = fopen(filename, "rb");
-
- if (!f)
- return false;
-
- CompressedBlobHeader header;
- fread(&header, sizeof(header), 1, f);
- fclose(f);
- return header.magic_cookie == kBlobCookie;
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#ifdef _WIN32 +#include <io.h> +#include <windows.h> +#else +#include <unistd.h> +#endif + +#include "Common.h" +#include "CompressedBlob.h" +#include "FileUtil.h" +#include "Hash.h" + +#ifdef _WIN32 +#include "../../../../Externals/zlib/zlib.h" +#else +// TODO: Include generic zlib.h +#include "../../../../Externals/zlib/zlib.h" +#endif + +namespace DiscIO +{ + +CompressedBlobReader::CompressedBlobReader(const char *filename) +{ + file = fopen(filename, "rb"); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + fseek(file, 0, SEEK_SET); + fread(&header, sizeof(CompressedBlobHeader), 1, file); + + SetSectorSize(header.block_size); + + // cache block pointers and hashes + block_pointers = new u64[header.num_blocks]; + fread(block_pointers, sizeof(u64), header.num_blocks, file); + hashes = new u32[header.num_blocks]; + fread(hashes, sizeof(u32), header.num_blocks, file); + + data_offset = (sizeof(CompressedBlobHeader)) + + (sizeof(u64)) * header.num_blocks // skip block pointers + + (sizeof(u32)) * header.num_blocks; // skip hashes + + // A compressed block is never ever longer than a decompressed block, so just header.block_size should be fine. + // I still add some safety margin. + zlib_buffer_size = header.block_size + 64; + zlib_buffer = new u8[zlib_buffer_size]; + memset(zlib_buffer, 0, zlib_buffer_size); +} + +CompressedBlobReader* CompressedBlobReader::Create(const char* filename) +{ + if (IsCompressedBlob(filename)) + return new CompressedBlobReader(filename); + else + return 0; +} + +CompressedBlobReader::~CompressedBlobReader() +{ + delete [] zlib_buffer; + delete [] block_pointers; + delete [] hashes; + fclose(file); + file = 0; +} + +// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function. +u64 CompressedBlobReader::GetBlockCompressedSize(u64 block_num) const +{ + u64 start = block_pointers[block_num]; + if (block_num < header.num_blocks - 1) + return block_pointers[block_num + 1] - start; + else if (block_num == header.num_blocks - 1) + return header.compressed_data_size - start; + else + PanicAlert("GetBlockCompressedSize - illegal block number %i", (int)block_num); + return 0; +} + +void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr) +{ + bool uncompressed = false; + u32 comp_block_size = (u32)GetBlockCompressedSize(block_num); + u64 offset = block_pointers[block_num] + data_offset; + + if (offset & (1ULL << 63)) + { + if (comp_block_size != header.block_size) + PanicAlert("Uncompressed block with wrong size"); + uncompressed = true; + offset &= ~(1ULL << 63); + } + + // clear unused part of zlib buffer. maybe this can be deleted when it works fully. + memset(zlib_buffer + comp_block_size, 0, zlib_buffer_size - comp_block_size); + + fseek(file, offset, SEEK_SET); + fread(zlib_buffer, 1, comp_block_size, file); + + u8* source = zlib_buffer; + u8* dest = out_ptr; + + // First, check hash. + u32 block_hash = HashAdler32(source, comp_block_size); + if (block_hash != hashes[block_num]) + PanicAlert("Hash of block %i is %08x instead of %08x. Your ISO is corrupt.", + block_num, block_hash, hashes[block_num]); + + if (uncompressed) + { + memcpy(dest, source, comp_block_size); + } + else + { + z_stream z; + memset(&z, 0, sizeof(z)); + z.next_in = source; + z.avail_in = comp_block_size; + if (z.avail_in > header.block_size) + { + PanicAlert("We have a problem"); + } + z.next_out = dest; + z.avail_out = header.block_size; + inflateInit(&z); + int status = inflate(&z, Z_FULL_FLUSH); + u32 uncomp_size = header.block_size - z.avail_out; + if (status != Z_STREAM_END) + { + // this seem to fire wrongly from time to time + // to be sure, don't use compressed isos :P + PanicAlert("Failure reading block %i - out of data and not at end.", block_num); + } + inflateEnd(&z); + if (uncomp_size != header.block_size) + PanicAlert("Wrong block size"); + } +} + +bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type, + int block_size, CompressCB callback, void* arg) +{ + if (File::GetSize(infile) > 2000000000ULL) { + PanicAlert("Sorry - compressing Wii games not yet supported."); + return false; + } + + if (IsCompressedBlob(infile)) + { + PanicAlert("%s is already compressed! Cannot compress it further.", infile); + return false; + } + + FILE* inf = fopen(infile, "rb"); + if (!inf) + return false; + + FILE* f = fopen(outfile, "wb"); + if (!f) + return false; + + callback("Files opened, ready to compress.", 0, arg); + + fseek(inf, 0, SEEK_END); + s64 insize = ftell(inf); + fseek(inf, 0, SEEK_SET); + CompressedBlobHeader header; + header.magic_cookie = kBlobCookie; + header.sub_type = sub_type; + header.block_size = block_size; + header.data_size = insize; + + // round upwards! + header.num_blocks = (u32)((header.data_size + (block_size - 1)) / block_size); + + u64* offsets = new u64[header.num_blocks]; + u32* hashes = new u32[header.num_blocks]; + u8* out_buf = new u8[block_size]; + u8* in_buf = new u8[block_size]; + + // seek past the header (we will write it at the end) + fseek(f, sizeof(CompressedBlobHeader), SEEK_CUR); + // seek past the offset and hash tables (we will write them at the end) + fseek(f, (sizeof(u64) + sizeof(u32)) * header.num_blocks, SEEK_CUR); + + // Now we are ready to write compressed data! + u64 position = 0; + int num_compressed = 0; + int num_stored = 0; + for (u32 i = 0; i < header.num_blocks; i++) + { + if (i % (header.num_blocks / 1000) == 0) + { + u64 inpos = ftell(inf); + int ratio = 0; + if (inpos != 0) + ratio = (int)(100 * position / inpos); + char temp[512]; + sprintf(temp, "%i of %i blocks. compression ratio %i%%", i, header.num_blocks, ratio); + callback(temp, (float)i / (float)header.num_blocks, arg); + } + + offsets[i] = position; + // u64 start = i * header.block_size; + // u64 size = header.block_size; + memset(in_buf, 0, header.block_size); + fread(in_buf, header.block_size, 1, inf); + z_stream z; + memset(&z, 0, sizeof(z)); + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + z.next_in = in_buf; + z.avail_in = header.block_size; + z.next_out = out_buf; + z.avail_out = block_size; + int retval = deflateInit(&z, 9); + + if (retval != Z_OK) + { + PanicAlert("Deflate failed"); + goto cleanup; + } + + int status = deflate(&z, Z_FINISH); + int comp_size = block_size - z.avail_out; + if ((status != Z_STREAM_END) || (z.avail_out < 10)) + { + //PanicAlert("%i %i Store %i", i*block_size, position, comp_size); + // let's store uncompressed + offsets[i] |= 0x8000000000000000ULL; + fwrite(in_buf, block_size, 1, f); + hashes[i] = HashAdler32(in_buf, block_size); + position += block_size; + num_stored++; + } + else + { + // let's store compressed + //PanicAlert("Comp %i to %i", block_size, comp_size); + fwrite(out_buf, comp_size, 1, f); + hashes[i] = HashAdler32(out_buf, comp_size); + position += comp_size; + num_compressed++; + } + + deflateEnd(&z); + } + + header.compressed_data_size = position; + + // Okay, go back and fill in headers + fseek(f, 0, SEEK_SET); + fwrite(&header, sizeof(header), 1, f); + fwrite(offsets, sizeof(u64), header.num_blocks, f); + fwrite(hashes, sizeof(u32), header.num_blocks, f); + +cleanup: + // Cleanup + delete[] in_buf; + delete[] out_buf; + delete[] offsets; + fclose(f); + fclose(inf); + callback("Done compressing disc image.", 1.0f, arg); + return true; +} + +bool DecompressBlobToFile(const char* infile, const char* outfile, CompressCB callback, void* arg) +{ + if (!IsCompressedBlob(infile)) + { + PanicAlert("File not compressed"); + return false; + } + + CompressedBlobReader* reader = CompressedBlobReader::Create(infile); + if (!reader) return false; + + FILE* f = fopen(outfile, "wb"); + const CompressedBlobHeader &header = reader->GetHeader(); + u8* buffer = new u8[header.block_size]; + + for (u64 i = 0; i < header.num_blocks; i++) + { + if (i % (header.num_blocks / 100) == 0) + { + callback("Unpacking", (float)i / (float)header.num_blocks, arg); + } + reader->Read(i * header.block_size, header.block_size, buffer); + fwrite(buffer, header.block_size, 1, f); + } + + delete[] buffer; + +#ifdef _WIN32 + // ector: _chsize sucks, not 64-bit safe + // F|RES: changed to _chsize_s. i think it is 64-bit safe + _chsize_s(_fileno(f), (long)header.data_size); +#else + ftruncate(fileno(f), header.data_size); +#endif + fclose(f); + + delete reader; + + return true; +} + +bool IsCompressedBlob(const char* filename) +{ + FILE* f = fopen(filename, "rb"); + + if (!f) + return false; + + CompressedBlobHeader header; + fread(&header, sizeof(header), 1, f); + fclose(f); + return header.magic_cookie == kBlobCookie; +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp index aec48d14d0..11f99faada 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.cpp +++ b/Source/Core/DiscIO/Src/DriveBlob.cpp @@ -1,25 +1,25 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include "DriveBlob.h"
-
-namespace DiscIO
-{
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include "DriveBlob.h" + +namespace DiscIO +{ + +} // namespace diff --git a/Source/Core/DiscIO/Src/FileBlob.cpp b/Source/Core/DiscIO/Src/FileBlob.cpp index 87de28a8da..d3465140ae 100644 --- a/Source/Core/DiscIO/Src/FileBlob.cpp +++ b/Source/Core/DiscIO/Src/FileBlob.cpp @@ -1,110 +1,110 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include "Blob.h"
-#include "FileBlob.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-namespace DiscIO
-{
-
-#ifdef _WIN32
-
-PlainFileReader::PlainFileReader(HANDLE hFile_)
-{
- hFile = hFile_;
- DWORD size_low, size_high;
- size_low = GetFileSize(hFile, &size_high);
- size = ((u64)size_low) | ((u64)size_high << 32);
-}
-
-PlainFileReader* PlainFileReader::Create(const char* filename)
-{
- HANDLE hFile = CreateFile(
- filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- return new PlainFileReader(hFile);
- else
- return 0;
-}
-
-PlainFileReader::~PlainFileReader()
-{
- CloseHandle(hFile);
-}
-
-bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
-{
- LONG offset_high = (LONG)(offset >> 32);
- SetFilePointer(hFile, (DWORD)(offset & 0xFFFFFFFF), &offset_high, FILE_BEGIN);
-
- if (nbytes >= 0x100000000ULL)
- return false; // WTF, does windows really have this limitation?
-
- DWORD unused = 0;
- if (!ReadFile(hFile, out_ptr, DWORD(nbytes & 0xFFFFFFFF), &unused, NULL))
- return false;
- else
- return true;
-}
-
-#else // POSIX
-
-PlainFileReader::PlainFileReader(FILE* file__)
-{
- file_ = file__;
- #if 0
- fseek64(file_, 0, SEEK_END);
- #else
- fseek(file_, 0, SEEK_END); // I don't have fseek64 with gcc 4.3
- #endif
- size = ftell(file_);
- fseek(file_, 0, SEEK_SET);
-}
-
-PlainFileReader* PlainFileReader::Create(const char* filename)
-{
- FILE* file_ = fopen(filename, "rb");
- if (file_)
- return new PlainFileReader(file_);
- else
- return 0;
-}
-
-PlainFileReader::~PlainFileReader()
-{
- fclose(file_);
-}
-
-bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
-{
- int seekStatus = fseek(file_, offset, SEEK_SET);
- if (seekStatus != 0)
- return false;
- size_t bytesRead = fread(out_ptr, 1, nbytes, file_);
- return bytesRead == nbytes;
-}
-
-#endif
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include "Blob.h" +#include "FileBlob.h" + +#ifdef _WIN32 +#include <windows.h> +#endif + +namespace DiscIO +{ + +#ifdef _WIN32 + +PlainFileReader::PlainFileReader(HANDLE hFile_) +{ + hFile = hFile_; + DWORD size_low, size_high; + size_low = GetFileSize(hFile, &size_high); + size = ((u64)size_low) | ((u64)size_high << 32); +} + +PlainFileReader* PlainFileReader::Create(const char* filename) +{ + HANDLE hFile = CreateFile( + filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hFile != INVALID_HANDLE_VALUE) + return new PlainFileReader(hFile); + else + return 0; +} + +PlainFileReader::~PlainFileReader() +{ + CloseHandle(hFile); +} + +bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr) +{ + LONG offset_high = (LONG)(offset >> 32); + SetFilePointer(hFile, (DWORD)(offset & 0xFFFFFFFF), &offset_high, FILE_BEGIN); + + if (nbytes >= 0x100000000ULL) + return false; // WTF, does windows really have this limitation? + + DWORD unused = 0; + if (!ReadFile(hFile, out_ptr, DWORD(nbytes & 0xFFFFFFFF), &unused, NULL)) + return false; + else + return true; +} + +#else // POSIX + +PlainFileReader::PlainFileReader(FILE* file__) +{ + file_ = file__; + #if 0 + fseek64(file_, 0, SEEK_END); + #else + fseek(file_, 0, SEEK_END); // I don't have fseek64 with gcc 4.3 + #endif + size = ftell(file_); + fseek(file_, 0, SEEK_SET); +} + +PlainFileReader* PlainFileReader::Create(const char* filename) +{ + FILE* file_ = fopen(filename, "rb"); + if (file_) + return new PlainFileReader(file_); + else + return 0; +} + +PlainFileReader::~PlainFileReader() +{ + fclose(file_); +} + +bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr) +{ + int seekStatus = fseek(file_, offset, SEEK_SET); + if (seekStatus != 0) + return false; + size_t bytesRead = fread(out_ptr, 1, nbytes, file_); + return bytesRead == nbytes; +} + +#endif + +} // namespace diff --git a/Source/Core/DiscIO/Src/FileHandlerARC.cpp b/Source/Core/DiscIO/Src/FileHandlerARC.cpp index 17c7270efb..e9a7b96044 100644 --- a/Source/Core/DiscIO/Src/FileHandlerARC.cpp +++ b/Source/Core/DiscIO/Src/FileHandlerARC.cpp @@ -1,237 +1,237 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-#include "Common.h"
-
-#include "FileHandlerARC.h"
-#include "StringUtil.h"
-
-
-#define ARC_ID 0x55aa382d
-
-namespace DiscIO
-{
-CARCFile::CARCFile(const u8* _pBuffer, size_t _BufferSize)
- : m_pBuffer(NULL),
- m_Initialized(false)
-{
- m_pBuffer = new u8[_BufferSize];
-
- if (m_pBuffer)
- {
- memcpy(m_pBuffer, _pBuffer, _BufferSize);
- m_Initialized = ParseBuffer();
- }
-}
-
-
-CARCFile::~CARCFile()
-{
- delete [] m_pBuffer;
-}
-
-
-bool
-CARCFile::IsInitialized()
-{
- return(m_Initialized);
-}
-
-
-size_t
-CARCFile::GetFileSize(const std::string& _rFullPath)
-{
- if (!m_Initialized)
- {
- return(0);
- }
-
- const SFileInfo* pFileInfo = FindFileInfo(_rFullPath);
-
- if (pFileInfo != NULL)
- {
- return(pFileInfo->m_FileSize);
- }
-
- return(0);
-}
-
-
-size_t
-CARCFile::ReadFile(const std::string& _rFullPath, u8* _pBuffer, size_t _MaxBufferSize)
-{
- if (!m_Initialized)
- {
- return(0);
- }
-
- const SFileInfo* pFileInfo = FindFileInfo(_rFullPath);
-
- if (pFileInfo == NULL)
- {
- return(0);
- }
-
- if (pFileInfo->m_FileSize > _MaxBufferSize)
- {
- return(0);
- }
-
- memcpy(_pBuffer, &m_pBuffer[pFileInfo->m_Offset], pFileInfo->m_FileSize);
- return(pFileInfo->m_FileSize);
-}
-
-
-bool
-CARCFile::ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename)
-{
- if (!m_Initialized)
- {
- return(false);
- }
-
- const SFileInfo* pFileInfo = FindFileInfo(_rFullPath);
-
- if (pFileInfo == NULL)
- {
- return(false);
- }
-
- FILE* pFile = fopen(_rExportFilename.c_str(), "wb");
-
- if (pFile == NULL)
- {
- return(false);
- }
-
- fwrite(&m_pBuffer[pFileInfo->m_Offset], pFileInfo->m_FileSize, 1, pFile);
- fclose(pFile);
- return(true);
-}
-
-
-bool
-CARCFile::ExportAllFiles(const std::string& _rFullPath)
-{
- return(false);
-}
-
-
-bool
-CARCFile::ParseBuffer()
-{
- // check ID
- u32 ID = Common::swap32(*(u32*)(m_pBuffer));
-
- if (ID != ARC_ID)
- {
- return(false);
- }
-
- // read header
- u32 FSTOffset = Common::swap32(*(u32*)(m_pBuffer + 0x4));
- //u32 FSTSize = Common::swap32(*(u32*)(m_pBuffer + 0x8));
- //u32 FileOffset = Common::swap32(*(u32*)(m_pBuffer + 0xC));
-
- // read all file infos
- SFileInfo Root;
- Root.m_NameOffset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x0));
- Root.m_Offset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x4));
- Root.m_FileSize = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x8));
-
- if (Root.IsDirectory())
- {
- m_FileInfoVector.resize(Root.m_FileSize);
- const char* szNameTable = (char*)(m_pBuffer + FSTOffset);
-
- for (size_t i = 0; i < m_FileInfoVector.size(); i++)
- {
- u8* Offset = m_pBuffer + FSTOffset + (i * 0xC);
- m_FileInfoVector[i].m_NameOffset = Common::swap32(*(u32*)(Offset + 0x0));
- m_FileInfoVector[i].m_Offset = Common::swap32(*(u32*)(Offset + 0x4));
- m_FileInfoVector[i].m_FileSize = Common::swap32(*(u32*)(Offset + 0x8));
-
- szNameTable += 0xC;
- }
-
- BuildFilenames(1, m_FileInfoVector.size(), NULL, szNameTable);
- }
-
- return(true);
-}
-
-
-size_t
-CARCFile::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, const char* _szNameTable)
-{
- size_t CurrentIndex = _FirstIndex;
-
- while (CurrentIndex < _LastIndex)
- {
- SFileInfo& rFileInfo = m_FileInfoVector[CurrentIndex];
- int uOffset = rFileInfo.m_NameOffset & 0xFFFFFF;
-
- // check next index
- if (rFileInfo.IsDirectory())
- {
- // this is a directory, build up the new szDirectory
- if (_szDirectory != NULL)
- {
- sprintf(rFileInfo.m_FullPath, "%s%s\\", _szDirectory, &_szNameTable[uOffset]);
- }
- else
- {
- sprintf(rFileInfo.m_FullPath, "%s\\", &_szNameTable[uOffset]);
- }
-
- CurrentIndex = BuildFilenames(CurrentIndex + 1, rFileInfo.m_FileSize, rFileInfo.m_FullPath, _szNameTable);
- }
- else
- {
- // this is a filename
- if (_szDirectory != NULL)
- {
- sprintf(rFileInfo.m_FullPath, "%s%s", _szDirectory, &_szNameTable[uOffset]);
- }
- else
- {
- sprintf(rFileInfo.m_FullPath, "%s", &_szNameTable[uOffset]);
- }
-
- CurrentIndex++;
- }
- }
-
- return(CurrentIndex);
-}
-
-
-const SFileInfo*
-CARCFile::FindFileInfo(std::string _rFullPath) const
-{
- for (size_t i = 0; i < m_FileInfoVector.size(); i++)
- {
- if (!strcasecmp(m_FileInfoVector[i].m_FullPath, _rFullPath.c_str()))
- {
- return(&m_FileInfoVector[i]);
- }
- }
-
- return(NULL);
-}
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "Common.h" + +#include "FileHandlerARC.h" +#include "StringUtil.h" + + +#define ARC_ID 0x55aa382d + +namespace DiscIO +{ +CARCFile::CARCFile(const u8* _pBuffer, size_t _BufferSize) + : m_pBuffer(NULL), + m_Initialized(false) +{ + m_pBuffer = new u8[_BufferSize]; + + if (m_pBuffer) + { + memcpy(m_pBuffer, _pBuffer, _BufferSize); + m_Initialized = ParseBuffer(); + } +} + + +CARCFile::~CARCFile() +{ + delete [] m_pBuffer; +} + + +bool +CARCFile::IsInitialized() +{ + return(m_Initialized); +} + + +size_t +CARCFile::GetFileSize(const std::string& _rFullPath) +{ + if (!m_Initialized) + { + return(0); + } + + const SFileInfo* pFileInfo = FindFileInfo(_rFullPath); + + if (pFileInfo != NULL) + { + return(pFileInfo->m_FileSize); + } + + return(0); +} + + +size_t +CARCFile::ReadFile(const std::string& _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) +{ + if (!m_Initialized) + { + return(0); + } + + const SFileInfo* pFileInfo = FindFileInfo(_rFullPath); + + if (pFileInfo == NULL) + { + return(0); + } + + if (pFileInfo->m_FileSize > _MaxBufferSize) + { + return(0); + } + + memcpy(_pBuffer, &m_pBuffer[pFileInfo->m_Offset], pFileInfo->m_FileSize); + return(pFileInfo->m_FileSize); +} + + +bool +CARCFile::ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename) +{ + if (!m_Initialized) + { + return(false); + } + + const SFileInfo* pFileInfo = FindFileInfo(_rFullPath); + + if (pFileInfo == NULL) + { + return(false); + } + + FILE* pFile = fopen(_rExportFilename.c_str(), "wb"); + + if (pFile == NULL) + { + return(false); + } + + fwrite(&m_pBuffer[pFileInfo->m_Offset], pFileInfo->m_FileSize, 1, pFile); + fclose(pFile); + return(true); +} + + +bool +CARCFile::ExportAllFiles(const std::string& _rFullPath) +{ + return(false); +} + + +bool +CARCFile::ParseBuffer() +{ + // check ID + u32 ID = Common::swap32(*(u32*)(m_pBuffer)); + + if (ID != ARC_ID) + { + return(false); + } + + // read header + u32 FSTOffset = Common::swap32(*(u32*)(m_pBuffer + 0x4)); + //u32 FSTSize = Common::swap32(*(u32*)(m_pBuffer + 0x8)); + //u32 FileOffset = Common::swap32(*(u32*)(m_pBuffer + 0xC)); + + // read all file infos + SFileInfo Root; + Root.m_NameOffset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x0)); + Root.m_Offset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x4)); + Root.m_FileSize = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x8)); + + if (Root.IsDirectory()) + { + m_FileInfoVector.resize(Root.m_FileSize); + const char* szNameTable = (char*)(m_pBuffer + FSTOffset); + + for (size_t i = 0; i < m_FileInfoVector.size(); i++) + { + u8* Offset = m_pBuffer + FSTOffset + (i * 0xC); + m_FileInfoVector[i].m_NameOffset = Common::swap32(*(u32*)(Offset + 0x0)); + m_FileInfoVector[i].m_Offset = Common::swap32(*(u32*)(Offset + 0x4)); + m_FileInfoVector[i].m_FileSize = Common::swap32(*(u32*)(Offset + 0x8)); + + szNameTable += 0xC; + } + + BuildFilenames(1, m_FileInfoVector.size(), NULL, szNameTable); + } + + return(true); +} + + +size_t +CARCFile::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, const char* _szNameTable) +{ + size_t CurrentIndex = _FirstIndex; + + while (CurrentIndex < _LastIndex) + { + SFileInfo& rFileInfo = m_FileInfoVector[CurrentIndex]; + int uOffset = rFileInfo.m_NameOffset & 0xFFFFFF; + + // check next index + if (rFileInfo.IsDirectory()) + { + // this is a directory, build up the new szDirectory + if (_szDirectory != NULL) + { + sprintf(rFileInfo.m_FullPath, "%s%s\\", _szDirectory, &_szNameTable[uOffset]); + } + else + { + sprintf(rFileInfo.m_FullPath, "%s\\", &_szNameTable[uOffset]); + } + + CurrentIndex = BuildFilenames(CurrentIndex + 1, rFileInfo.m_FileSize, rFileInfo.m_FullPath, _szNameTable); + } + else + { + // this is a filename + if (_szDirectory != NULL) + { + sprintf(rFileInfo.m_FullPath, "%s%s", _szDirectory, &_szNameTable[uOffset]); + } + else + { + sprintf(rFileInfo.m_FullPath, "%s", &_szNameTable[uOffset]); + } + + CurrentIndex++; + } + } + + return(CurrentIndex); +} + + +const SFileInfo* +CARCFile::FindFileInfo(std::string _rFullPath) const +{ + for (size_t i = 0; i < m_FileInfoVector.size(); i++) + { + if (!strcasecmp(m_FileInfoVector[i].m_FullPath, _rFullPath.c_str())) + { + return(&m_FileInfoVector[i]); + } + } + + return(NULL); +} +} // namespace diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index a06b55836e..13376e447c 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -1,249 +1,249 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-#include "Common.h"
-
-#include <string>
-
-#include "FileSystemGCWii.h"
-#include "StringUtil.h"
-
-namespace DiscIO
-{
-CFileSystemGCWii::CFileSystemGCWii(const IVolume *_rVolume)
- : IFileSystem(_rVolume),
- m_Initialized(false),
- m_OffsetShift(0)
-{
- m_Initialized = InitFileSystem();
-}
-
-
-CFileSystemGCWii::~CFileSystemGCWii()
-{
-}
-
-bool CFileSystemGCWii::IsInitialized() const
-{
- return m_Initialized;
-}
-
-u64 CFileSystemGCWii::GetFileSize(const char* _rFullPath) const
-{
- if (!m_Initialized)
- return 0;
-
- const SFileInfo* pFileInfo = FindFileInfo(_rFullPath);
-
- if (pFileInfo != NULL)
- return pFileInfo->m_FileSize;
-
- return 0;
-}
-
-const char* CFileSystemGCWii::GetFileName(u64 _Address) const
-{
- for (size_t i = 0; i < m_FileInfoVector.size(); i++)
- {
- if ((m_FileInfoVector[i].m_Offset <= _Address) &&
- ((m_FileInfoVector[i].m_Offset + m_FileInfoVector[i].m_FileSize) > _Address))
- {
- return m_FileInfoVector[i].m_FullPath;
- }
- }
-
- return NULL;
-}
-
-u64 CFileSystemGCWii::ReadFile(const char* _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) const
-{
- if (!m_Initialized)
- return 0;
-
- const SFileInfo* pFileInfo = FindFileInfo(_rFullPath);
- if (pFileInfo == NULL)
- return 0;
-
- if (pFileInfo->m_FileSize > _MaxBufferSize)
- return 0;
-
- m_rVolume->Read(pFileInfo->m_Offset, pFileInfo->m_FileSize, _pBuffer);
- return pFileInfo->m_FileSize;
-}
-
-bool CFileSystemGCWii::ExportFile(const char* _rFullPath, const char* _rExportFilename) const
-{
- size_t filesize = GetFileSize(_rFullPath);
-
- if (filesize == 0)
- return false;
-
- u8* buffer = new u8[filesize];
-
- if (!ReadFile(_rFullPath, buffer, filesize))
- {
- delete[] buffer;
- return false;
- }
-
- FILE* f = fopen(_rExportFilename, "wb");
-
- if (f)
- {
- fwrite(buffer, filesize, 1, f);
- fclose(f);
- delete[] buffer;
- return true;
- }
-
- delete[] buffer;
- return false;
-}
-
-bool CFileSystemGCWii::ExportAllFiles(const char* _rFullPath) const
-{
- return false;
-}
-
-u32 CFileSystemGCWii::Read32(u64 _Offset) const
-{
- u32 Temp = 0;
- m_rVolume->Read(_Offset, 4, (u8*)&Temp);
- return Common::swap32(Temp);
-}
-
-void CFileSystemGCWii::GetStringFromOffset(u64 _Offset, char* Filename) const
-{
- m_rVolume->Read(_Offset, 255, (u8*)Filename);
-}
-
-size_t CFileSystemGCWii::GetFileList(std::vector<const SFileInfo *> &_rFilenames) const
-{
- if (_rFilenames.size())
- PanicAlert("GetFileList : input list has contents?");
- _rFilenames.clear();
- _rFilenames.reserve(m_FileInfoVector.size());
- for (size_t i = 0; i < m_FileInfoVector.size(); i++)
- _rFilenames.push_back(&m_FileInfoVector[i]);
- return m_FileInfoVector.size();
-}
-
-const SFileInfo* CFileSystemGCWii::FindFileInfo(const char* _rFullPath) const
-{
- for (size_t i = 0; i < m_FileInfoVector.size(); i++)
- {
- if (!strcasecmp(m_FileInfoVector[i].m_FullPath, _rFullPath))
- return &m_FileInfoVector[i];
- }
-
- return NULL;
-}
-
-bool CFileSystemGCWii::InitFileSystem()
-{
- if (Read32(0x18) == 0x5D1C9EA3)
- {
- m_OffsetShift = 2; // Wii file system
- }
- else if (Read32(0x1c) == 0xC2339F3D)
- {
- m_OffsetShift = 0; // GC file system
- }
- else
- {
- return false;
- }
-
- // read the whole FST
- u64 FSTOffset = (u64)Read32(0x424) << m_OffsetShift;
- // u32 FSTSize = Read32(0x428);
- // u32 FSTMaxSize = Read32(0x42C);
-
-
- // read all fileinfos
- SFileInfo Root;
- Root.m_NameOffset = Read32(FSTOffset + 0x0);
- Root.m_Offset = (u64)Read32(FSTOffset + 0x4) << m_OffsetShift;
- Root.m_FileSize = Read32(FSTOffset + 0x8);
-
- if (Root.IsDirectory())
- {
- if (m_FileInfoVector.size())
- PanicAlert("Wtf?");
- u64 NameTableOffset = FSTOffset;
-
- m_FileInfoVector.reserve(Root.m_FileSize);
- for (u32 i = 0; i < Root.m_FileSize; i++)
- {
- SFileInfo sfi;
- u64 Offset = FSTOffset + (i * 0xC);
- sfi.m_NameOffset = Read32(Offset + 0x0);
- sfi.m_Offset = (u64)Read32(Offset + 0x4) << m_OffsetShift;
- sfi.m_FileSize = Read32(Offset + 0x8);
-
- m_FileInfoVector.push_back(sfi);
- NameTableOffset += 0xC;
- }
-
- BuildFilenames(1, m_FileInfoVector.size(), NULL, NameTableOffset);
- }
-
- return true;
-}
-
-// Changed this stuff from C++ string to C strings for speed in debug mode. Doesn't matter in release, but
-// std::string is SLOW in debug mode.
-size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, u64 _NameTableOffset)
-{
- size_t CurrentIndex = _FirstIndex;
-
- while (CurrentIndex < _LastIndex)
- {
- SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex];
- u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF);
- char filename[512];
- memset(filename, 0, sizeof(filename));
- GetStringFromOffset(uOffset, filename);
-
- // check next index
- if (rFileInfo->IsDirectory())
- {
- // this is a directory, build up the new szDirectory
- if (_szDirectory != NULL)
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s\\", _szDirectory, filename);
- else
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s\\", filename);
-
- CurrentIndex = BuildFilenames(CurrentIndex + 1, rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset);
- }
- else
- {
- // this is a filename
- if (_szDirectory != NULL)
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename);
- else
- CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename);
-
- CurrentIndex++;
- }
- }
-
- return CurrentIndex;
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "Common.h" + +#include <string> + +#include "FileSystemGCWii.h" +#include "StringUtil.h" + +namespace DiscIO +{ +CFileSystemGCWii::CFileSystemGCWii(const IVolume *_rVolume) + : IFileSystem(_rVolume), + m_Initialized(false), + m_OffsetShift(0) +{ + m_Initialized = InitFileSystem(); +} + + +CFileSystemGCWii::~CFileSystemGCWii() +{ +} + +bool CFileSystemGCWii::IsInitialized() const +{ + return m_Initialized; +} + +u64 CFileSystemGCWii::GetFileSize(const char* _rFullPath) const +{ + if (!m_Initialized) + return 0; + + const SFileInfo* pFileInfo = FindFileInfo(_rFullPath); + + if (pFileInfo != NULL) + return pFileInfo->m_FileSize; + + return 0; +} + +const char* CFileSystemGCWii::GetFileName(u64 _Address) const +{ + for (size_t i = 0; i < m_FileInfoVector.size(); i++) + { + if ((m_FileInfoVector[i].m_Offset <= _Address) && + ((m_FileInfoVector[i].m_Offset + m_FileInfoVector[i].m_FileSize) > _Address)) + { + return m_FileInfoVector[i].m_FullPath; + } + } + + return NULL; +} + +u64 CFileSystemGCWii::ReadFile(const char* _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) const +{ + if (!m_Initialized) + return 0; + + const SFileInfo* pFileInfo = FindFileInfo(_rFullPath); + if (pFileInfo == NULL) + return 0; + + if (pFileInfo->m_FileSize > _MaxBufferSize) + return 0; + + m_rVolume->Read(pFileInfo->m_Offset, pFileInfo->m_FileSize, _pBuffer); + return pFileInfo->m_FileSize; +} + +bool CFileSystemGCWii::ExportFile(const char* _rFullPath, const char* _rExportFilename) const +{ + size_t filesize = GetFileSize(_rFullPath); + + if (filesize == 0) + return false; + + u8* buffer = new u8[filesize]; + + if (!ReadFile(_rFullPath, buffer, filesize)) + { + delete[] buffer; + return false; + } + + FILE* f = fopen(_rExportFilename, "wb"); + + if (f) + { + fwrite(buffer, filesize, 1, f); + fclose(f); + delete[] buffer; + return true; + } + + delete[] buffer; + return false; +} + +bool CFileSystemGCWii::ExportAllFiles(const char* _rFullPath) const +{ + return false; +} + +u32 CFileSystemGCWii::Read32(u64 _Offset) const +{ + u32 Temp = 0; + m_rVolume->Read(_Offset, 4, (u8*)&Temp); + return Common::swap32(Temp); +} + +void CFileSystemGCWii::GetStringFromOffset(u64 _Offset, char* Filename) const +{ + m_rVolume->Read(_Offset, 255, (u8*)Filename); +} + +size_t CFileSystemGCWii::GetFileList(std::vector<const SFileInfo *> &_rFilenames) const +{ + if (_rFilenames.size()) + PanicAlert("GetFileList : input list has contents?"); + _rFilenames.clear(); + _rFilenames.reserve(m_FileInfoVector.size()); + for (size_t i = 0; i < m_FileInfoVector.size(); i++) + _rFilenames.push_back(&m_FileInfoVector[i]); + return m_FileInfoVector.size(); +} + +const SFileInfo* CFileSystemGCWii::FindFileInfo(const char* _rFullPath) const +{ + for (size_t i = 0; i < m_FileInfoVector.size(); i++) + { + if (!strcasecmp(m_FileInfoVector[i].m_FullPath, _rFullPath)) + return &m_FileInfoVector[i]; + } + + return NULL; +} + +bool CFileSystemGCWii::InitFileSystem() +{ + if (Read32(0x18) == 0x5D1C9EA3) + { + m_OffsetShift = 2; // Wii file system + } + else if (Read32(0x1c) == 0xC2339F3D) + { + m_OffsetShift = 0; // GC file system + } + else + { + return false; + } + + // read the whole FST + u64 FSTOffset = (u64)Read32(0x424) << m_OffsetShift; + // u32 FSTSize = Read32(0x428); + // u32 FSTMaxSize = Read32(0x42C); + + + // read all fileinfos + SFileInfo Root; + Root.m_NameOffset = Read32(FSTOffset + 0x0); + Root.m_Offset = (u64)Read32(FSTOffset + 0x4) << m_OffsetShift; + Root.m_FileSize = Read32(FSTOffset + 0x8); + + if (Root.IsDirectory()) + { + if (m_FileInfoVector.size()) + PanicAlert("Wtf?"); + u64 NameTableOffset = FSTOffset; + + m_FileInfoVector.reserve(Root.m_FileSize); + for (u32 i = 0; i < Root.m_FileSize; i++) + { + SFileInfo sfi; + u64 Offset = FSTOffset + (i * 0xC); + sfi.m_NameOffset = Read32(Offset + 0x0); + sfi.m_Offset = (u64)Read32(Offset + 0x4) << m_OffsetShift; + sfi.m_FileSize = Read32(Offset + 0x8); + + m_FileInfoVector.push_back(sfi); + NameTableOffset += 0xC; + } + + BuildFilenames(1, m_FileInfoVector.size(), NULL, NameTableOffset); + } + + return true; +} + +// Changed this stuff from C++ string to C strings for speed in debug mode. Doesn't matter in release, but +// std::string is SLOW in debug mode. +size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, u64 _NameTableOffset) +{ + size_t CurrentIndex = _FirstIndex; + + while (CurrentIndex < _LastIndex) + { + SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex]; + u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF); + char filename[512]; + memset(filename, 0, sizeof(filename)); + GetStringFromOffset(uOffset, filename); + + // check next index + if (rFileInfo->IsDirectory()) + { + // this is a directory, build up the new szDirectory + if (_szDirectory != NULL) + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s\\", _szDirectory, filename); + else + CharArrayFromFormat(rFileInfo->m_FullPath, "%s\\", filename); + + CurrentIndex = BuildFilenames(CurrentIndex + 1, rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset); + } + else + { + // this is a filename + if (_szDirectory != NULL) + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename); + else + CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename); + + CurrentIndex++; + } + } + + return CurrentIndex; +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/Filesystem.cpp b/Source/Core/DiscIO/Src/Filesystem.cpp index 39bf82e822..5118c8e7b2 100644 --- a/Source/Core/DiscIO/Src/Filesystem.cpp +++ b/Source/Core/DiscIO/Src/Filesystem.cpp @@ -1,50 +1,50 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-#include "Filesystem.h"
-
-#include "VolumeCreator.h"
-#include "FileSystemGCWii.h"
-
-namespace DiscIO
-{
-IFileSystem::IFileSystem(const IVolume *_rVolume)
- : m_rVolume(_rVolume)
-{}
-
-
-IFileSystem::~IFileSystem()
-{}
-
-
-IFileSystem* CreateFileSystem(const IVolume* _rVolume)
-{
- IFileSystem* pFileSystem = new CFileSystemGCWii(_rVolume);
-
- if (!pFileSystem)
- return 0;
-
- if (!pFileSystem->IsInitialized())
- {
- delete pFileSystem;
- pFileSystem = NULL;
- }
-
- return pFileSystem;
-}
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" +#include "Filesystem.h" + +#include "VolumeCreator.h" +#include "FileSystemGCWii.h" + +namespace DiscIO +{ +IFileSystem::IFileSystem(const IVolume *_rVolume) + : m_rVolume(_rVolume) +{} + + +IFileSystem::~IFileSystem() +{} + + +IFileSystem* CreateFileSystem(const IVolume* _rVolume) +{ + IFileSystem* pFileSystem = new CFileSystemGCWii(_rVolume); + + if (!pFileSystem) + return 0; + + if (!pFileSystem->IsInitialized()) + { + delete pFileSystem; + pFileSystem = NULL; + } + + return pFileSystem; +} +} // namespace diff --git a/Source/Core/DiscIO/Src/VolumeCreator.cpp b/Source/Core/DiscIO/Src/VolumeCreator.cpp index 319af6b7d9..2ff5e8471b 100644 --- a/Source/Core/DiscIO/Src/VolumeCreator.cpp +++ b/Source/Core/DiscIO/Src/VolumeCreator.cpp @@ -1,262 +1,262 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include <vector>
-
-#include "AES/aes.h"
-
-#include "VolumeCreator.h"
-
-#include "Volume.h"
-#include "VolumeDirectory.h"
-#include "VolumeGC.h"
-#include "VolumeWiiCrypted.h"
-
-#include "Hash.h"
-
-namespace DiscIO
-{
-enum EDiscType
-{
- DISC_TYPE_UNK,
- DISC_TYPE_WII,
- DISC_TYPE_WII_CONTAINER,
- DISC_TYPE_GC
-};
-
-#ifndef _WIN32
-struct SPartition
-{
- u64 Offset;
- u32 Type;
-}; //gcc 4.3 cries if it's local
-#endif
-
-class CBlobBigEndianReader
-{
-public:
- CBlobBigEndianReader(IBlobReader& _rReader) : m_rReader(_rReader) {}
-
- u32 Read32(u64 _Offset)
- {
- u32 Temp;
- m_rReader.Read(_Offset, 4, (u8*)&Temp);
- return(Common::swap32(Temp));
- }
-
-private:
- IBlobReader& m_rReader;
-};
-
-unsigned char g_MasterKey[16];
-bool g_MasterKeyInit = false;
-
-IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _VolumeType);
-EDiscType GetDiscType(IBlobReader& _rReader);
-
-IVolume* CreateVolumeFromFilename(const std::string& _rFilename)
-{
- IBlobReader* pReader = CreateBlobReader(_rFilename.c_str());
-
- if (pReader == NULL)
- return NULL;
-
- switch (GetDiscType(*pReader))
- {
- case DISC_TYPE_WII:
- case DISC_TYPE_GC:
- return new CVolumeGC(pReader);
-
- case DISC_TYPE_WII_CONTAINER:
- {
- IVolume* pVolume = CreateVolumeFromCryptedWiiImage(*pReader, 0);
-
- if (pVolume == NULL)
- {
- delete pReader;
- }
-
- return(pVolume);
- }
- break;
-
- case DISC_TYPE_UNK:
- default:
- delete pReader;
- return NULL;
- }
-
- // unreachable code
- return NULL;
-}
-
-IVolume* CreateVolumeFromDirectory(const std::string& _rDirectory, bool _bIsWii)
-{
- if (CVolumeDirectory::IsValidDirectory(_rDirectory))
- return new CVolumeDirectory(_rDirectory, _bIsWii);
-
- return NULL;
-}
-
-bool IsVolumeWiiDisc(const IVolume *_rVolume)
-{
- u32 MagicWord = 0;
- _rVolume->Read(0x18, 4, (u8*)&MagicWord);
-
- return (Common::swap32(MagicWord) == 0x5D1C9EA3);
-}
-
-IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _VolumeType)
-{
- if (!g_MasterKeyInit)
- {
- FILE* pT = fopen(WII_MASTERKEY_FILE, "rb");
- if (pT == NULL)
- {
- if(PanicYesNo("Can't open '" WII_MASTERKEY_FILE "'.\n If you know the key, now it's the time to paste it into '"
- WII_MASTERKEY_FILE_HEX "' before pressing [YES]."))
- {
- pT = fopen(WII_MASTERKEY_FILE_HEX, "r");
- if(pT==NULL){
- PanicAlert("could not open " WII_MASTERKEY_FILE_HEX );
- return NULL;
- }
-
- static char hexkey[32];
- if(fread(hexkey,1,32,pT)<32)
- {
- PanicAlert(WII_MASTERKEY_FILE_HEX " is not the right size" );
- fclose(pT);
- return NULL;
- }
- fclose(pT);
-
- static char binkey[16];
- char *t=hexkey;
- for(int i=0;i<16;i++)
- {
- char h[3]={*(t++),*(t++),0};
- binkey[i] = strtol(h,NULL,16);
- }
-
- pT = fopen(WII_MASTERKEY_FILE, "wb");
- if(pT==NULL){
- PanicAlert("could not open/make '" WII_MASTERKEY_FILE "' for writing!");
- return NULL;
- }
-
- fwrite(binkey,16,1,pT);
- fclose(pT);
-
- pT = fopen(WII_MASTERKEY_FILE, "rb");
- if(pT==NULL){
- PanicAlert("could not open '" WII_MASTERKEY_FILE "' for reading!\n did the file get deleted or locked after converting?");
- return NULL;
- }
- }
- else
- return NULL;
- }
-
- fread(g_MasterKey, 16, 1, pT);
- fclose(pT);
- const u32 keyhash = 0x4bc30936;
- u32 hash = HashAdler32(g_MasterKey, 16);
- if (hash != keyhash)
- PanicAlert("Your Wii disc decryption key is bad.", keyhash, hash);
- else
- g_MasterKeyInit = true;
- }
-
- CBlobBigEndianReader Reader(_rReader);
-
- u32 numPartitions = Reader.Read32(0x40000);
- u64 PartitionsOffset = (u64)Reader.Read32(0x40004) << 2;
- #ifdef _WIN32
- struct SPartition
- {
- u64 Offset;
- u32 Type;
- };
- #endif
- std::vector<SPartition> PartitionsVec;
-
- // read all partitions
- for (u32 i = 0; i < numPartitions; i++)
- {
- SPartition Partition;
- Partition.Offset = ((u64)Reader.Read32(PartitionsOffset + (i * 8) + 0)) << 2;
- Partition.Type = Reader.Read32(PartitionsOffset + (i * 8) + 4);
- PartitionsVec.push_back(Partition);
- }
-
- // find the partition with the game... type == 1 is prolly the firmware update partition
- for (size_t i = 0; i < PartitionsVec.size(); i++)
- {
- const SPartition& rPartition = PartitionsVec[i];
-
- if (rPartition.Type == _VolumeType)
- {
- u8 SubKey[16];
- _rReader.Read(rPartition.Offset + 0x1bf, 16, SubKey);
-
- u8 IV[16];
- memset(IV, 0, 16);
- _rReader.Read(rPartition.Offset + 0x44c, 8, IV);
-
- AES_KEY AES_KEY;
- AES_set_decrypt_key(g_MasterKey, 128, &AES_KEY);
-
- u8 VolumeKey[16];
- AES_cbc_encrypt(SubKey, VolumeKey, 16, &AES_KEY, IV, AES_DECRYPT);
-
- return new CVolumeWiiCrypted(&_rReader, rPartition.Offset + 0x20000, VolumeKey);
- }
- }
-
- return NULL;
-}
-
-EDiscType GetDiscType(IBlobReader& _rReader)
-{
- CBlobBigEndianReader Reader(_rReader);
-
- // check for wii
- {
- u32 MagicWord = Reader.Read32(0x18);
-
- if (MagicWord == 0x5D1C9EA3)
- {
- if (Reader.Read32(0x60) != 0)
- return(DISC_TYPE_WII);
- else
- return(DISC_TYPE_WII_CONTAINER);
- }
- }
-
- // check for GC
- {
- u32 MagicWord = Reader.Read32(0x1C);
-
- if (MagicWord == 0xC2339F3D)
- return(DISC_TYPE_GC);
- }
-
- return DISC_TYPE_UNK;
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include <vector> + +#include "AES/aes.h" + +#include "VolumeCreator.h" + +#include "Volume.h" +#include "VolumeDirectory.h" +#include "VolumeGC.h" +#include "VolumeWiiCrypted.h" + +#include "Hash.h" + +namespace DiscIO +{ +enum EDiscType +{ + DISC_TYPE_UNK, + DISC_TYPE_WII, + DISC_TYPE_WII_CONTAINER, + DISC_TYPE_GC +}; + +#ifndef _WIN32 +struct SPartition +{ + u64 Offset; + u32 Type; +}; //gcc 4.3 cries if it's local +#endif + +class CBlobBigEndianReader +{ +public: + CBlobBigEndianReader(IBlobReader& _rReader) : m_rReader(_rReader) {} + + u32 Read32(u64 _Offset) + { + u32 Temp; + m_rReader.Read(_Offset, 4, (u8*)&Temp); + return(Common::swap32(Temp)); + } + +private: + IBlobReader& m_rReader; +}; + +unsigned char g_MasterKey[16]; +bool g_MasterKeyInit = false; + +IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _VolumeType); +EDiscType GetDiscType(IBlobReader& _rReader); + +IVolume* CreateVolumeFromFilename(const std::string& _rFilename) +{ + IBlobReader* pReader = CreateBlobReader(_rFilename.c_str()); + + if (pReader == NULL) + return NULL; + + switch (GetDiscType(*pReader)) + { + case DISC_TYPE_WII: + case DISC_TYPE_GC: + return new CVolumeGC(pReader); + + case DISC_TYPE_WII_CONTAINER: + { + IVolume* pVolume = CreateVolumeFromCryptedWiiImage(*pReader, 0); + + if (pVolume == NULL) + { + delete pReader; + } + + return(pVolume); + } + break; + + case DISC_TYPE_UNK: + default: + delete pReader; + return NULL; + } + + // unreachable code + return NULL; +} + +IVolume* CreateVolumeFromDirectory(const std::string& _rDirectory, bool _bIsWii) +{ + if (CVolumeDirectory::IsValidDirectory(_rDirectory)) + return new CVolumeDirectory(_rDirectory, _bIsWii); + + return NULL; +} + +bool IsVolumeWiiDisc(const IVolume *_rVolume) +{ + u32 MagicWord = 0; + _rVolume->Read(0x18, 4, (u8*)&MagicWord); + + return (Common::swap32(MagicWord) == 0x5D1C9EA3); +} + +IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _VolumeType) +{ + if (!g_MasterKeyInit) + { + FILE* pT = fopen(WII_MASTERKEY_FILE, "rb"); + if (pT == NULL) + { + if(PanicYesNo("Can't open '" WII_MASTERKEY_FILE "'.\n If you know the key, now it's the time to paste it into '" + WII_MASTERKEY_FILE_HEX "' before pressing [YES].")) + { + pT = fopen(WII_MASTERKEY_FILE_HEX, "r"); + if(pT==NULL){ + PanicAlert("could not open " WII_MASTERKEY_FILE_HEX ); + return NULL; + } + + static char hexkey[32]; + if(fread(hexkey,1,32,pT)<32) + { + PanicAlert(WII_MASTERKEY_FILE_HEX " is not the right size" ); + fclose(pT); + return NULL; + } + fclose(pT); + + static char binkey[16]; + char *t=hexkey; + for(int i=0;i<16;i++) + { + char h[3]={*(t++),*(t++),0}; + binkey[i] = strtol(h,NULL,16); + } + + pT = fopen(WII_MASTERKEY_FILE, "wb"); + if(pT==NULL){ + PanicAlert("could not open/make '" WII_MASTERKEY_FILE "' for writing!"); + return NULL; + } + + fwrite(binkey,16,1,pT); + fclose(pT); + + pT = fopen(WII_MASTERKEY_FILE, "rb"); + if(pT==NULL){ + PanicAlert("could not open '" WII_MASTERKEY_FILE "' for reading!\n did the file get deleted or locked after converting?"); + return NULL; + } + } + else + return NULL; + } + + fread(g_MasterKey, 16, 1, pT); + fclose(pT); + const u32 keyhash = 0x4bc30936; + u32 hash = HashAdler32(g_MasterKey, 16); + if (hash != keyhash) + PanicAlert("Your Wii disc decryption key is bad.", keyhash, hash); + else + g_MasterKeyInit = true; + } + + CBlobBigEndianReader Reader(_rReader); + + u32 numPartitions = Reader.Read32(0x40000); + u64 PartitionsOffset = (u64)Reader.Read32(0x40004) << 2; + #ifdef _WIN32 + struct SPartition + { + u64 Offset; + u32 Type; + }; + #endif + std::vector<SPartition> PartitionsVec; + + // read all partitions + for (u32 i = 0; i < numPartitions; i++) + { + SPartition Partition; + Partition.Offset = ((u64)Reader.Read32(PartitionsOffset + (i * 8) + 0)) << 2; + Partition.Type = Reader.Read32(PartitionsOffset + (i * 8) + 4); + PartitionsVec.push_back(Partition); + } + + // find the partition with the game... type == 1 is prolly the firmware update partition + for (size_t i = 0; i < PartitionsVec.size(); i++) + { + const SPartition& rPartition = PartitionsVec[i]; + + if (rPartition.Type == _VolumeType) + { + u8 SubKey[16]; + _rReader.Read(rPartition.Offset + 0x1bf, 16, SubKey); + + u8 IV[16]; + memset(IV, 0, 16); + _rReader.Read(rPartition.Offset + 0x44c, 8, IV); + + AES_KEY AES_KEY; + AES_set_decrypt_key(g_MasterKey, 128, &AES_KEY); + + u8 VolumeKey[16]; + AES_cbc_encrypt(SubKey, VolumeKey, 16, &AES_KEY, IV, AES_DECRYPT); + + return new CVolumeWiiCrypted(&_rReader, rPartition.Offset + 0x20000, VolumeKey); + } + } + + return NULL; +} + +EDiscType GetDiscType(IBlobReader& _rReader) +{ + CBlobBigEndianReader Reader(_rReader); + + // check for wii + { + u32 MagicWord = Reader.Read32(0x18); + + if (MagicWord == 0x5D1C9EA3) + { + if (Reader.Read32(0x60) != 0) + return(DISC_TYPE_WII); + else + return(DISC_TYPE_WII_CONTAINER); + } + } + + // check for GC + { + u32 MagicWord = Reader.Read32(0x1C); + + if (MagicWord == 0xC2339F3D) + return(DISC_TYPE_GC); + } + + return DISC_TYPE_UNK; +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.cpp b/Source/Core/DiscIO/Src/VolumeDirectory.cpp index 0b9396fa61..ff7f883636 100644 --- a/Source/Core/DiscIO/Src/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/Src/VolumeDirectory.cpp @@ -1,466 +1,466 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-#include "stdafx.h"
-
-#include "VolumeDirectory.h"
-#include "FileBlob.h"
-
-namespace DiscIO
-{
-
-static const u8 ENTRY_SIZE = 0x0c;
-static const u8 FILE_ENTRY = 0;
-static const u8 DIRECTORY_ENTRY = 1;
-static const u64 FST_ADDRESS = 0x440;
-static const u32 MAX_NAME_LENGTH = 0x3df;
-
-CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii)
- : m_totalNameSize(0)
- , m_dataStartAddress(-1)
- , m_fstSize(0)
- , m_FSTData(NULL)
-{
- m_rootDirectory = ExtractDirectoryName(_rDirectory);
-
- // create the default disk header
- m_diskHeader = new u8[FST_ADDRESS];
- memset(m_diskHeader, 0, (size_t)FST_ADDRESS);
- SetUniqueID("RZDE01");
- SetName("Default name");
-
- if(_bIsWii)
- {
- SetDiskTypeWii();
- }
- else
- {
- SetDiskTypeGC();
- }
-
- BuildFST();
-}
-
-CVolumeDirectory::~CVolumeDirectory()
-{
- delete m_FSTData;
- m_FSTData = NULL;
-
- delete m_diskHeader;
- m_diskHeader = NULL;
-}
-
-bool CVolumeDirectory::IsValidDirectory(const std::string& _rDirectory)
-{
- std::string directoryName = ExtractDirectoryName(_rDirectory);
- return File::IsDirectory(directoryName.c_str());
-}
-
-bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
-{
- if(_Offset < FST_ADDRESS)
- {
- WriteToBuffer(0, FST_ADDRESS, m_diskHeader, _Offset, _Length, _pBuffer);
- }
-
- if(_Offset < m_dataStartAddress)
- {
- WriteToBuffer(FST_ADDRESS, m_fstSize, m_FSTData, _Offset, _Length, _pBuffer);
- }
-
- if(m_virtualDisk.size() == 0)
- return true;
-
- // Determine which file the offset refers to
- std::map<u64, std::string>::const_iterator fileIter = m_virtualDisk.lower_bound(_Offset);
- if(fileIter->first > _Offset && fileIter != m_virtualDisk.begin())
- --fileIter;
-
- // zero fill to start of file data
- PadToAddress(fileIter->first, _Offset, _Length, _pBuffer);
-
- while(fileIter != m_virtualDisk.end() && _Length > 0)
- {
- _dbg_assert_(DVDINTERFACE, fileIter->first <= _Offset);
- u64 fileOffset = _Offset - fileIter->first;
-
- PlainFileReader* reader = PlainFileReader::Create(fileIter->second.c_str());
- if(reader == NULL)
- return false;
-
- u64 fileSize = reader->GetDataSize();
-
- if(fileOffset < fileSize)
- {
- u64 fileBytes = fileSize - fileOffset;
- if(_Length < fileBytes)
- fileBytes = _Length;
-
- if(!reader->Read(fileOffset, fileBytes, _pBuffer))
- return false;
-
- _Length -= fileBytes;
- _pBuffer += fileBytes;
- _Offset += fileBytes;
- }
-
- ++fileIter;
-
- if(fileIter != m_virtualDisk.end())
- {
- _dbg_assert_(DVDINTERFACE, fileIter->first >= _Offset);
- PadToAddress(fileIter->first, _Offset, _Length, _pBuffer);
- }
- }
-
- return true;
-}
-
-std::string CVolumeDirectory::GetUniqueID() const
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- char buffer[7];
- memcpy(buffer, m_diskHeader, 6);
- buffer[6] = 0;
-
- std::string id = buffer;
- return id;
-}
-
-void CVolumeDirectory::SetUniqueID(std::string _ID)
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- u32 length = _ID.length();
- if(length > 6)
- length = 6;
-
- memcpy(m_diskHeader, _ID.c_str(), length);
-}
-
-IVolume::ECountry CVolumeDirectory::GetCountry() const
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- u8 CountryCode = m_diskHeader[3];
-
- ECountry country = COUNTRY_UNKNOWN;
-
- switch (CountryCode)
- {
- case 'S':
- country = COUNTRY_EUROPE;
- break; // PAL <- that is shitty :) zelda demo disc
-
- case 'P':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'D':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'F':
- country = COUNTRY_FRANCE;
- break; // PAL
-
- case 'X':
- country = COUNTRY_EUROPE;
- break; // XIII <- uses X but is PAL rip
-
- case 'E':
- country = COUNTRY_USA;
- break; // USA
-
- case 'J':
- country = COUNTRY_JAP;
- break; // JAP
-
- case 'O':
- country = COUNTRY_UNKNOWN;
- break; // SDK
-
- default:
- country = COUNTRY_UNKNOWN;
- break;
- }
-
- return(country);
-}
-
-std::string CVolumeDirectory::GetMakerID() const
-{
- return "VOID";
-}
-
-std::string CVolumeDirectory::GetName() const
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
- std::string name = (char*)(m_diskHeader + 0x20);
- return name;
-}
-
-void CVolumeDirectory::SetName(std::string _Name)
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- u32 length = _Name.length();
- if(length > MAX_NAME_LENGTH)
- length = MAX_NAME_LENGTH;
-
- memcpy(m_diskHeader + 0x20, _Name.c_str(), length);
- m_diskHeader[length + 0x20] = 0;
-}
-
-u32 CVolumeDirectory::GetFSTSize() const
-{
- return 0;
-}
-
-std::string CVolumeDirectory::GetApploaderDate() const
-{
- return "VOID";
-}
-
-u64 CVolumeDirectory::GetSize() const
-{
- return 0;
-}
-
-static const char DIR_SEPARATOR =
-#ifdef _WIN32
- '\\';
-#else
- '/';
-#endif
-
-std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirectory)
-{
- std::string directoryName = _rDirectory;
-
- size_t lastSep = directoryName.find_last_of(DIR_SEPARATOR);
-
- if(lastSep != directoryName.size() - 1)
- {
- // TODO: This assumes that file names will always have a dot in them
- // and directory names never will; both assumptions are often
- // right but in general wrong.
- size_t extensionStart = directoryName.find_last_of('.');
- if(extensionStart != std::string::npos && extensionStart > lastSep)
- {
- directoryName.resize(lastSep);
- }
- }
- else
- {
- directoryName.resize(lastSep);
- }
-
- return directoryName;
-}
-
-void CVolumeDirectory::SetDiskTypeWii()
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- m_diskHeader[0x18] = 0x5d;
- m_diskHeader[0x19] = 0x1c;
- m_diskHeader[0x1a] = 0x9e;
- m_diskHeader[0x1b] = 0xa3;
- memset(m_diskHeader + 0x1c, 0, 4);
-
- m_addressShift = 2;
-}
-
-void CVolumeDirectory::SetDiskTypeGC()
-{
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
-
- memset(m_diskHeader + 0x18, 0, 4);
- m_diskHeader[0x1c] = 0xc2;
- m_diskHeader[0x1d] = 0x33;
- m_diskHeader[0x1e] = 0x9f;
- m_diskHeader[0x1f] = 0x3d;
-
- m_addressShift = 0;
-}
-
-void CVolumeDirectory::BuildFST()
-{
- if(m_FSTData)
- {
- delete m_FSTData;
- }
-
- File::FSTEntry rootEntry;
-
- // read data from physical disk to rootEntry
- u32 totalEntries = AddDirectoryEntries(m_rootDirectory, rootEntry) + 1;
-
- m_fstNameOffset = totalEntries * ENTRY_SIZE; // offset in FST nameTable
- m_fstSize = m_fstNameOffset + m_totalNameSize;
- m_FSTData = new u8[(u32)m_fstSize];
-
- // 4 byte aligned start of data on disk
- m_dataStartAddress = (FST_ADDRESS + m_fstSize + 3) & ~3;
- u64 curDataAddress = m_dataStartAddress;
-
- u32 fstOffset = 0; // offset within FST data
- u32 nameOffset = 0; // offset within name table
- u32 rootOffset = 0; // offset of root of FST
-
- // write root entry
- WriteEntryData(fstOffset, DIRECTORY_ENTRY, 0, 0, totalEntries);
-
- for(std::vector<File::FSTEntry>::iterator iter = rootEntry.children.begin(); iter != rootEntry.children.end(); ++iter)
- {
- WriteEntry(*iter, fstOffset, nameOffset, curDataAddress, rootOffset);
- }
-
- // overflow check
- _dbg_assert_(DVDINTERFACE, nameOffset == m_fstSize);
-
- // write FST size and location
- _dbg_assert_(DVDINTERFACE, m_diskHeader);
- Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader);
- Write32((u32)m_fstSize, 0x0428, m_diskHeader);
- Write32((u32)m_fstSize, 0x042c, m_diskHeader);
-}
-
-void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src,
- u64& _Address, u64& _Length, u8*& _pBuffer) const
-{
- _dbg_assert_(DVDINTERFACE, _Address >= _SrcStartAddress);
-
- u64 srcOffset = _Address - _SrcStartAddress;
-
- if(srcOffset < _SrcLength)
- {
- u64 srcBytes = _SrcLength - srcOffset;
- if(_Length < srcBytes)
- srcBytes = _Length;
-
- memcpy(_pBuffer, _Src + srcOffset, (size_t)srcBytes);
-
- _Length -= srcBytes;
- _pBuffer += srcBytes;
- _Address += srcBytes;
- }
-}
-
-void CVolumeDirectory::PadToAddress(u64 _StartAddress, u64& _Address, u64& _Length, u8*& _pBuffer) const
-{
- if(_StartAddress <= _Address)
- return;
-
- u64 padBytes = _StartAddress - _Address;
- if(padBytes > _Length)
- padBytes = _Length;
-
- if(_Length > 0)
- {
- memset(_pBuffer, 0, (size_t)padBytes);
- _Length -= padBytes;
- _pBuffer += padBytes;
- _Address += padBytes;
- }
-}
-
-void CVolumeDirectory::Write32(u32 data, u32 offset, u8* buffer)
-{
- buffer[offset++] = (data >> 24);
- buffer[offset++] = (data >> 16) & 0xff;
- buffer[offset++] = (data >> 8) & 0xff;
- buffer[offset] = (data) & 0xff;
-}
-
-void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length)
-{
- m_FSTData[entryOffset++] = type;
-
- m_FSTData[entryOffset++] = (nameOffset >> 16) & 0xff;
- m_FSTData[entryOffset++] = (nameOffset >> 8) & 0xff;
- m_FSTData[entryOffset++] = (nameOffset) & 0xff;
-
- Write32((u32)(dataOffset >> m_addressShift), entryOffset, m_FSTData);
- entryOffset += 4;
-
- Write32((u32)length, entryOffset, m_FSTData);
- entryOffset += 4;
-}
-
-void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name)
-{
- strncpy((char*)(m_FSTData + nameOffset + m_fstNameOffset), name.c_str(), name.length() + 1);
-
- nameOffset += (name.length() + 1);
-}
-
-void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u32& nameOffset, u64& dataOffset, u32 parentEntryNum)
-{
- if(entry.isDirectory)
- {
- u32 myOffset = fstOffset;
- u32 myEntryNum = myOffset / ENTRY_SIZE;
- WriteEntryData(fstOffset, DIRECTORY_ENTRY, nameOffset, parentEntryNum, myEntryNum + entry.size + 1);
- WriteEntryName(nameOffset, entry.virtualName);
-
- for(std::vector<File::FSTEntry>::const_iterator iter = entry.children.begin(); iter != entry.children.end(); ++iter)
- {
- WriteEntry(*iter, fstOffset, nameOffset, dataOffset, myEntryNum);
- }
- }
- else
- {
- // put entry in FST
- WriteEntryData(fstOffset, FILE_ENTRY, nameOffset, dataOffset, entry.size);
- WriteEntryName(nameOffset, entry.virtualName);
-
- // write entry to virtual disk
- _dbg_assert_(DVDINTERFACE, m_virtualDisk.find(dataOffset) == m_virtualDisk.end());
- m_virtualDisk.insert(make_pair(dataOffset, entry.physicalName));
-
- // 4 byte aligned
- dataOffset = (dataOffset + entry.size + 3) & ~3ULL;
- }
-}
-
-static u32 ComputeNameSize(const File::FSTEntry& parentEntry)
-{
- u32 nameSize = 0;
- const std::vector<File::FSTEntry>& children = parentEntry.children;
- for (std::vector<File::FSTEntry>::const_iterator it = children.begin();
- it != children.end(); ++it)
- {
- const File::FSTEntry& entry = *it;
- if (entry.isDirectory)
- {
- nameSize += ComputeNameSize(entry);
- }
- nameSize += entry.virtualName.length() + 1;
- }
- return nameSize;
-}
-
-u32 CVolumeDirectory::AddDirectoryEntries(const std::string& _Directory, File::FSTEntry& parentEntry)
-{
- u32 foundEntries = ScanDirectoryTree(_Directory, parentEntry);
- m_totalNameSize += ComputeNameSize(parentEntry);
- return foundEntries;
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "stdafx.h" + +#include "VolumeDirectory.h" +#include "FileBlob.h" + +namespace DiscIO +{ + +static const u8 ENTRY_SIZE = 0x0c; +static const u8 FILE_ENTRY = 0; +static const u8 DIRECTORY_ENTRY = 1; +static const u64 FST_ADDRESS = 0x440; +static const u32 MAX_NAME_LENGTH = 0x3df; + +CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii) + : m_totalNameSize(0) + , m_dataStartAddress(-1) + , m_fstSize(0) + , m_FSTData(NULL) +{ + m_rootDirectory = ExtractDirectoryName(_rDirectory); + + // create the default disk header + m_diskHeader = new u8[FST_ADDRESS]; + memset(m_diskHeader, 0, (size_t)FST_ADDRESS); + SetUniqueID("RZDE01"); + SetName("Default name"); + + if(_bIsWii) + { + SetDiskTypeWii(); + } + else + { + SetDiskTypeGC(); + } + + BuildFST(); +} + +CVolumeDirectory::~CVolumeDirectory() +{ + delete m_FSTData; + m_FSTData = NULL; + + delete m_diskHeader; + m_diskHeader = NULL; +} + +bool CVolumeDirectory::IsValidDirectory(const std::string& _rDirectory) +{ + std::string directoryName = ExtractDirectoryName(_rDirectory); + return File::IsDirectory(directoryName.c_str()); +} + +bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const +{ + if(_Offset < FST_ADDRESS) + { + WriteToBuffer(0, FST_ADDRESS, m_diskHeader, _Offset, _Length, _pBuffer); + } + + if(_Offset < m_dataStartAddress) + { + WriteToBuffer(FST_ADDRESS, m_fstSize, m_FSTData, _Offset, _Length, _pBuffer); + } + + if(m_virtualDisk.size() == 0) + return true; + + // Determine which file the offset refers to + std::map<u64, std::string>::const_iterator fileIter = m_virtualDisk.lower_bound(_Offset); + if(fileIter->first > _Offset && fileIter != m_virtualDisk.begin()) + --fileIter; + + // zero fill to start of file data + PadToAddress(fileIter->first, _Offset, _Length, _pBuffer); + + while(fileIter != m_virtualDisk.end() && _Length > 0) + { + _dbg_assert_(DVDINTERFACE, fileIter->first <= _Offset); + u64 fileOffset = _Offset - fileIter->first; + + PlainFileReader* reader = PlainFileReader::Create(fileIter->second.c_str()); + if(reader == NULL) + return false; + + u64 fileSize = reader->GetDataSize(); + + if(fileOffset < fileSize) + { + u64 fileBytes = fileSize - fileOffset; + if(_Length < fileBytes) + fileBytes = _Length; + + if(!reader->Read(fileOffset, fileBytes, _pBuffer)) + return false; + + _Length -= fileBytes; + _pBuffer += fileBytes; + _Offset += fileBytes; + } + + ++fileIter; + + if(fileIter != m_virtualDisk.end()) + { + _dbg_assert_(DVDINTERFACE, fileIter->first >= _Offset); + PadToAddress(fileIter->first, _Offset, _Length, _pBuffer); + } + } + + return true; +} + +std::string CVolumeDirectory::GetUniqueID() const +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + char buffer[7]; + memcpy(buffer, m_diskHeader, 6); + buffer[6] = 0; + + std::string id = buffer; + return id; +} + +void CVolumeDirectory::SetUniqueID(std::string _ID) +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + u32 length = _ID.length(); + if(length > 6) + length = 6; + + memcpy(m_diskHeader, _ID.c_str(), length); +} + +IVolume::ECountry CVolumeDirectory::GetCountry() const +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + u8 CountryCode = m_diskHeader[3]; + + ECountry country = COUNTRY_UNKNOWN; + + switch (CountryCode) + { + case 'S': + country = COUNTRY_EUROPE; + break; // PAL <- that is shitty :) zelda demo disc + + case 'P': + country = COUNTRY_EUROPE; + break; // PAL + + case 'D': + country = COUNTRY_EUROPE; + break; // PAL + + case 'F': + country = COUNTRY_FRANCE; + break; // PAL + + case 'X': + country = COUNTRY_EUROPE; + break; // XIII <- uses X but is PAL rip + + case 'E': + country = COUNTRY_USA; + break; // USA + + case 'J': + country = COUNTRY_JAP; + break; // JAP + + case 'O': + country = COUNTRY_UNKNOWN; + break; // SDK + + default: + country = COUNTRY_UNKNOWN; + break; + } + + return(country); +} + +std::string CVolumeDirectory::GetMakerID() const +{ + return "VOID"; +} + +std::string CVolumeDirectory::GetName() const +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + std::string name = (char*)(m_diskHeader + 0x20); + return name; +} + +void CVolumeDirectory::SetName(std::string _Name) +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + u32 length = _Name.length(); + if(length > MAX_NAME_LENGTH) + length = MAX_NAME_LENGTH; + + memcpy(m_diskHeader + 0x20, _Name.c_str(), length); + m_diskHeader[length + 0x20] = 0; +} + +u32 CVolumeDirectory::GetFSTSize() const +{ + return 0; +} + +std::string CVolumeDirectory::GetApploaderDate() const +{ + return "VOID"; +} + +u64 CVolumeDirectory::GetSize() const +{ + return 0; +} + +static const char DIR_SEPARATOR = +#ifdef _WIN32 + '\\'; +#else + '/'; +#endif + +std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirectory) +{ + std::string directoryName = _rDirectory; + + size_t lastSep = directoryName.find_last_of(DIR_SEPARATOR); + + if(lastSep != directoryName.size() - 1) + { + // TODO: This assumes that file names will always have a dot in them + // and directory names never will; both assumptions are often + // right but in general wrong. + size_t extensionStart = directoryName.find_last_of('.'); + if(extensionStart != std::string::npos && extensionStart > lastSep) + { + directoryName.resize(lastSep); + } + } + else + { + directoryName.resize(lastSep); + } + + return directoryName; +} + +void CVolumeDirectory::SetDiskTypeWii() +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + m_diskHeader[0x18] = 0x5d; + m_diskHeader[0x19] = 0x1c; + m_diskHeader[0x1a] = 0x9e; + m_diskHeader[0x1b] = 0xa3; + memset(m_diskHeader + 0x1c, 0, 4); + + m_addressShift = 2; +} + +void CVolumeDirectory::SetDiskTypeGC() +{ + _dbg_assert_(DVDINTERFACE, m_diskHeader); + + memset(m_diskHeader + 0x18, 0, 4); + m_diskHeader[0x1c] = 0xc2; + m_diskHeader[0x1d] = 0x33; + m_diskHeader[0x1e] = 0x9f; + m_diskHeader[0x1f] = 0x3d; + + m_addressShift = 0; +} + +void CVolumeDirectory::BuildFST() +{ + if(m_FSTData) + { + delete m_FSTData; + } + + File::FSTEntry rootEntry; + + // read data from physical disk to rootEntry + u32 totalEntries = AddDirectoryEntries(m_rootDirectory, rootEntry) + 1; + + m_fstNameOffset = totalEntries * ENTRY_SIZE; // offset in FST nameTable + m_fstSize = m_fstNameOffset + m_totalNameSize; + m_FSTData = new u8[(u32)m_fstSize]; + + // 4 byte aligned start of data on disk + m_dataStartAddress = (FST_ADDRESS + m_fstSize + 3) & ~3; + u64 curDataAddress = m_dataStartAddress; + + u32 fstOffset = 0; // offset within FST data + u32 nameOffset = 0; // offset within name table + u32 rootOffset = 0; // offset of root of FST + + // write root entry + WriteEntryData(fstOffset, DIRECTORY_ENTRY, 0, 0, totalEntries); + + for(std::vector<File::FSTEntry>::iterator iter = rootEntry.children.begin(); iter != rootEntry.children.end(); ++iter) + { + WriteEntry(*iter, fstOffset, nameOffset, curDataAddress, rootOffset); + } + + // overflow check + _dbg_assert_(DVDINTERFACE, nameOffset == m_fstSize); + + // write FST size and location + _dbg_assert_(DVDINTERFACE, m_diskHeader); + Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader); + Write32((u32)m_fstSize, 0x0428, m_diskHeader); + Write32((u32)m_fstSize, 0x042c, m_diskHeader); +} + +void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src, + u64& _Address, u64& _Length, u8*& _pBuffer) const +{ + _dbg_assert_(DVDINTERFACE, _Address >= _SrcStartAddress); + + u64 srcOffset = _Address - _SrcStartAddress; + + if(srcOffset < _SrcLength) + { + u64 srcBytes = _SrcLength - srcOffset; + if(_Length < srcBytes) + srcBytes = _Length; + + memcpy(_pBuffer, _Src + srcOffset, (size_t)srcBytes); + + _Length -= srcBytes; + _pBuffer += srcBytes; + _Address += srcBytes; + } +} + +void CVolumeDirectory::PadToAddress(u64 _StartAddress, u64& _Address, u64& _Length, u8*& _pBuffer) const +{ + if(_StartAddress <= _Address) + return; + + u64 padBytes = _StartAddress - _Address; + if(padBytes > _Length) + padBytes = _Length; + + if(_Length > 0) + { + memset(_pBuffer, 0, (size_t)padBytes); + _Length -= padBytes; + _pBuffer += padBytes; + _Address += padBytes; + } +} + +void CVolumeDirectory::Write32(u32 data, u32 offset, u8* buffer) +{ + buffer[offset++] = (data >> 24); + buffer[offset++] = (data >> 16) & 0xff; + buffer[offset++] = (data >> 8) & 0xff; + buffer[offset] = (data) & 0xff; +} + +void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length) +{ + m_FSTData[entryOffset++] = type; + + m_FSTData[entryOffset++] = (nameOffset >> 16) & 0xff; + m_FSTData[entryOffset++] = (nameOffset >> 8) & 0xff; + m_FSTData[entryOffset++] = (nameOffset) & 0xff; + + Write32((u32)(dataOffset >> m_addressShift), entryOffset, m_FSTData); + entryOffset += 4; + + Write32((u32)length, entryOffset, m_FSTData); + entryOffset += 4; +} + +void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name) +{ + strncpy((char*)(m_FSTData + nameOffset + m_fstNameOffset), name.c_str(), name.length() + 1); + + nameOffset += (name.length() + 1); +} + +void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u32& nameOffset, u64& dataOffset, u32 parentEntryNum) +{ + if(entry.isDirectory) + { + u32 myOffset = fstOffset; + u32 myEntryNum = myOffset / ENTRY_SIZE; + WriteEntryData(fstOffset, DIRECTORY_ENTRY, nameOffset, parentEntryNum, myEntryNum + entry.size + 1); + WriteEntryName(nameOffset, entry.virtualName); + + for(std::vector<File::FSTEntry>::const_iterator iter = entry.children.begin(); iter != entry.children.end(); ++iter) + { + WriteEntry(*iter, fstOffset, nameOffset, dataOffset, myEntryNum); + } + } + else + { + // put entry in FST + WriteEntryData(fstOffset, FILE_ENTRY, nameOffset, dataOffset, entry.size); + WriteEntryName(nameOffset, entry.virtualName); + + // write entry to virtual disk + _dbg_assert_(DVDINTERFACE, m_virtualDisk.find(dataOffset) == m_virtualDisk.end()); + m_virtualDisk.insert(make_pair(dataOffset, entry.physicalName)); + + // 4 byte aligned + dataOffset = (dataOffset + entry.size + 3) & ~3ULL; + } +} + +static u32 ComputeNameSize(const File::FSTEntry& parentEntry) +{ + u32 nameSize = 0; + const std::vector<File::FSTEntry>& children = parentEntry.children; + for (std::vector<File::FSTEntry>::const_iterator it = children.begin(); + it != children.end(); ++it) + { + const File::FSTEntry& entry = *it; + if (entry.isDirectory) + { + nameSize += ComputeNameSize(entry); + } + nameSize += entry.virtualName.length() + 1; + } + return nameSize; +} + +u32 CVolumeDirectory::AddDirectoryEntries(const std::string& _Directory, File::FSTEntry& parentEntry) +{ + u32 foundEntries = ScanDirectoryTree(_Directory, parentEntry); + m_totalNameSize += ComputeNameSize(parentEntry); + return foundEntries; +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/VolumeGC.cpp b/Source/Core/DiscIO/Src/VolumeGC.cpp index b10319c7cb..638355a943 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.cpp +++ b/Source/Core/DiscIO/Src/VolumeGC.cpp @@ -1,169 +1,169 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include "VolumeGC.h"
-#include "StringUtil.h"
-
-namespace DiscIO
-{
-CVolumeGC::CVolumeGC(IBlobReader* _pReader)
- : m_pReader(_pReader)
-{}
-
-CVolumeGC::~CVolumeGC()
-{
- delete m_pReader;
-}
-
-bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
-{
- if (m_pReader == NULL)
- return false;
- return m_pReader->Read(_Offset, _Length, _pBuffer);
-}
-
-std::string CVolumeGC::GetUniqueID() const
-{
- static const std::string NO_UID("NO_UID");
- if (m_pReader == NULL)
- return NO_UID;
-
- char id[6];
- if (!Read(0, sizeof(id), reinterpret_cast<u8*>(id)))
- {
- PanicAlert("Failed to read unique ID from disc image");
- return NO_UID;
- }
-
- return std::string(id, sizeof(id));
-}
-
-IVolume::ECountry CVolumeGC::GetCountry() const
-{
- if (!m_pReader)
- return COUNTRY_UNKNOWN;
-
- u8 CountryCode;
- m_pReader->Read(3, 1, &CountryCode);
-
- ECountry country = COUNTRY_UNKNOWN;
-
- switch (CountryCode)
- {
- case 'S':
- country = COUNTRY_EUROPE;
- break; // PAL // <- that is shitty :) zelda demo disc
-
- case 'P':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'D':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'F':
- country = COUNTRY_FRANCE;
- break; // PAL
-
- case 'X':
- country = COUNTRY_EUROPE;
- break; // XIII <- uses X but is PAL
-
- case 'E':
- country = COUNTRY_USA;
- break; // USA
-
- case 'J':
- country = COUNTRY_JAP;
- break; // JAP
-
- case 'O':
- country = COUNTRY_UNKNOWN;
- break; // SDK
-
- default:
- // PanicAlert(StringFromFormat("Unknown Country Code!").c_str());
- country = COUNTRY_UNKNOWN;
- break;
- }
-
- return(country);
-}
-
-std::string CVolumeGC::GetMakerID() const
-{
- if (m_pReader == NULL)
- return false;
-
- char makerID[3];
- if (!Read(0x4, 0x2, (u8*)&makerID))
- return false;
- makerID[2] = 0;
-
- return makerID;
-}
-
-std::string CVolumeGC::GetName() const
-{
- if (m_pReader == NULL)
- return false;
-
- char name[128];
- if (!Read(0x20, 0x60, (u8*)&name))
- return false;
-
- return name;
-}
-
-u32 CVolumeGC::GetFSTSize() const
-{
- if (m_pReader == NULL)
- return false;
-
- u32 size;
- if (!Read(0x428, 0x4, (u8*)&size))
- return false;
-
- return Common::swap32(size);
-}
-
-std::string CVolumeGC::GetApploaderDate() const
-{
- if (m_pReader == NULL)
- return false;
-
- char date[16];
- if (!Read(0x2440, 0x10, (u8*)&date))
- return false;
- // Should be 0 already, but just in case
- date[10] = 0;
-
- return date;
-}
-
-u64 CVolumeGC::GetSize() const
-{
- if (m_pReader)
- return (size_t)m_pReader->GetDataSize();
- else
- return 0;
-}
-
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include "VolumeGC.h" +#include "StringUtil.h" + +namespace DiscIO +{ +CVolumeGC::CVolumeGC(IBlobReader* _pReader) + : m_pReader(_pReader) +{} + +CVolumeGC::~CVolumeGC() +{ + delete m_pReader; +} + +bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const +{ + if (m_pReader == NULL) + return false; + return m_pReader->Read(_Offset, _Length, _pBuffer); +} + +std::string CVolumeGC::GetUniqueID() const +{ + static const std::string NO_UID("NO_UID"); + if (m_pReader == NULL) + return NO_UID; + + char id[6]; + if (!Read(0, sizeof(id), reinterpret_cast<u8*>(id))) + { + PanicAlert("Failed to read unique ID from disc image"); + return NO_UID; + } + + return std::string(id, sizeof(id)); +} + +IVolume::ECountry CVolumeGC::GetCountry() const +{ + if (!m_pReader) + return COUNTRY_UNKNOWN; + + u8 CountryCode; + m_pReader->Read(3, 1, &CountryCode); + + ECountry country = COUNTRY_UNKNOWN; + + switch (CountryCode) + { + case 'S': + country = COUNTRY_EUROPE; + break; // PAL // <- that is shitty :) zelda demo disc + + case 'P': + country = COUNTRY_EUROPE; + break; // PAL + + case 'D': + country = COUNTRY_EUROPE; + break; // PAL + + case 'F': + country = COUNTRY_FRANCE; + break; // PAL + + case 'X': + country = COUNTRY_EUROPE; + break; // XIII <- uses X but is PAL + + case 'E': + country = COUNTRY_USA; + break; // USA + + case 'J': + country = COUNTRY_JAP; + break; // JAP + + case 'O': + country = COUNTRY_UNKNOWN; + break; // SDK + + default: + // PanicAlert(StringFromFormat("Unknown Country Code!").c_str()); + country = COUNTRY_UNKNOWN; + break; + } + + return(country); +} + +std::string CVolumeGC::GetMakerID() const +{ + if (m_pReader == NULL) + return false; + + char makerID[3]; + if (!Read(0x4, 0x2, (u8*)&makerID)) + return false; + makerID[2] = 0; + + return makerID; +} + +std::string CVolumeGC::GetName() const +{ + if (m_pReader == NULL) + return false; + + char name[128]; + if (!Read(0x20, 0x60, (u8*)&name)) + return false; + + return name; +} + +u32 CVolumeGC::GetFSTSize() const +{ + if (m_pReader == NULL) + return false; + + u32 size; + if (!Read(0x428, 0x4, (u8*)&size)) + return false; + + return Common::swap32(size); +} + +std::string CVolumeGC::GetApploaderDate() const +{ + if (m_pReader == NULL) + return false; + + char date[16]; + if (!Read(0x2440, 0x10, (u8*)&date)) + return false; + // Should be 0 already, but just in case + date[10] = 0; + + return date; +} + +u64 CVolumeGC::GetSize() const +{ + if (m_pReader) + return (size_t)m_pReader->GetDataSize(); + else + return 0; +} + +} // namespace diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp index 549664f9b0..d5e744bed2 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp @@ -1,254 +1,254 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-#include "VolumeWiiCrypted.h"
-#include "StringUtil.h"
-
-namespace DiscIO
-{
-CVolumeWiiCrypted::CVolumeWiiCrypted(IBlobReader* _pReader, u64 _VolumeOffset, const unsigned char* _pVolumeKey)
- : m_pReader(_pReader),
- m_pBuffer(0),
- m_VolumeOffset(_VolumeOffset),
- m_LastDecryptedBlockOffset(-1)
-{
- AES_set_decrypt_key(_pVolumeKey, 128, &m_AES_KEY);
- m_pBuffer = new u8[0x8000];
-}
-
-
-CVolumeWiiCrypted::~CVolumeWiiCrypted()
-{
- delete m_pReader; // is this really our responsibility?
- m_pReader = NULL;
- delete[] m_pBuffer;
- m_pBuffer = NULL;
-}
-
-
-bool
-CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer) const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- while (_Length > 0)
- {
- static unsigned char IV[16];
-
- // math block offset
- u64 Block = _ReadOffset / 0x7C00;
- u64 Offset = _ReadOffset % 0x7C00;
-
- // read current block
- if (!m_pReader->Read(m_VolumeOffset + Block * 0x8000, 0x8000, m_pBuffer))
- {
- return(false);
- }
-
- if (m_LastDecryptedBlockOffset != Block)
- {
- memcpy(IV, m_pBuffer + 0x3d0, 16);
- AES_cbc_encrypt(m_pBuffer + 0x400, m_LastDecryptedBlock, 0x7C00, &m_AES_KEY, IV, AES_DECRYPT);
-
- m_LastDecryptedBlockOffset = Block;
- }
-
- // copy the encrypted data
- u64 MaxSizeToCopy = 0x7C00 - Offset;
- u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length;
- memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize);
-
- // increase buffers
- _Length -= CopySize;
- _pBuffer += CopySize;
- _ReadOffset += CopySize;
- }
-
- return(true);
-}
-
-std::string
-CVolumeWiiCrypted::GetUniqueID() const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- char ID[7];
-
- if (!Read(0, 6, (u8*)ID))
- {
- return(false);
- }
-
- ID[6] = 0;
-
- return(ID);
-}
-
-
-IVolume::ECountry
-CVolumeWiiCrypted::GetCountry() const
-{
- if (!m_pReader)
- {
- return(COUNTRY_UNKNOWN);
- }
-
- u8 CountryCode;
- m_pReader->Read(3, 1, &CountryCode);
-
- ECountry country = COUNTRY_UNKNOWN;
-
- switch (CountryCode)
- {
- case 'S':
- country = COUNTRY_EUROPE;
- break; // PAL // <- that is shitty :) zelda demo disc
-
- case 'P':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'D':
- country = COUNTRY_EUROPE;
- break; // PAL
-
- case 'F':
- country = COUNTRY_FRANCE;
- break; // PAL
-
- case 'X':
- country = COUNTRY_EUROPE;
- break; // XIII <- uses X but is PAL rip
-
- case 'E':
- country = COUNTRY_USA;
- break; // USA
-
- case 'J':
- country = COUNTRY_JAP;
- break; // JAP
-
- case 'O':
- country = COUNTRY_UNKNOWN;
- break; // SDK
-
- default:
- PanicAlert(StringFromFormat("Unknown Country Code!").c_str());
- break;
- }
-
- return(country);
-}
-
-std::string
-CVolumeWiiCrypted::GetMakerID() const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- char makerID[3];
-
- if (!Read(0x4, 0x2, (u8*)&makerID))
- {
- return(false);
- }
-
- makerID[2] = 0;
-
- return(makerID);
-}
-
-std::string
-CVolumeWiiCrypted::GetName() const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- char name[0xFF];
-
- if (!Read(0x20, 0x60, (u8*)&name))
- {
- return(false);
- }
-
- return(name);
-}
-
-u32
-CVolumeWiiCrypted::GetFSTSize() const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- u32 size;
-
- if (!Read(0x428, 0x4, (u8*)&size))
- {
- return(false);
- }
-
- return(size);
-}
-
-std::string
-CVolumeWiiCrypted::GetApploaderDate() const
-{
- if (m_pReader == NULL)
- {
- return(false);
- }
-
- char date[16];
-
- if (!Read(0x2440, 0x10, (u8*)&date))
- {
- return(false);
- }
-
- date[10] = 0;
-
- return(date);
-}
-
-
-u64
-CVolumeWiiCrypted::GetSize() const
-{
- if (m_pReader)
- {
- return(m_pReader->GetDataSize());
- }
- else
- {
- return(0);
- }
-}
-} // namespace
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +#include "VolumeWiiCrypted.h" +#include "StringUtil.h" + +namespace DiscIO +{ +CVolumeWiiCrypted::CVolumeWiiCrypted(IBlobReader* _pReader, u64 _VolumeOffset, const unsigned char* _pVolumeKey) + : m_pReader(_pReader), + m_pBuffer(0), + m_VolumeOffset(_VolumeOffset), + m_LastDecryptedBlockOffset(-1) +{ + AES_set_decrypt_key(_pVolumeKey, 128, &m_AES_KEY); + m_pBuffer = new u8[0x8000]; +} + + +CVolumeWiiCrypted::~CVolumeWiiCrypted() +{ + delete m_pReader; // is this really our responsibility? + m_pReader = NULL; + delete[] m_pBuffer; + m_pBuffer = NULL; +} + + +bool +CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer) const +{ + if (m_pReader == NULL) + { + return(false); + } + + while (_Length > 0) + { + static unsigned char IV[16]; + + // math block offset + u64 Block = _ReadOffset / 0x7C00; + u64 Offset = _ReadOffset % 0x7C00; + + // read current block + if (!m_pReader->Read(m_VolumeOffset + Block * 0x8000, 0x8000, m_pBuffer)) + { + return(false); + } + + if (m_LastDecryptedBlockOffset != Block) + { + memcpy(IV, m_pBuffer + 0x3d0, 16); + AES_cbc_encrypt(m_pBuffer + 0x400, m_LastDecryptedBlock, 0x7C00, &m_AES_KEY, IV, AES_DECRYPT); + + m_LastDecryptedBlockOffset = Block; + } + + // copy the encrypted data + u64 MaxSizeToCopy = 0x7C00 - Offset; + u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length; + memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize); + + // increase buffers + _Length -= CopySize; + _pBuffer += CopySize; + _ReadOffset += CopySize; + } + + return(true); +} + +std::string +CVolumeWiiCrypted::GetUniqueID() const +{ + if (m_pReader == NULL) + { + return(false); + } + + char ID[7]; + + if (!Read(0, 6, (u8*)ID)) + { + return(false); + } + + ID[6] = 0; + + return(ID); +} + + +IVolume::ECountry +CVolumeWiiCrypted::GetCountry() const +{ + if (!m_pReader) + { + return(COUNTRY_UNKNOWN); + } + + u8 CountryCode; + m_pReader->Read(3, 1, &CountryCode); + + ECountry country = COUNTRY_UNKNOWN; + + switch (CountryCode) + { + case 'S': + country = COUNTRY_EUROPE; + break; // PAL // <- that is shitty :) zelda demo disc + + case 'P': + country = COUNTRY_EUROPE; + break; // PAL + + case 'D': + country = COUNTRY_EUROPE; + break; // PAL + + case 'F': + country = COUNTRY_FRANCE; + break; // PAL + + case 'X': + country = COUNTRY_EUROPE; + break; // XIII <- uses X but is PAL rip + + case 'E': + country = COUNTRY_USA; + break; // USA + + case 'J': + country = COUNTRY_JAP; + break; // JAP + + case 'O': + country = COUNTRY_UNKNOWN; + break; // SDK + + default: + PanicAlert(StringFromFormat("Unknown Country Code!").c_str()); + break; + } + + return(country); +} + +std::string +CVolumeWiiCrypted::GetMakerID() const +{ + if (m_pReader == NULL) + { + return(false); + } + + char makerID[3]; + + if (!Read(0x4, 0x2, (u8*)&makerID)) + { + return(false); + } + + makerID[2] = 0; + + return(makerID); +} + +std::string +CVolumeWiiCrypted::GetName() const +{ + if (m_pReader == NULL) + { + return(false); + } + + char name[0xFF]; + + if (!Read(0x20, 0x60, (u8*)&name)) + { + return(false); + } + + return(name); +} + +u32 +CVolumeWiiCrypted::GetFSTSize() const +{ + if (m_pReader == NULL) + { + return(false); + } + + u32 size; + + if (!Read(0x428, 0x4, (u8*)&size)) + { + return(false); + } + + return(size); +} + +std::string +CVolumeWiiCrypted::GetApploaderDate() const +{ + if (m_pReader == NULL) + { + return(false); + } + + char date[16]; + + if (!Read(0x2440, 0x10, (u8*)&date)) + { + return(false); + } + + date[10] = 0; + + return(date); +} + + +u64 +CVolumeWiiCrypted::GetSize() const +{ + if (m_pReader) + { + return(m_pReader->GetDataSize()); + } + else + { + return(0); + } +} +} // namespace diff --git a/Source/Core/DiscIO/Src/stdafx.cpp b/Source/Core/DiscIO/Src/stdafx.cpp index 80a57737ae..903e31a1fc 100644 --- a/Source/Core/DiscIO/Src/stdafx.cpp +++ b/Source/Core/DiscIO/Src/stdafx.cpp @@ -1,21 +1,21 @@ -// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "stdafx.h"
-
-// TODO: reference any additional headers you need in STDAFX.H
-// and not in this file
+// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file |
