mirror of
https://github.com/libretro/parallel-dc.git
synced 2026-11-07 12:37:53 -10:00
Use file extension to select the right disc driver Better error reporting, less memory leaks and crashes on invalid content Force HLE off when booting BIOS Don't crash if missing BIOS file
389 lines
8.2 KiB
C++
389 lines
8.2 KiB
C++
#include "common.h"
|
|
|
|
Disc* chd_parse(const wchar* file);
|
|
Disc* gdi_parse(const wchar* file);
|
|
Disc* cdi_parse(const wchar* file);
|
|
Disc* cue_parse(const wchar* file);
|
|
|
|
u32 NullDriveDiscType;
|
|
Disc* disc;
|
|
|
|
Disc*(*drivers[])(const wchar* path)=
|
|
{
|
|
chd_parse,
|
|
gdi_parse,
|
|
cdi_parse,
|
|
cue_parse,
|
|
0
|
|
};
|
|
|
|
u8 q_subchannel[96];
|
|
|
|
static void PatchRegion_0(u8* sector,int size)
|
|
{
|
|
if (!settings.imgread.PatchRegion)
|
|
return;
|
|
|
|
u8* usersect=sector;
|
|
|
|
if (size!=2048)
|
|
{
|
|
INFO_LOG(GDROM, "PatchRegion_0 -> sector size %d , skipping patch", size);
|
|
}
|
|
|
|
//patch meta info
|
|
u8* p_area_symbol=&usersect[0x30];
|
|
memcpy(p_area_symbol,"JUE ",8);
|
|
}
|
|
|
|
static void PatchRegion_6(u8* sector,int size)
|
|
{
|
|
if (!settings.imgread.PatchRegion)
|
|
return;
|
|
|
|
u8* usersect=sector;
|
|
|
|
if (size!=2048)
|
|
{
|
|
INFO_LOG(GDROM, "PatchRegion_6 -> sector size %d , skipping patch", size);
|
|
}
|
|
|
|
//patch area symbols
|
|
u8* p_area_text=&usersect[0x700];
|
|
memcpy(&p_area_text[4],"For JAPAN,TAIWAN,PHILIPINES.",28);
|
|
memcpy(&p_area_text[4 + 32],"For USA and CANADA. ",28);
|
|
memcpy(&p_area_text[4 + 32 + 32],"For EUROPE. ",28);
|
|
}
|
|
|
|
bool ConvertSector(u8* in_buff , u8* out_buff , int from , int to,int sector)
|
|
{
|
|
//get subchannel data, if any
|
|
if (from==2448)
|
|
{
|
|
memcpy(q_subchannel,in_buff+2352,96);
|
|
from-=96;
|
|
}
|
|
//if no conversion
|
|
if (to==from)
|
|
{
|
|
memcpy(out_buff,in_buff,to);
|
|
return true;
|
|
}
|
|
switch (to)
|
|
{
|
|
case 2340:
|
|
verify((from==2352));
|
|
memcpy(out_buff,&in_buff[12],2340);
|
|
break;
|
|
case 2328:
|
|
verify((from==2352));
|
|
memcpy(out_buff,&in_buff[24],2328);
|
|
break;
|
|
case 2336:
|
|
verify(from>=2336);
|
|
verify((from==2352));
|
|
memcpy(out_buff,&in_buff[0x10],2336);
|
|
break;
|
|
case 2048:
|
|
verify(from>=2048);
|
|
verify((from==2448) || (from==2352) || (from==2336));
|
|
if ((from == 2352) || (from == 2448))
|
|
{
|
|
if (in_buff[15]==1)
|
|
memcpy(out_buff,&in_buff[0x10],2048); //0x10 -> mode1
|
|
else
|
|
memcpy(out_buff,&in_buff[0x18],2048); //0x18 -> mode2 (all forms ?)
|
|
}
|
|
else
|
|
memcpy(out_buff,&in_buff[0x8],2048); //hmm only possible on mode2.Skip the mode2 header
|
|
break;
|
|
case 2352:
|
|
//if (from >= 2352)
|
|
memcpy(out_buff,&in_buff[0],2352);
|
|
break;
|
|
default :
|
|
INFO_LOG(GDROM, "Sector conversion from %d to %d not supported \n", from , to);
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
Disc* OpenDisc(const wchar* fn)
|
|
{
|
|
Disc* rv;
|
|
|
|
for (int i=0;drivers[i] && !(rv=drivers[i](fn));i++) ;
|
|
|
|
return rv;
|
|
}
|
|
|
|
bool InitDrive_(wchar* fn)
|
|
{
|
|
TermDrive();
|
|
|
|
//try all drivers
|
|
disc = OpenDisc(fn);
|
|
|
|
if (disc != NULL)
|
|
{
|
|
INFO_LOG(GDROM, "gdrom: Opened image \"%s\"", fn);
|
|
NullDriveDiscType = Busy;
|
|
}
|
|
else
|
|
{
|
|
INFO_LOG(GDROM, "gdrom: Failed to open image \"%s\"", fn);
|
|
NullDriveDiscType = NoDisk; //no disc :)
|
|
}
|
|
libCore_gdrom_disc_change();
|
|
|
|
return disc != NULL;
|
|
}
|
|
|
|
bool InitDrive(u32 fileflags)
|
|
{
|
|
if (settings.imgread.LoadDefaultImage)
|
|
{
|
|
INFO_LOG(GDROM, "Loading default image \"%s\"", settings.imgread.DefaultImage);
|
|
if (!InitDrive_(settings.imgread.DefaultImage))
|
|
{
|
|
msgboxf("Default image \"%s\" failed to load", MBX_ICONERROR, settings.imgread.DefaultImage);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
wchar fn[512];
|
|
fn[0] = '\0';
|
|
int gfrv = 0;
|
|
if (settings.System == DC_PLATFORM_DREAMCAST)
|
|
gfrv=GetFile(fn,0,fileflags);
|
|
|
|
switch (gfrv)
|
|
{
|
|
case 0:
|
|
NullDriveDiscType=NoDisk;
|
|
gd_setdisc();
|
|
sns_asc=0x29;
|
|
sns_ascq=0x00;
|
|
sns_key=0x6;
|
|
return true;
|
|
case -1:
|
|
return false;
|
|
}
|
|
|
|
if (!InitDrive_(fn))
|
|
{
|
|
//msgboxf("Selected image failed to load",MBX_ICONERROR);
|
|
NullDriveDiscType=NoDisk;
|
|
gd_setdisc();
|
|
sns_asc=0x29;
|
|
sns_ascq=0x00;
|
|
sns_key=0x6;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void DiscOpenLid()
|
|
{
|
|
TermDrive();
|
|
NullDriveDiscType = Open;
|
|
gd_setdisc();
|
|
sns_asc = 0x29;
|
|
sns_ascq = 0x00;
|
|
sns_key = 0x6;
|
|
}
|
|
|
|
bool DiscSwap(u32 fileflags)
|
|
{
|
|
// These Additional Sense Codes mean "The lid was closed"
|
|
sns_asc = 0x28;
|
|
sns_ascq = 0x00;
|
|
sns_key = 0x6;
|
|
if (settings.imgread.LoadDefaultImage)
|
|
{
|
|
INFO_LOG(GDROM, "Loading default image \"%s\"", settings.imgread.DefaultImage);
|
|
if (!InitDrive_(settings.imgread.DefaultImage))
|
|
{
|
|
msgboxf("Default image \"%s\" failed to load", MBX_ICONERROR, settings.imgread.DefaultImage);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
wchar fn[512];
|
|
fn[0] = '\0';
|
|
int gfrv = 0;
|
|
if (settings.System == DC_PLATFORM_DREAMCAST)
|
|
gfrv=GetFile(fn,0,fileflags);
|
|
if (gfrv == 0)
|
|
{
|
|
NullDriveDiscType=Open;
|
|
gd_setdisc();
|
|
return true;
|
|
}
|
|
else if (gfrv == -1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!InitDrive_(fn))
|
|
{
|
|
//msgboxf("Selected image failed to load",MBX_ICONERROR);
|
|
NullDriveDiscType=Open;
|
|
gd_setdisc();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void TermDrive()
|
|
{
|
|
if (disc != NULL)
|
|
delete disc;
|
|
|
|
disc = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
//convert our nice toc struct to dc's native one :)
|
|
|
|
static u32 CreateTrackInfo(u32 ctrl,u32 addr,u32 fad)
|
|
{
|
|
u8 p[4];
|
|
#ifdef MSB_FIRST
|
|
p[1]=(ctrl<<4)|(addr<<0);
|
|
p[0]=fad>>16;
|
|
p[3]=fad>>8;
|
|
p[2]=fad>>0;
|
|
#else
|
|
p[0]=(ctrl<<4)|(addr<<0);
|
|
p[1]=fad>>16;
|
|
p[2]=fad>>8;
|
|
p[3]=fad>>0;
|
|
#endif
|
|
|
|
return *(u32*)p;
|
|
}
|
|
|
|
static u32 CreateTrackInfo_se(u32 ctrl,u32 addr,u32 tracknum)
|
|
{
|
|
u8 p[4];
|
|
#ifdef MSB_FIRST
|
|
p[1]=(ctrl<<4)|(addr<<0);
|
|
p[0]=tracknum;
|
|
p[3]=0;
|
|
p[2]=0;
|
|
#else
|
|
p[0]=(ctrl<<4)|(addr<<0);
|
|
p[1]=tracknum;
|
|
p[2]=0;
|
|
p[3]=0;
|
|
#endif
|
|
return *(u32*)p;
|
|
}
|
|
|
|
|
|
void GetDriveSector(u8 * buff,u32 StartSector,u32 SectorCount,u32 secsz)
|
|
{
|
|
//printf("GD: read %08X, %d\n",StartSector,SectorCount);
|
|
if (!disc)
|
|
return;
|
|
|
|
disc->ReadSectors(StartSector,SectorCount,buff,secsz);
|
|
|
|
if (disc->type == GdRom && StartSector==45150 && SectorCount==7)
|
|
{
|
|
PatchRegion_0(buff,secsz);
|
|
PatchRegion_6(buff+2048*6,secsz);
|
|
}
|
|
}
|
|
void GetDriveToc(u32* to,DiskArea area)
|
|
{
|
|
if (!disc)
|
|
return;
|
|
memset(to, 0xFF, 102 * 4);
|
|
|
|
//can't get toc on the second area on discs that don't have it
|
|
verify(area != DoubleDensity || disc->type == GdRom);
|
|
|
|
//normal CDs: 1 .. tc
|
|
//GDROM: area0 is 1 .. 2, area1 is 3 ... tc
|
|
|
|
u32 first_track=1;
|
|
u32 last_track=disc->tracks.size();
|
|
if (area==DoubleDensity)
|
|
first_track=3;
|
|
else if (disc->type==GdRom)
|
|
last_track=2;
|
|
|
|
//Generate the TOC info
|
|
|
|
//-1 for 1..99 0 ..98
|
|
to[99] = CreateTrackInfo_se(disc->tracks[first_track-1].CTRL,disc->tracks[first_track-1].ADDR,first_track);
|
|
to[100] = CreateTrackInfo_se(disc->tracks[last_track-1].CTRL,disc->tracks[last_track-1].ADDR,last_track);
|
|
|
|
if (disc->type==GdRom)
|
|
{
|
|
//use smaller LEADOUT
|
|
if (area==SingleDensity)
|
|
to[101] = CreateTrackInfo(disc->LeadOut.CTRL,disc->LeadOut.ADDR,13085);
|
|
}
|
|
else
|
|
to[101] = CreateTrackInfo(disc->LeadOut.CTRL, disc->LeadOut.ADDR, disc->LeadOut.StartFAD);
|
|
|
|
for (u32 i=first_track-1;i<last_track;i++)
|
|
to[i] = CreateTrackInfo(disc->tracks[i].CTRL,disc->tracks[i].ADDR,disc->tracks[i].StartFAD);
|
|
}
|
|
|
|
void GetDriveSessionInfo(u8* to,u8 session)
|
|
{
|
|
if (!disc)
|
|
return;
|
|
to[0]=2;//status, will get overwritten anyway
|
|
to[1]=0;//0's
|
|
|
|
if (session==0)
|
|
{
|
|
to[2]=disc->sessions.size();//count of sessions
|
|
to[3]=disc->EndFAD>>16;//fad is sessions end
|
|
to[4]=disc->EndFAD>>8;
|
|
to[5]=disc->EndFAD>>0;
|
|
}
|
|
else
|
|
{
|
|
to[2]=disc->sessions[session-1].FirstTrack;//start track of this session
|
|
to[3]=disc->sessions[session-1].StartFAD>>16;//fad is session start
|
|
to[4]=disc->sessions[session-1].StartFAD>>8;
|
|
to[5]=disc->sessions[session-1].StartFAD>>0;
|
|
}
|
|
}
|
|
|
|
void printtoc(TocInfo* toc,SessionInfo* ses)
|
|
{
|
|
INFO_LOG(GDROM, "Sessions %d", ses->SessionCount);
|
|
for (u32 i=0;i<ses->SessionCount;i++)
|
|
{
|
|
INFO_LOG(GDROM, "Session %d: FAD %d,First Track %d", i + 1, ses->SessionFAD[i], ses->SessionStart[i]);
|
|
for (u32 t=toc->FistTrack-1;t<=toc->LastTrack;t++)
|
|
{
|
|
if (toc->tracks[t].Session==i+1)
|
|
{
|
|
INFO_LOG(GDROM, " Track %d : FAD %d CTRL %d ADR %d", t, toc->tracks[t].FAD, toc->tracks[t].Control, toc->tracks[t].Addr);
|
|
}
|
|
}
|
|
}
|
|
INFO_LOG(GDROM, "Session END: FAD END %d", ses->SessionsEndFAD);
|
|
}
|
|
|
|
DiscType GuessDiscType(bool m1, bool m2, bool da)
|
|
{
|
|
if ((m1==true) && (da==false) && (m2==false))
|
|
return CdRom;
|
|
else if (m2)
|
|
return CdRom_XA;
|
|
else if (da && m1)
|
|
return CdRom_Extra;
|
|
return CdRom;
|
|
}
|