Files
Flyinghead bc5be5e695 force HLE off to boot BIOS. Avoid crash when loading invalid content
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
2020-01-31 12:32:05 +01:00

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;
}