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/CDVDdiscThread.cpp
|
||||
CDVD/InputIsoFile.cpp
|
||||
CDVD/IsoHasher.cpp
|
||||
CDVD/IsoReader.cpp
|
||||
CDVD/OutputIsoFile.cpp
|
||||
CDVD/ChunksCache.cpp
|
||||
|
@ -271,6 +272,7 @@ set(pcsx2CDVDHeaders
|
|||
CDVD/GzippedFileReader.h
|
||||
CDVD/ThreadedFileReader.h
|
||||
CDVD/IsoFileFormats.h
|
||||
CDVD/IsoHasher.h
|
||||
CDVD/IsoReader.h
|
||||
CDVD/zlib_indexed.h
|
||||
)
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
<ClCompile Include="CDVD\CsoFileReader.cpp" />
|
||||
<ClCompile Include="CDVD\GzippedFileReader.cpp" />
|
||||
<ClCompile Include="CDVD\IsoReader.cpp" />
|
||||
<ClCompile Include="CDVD\IsoHasher.cpp" />
|
||||
<ClCompile Include="CDVD\OutputIsoFile.cpp" />
|
||||
<ClCompile Include="CDVD\ThreadedFileReader.cpp" />
|
||||
<ClCompile Include="CDVD\Linux\DriveUtility.cpp">
|
||||
|
@ -483,6 +484,7 @@
|
|||
<ClInclude Include="CDVD\ChdFileReader.h" />
|
||||
<ClInclude Include="CDVD\GzippedFileReader.h" />
|
||||
<ClInclude Include="CDVD\IsoReader.h" />
|
||||
<ClInclude Include="CDVD\IsoHasher.h" />
|
||||
<ClInclude Include="CDVD\ThreadedFileReader.h" />
|
||||
<ClInclude Include="CDVD\zlib_indexed.h" />
|
||||
<ClInclude Include="DebugTools\Breakpoints.h" />
|
||||
|
|
|
@ -109,9 +109,6 @@
|
|||
<Filter Include="System\Ps2\iCore">
|
||||
<UniqueIdentifier>{5e741f2d-9e0b-4e43-b2a2-44a8370e1546}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\IsoFS">
|
||||
<UniqueIdentifier>{c5237754-2509-4291-b869-c5dacc1a8aba}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="System\Ps2\Iop\CDVD\Windows">
|
||||
<UniqueIdentifier>{be861049-a142-4650-85a5-a2fdd4eef011}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -1409,7 +1406,12 @@
|
|||
<ClCompile Include="ImGui\ImGuiFullscreen.cpp">
|
||||
<Filter>Misc\ImGui</Filter>
|
||||
</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>
|
||||
<ClInclude Include="Patch.h">
|
||||
|
@ -2328,7 +2330,12 @@
|
|||
<ClInclude Include="ImGui\ImGuiFullscreen.h">
|
||||
<Filter>Misc\ImGui</Filter>
|
||||
</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>
|
||||
<CustomBuildStep Include="rdebug\deci2.h">
|
||||
|
|
Loading…
Reference in New Issue