mirror of https://github.com/PCSX2/pcsx2.git
CDVD: Add IsoHasher
This commit is contained in:
parent
eb8d938c94
commit
94c48a4c2d
|
@ -0,0 +1,200 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
|
#include "CDVD/CDVDcommon.h"
|
||||||
|
#include "CDVD/IsoHasher.h"
|
||||||
|
#include "Host.h"
|
||||||
|
|
||||||
|
#include "common/Error.h"
|
||||||
|
#include "common/MD5Digest.h"
|
||||||
|
#include "common/StringUtil.h"
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
IsoHasher::IsoHasher() = default;
|
||||||
|
|
||||||
|
IsoHasher::~IsoHasher()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view IsoHasher::GetTrackTypeString(u32 type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CDVD_AUDIO_TRACK:
|
||||||
|
return TRANSLATE_SV("CDVD", "Audio");
|
||||||
|
case CDVD_MODE1_TRACK:
|
||||||
|
return TRANSLATE_SV("CDVD", "Mode 1");
|
||||||
|
case CDVD_MODE2_TRACK:
|
||||||
|
return TRANSLATE_SV("CDVD", "Mode 2");
|
||||||
|
default:
|
||||||
|
return TRANSLATE_SV("CDVD", "Unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsoHasher::Open(std::string iso_path, Error* error)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
|
||||||
|
CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path));
|
||||||
|
CDVDsys_ChangeSource(CDVD_SourceType::Iso);
|
||||||
|
|
||||||
|
m_is_open = DoCDVDopen();
|
||||||
|
if (!m_is_open)
|
||||||
|
{
|
||||||
|
Error::SetString(error, "Failed to open CDVD.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const s32 type = DoCDVDdetectDiskType();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CDVD_TYPE_PSCD:
|
||||||
|
case CDVD_TYPE_PSCDDA:
|
||||||
|
case CDVD_TYPE_PS2CD:
|
||||||
|
case CDVD_TYPE_PS2CDDA:
|
||||||
|
m_is_cd = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CDVD_TYPE_PS2DVD:
|
||||||
|
m_is_cd = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error::SetString(error, fmt::format("Unknown CDVD disk type {}", type));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdvdTN tn;
|
||||||
|
if (CDVD->getTN(&tn) < 0)
|
||||||
|
{
|
||||||
|
Error::SetString(error, "Failed to get track count.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u8 track = tn.strack; track <= tn.etrack; track++)
|
||||||
|
{
|
||||||
|
cdvdTD td, next_td;
|
||||||
|
if (CDVD->getTD(track, &td) < 0 || CDVD->getTD((track == tn.etrack) ? 0 : (track + 1), &next_td) < 0)
|
||||||
|
{
|
||||||
|
Error::SetString(error, fmt::format("Failed to get track range for {}", static_cast<unsigned>(track)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check..
|
||||||
|
if (next_td.lsn < td.lsn)
|
||||||
|
{
|
||||||
|
Error::SetString(error,
|
||||||
|
fmt::format("Invalid track range for {} ({},{})", static_cast<unsigned>(track), td.lsn, next_td.lsn));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track strack;
|
||||||
|
strack.number = track;
|
||||||
|
strack.type = td.type;
|
||||||
|
strack.start_lsn = td.lsn;
|
||||||
|
strack.sectors = next_td.lsn - td.lsn;
|
||||||
|
strack.size = static_cast<u64>(strack.sectors) * (m_is_cd ? 2352 : 2048);
|
||||||
|
m_tracks.push_back(std::move(strack));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoHasher::Close()
|
||||||
|
{
|
||||||
|
if (!m_is_open)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DoCDVDclose();
|
||||||
|
m_tracks.clear();
|
||||||
|
m_is_cd = false;
|
||||||
|
m_is_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsoHasher::ComputeHashes(ProgressCallback* callback)
|
||||||
|
{
|
||||||
|
callback->SetProgressRange(GetTrackCount());
|
||||||
|
callback->SetProgressValue(0);
|
||||||
|
callback->SetCancellable(true);
|
||||||
|
|
||||||
|
for (u32 index = 0; index < GetTrackCount(); index++)
|
||||||
|
{
|
||||||
|
Track& track = m_tracks[index];
|
||||||
|
if (!track.hash.empty())
|
||||||
|
{
|
||||||
|
callback->SetProgressValue(index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback->PushState();
|
||||||
|
const bool result = ComputeTrackHash(track, callback);
|
||||||
|
callback->PopState();
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
break;
|
||||||
|
|
||||||
|
callback->SetProgressValue(index + 1);
|
||||||
|
callback->IncrementProgressValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
callback->SetProgressValue(GetTrackCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsoHasher::ComputeTrackHash(Track& track, ProgressCallback* callback)
|
||||||
|
{
|
||||||
|
// use 2048 byte reads for DVDs, otherwise 2352 raw.
|
||||||
|
const int read_mode = m_is_cd ? CDVD_MODE_2352 : CDVD_MODE_2048;
|
||||||
|
const u32 sector_size = m_is_cd ? 2352 : 2048;
|
||||||
|
std::vector<u8> sector_buffer(sector_size);
|
||||||
|
|
||||||
|
const u32 update_interval = std::max<u32>(track.sectors / 100u, 1u);
|
||||||
|
callback->SetFormattedStatusText("Computing hash for track %u...", track.number);
|
||||||
|
callback->SetProgressRange(track.sectors);
|
||||||
|
|
||||||
|
MD5Digest md5;
|
||||||
|
for (u32 i = 0; i < track.sectors; i++)
|
||||||
|
{
|
||||||
|
if (callback->IsCancelled())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 lsn = track.start_lsn + i;
|
||||||
|
if (DoCDVDreadSector(sector_buffer.data(), lsn, read_mode) != 0)
|
||||||
|
{
|
||||||
|
callback->DisplayFormattedModalError("Read error at LSN %u", lsn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
md5.Update(sector_buffer.data(), sector_size);
|
||||||
|
|
||||||
|
if ((i % update_interval) == 0)
|
||||||
|
callback->SetProgressValue(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 digest[16];
|
||||||
|
md5.Final(digest);
|
||||||
|
track.hash =
|
||||||
|
fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
||||||
|
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8],
|
||||||
|
digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
|
||||||
|
|
||||||
|
callback->SetProgressValue(track.sectors);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/Pcsx2Defs.h"
|
||||||
|
#include "common/ProgressCallback.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Error;
|
||||||
|
|
||||||
|
class IsoHasher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Track
|
||||||
|
{
|
||||||
|
u32 number;
|
||||||
|
u32 type;
|
||||||
|
u32 start_lsn;
|
||||||
|
u32 sectors;
|
||||||
|
u64 size;
|
||||||
|
std::string hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
IsoHasher();
|
||||||
|
~IsoHasher();
|
||||||
|
|
||||||
|
static std::string_view GetTrackTypeString(u32 type);
|
||||||
|
|
||||||
|
const u32 GetTrackCount() const { return static_cast<u32>(m_tracks.size()); }
|
||||||
|
const Track& GetTrack(u32 n) const { return m_tracks.at(n); }
|
||||||
|
const std::vector<Track>& GetTracks() const { return m_tracks; }
|
||||||
|
bool IsCD() const { return m_is_cd; }
|
||||||
|
|
||||||
|
bool Open(std::string iso_path, Error* error = nullptr);
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
void ComputeHashes(ProgressCallback* callback = ProgressCallback::NullProgressCallback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ComputeTrackHash(Track& track, ProgressCallback* callback);
|
||||||
|
|
||||||
|
std::vector<Track> m_tracks;
|
||||||
|
bool m_is_open = false;
|
||||||
|
bool m_is_cd = false;
|
||||||
|
};
|
|
@ -247,6 +247,7 @@ set(pcsx2CDVDSources
|
||||||
CDVD/CDVDisoReader.cpp
|
CDVD/CDVDisoReader.cpp
|
||||||
CDVD/CDVDdiscThread.cpp
|
CDVD/CDVDdiscThread.cpp
|
||||||
CDVD/InputIsoFile.cpp
|
CDVD/InputIsoFile.cpp
|
||||||
|
CDVD/IsoHasher.cpp
|
||||||
CDVD/IsoReader.cpp
|
CDVD/IsoReader.cpp
|
||||||
CDVD/OutputIsoFile.cpp
|
CDVD/OutputIsoFile.cpp
|
||||||
CDVD/ChunksCache.cpp
|
CDVD/ChunksCache.cpp
|
||||||
|
@ -271,6 +272,7 @@ set(pcsx2CDVDHeaders
|
||||||
CDVD/GzippedFileReader.h
|
CDVD/GzippedFileReader.h
|
||||||
CDVD/ThreadedFileReader.h
|
CDVD/ThreadedFileReader.h
|
||||||
CDVD/IsoFileFormats.h
|
CDVD/IsoFileFormats.h
|
||||||
|
CDVD/IsoHasher.h
|
||||||
CDVD/IsoReader.h
|
CDVD/IsoReader.h
|
||||||
CDVD/zlib_indexed.h
|
CDVD/zlib_indexed.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -122,6 +122,7 @@
|
||||||
<ClCompile Include="CDVD\CsoFileReader.cpp" />
|
<ClCompile Include="CDVD\CsoFileReader.cpp" />
|
||||||
<ClCompile Include="CDVD\GzippedFileReader.cpp" />
|
<ClCompile Include="CDVD\GzippedFileReader.cpp" />
|
||||||
<ClCompile Include="CDVD\IsoReader.cpp" />
|
<ClCompile Include="CDVD\IsoReader.cpp" />
|
||||||
|
<ClCompile Include="CDVD\IsoHasher.cpp" />
|
||||||
<ClCompile Include="CDVD\OutputIsoFile.cpp" />
|
<ClCompile Include="CDVD\OutputIsoFile.cpp" />
|
||||||
<ClCompile Include="CDVD\ThreadedFileReader.cpp" />
|
<ClCompile Include="CDVD\ThreadedFileReader.cpp" />
|
||||||
<ClCompile Include="CDVD\Linux\DriveUtility.cpp">
|
<ClCompile Include="CDVD\Linux\DriveUtility.cpp">
|
||||||
|
@ -483,6 +484,7 @@
|
||||||
<ClInclude Include="CDVD\ChdFileReader.h" />
|
<ClInclude Include="CDVD\ChdFileReader.h" />
|
||||||
<ClInclude Include="CDVD\GzippedFileReader.h" />
|
<ClInclude Include="CDVD\GzippedFileReader.h" />
|
||||||
<ClInclude Include="CDVD\IsoReader.h" />
|
<ClInclude Include="CDVD\IsoReader.h" />
|
||||||
|
<ClInclude Include="CDVD\IsoHasher.h" />
|
||||||
<ClInclude Include="CDVD\ThreadedFileReader.h" />
|
<ClInclude Include="CDVD\ThreadedFileReader.h" />
|
||||||
<ClInclude Include="CDVD\zlib_indexed.h" />
|
<ClInclude Include="CDVD\zlib_indexed.h" />
|
||||||
<ClInclude Include="DebugTools\Breakpoints.h" />
|
<ClInclude Include="DebugTools\Breakpoints.h" />
|
||||||
|
|
|
@ -109,9 +109,6 @@
|
||||||
<Filter Include="System\Ps2\iCore">
|
<Filter Include="System\Ps2\iCore">
|
||||||
<UniqueIdentifier>{5e741f2d-9e0b-4e43-b2a2-44a8370e1546}</UniqueIdentifier>
|
<UniqueIdentifier>{5e741f2d-9e0b-4e43-b2a2-44a8370e1546}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="System\IsoFS">
|
|
||||||
<UniqueIdentifier>{c5237754-2509-4291-b869-c5dacc1a8aba}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
||||||
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@ -1409,7 +1406,12 @@
|
||||||
<ClCompile Include="ImGui\ImGuiFullscreen.cpp">
|
<ClCompile Include="ImGui\ImGuiFullscreen.cpp">
|
||||||
<Filter>Misc\ImGui</Filter>
|
<Filter>Misc\ImGui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="CDVD\IsoReader.cpp" />
|
<ClCompile Include="CDVD\IsoHasher.cpp">
|
||||||
|
<Filter>System\ISO</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="CDVD\IsoReader.cpp">
|
||||||
|
<Filter>System\ISO</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Patch.h">
|
<ClInclude Include="Patch.h">
|
||||||
|
@ -2328,7 +2330,12 @@
|
||||||
<ClInclude Include="ImGui\ImGuiFullscreen.h">
|
<ClInclude Include="ImGui\ImGuiFullscreen.h">
|
||||||
<Filter>Misc\ImGui</Filter>
|
<Filter>Misc\ImGui</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="CDVD\IsoReader.h" />
|
<ClInclude Include="CDVD\IsoHasher.h">
|
||||||
|
<Filter>System\ISO</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="CDVD\IsoReader.h">
|
||||||
|
<Filter>System\ISO</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuildStep Include="rdebug\deci2.h">
|
<CustomBuildStep Include="rdebug\deci2.h">
|
||||||
|
|
Loading…
Reference in New Issue