flycast/core/imgread/cdi.cpp

156 lines
3.8 KiB
C++
Raw Normal View History

2013-12-19 17:10:14 +00:00
#include "common.h"
#include "stdclass.h"
2013-12-19 17:10:14 +00:00
#include "deps/chdpsr/cdipsr.h"
Disc* cdi_parse(const char* file, std::vector<u8> *digest)
2013-12-19 17:10:14 +00:00
{
if (get_file_extension(file) != "cdi")
return nullptr;
FILE *fsource = nowide::fopen(file, "rb");
2013-12-19 17:10:14 +00:00
if (fsource == nullptr)
{
WARN_LOG(GDROM, "Cannot open file '%s' errno %d", file, errno);
throw FlycastException(std::string("Cannot open CDI file ") + file);
}
2013-12-19 17:10:14 +00:00
image_s image = { 0 };
track_s track = { 0 };
if (!CDI_init(fsource, &image, file))
{
std::fclose(fsource);
throw FlycastException(std::string("Invalid CDI file ") + file);
}
2013-12-19 17:10:14 +00:00
CDI_get_sessions(fsource,&image);
Disc* rv= new Disc();
2013-12-19 17:10:14 +00:00
image.remaining_sessions = image.sessions;
/////////////////////////////////////////////////////////////// Loop sessions
2013-12-19 17:10:14 +00:00
bool ft=true, CD_M2=false,CD_M1=false,CD_DA=false;
while(image.remaining_sessions > 0)
{
ft=true;
image.global_current_session++;
CDI_get_tracks (fsource, &image);
image.header_position = std::ftell(fsource);
2013-12-19 17:10:14 +00:00
if (image.tracks == 0)
2019-07-01 14:10:28 +00:00
INFO_LOG(GDROM, "Open session");
2013-12-19 17:10:14 +00:00
else
{
// Clear cuesheet
2013-12-19 17:10:14 +00:00
image.remaining_tracks = image.tracks;
///////////////////////////////////////////////////////////////// Loop tracks
2013-12-19 17:10:14 +00:00
while(image.remaining_tracks > 0)
{
track.global_current_track++;
track.number = image.tracks - image.remaining_tracks + 1;
CDI_read_track (fsource, &image, &track);
image.header_position = std::ftell(fsource);
2013-12-19 17:10:14 +00:00
// Show info
#if 0
2013-12-19 17:10:14 +00:00
printf("Saving ");
printf("Track: %2d ",track.global_current_track);
printf("Type: ");
switch(track.mode)
{
case 0 : printf("Audio/"); break;
case 1 : printf("Mode1/"); break;
case 2 :
default: printf("Mode2/"); break;
}
printf("%lu ",track.sector_size);
2013-12-19 17:10:14 +00:00
printf("Pregap: %-3ld ",track.pregap_length);
printf("Size: %-6ld ",track.length);
printf("LBA: %-6ld ",track.start_lba);
#endif
2013-12-19 17:10:14 +00:00
if (ft)
{
ft = false;
2013-12-19 17:10:14 +00:00
Session s;
s.StartFAD = track.pregap_length + track.start_lba;
s.FirstTrack = (u8)track.global_current_track;
2013-12-19 17:10:14 +00:00
rv->sessions.push_back(s);
}
Track t;
if (track.mode==2)
CD_M2=true;
if (track.mode==1)
CD_M1=true;
if (track.mode==0)
CD_DA=true;
t.ADDR=1;//hmm is that ok ?
t.CTRL=track.mode==0?0:4;
t.StartFAD=track.start_lba+track.pregap_length;
t.EndFAD=t.StartFAD+track.length-1;
FILE *trackFile = nowide::fopen(file, "rb");
if (trackFile == nullptr)
{
delete rv;
std::fclose(fsource);
WARN_LOG(GDROM, "Cannot re-open file '%s' errno %d", file, errno);
throw FlycastException("Cannot re-open CDI file");
}
t.file = new RawTrackFile(trackFile, track.position + track.pregap_length * track.sector_size, t.StartFAD, track.sector_size);
2013-12-19 17:10:14 +00:00
rv->tracks.push_back(t);
if (track.length < 0)
2019-07-01 14:10:28 +00:00
WARN_LOG(GDROM, "Negative track size found. You must extract image with /pregap option");
2013-12-19 17:10:14 +00:00
std::fseek(fsource, track.position, SEEK_SET);
if (track.total_length < track.length + track.pregap_length)
2013-12-19 17:10:14 +00:00
{
WARN_LOG(GDROM, "This track seems truncated. Skipping...");
// FIXME that can't be right
std::fseek(fsource, track.total_length, SEEK_CUR);
2013-12-19 17:10:14 +00:00
}
else
{
std::fseek(fsource, track.total_length * track.sector_size, SEEK_CUR);
rv->EndFAD=track.start_lba +track.total_length;
}
track.position = std::ftell(fsource);
2013-12-19 17:10:14 +00:00
std::fseek(fsource, image.header_position, SEEK_SET);
2013-12-19 17:10:14 +00:00
image.remaining_tracks--;
}
}
CDI_skip_next_session(fsource, &image);
2013-12-19 17:10:14 +00:00
image.remaining_sessions--;
}
if (digest != nullptr)
*digest = MD5Sum().add(fsource).getDigest();
std::fclose(fsource);
2013-12-19 17:10:14 +00:00
rv->type=GuessDiscType(CD_M1,CD_M2,CD_DA);
rv->LeadOut.StartFAD=rv->EndFAD;
rv->LeadOut.ADDR=0;
rv->LeadOut.CTRL=0;
return rv;
}