mirror of https://github.com/PCSX2/pcsx2.git
Merge 37555e3048
into de9d08075e
This commit is contained in:
commit
fffff75a63
|
@ -66,6 +66,14 @@ struct cdvdTN
|
||||||
u8 etrack; //number of the last track
|
u8 etrack; //number of the last track
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct toc_entry
|
||||||
|
{
|
||||||
|
u32 lba;
|
||||||
|
u8 track;
|
||||||
|
u8 adr : 4;
|
||||||
|
u8 control : 4;
|
||||||
|
};
|
||||||
|
|
||||||
// SpindleCtrl Masks
|
// SpindleCtrl Masks
|
||||||
#define CDVD_SPINDLE_SPEED 0x7 // Speed ranges from 0-3 (1, 2, 3, 4x for DVD) and 0-5 (1, 2, 4, 12, 24x for CD)
|
#define CDVD_SPINDLE_SPEED 0x7 // Speed ranges from 0-3 (1, 2, 3, 4x for DVD) and 0-5 (1, 2, 4, 12, 24x for CD)
|
||||||
#define CDVD_SPINDLE_NOMINAL 0x40 // Changes the speed to be constant (CLV) based on current speed
|
#define CDVD_SPINDLE_NOMINAL 0x40 // Changes the speed to be constant (CLV) based on current speed
|
||||||
|
|
|
@ -21,14 +21,6 @@ class Error;
|
||||||
extern int curDiskType;
|
extern int curDiskType;
|
||||||
extern int curTrayStatus;
|
extern int curTrayStatus;
|
||||||
|
|
||||||
struct toc_entry
|
|
||||||
{
|
|
||||||
u32 lba;
|
|
||||||
u8 track;
|
|
||||||
u8 adr : 4;
|
|
||||||
u8 control : 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IOCtlSrc
|
class IOCtlSrc
|
||||||
{
|
{
|
||||||
IOCtlSrc(const IOCtlSrc&) = delete;
|
IOCtlSrc(const IOCtlSrc&) = delete;
|
||||||
|
|
|
@ -18,6 +18,44 @@ static int pmode, cdtype;
|
||||||
static s32 layer1start = -1;
|
static s32 layer1start = -1;
|
||||||
static bool layer1searched = false;
|
static bool layer1searched = false;
|
||||||
|
|
||||||
|
static void ISOParseTOC()
|
||||||
|
{
|
||||||
|
tracks.fill(cdvdTrack{});
|
||||||
|
if (iso.GetType() != ISOTYPE_AUDIO)
|
||||||
|
{
|
||||||
|
strack = 1;
|
||||||
|
etrack = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strack = 0xFF;
|
||||||
|
etrack = 0;
|
||||||
|
// Audio CD
|
||||||
|
for (const auto& entry : iso.ReadTOC())
|
||||||
|
{
|
||||||
|
const u8 track = entry.track;
|
||||||
|
if (track < 1 || track >= tracks.size())
|
||||||
|
{
|
||||||
|
Console.Warning("CDVD: Invalid track index %u, ignoring\n", track);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
strack = std::min(strack, track);
|
||||||
|
etrack = std::max(etrack, track);
|
||||||
|
tracks[track].start_lba = entry.lba;
|
||||||
|
|
||||||
|
if ((entry.control & 0x0C) == 0x04)
|
||||||
|
{
|
||||||
|
Console.Warning("CDVD: Unsupported data track reading. Assuming MODE1?\n");
|
||||||
|
tracks[track].type = CDVD_MODE1_TRACK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tracks[track].type = CDVD_AUDIO_TRACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void ISOclose()
|
static void ISOclose()
|
||||||
{
|
{
|
||||||
iso.Close();
|
iso.Close();
|
||||||
|
@ -49,6 +87,8 @@ static bool ISOopen(std::string filename, Error* error)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISOParseTOC();
|
||||||
|
|
||||||
layer1start = -1;
|
layer1start = -1;
|
||||||
layer1searched = false;
|
layer1searched = false;
|
||||||
|
|
||||||
|
@ -60,34 +100,56 @@ static bool ISOprecache(ProgressCallback* progress, Error* error)
|
||||||
return iso.Precache(progress, error);
|
return iso.Precache(progress, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lsn_to_msf(u8* minute, u8* second, u8* frame, u32 lsn)
|
||||||
|
{
|
||||||
|
*frame = itob(lsn % 75);
|
||||||
|
lsn /= 75;
|
||||||
|
*second = itob(lsn % 60);
|
||||||
|
lsn /= 60;
|
||||||
|
*minute = itob(lsn % 100);
|
||||||
|
}
|
||||||
|
|
||||||
static s32 ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
|
static s32 ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
|
||||||
{
|
{
|
||||||
// fake it
|
// fake it
|
||||||
u8 min, sec, frm;
|
|
||||||
subq->ctrl = 4;
|
|
||||||
subq->adr = 1;
|
|
||||||
subq->trackNum = itob(1);
|
|
||||||
subq->trackIndex = itob(1);
|
|
||||||
|
|
||||||
lba_to_msf(lsn, &min, &sec, &frm);
|
memset(subq, 0, sizeof(cdvdSubQ));
|
||||||
subq->trackM = itob(min);
|
|
||||||
subq->trackS = itob(sec);
|
|
||||||
subq->trackF = itob(frm);
|
|
||||||
|
|
||||||
subq->pad = 0;
|
lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150);
|
||||||
|
|
||||||
lba_to_msf(lsn + (2 * 75), &min, &sec, &frm);
|
// FIXME: Verify this is correct for ISOTYPE_CD :S
|
||||||
subq->discM = itob(min);
|
if (iso.GetType() != ISOTYPE_AUDIO && iso.GetType() != ISOTYPE_CD)
|
||||||
subq->discS = itob(sec);
|
{
|
||||||
subq->discF = itob(frm);
|
subq->ctrl = 4;
|
||||||
|
subq->adr = 1;
|
||||||
|
subq->trackNum = itob(1);
|
||||||
|
subq->trackIndex = itob(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u8 i = strack;
|
||||||
|
while (i < etrack && lsn >= tracks[i + 1].start_lba)
|
||||||
|
++i;
|
||||||
|
|
||||||
|
lsn -= tracks[i].start_lba;
|
||||||
|
|
||||||
|
subq->ctrl = 1;
|
||||||
|
subq->adr = 1;
|
||||||
|
subq->trackNum = i;
|
||||||
|
subq->trackIndex = 1; // FIXME ???
|
||||||
|
}
|
||||||
|
|
||||||
|
lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn);
|
||||||
|
|
||||||
|
Console.Warning("CDVD: SubQ M %02x S %02x F %02x\n", subq->trackM, subq->trackS, subq->trackF);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 ISOgetTN(cdvdTN* Buffer)
|
static s32 ISOgetTN(cdvdTN* Buffer)
|
||||||
{
|
{
|
||||||
Buffer->strack = 1;
|
Buffer->strack = strack;
|
||||||
Buffer->etrack = 1;
|
Buffer->etrack = etrack;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -97,13 +159,15 @@ static s32 ISOgetTD(u8 Track, cdvdTD* Buffer)
|
||||||
if (Track == 0)
|
if (Track == 0)
|
||||||
{
|
{
|
||||||
Buffer->lsn = iso.GetBlockCount();
|
Buffer->lsn = iso.GetBlockCount();
|
||||||
|
Buffer->type = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (Track < strack || Track > etrack)
|
||||||
Buffer->type = CDVD_MODE1_TRACK;
|
return -1;
|
||||||
Buffer->lsn = 0;
|
|
||||||
}
|
Buffer->lsn = tracks[Track].start_lba;
|
||||||
|
Buffer->type = tracks[Track].type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,11 +363,12 @@ static s32 ISOgetTOC(void* toc)
|
||||||
{
|
{
|
||||||
err = ISOgetTD(i, &trackInfo);
|
err = ISOgetTD(i, &trackInfo);
|
||||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||||
tocBuff[i * 10 + 30] = trackInfo.type;
|
const u8 tocIndex = i - diskInfo.strack;
|
||||||
tocBuff[i * 10 + 32] = err == -1 ? 0 : itob(i); //number
|
tocBuff[tocIndex * 10 + 30] = trackInfo.type;
|
||||||
tocBuff[i * 10 + 37] = itob(min);
|
tocBuff[tocIndex * 10 + 32] = err == -1 ? 0 : itob(i); //number
|
||||||
tocBuff[i * 10 + 38] = itob(sec);
|
tocBuff[tocIndex * 10 + 37] = itob(min);
|
||||||
tocBuff[i * 10 + 39] = itob(frm);
|
tocBuff[tocIndex * 10 + 38] = itob(sec);
|
||||||
|
tocBuff[tocIndex * 10 + 39] = itob(frm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -386,8 +386,9 @@ bool ChdFileReader::Open2(std::string filename, Error* error)
|
||||||
|
|
||||||
// The file size in the header is incorrect, each track gets padded to a multiple of 4 frames.
|
// The file size in the header is incorrect, each track gets padded to a multiple of 4 frames.
|
||||||
// (see chdman.cpp from MAME). Instead, we pull the real frame count from the TOC.
|
// (see chdman.cpp from MAME). Instead, we pull the real frame count from the TOC.
|
||||||
|
std::vector<toc_entry> entries;
|
||||||
u64 total_frames;
|
u64 total_frames;
|
||||||
if (ParseTOC(&total_frames))
|
if (ParseTOC(&total_frames, entries))
|
||||||
{
|
{
|
||||||
file_size = total_frames * static_cast<u64>(chd_header->unitbytes);
|
file_size = total_frames * static_cast<u64>(chd_header->unitbytes);
|
||||||
}
|
}
|
||||||
|
@ -409,6 +410,21 @@ bool ChdFileReader::Precache2(ProgressCallback* progress, Error* error)
|
||||||
return fileWrapper->Precache(progress, error);
|
return fileWrapper->Precache(progress, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<toc_entry> ChdFileReader::ReadTOC()
|
||||||
|
{
|
||||||
|
u64 total_frames;
|
||||||
|
std::vector<toc_entry> entries;
|
||||||
|
if (ParseTOC(&total_frames, entries))
|
||||||
|
{
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Warning("Failed to parse CHD TOC, file size may be incorrect.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ThreadedFileReader::Chunk ChdFileReader::ChunkForOffset(u64 offset)
|
ThreadedFileReader::Chunk ChdFileReader::ChunkForOffset(u64 offset)
|
||||||
{
|
{
|
||||||
Chunk chunk = {0};
|
Chunk chunk = {0};
|
||||||
|
@ -454,11 +470,11 @@ u32 ChdFileReader::GetBlockCount() const
|
||||||
return (file_size - m_dataoffset) / m_internalBlockSize;
|
return (file_size - m_dataoffset) / m_internalBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChdFileReader::ParseTOC(u64* out_frame_count)
|
bool ChdFileReader::ParseTOC(u64* out_frame_count, std::vector<toc_entry>& entries)
|
||||||
{
|
{
|
||||||
u64 total_frames = 0;
|
u64 total_frames = 0;
|
||||||
int max_found_track = -1;
|
int max_found_track = -1;
|
||||||
|
u64 total_gap_frames = 0;
|
||||||
for (int search_index = 0;; search_index++)
|
for (int search_index = 0;; search_index++)
|
||||||
{
|
{
|
||||||
char metadata_str[256];
|
char metadata_str[256];
|
||||||
|
@ -498,17 +514,28 @@ bool ChdFileReader::ParseTOC(u64* out_frame_count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DevCon.WriteLn(fmt::format("CHD Track {}: frames:{} pregap:{} postgap:{} type:{} sub:{} pgtype:{} pgsub:{}",
|
Console.WriteLn(fmt::format("CHD Track {}: frames:{} pregap:{} postgap:{} type:{} sub:{} pgtype:{} pgsub:{}",
|
||||||
track_num, frames, pregap_frames, postgap_frames, type_str, subtype_str, pgtype_str, pgsub_str));
|
track_num, frames, pregap_frames, postgap_frames, type_str, subtype_str, pgtype_str, pgsub_str));
|
||||||
|
|
||||||
// PCSX2 doesn't currently support multiple tracks for CDs.
|
if (track_num != 0)
|
||||||
if (track_num != 1)
|
|
||||||
{
|
{
|
||||||
Console.Warning(fmt::format(" Ignoring track {} in CHD.", track_num, frames));
|
toc_entry entry{};
|
||||||
continue;
|
entry.lba = static_cast<u32>(total_frames) - total_gap_frames;
|
||||||
|
entry.track = static_cast<u8>(track_num);
|
||||||
|
entry.adr = 1;
|
||||||
|
entry.control = 0;
|
||||||
|
|
||||||
|
//FIXME: DATA track?
|
||||||
|
if (strncmp(type_str, "AUDIO", 5) != 0)
|
||||||
|
entry.control |= 0x04;
|
||||||
|
|
||||||
|
entries.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
total_frames += static_cast<u64>(pregap_frames) + static_cast<u64>(frames) + static_cast<u64>(postgap_frames);
|
// I have not found a CHD with an audio track with a postgap, consider that untested
|
||||||
|
total_gap_frames += static_cast<u64>(pregap_frames) + static_cast<u64>(postgap_frames);
|
||||||
|
total_frames += total_gap_frames + static_cast<u64>(frames);
|
||||||
|
|
||||||
max_found_track = std::max(max_found_track, track_num);
|
max_found_track = std::max(max_found_track, track_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
|
|
||||||
bool Precache2(ProgressCallback* progress, Error* error) override;
|
bool Precache2(ProgressCallback* progress, Error* error) override;
|
||||||
|
|
||||||
|
std::vector<toc_entry> ReadTOC() override;
|
||||||
|
|
||||||
Chunk ChunkForOffset(u64 offset) override;
|
Chunk ChunkForOffset(u64 offset) override;
|
||||||
int ReadChunk(void* dst, s64 blockID) override;
|
int ReadChunk(void* dst, s64 blockID) override;
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ public:
|
||||||
uint GetBlockCount(void) const override;
|
uint GetBlockCount(void) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ParseTOC(u64* out_frame_count);
|
bool ParseTOC(u64* out_frame_count, std::vector<toc_entry>& entries);
|
||||||
|
|
||||||
chd_file* ChdFile = nullptr;
|
chd_file* ChdFile = nullptr;
|
||||||
u64 file_size = 0;
|
u64 file_size = 0;
|
||||||
|
|
|
@ -160,9 +160,31 @@ int InputIsoFile::FinishRead3(u8* dst, uint mode)
|
||||||
dst[diff - 9] = 2;
|
dst[diff - 9] = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Seems like CHD data ends up being the wrong endianess for audio
|
||||||
|
// Confidence is about 50% on this one, but it seems to work
|
||||||
|
// (CHD is the only file with a TOC anyways, so who cares about the other formats)
|
||||||
|
if (m_type == ISOTYPE_AUDIO && mode == CDVD_MODE_2352)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2352; i += 2)
|
||||||
|
{
|
||||||
|
std::swap(dst[diff + i], dst[diff + i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<toc_entry> InputIsoFile::ReadTOC() const
|
||||||
|
{
|
||||||
|
std::vector<toc_entry> toc;
|
||||||
|
|
||||||
|
if (m_type == ISOTYPE_ILLEGAL)
|
||||||
|
return toc;
|
||||||
|
|
||||||
|
toc = m_reader->ReadTOC();
|
||||||
|
return toc;
|
||||||
|
}
|
||||||
|
|
||||||
InputIsoFile::InputIsoFile()
|
InputIsoFile::InputIsoFile()
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
|
@ -271,7 +293,7 @@ bool InputIsoFile::tryIsoType(u32 size, u32 offset, u32 blockofs)
|
||||||
// Returns true if the image is valid/known/supported, or false if not (type == ISOTYPE_ILLEGAL).
|
// Returns true if the image is valid/known/supported, or false if not (type == ISOTYPE_ILLEGAL).
|
||||||
bool InputIsoFile::Detect(bool readType)
|
bool InputIsoFile::Detect(bool readType)
|
||||||
{
|
{
|
||||||
m_type = ISOTYPE_ILLEGAL;
|
m_type = ISOTYPE_ILLEGAL;
|
||||||
|
|
||||||
// First sanity check: no sane CD image has less than 16 sectors, since that's what
|
// First sanity check: no sane CD image has less than 16 sectors, since that's what
|
||||||
// we need simply to contain a TOC. So if the file size is not large enough to
|
// we need simply to contain a TOC. So if the file size is not large enough to
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDVDcommon.h"
|
||||||
#include "CDVD/CDVD.h"
|
#include "CDVD/CDVD.h"
|
||||||
#include "CDVD/ThreadedFileReader.h"
|
#include "CDVD/ThreadedFileReader.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -75,6 +76,8 @@ public:
|
||||||
void BeginRead2(uint lsn);
|
void BeginRead2(uint lsn);
|
||||||
int FinishRead3(u8* dest, uint mode);
|
int FinishRead3(u8* dest, uint mode);
|
||||||
|
|
||||||
|
std::vector<toc_entry> ReadTOC() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,12 @@ bool ThreadedFileReader::Precache2(ProgressCallback* progress, Error* error)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<toc_entry> ThreadedFileReader::ReadTOC()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ThreadedFileReader::CheckAvailableMemoryForPrecaching(u64 required_size, Error* error)
|
bool ThreadedFileReader::CheckAvailableMemoryForPrecaching(u64 required_size, Error* error)
|
||||||
{
|
{
|
||||||
// Don't allow precaching to use more than 50% of system memory.
|
// Don't allow precaching to use more than 50% of system memory.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Pcsx2Defs.h"
|
#include "common/Pcsx2Defs.h"
|
||||||
|
#include "CDVDcommon.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -117,6 +118,7 @@ public:
|
||||||
|
|
||||||
bool Open(std::string filename, Error* error);
|
bool Open(std::string filename, Error* error);
|
||||||
bool Precache(ProgressCallback* progress, Error* error);
|
bool Precache(ProgressCallback* progress, Error* error);
|
||||||
|
virtual std::vector<toc_entry> ReadTOC();
|
||||||
int ReadSync(void* pBuffer, u32 sector, u32 count);
|
int ReadSync(void* pBuffer, u32 sector, u32 count);
|
||||||
void BeginRead(void* pBuffer, u32 sector, u32 count);
|
void BeginRead(void* pBuffer, u32 sector, u32 count);
|
||||||
int FinishRead();
|
int FinishRead();
|
||||||
|
|
Loading…
Reference in New Issue