PCE: Improved cue loading (MODE1/2048 + multi-file discs)

This commit is contained in:
Sour 2022-08-15 20:57:41 -04:00
parent 189f1118aa
commit c170fc2bdf
2 changed files with 58 additions and 26 deletions

View file

@ -138,7 +138,7 @@ bool CdReader::LoadCue(VirtualFile& cueFile, DiscInfo& disc)
}
}
uint32_t discSize = 0;
int sectorsInPrevFiles = 0;
uint32_t totalPregapLbaLength = 0;
for(size_t i = 0; i < files.size(); i++) {
VirtualFile physicalFile = files[i].Filename;
@ -148,7 +148,7 @@ bool CdReader::LoadCue(VirtualFile& cueFile, DiscInfo& disc)
}
disc.Files.push_back(files[i].Filename);
int sectorsInFile = 0;
for(size_t j = 0; j < files[i].Tracks.size(); j++) {
CueTrackEntry entry = files[i].Tracks[j];
TrackInfo trk = {};
@ -161,14 +161,17 @@ bool CdReader::LoadCue(VirtualFile& cueFile, DiscInfo& disc)
for(CueIndexEntry& idx : entry.Indexes) {
if(idx.Number == 0) {
trk.HasLeadIn = true;
trk.LeadInPosition = DiscPosition::FromLba(idx.Position.ToLba() + discSize / DiscInfo::SectorSize);
trk.LeadInPosition = DiscPosition::FromLba(idx.Position.ToLba() + sectorsInPrevFiles);
} else if(idx.Number == 1) {
if(entry.PreGap.HasGap) {
trk.HasLeadIn = true;
trk.LeadInPosition = DiscPosition::FromLba(idx.Position.ToLba() + totalPregapLbaLength - entry.PreGap.Length.ToLba() + discSize / DiscInfo::SectorSize);
trk.LeadInPosition = DiscPosition::FromLba(idx.Position.ToLba() + totalPregapLbaLength - entry.PreGap.Length.ToLba() + sectorsInPrevFiles);
}
trk.StartPosition = DiscPosition::FromLba(idx.Position.ToLba() + totalPregapLbaLength + discSize / DiscInfo::SectorSize);
trk.StartPosition = DiscPosition::FromLba(idx.Position.ToLba() + totalPregapLbaLength + sectorsInPrevFiles);
startPos = idx.Position;
} else {
MessageManager::Log("[CUE] Unsupported index number: " + idx.Number);
return false;
}
}
@ -176,38 +179,53 @@ bool CdReader::LoadCue(VirtualFile& cueFile, DiscInfo& disc)
trk.Format = TrackFormat::Audio;
} else if(entry.Format == "MODE1/2352") {
trk.Format = TrackFormat::Mode1_2352;
} else if(entry.Format == "MODE1/2048") {
trk.Format = TrackFormat::Mode1_2048;
} else {
MessageManager::Log("[CUE] Unsupported track format: " + entry.Format);
return false;
}
trk.FirstSector = trk.StartPosition.ToLba();
trk.FileOffset = startPos.ToLba() * DiscInfo::SectorSize;
trk.FileIndex = (uint32_t)disc.Files.size() - 1;
uint32_t currentFileOffset = 0;
if(disc.Tracks.size() > 0) {
TrackInfo& prvTrk = disc.Tracks[disc.Tracks.size() - 1];
prvTrk.EndPosition = DiscPosition::FromLba((trk.HasLeadIn ? trk.LeadInPosition.ToLba() : trk.FirstSector) - 1);
prvTrk.LastSector = prvTrk.EndPosition.ToLba();
prvTrk.SectorCount = prvTrk.LastSector - prvTrk.FirstSector + 1;
prvTrk.Size = prvTrk.SectorCount * DiscInfo::SectorSize;
if(prvTrk.Size == 0) {
//Update end position for this file's previous track based on the start of the current track
prvTrk.EndPosition = DiscPosition::FromLba((trk.HasLeadIn ? trk.LeadInPosition.ToLba() : trk.FirstSector) - 1);
prvTrk.LastSector = prvTrk.EndPosition.ToLba();
prvTrk.SectorCount = prvTrk.LastSector - prvTrk.FirstSector + 1;
prvTrk.Size = prvTrk.SectorCount * trk.GetSectorSize();
sectorsInFile += prvTrk.SectorCount;
currentFileOffset = prvTrk.FileOffset + prvTrk.Size;
}
}
trk.FileOffset = currentFileOffset;
if(trk.HasLeadIn && !entry.PreGap.HasGap) {
trk.FileOffset += (trk.StartPosition.ToLba() - trk.LeadInPosition.ToLba()) * trk.GetSectorSize();
}
trk.FileIndex = (uint32_t)disc.Files.size() - 1;
disc.Tracks.push_back(trk);
}
discSize += (uint32_t)physicalFile.GetSize();
//Set end position for last track to be the end of the current file
TrackInfo& lastTrk = disc.Tracks[disc.Tracks.size() - 1];
lastTrk.Size = (disc.Files[lastTrk.FileIndex].GetSize() - lastTrk.FileOffset) / lastTrk.GetSectorSize() * lastTrk.GetSectorSize();
lastTrk.SectorCount = lastTrk.Size / lastTrk.GetSectorSize();
lastTrk.EndPosition = DiscPosition::FromLba(lastTrk.FirstSector + lastTrk.SectorCount - 1);
lastTrk.LastSector = lastTrk.EndPosition.ToLba();
sectorsInFile += lastTrk.SectorCount;
sectorsInPrevFiles += sectorsInFile;
}
TrackInfo& lastTrk = disc.Tracks[disc.Tracks.size() - 1];
lastTrk.Size = (disc.Files[lastTrk.FileIndex].GetSize() - lastTrk.FileOffset) / DiscInfo::SectorSize * DiscInfo::SectorSize;
lastTrk.SectorCount = lastTrk.Size / DiscInfo::SectorSize;
lastTrk.EndPosition = DiscPosition::FromLba(lastTrk.FirstSector+lastTrk.SectorCount-1);
lastTrk.LastSector = lastTrk.EndPosition.ToLba();
disc.EndPosition = lastTrk.EndPosition;
disc.DiscSize = discSize;
disc.DiscSectorCount = discSize / DiscInfo::SectorSize;
TrackInfo& discLastTrk = disc.Tracks[disc.Tracks.size() - 1];
disc.EndPosition = discLastTrk.EndPosition;
disc.DiscSize = discLastTrk.FileOffset + discLastTrk.Size;
disc.DiscSectorCount = discLastTrk.LastSector + 1;
MessageManager::Log("---- DISC TRACKS ----");
int i = 1;

