2013-12-19 17:10:14 +00:00
# include "common.h"
2014-06-13 15:41:48 +00:00
Disc * chd_parse ( const wchar * file ) ;
Disc * gdi_parse ( const wchar * file ) ;
Disc * cdi_parse ( const wchar * file ) ;
2013-12-19 17:10:14 +00:00
# if HOST_OS==OS_WINDOWS
2014-06-13 15:41:48 +00:00
Disc * ioctl_parse ( const wchar * file ) ;
2013-12-19 17:10:14 +00:00
# endif
u32 NullDriveDiscType ;
Disc * disc ;
2014-06-13 15:41:48 +00:00
Disc * ( * drivers [ ] ) ( const wchar * path ) =
2013-12-19 17:10:14 +00:00
{
chd_parse ,
gdi_parse ,
cdi_parse ,
# if HOST_OS==OS_WINDOWS
ioctl_parse ,
# endif
0
} ;
u8 q_subchannel [ 96 ] ;
void PatchRegion_0 ( u8 * sector , int size )
{
2014-05-26 12:32:07 +00:00
# ifndef NOT_REICAST
2013-12-19 17:10:14 +00:00
if ( settings . imgread . PatchRegion = = 0 )
return ;
2014-05-26 12:32:07 +00:00
# else
return ;
# endif
2013-12-19 17:10:14 +00:00
u8 * usersect = sector ;
if ( size ! = 2048 )
{
2013-12-23 15:02:56 +00:00
printf ( " PatchRegion_0 -> sector size %d , skipping patch \n " , size ) ;
2013-12-19 17:10:14 +00:00
}
//patch meta info
u8 * p_area_symbol = & usersect [ 0x30 ] ;
2013-12-23 15:02:56 +00:00
memcpy ( p_area_symbol , " JUE " , 8 ) ;
2013-12-19 17:10:14 +00:00
}
void PatchRegion_6 ( u8 * sector , int size )
{
2014-05-26 12:32:07 +00:00
# ifndef NOT_REICAST
2013-12-19 17:10:14 +00:00
if ( settings . imgread . PatchRegion = = 0 )
return ;
2014-05-26 12:32:07 +00:00
# else
return ;
# endif
2013-12-19 17:10:14 +00:00
u8 * usersect = sector ;
if ( size ! = 2048 )
{
2013-12-23 15:02:56 +00:00
printf ( " PatchRegion_6 -> sector size %d , skipping patch \n " , size ) ;
2013-12-19 17:10:14 +00:00
}
//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 ;
}
2013-12-24 00:56:44 +00:00
//if no conversion
2013-12-19 17:10:14 +00:00
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 :
2013-12-23 15:02:56 +00:00
printf ( " Sector conversion from %d to %d not supported \n " , from , to ) ;
2013-12-19 17:10:14 +00:00
break ;
}
return true ;
}
2014-06-13 15:41:48 +00:00
Disc * OpenDisc ( const wchar * fn )
2014-05-26 12:32:07 +00:00
{
2018-10-24 15:37:31 +00:00
Disc * rv = NULL ;
2018-08-27 08:40:08 +00:00
2018-08-06 19:01:15 +00:00
for ( unat i = 0 ; drivers [ i ] & & ! rv ; i + + ) { // ;drivers[i] && !(rv=drivers[i](fn));
rv = drivers [ i ] ( fn ) ;
2018-08-27 08:40:08 +00:00
if ( rv & & cdi_parse = = drivers [ i ] ) {
2018-08-06 19:01:15 +00:00
const wchar warn_str [ ] = " Warning: CDI Image Loaded! \n Many CDI images are known to be defective, GDI or CHD format is preferred. Please only file bug reports when using images known to be good (GDI or CHD). " ;
2018-08-20 16:35:59 +00:00
# ifdef _ANDROID
printf ( warn_str ) ;
# else
msgboxf ( warn_str , MBX_ICONASTERISK ) ; // if (OS_DlgYes!=os_Dialog(OS_DialogYesNo, cdiWarn_S)) rv=0;
# endif
break ;
2018-08-06 19:01:15 +00:00
}
}
2014-05-26 12:32:07 +00:00
return rv ;
}
2018-08-28 17:38:11 +00:00
bool InitDrive_ ( wchar * fn )
2013-12-19 17:10:14 +00:00
{
2018-08-28 17:38:11 +00:00
TermDrive ( ) ;
2013-12-19 17:10:14 +00:00
2018-08-28 17:38:11 +00:00
//try all drivers
disc = OpenDisc ( fn ) ;
2013-12-19 17:10:14 +00:00
2018-08-28 17:38:11 +00:00
if ( disc ! = 0 )
{
printf ( " gdrom: Opened image \" %s \" \n " , fn ) ;
NullDriveDiscType = Busy ;
2014-05-26 12:32:07 +00:00
# ifndef NOT_REICAST
2018-08-28 17:38:11 +00:00
libCore_gdrom_disc_change ( ) ;
2014-05-26 12:32:07 +00:00
# endif
2018-08-28 17:38:11 +00:00
// Sleep(400); //busy for a bit // what, really ?
return true ;
}
else
{
printf ( " gdrom: Failed to open image \" %s \" \n " , fn ) ;
NullDriveDiscType = NoDisk ; //no disc :)
}
return false ;
2013-12-19 17:10:14 +00:00
}
2014-05-26 12:32:07 +00:00
# ifndef NOT_REICAST
2018-08-28 17:38:11 +00:00
bool InitDrive ( u32 fileflags )
2013-12-19 17:10:14 +00:00
{
if ( settings . imgread . LoadDefaultImage )
{
2018-08-28 17:38:11 +00:00
printf ( " Loading default image \" %s \" \n " , settings . imgread . DefaultImage ) ;
if ( ! InitDrive_ ( settings . imgread . DefaultImage ) )
2013-12-19 17:10:14 +00:00
{
2018-08-28 17:38:11 +00:00
msgboxf ( " Default image \" %s \" failed to load " , MBX_ICONERROR , settings . imgread . DefaultImage ) ;
2013-12-19 17:10:14 +00:00
return false ;
}
else
return true ;
}
2018-08-28 17:38:11 +00:00
// FIXME: Data loss if buffer is too small
wchar fn [ 512 ] ;
strncpy ( fn , settings . imgread . LastImage , sizeof ( fn ) ) ;
fn [ sizeof ( fn ) - 1 ] = ' \0 ' ;
2013-12-19 17:10:14 +00:00
# ifdef BUILD_DREAMCAST
2018-08-28 17:38:11 +00:00
int gfrv = GetFile ( fn , 0 , fileflags ) ;
2013-12-19 17:10:14 +00:00
# else
2018-08-28 17:38:11 +00:00
int gfrv = 0 ;
2013-12-19 17:10:14 +00:00
# endif
2018-08-28 17:38:11 +00:00
if ( gfrv = = 0 )
{
NullDriveDiscType = NoDisk ;
gd_setdisc ( ) ;
sns_asc = 0x29 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return true ;
}
else if ( gfrv = = - 1 )
{
return false ;
}
// FIXME: Data loss if buffer is too small
strncpy ( settings . imgread . LastImage , fn , sizeof ( settings . imgread . LastImage ) ) ;
settings . imgread . LastImage [ sizeof ( settings . imgread . LastImage ) - 1 ] = ' \0 ' ;
2016-02-22 17:38:57 +00:00
2014-03-15 11:42:17 +00:00
SaveSettings ( ) ;
2018-08-28 17:38:11 +00:00
if ( ! InitDrive_ ( fn ) )
2014-03-15 11:42:17 +00:00
{
2018-08-28 17:38:11 +00:00
//msgboxf("Selected image failed to load",MBX_ICONERROR);
NullDriveDiscType = NoDisk ;
gd_setdisc ( ) ;
sns_asc = 0x29 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return true ;
}
else
{
return true ;
2014-03-15 11:42:17 +00:00
}
}
bool DiscSwap ( u32 fileflags )
{
if ( settings . imgread . LoadDefaultImage )
{
2018-08-28 17:38:11 +00:00
printf ( " Loading default image \" %s \" \n " , settings . imgread . DefaultImage ) ;
if ( ! InitDrive_ ( settings . imgread . DefaultImage ) )
2014-03-15 11:42:17 +00:00
{
2018-08-28 17:38:11 +00:00
msgboxf ( " Default image \" %s \" failed to load " , MBX_ICONERROR , settings . imgread . DefaultImage ) ;
2014-03-15 11:42:17 +00:00
return false ;
}
else
return true ;
}
2018-08-28 17:38:11 +00:00
// FIXME: Data loss if buffer is too small
wchar fn [ 512 ] ;
strncpy ( fn , settings . imgread . LastImage , sizeof ( fn ) ) ;
fn [ sizeof ( fn ) - 1 ] = ' \0 ' ;
2016-02-22 17:38:57 +00:00
2014-03-15 11:42:17 +00:00
# ifdef BUILD_DREAMCAST
2018-08-28 17:38:11 +00:00
int gfrv = GetFile ( fn , 0 , fileflags ) ;
2014-03-15 11:42:17 +00:00
# else
2018-08-28 17:38:11 +00:00
int gfrv = 0 ;
2014-03-15 11:42:17 +00:00
# endif
2018-08-28 17:38:11 +00:00
if ( gfrv = = 0 )
{
NullDriveDiscType = Open ;
gd_setdisc ( ) ;
sns_asc = 0x28 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return true ;
}
else if ( gfrv = = - 1 )
{
sns_asc = 0x28 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return false ;
}
// FIXME: Data loss if buffer is too small
strncpy ( settings . imgread . LastImage , fn , sizeof ( settings . imgread . LastImage ) ) ;
settings . imgread . LastImage [ sizeof ( settings . imgread . LastImage ) - 1 ] = ' \0 ' ;
SaveSettings ( ) ;
if ( ! InitDrive_ ( fn ) )
{
//msgboxf("Selected image failed to load",MBX_ICONERROR);
NullDriveDiscType = Open ;
gd_setdisc ( ) ;
sns_asc = 0x28 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return true ;
}
else
{
sns_asc = 0x28 ;
sns_ascq = 0x00 ;
sns_key = 0x6 ;
return true ;
}
2013-12-19 17:10:14 +00:00
}
2014-05-26 12:32:07 +00:00
# endif
2013-12-19 17:10:14 +00:00
void TermDrive ( )
{
if ( disc ! = 0 )
delete disc ;
disc = 0 ;
}
//
//convert our nice toc struct to dc's native one :)
u32 CreateTrackInfo ( u32 ctrl , u32 addr , u32 fad )
{
u8 p [ 4 ] ;
p [ 0 ] = ( ctrl < < 4 ) | ( addr < < 0 ) ;
p [ 1 ] = fad > > 16 ;
p [ 2 ] = fad > > 8 ;
p [ 3 ] = fad > > 0 ;
return * ( u32 * ) p ;
}
u32 CreateTrackInfo_se ( u32 ctrl , u32 addr , u32 tracknum )
{
u8 p [ 4 ] ;
p [ 0 ] = ( ctrl < < 4 ) | ( addr < < 0 ) ;
p [ 1 ] = tracknum ;
p [ 2 ] = 0 ;
p [ 3 ] = 0 ;
return * ( u32 * ) p ;
}
void GetDriveSector ( u8 * buff , u32 StartSector , u32 SectorCount , u32 secsz )
{
//printf("GD: read %08X, %d\n",StartSector,SectorCount);
if ( disc )
{
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 , 0xFFFFFFFF , 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 ;
}
2013-12-24 00:56:44 +00:00
//Generate the TOC info
2013-12-19 17:10:14 +00:00
//-1 for 1..99 0 ..98
2018-08-27 08:40:08 +00:00
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 ) ;
2013-12-19 17:10:14 +00:00
if ( disc - > type = = GdRom )
{
//use smaller LEADOUT
if ( area = = SingleDensity )
to [ 101 ] = CreateTrackInfo ( disc - > LeadOut . CTRL , disc - > LeadOut . ADDR , 13085 ) ;
}
else
2013-12-24 00:56:44 +00:00
{
to [ 101 ] = CreateTrackInfo ( disc - > LeadOut . CTRL , disc - > LeadOut . ADDR , disc - > LeadOut . StartFAD ) ;
}
2013-12-19 17:10:14 +00:00
for ( u32 i = first_track - 1 ; i < last_track ; i + + )
{
2018-08-27 08:40:08 +00:00
to [ i ] = CreateTrackInfo ( disc - > tracks [ i ] . CTRL , disc - > tracks [ i ] . ADDR , disc - > tracks [ i ] . StartFAD ) ;
2013-12-19 17:10:14 +00:00
}
}
void GetDriveSessionInfo ( u8 * to , u8 session )
{
if ( ! disc )
return ;
2013-12-24 00:56:44 +00:00
to [ 0 ] = 2 ; //status, will get overwritten anyway
2013-12-19 17:10:14 +00:00
to [ 1 ] = 0 ; //0's
2018-08-27 08:40:08 +00:00
2013-12-19 17:10:14 +00:00
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 )
{
printf ( " Sessions %d \n " , ses - > SessionCount ) ;
for ( u32 i = 0 ; i < ses - > SessionCount ; i + + )
{
printf ( " Session %d: FAD %d,First Track %d \n " , 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 )
{
printf ( " \t Track %d : FAD %d CTRL %d ADR %d \n " , t , toc - > tracks [ t ] . FAD , toc - > tracks [ t ] . Control , toc - > tracks [ t ] . Addr ) ;
}
}
}
printf ( " Session END: FAD END %d \n " , 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 ;
2018-08-27 08:40:08 +00:00
else if ( da & & m1 )
2013-12-19 17:10:14 +00:00
return CdRom_Extra ;
else
return CdRom ;
2018-08-20 16:35:59 +00:00
}