View file

@ -6,7 +6,8 @@
enum class TrackFormat
{
Audio,
Mode1_2352
Mode1_2352,
Mode1_2048
};
struct DiscPosition
@ -61,6 +62,16 @@ struct TrackInfo
uint32_t FirstSector;
uint32_t LastSector;
uint32_t GetSectorSize()
{
switch(Format) {
default:
case TrackFormat::Audio: return 2352;
case TrackFormat::Mode1_2352: return 2352;
case TrackFormat::Mode1_2048: return 2048;
}
}
};
struct DiscInfo
@ -101,16 +112,19 @@ struct DiscInfo
void ReadDataSector(uint32_t sector, deque<uint8_t>& outData)
{
constexpr int SectorHeaderSize = 16;
constexpr int Mode1_2352_SectorHeaderSize = 16;
int32_t track = GetTrack(sector);
if(track < 0) {
LogDebug("Invalid sector/track (or inside pregap that is not available)");
//TODO support reading pregap when it's ava
LogDebug("Invalid sector/track (or inside pregap)");
outData.insert(outData.end(), 2048, 0);
} else {
TrackInfo& trk = Tracks[track];
uint32_t byteOffset = trk.FileOffset + (sector - trk.FirstSector) * DiscInfo::SectorSize;
if(!Files[trk.FileIndex].ReadChunk(outData, byteOffset + SectorHeaderSize, 2048)) {
uint32_t sectorSize = trk.GetSectorSize();
uint32_t sectorHeaderSize = trk.Format == TrackFormat::Mode1_2352 ? Mode1_2352_SectorHeaderSize : 0;
uint32_t byteOffset = trk.FileOffset + (sector - trk.FirstSector) * sectorSize;
if(!Files[trk.FileIndex].ReadChunk(outData, byteOffset + sectorHeaderSize, 2048)) {
LogDebug("Invalid read offsets");
}
}