2011-05-08 09:07:46 +00:00
using System ;
2012-11-17 22:16:09 +00:00
using System.Linq ;
using System.Diagnostics ;
2012-10-29 08:37:22 +00:00
using System.Runtime.InteropServices ;
2011-08-08 01:48:31 +00:00
using System.Reflection ;
2011-05-08 09:07:46 +00:00
using System.Collections.Generic ;
2015-07-02 05:23:16 +00:00
using System.Threading ;
using System.Threading.Tasks ;
2011-05-08 09:07:46 +00:00
using System.IO ;
2013-11-03 23:45:44 +00:00
using BizHawk.Emulation.DiscSystem ;
2011-06-20 09:09:21 +00:00
//cue format preferences notes
//pcejin -
//does not like session commands
//it can handle binpercue
//it seems not to be able to handle binpertrack, or maybe i am doing something wrong (still havent ruled it out)
2013-11-03 12:28:33 +00:00
namespace BizHawk.Client.DiscoHawk
2011-05-08 09:07:46 +00:00
{
2013-08-19 01:43:18 +00:00
static class Program
2011-05-08 09:07:46 +00:00
{
2013-08-19 01:43:18 +00:00
static Program ( )
{
#if WINDOWS
2013-11-03 13:19:36 +00:00
//http://www.codeproject.com/Articles/310675/AppDomain-AssemblyResolve-Event-Tips
2013-08-19 01:43:18 +00:00
// this will look in subdirectory "dll" to load pinvoked stuff
string dllDir = System . IO . Path . Combine ( GetExeDirectoryAbsolute ( ) , "dll" ) ;
SetDllDirectory ( dllDir ) ;
2017-02-23 11:27:27 +00:00
//in case assembly resolution fails, such as if we moved them into the dll subdiretory, this event handler can reroute to them
AppDomain . CurrentDomain . AssemblyResolve + = new ResolveEventHandler ( CurrentDomain_AssemblyResolve ) ;
2013-08-19 01:43:18 +00:00
//but before we even try doing that, whack the MOTW from everything in that directory (thats a dll)
//otherwise, some people will have crashes at boot-up due to .net security disliking MOTW.
//some people are getting MOTW through a combination of browser used to download bizhawk, and program used to dearchive it
WhackAllMOTW ( dllDir ) ;
#endif
}
[STAThread]
static void Main ( string [ ] args )
{
SubMain ( args ) ;
}
2013-08-19 03:04:31 +00:00
//NoInlining should keep this code from getting jammed into Main() which would create dependencies on types which havent been setup by the resolver yet... or something like that
2013-08-19 01:43:18 +00:00
[DllImport("user32.dll", SetLastError = true)]
public static extern bool ChangeWindowMessageFilterEx ( IntPtr hWnd , uint msg , ChangeWindowMessageFilterExAction action , ref CHANGEFILTERSTRUCT changeInfo ) ;
2014-12-11 03:09:53 +00:00
private static class Win32
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary ( string dllToLoad ) ;
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress ( IntPtr hModule , string procedureName ) ;
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary ( IntPtr hModule ) ;
}
2013-08-19 01:43:18 +00:00
static void SubMain ( string [ ] args )
{
2014-12-11 03:09:53 +00:00
//MICROSOFT BROKE DRAG AND DROP IN WINDOWS 7. IT DOESNT WORK ANYMORE
//WELL, OBVIOUSLY IT DOES SOMETIMES. I DONT REMEMBER THE DETAILS OR WHY WE HAD TO DO THIS SHIT
2013-11-03 13:19:36 +00:00
#if WINDOWS
2014-12-11 03:09:53 +00:00
//BUT THE FUNCTION WE NEED DOESNT EXIST UNTIL WINDOWS 7, CONVENIENTLY
//SO CHECK FOR IT
IntPtr lib = Win32 . LoadLibrary ( "user32.dll" ) ;
IntPtr proc = Win32 . GetProcAddress ( lib , "ChangeWindowMessageFilterEx" ) ;
if ( proc ! = IntPtr . Zero )
{
ChangeWindowMessageFilter ( WM_DROPFILES , ChangeWindowMessageFilterFlags . Add ) ;
ChangeWindowMessageFilter ( WM_COPYDATA , ChangeWindowMessageFilterFlags . Add ) ;
ChangeWindowMessageFilter ( 0x0049 , ChangeWindowMessageFilterFlags . Add ) ;
}
Win32 . FreeLibrary ( lib ) ;
2013-11-03 13:19:36 +00:00
#endif
2013-08-19 01:43:18 +00:00
var ffmpegPath = Path . Combine ( GetExeDirectoryAbsolute ( ) , "ffmpeg.exe" ) ;
if ( ! File . Exists ( ffmpegPath ) )
ffmpegPath = Path . Combine ( Path . Combine ( GetExeDirectoryAbsolute ( ) , "dll" ) , "ffmpeg.exe" ) ;
2013-11-03 23:45:44 +00:00
FFMpeg . FFMpegPath = ffmpegPath ;
2013-08-19 01:43:18 +00:00
AudioExtractor . FFmpegPath = ffmpegPath ;
new DiscoHawk ( ) . Run ( args ) ;
}
2011-08-08 01:48:31 +00:00
2013-11-03 13:19:36 +00:00
public static string GetExeDirectoryAbsolute ( )
2011-08-08 01:48:31 +00:00
{
2012-10-29 08:37:22 +00:00
var uri = new Uri ( Assembly . GetEntryAssembly ( ) . GetName ( ) . CodeBase ) ;
string module = uri . LocalPath + System . Web . HttpUtility . UrlDecode ( uri . Fragment ) ;
return Path . GetDirectoryName ( module ) ;
2011-08-08 01:48:31 +00:00
}
2012-10-29 08:37:22 +00:00
static Assembly CurrentDomain_AssemblyResolve ( object sender , ResolveEventArgs args )
{
2013-08-19 03:04:31 +00:00
lock ( AppDomain . CurrentDomain )
{
var asms = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var asm in asms )
if ( asm . FullName = = args . Name )
return asm ;
//load missing assemblies by trying to find them in the dll directory
string dllname = new AssemblyName ( args . Name ) . Name + ".dll" ;
string directory = Path . Combine ( GetExeDirectoryAbsolute ( ) , "dll" ) ;
string fname = Path . Combine ( directory , dllname ) ;
if ( ! File . Exists ( fname ) ) return null ;
//it is important that we use LoadFile here and not load from a byte array; otherwise mixed (managed/unamanged) assemblies can't load
return Assembly . LoadFile ( fname ) ;
}
2012-10-29 08:37:22 +00:00
}
//declared here instead of a more usual place to avoid dependencies on the more usual place
#if WINDOWS
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory ( string lpPathName ) ;
2013-07-27 00:30:08 +00:00
[DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern bool DeleteFileW ( [ MarshalAs ( UnmanagedType . LPWStr ) ] string lpFileName ) ;
static void RemoveMOTW ( string path )
{
DeleteFileW ( path + ":Zone.Identifier" ) ;
}
static void WhackAllMOTW ( string dllDir )
{
var todo = new Queue < DirectoryInfo > ( new [ ] { new DirectoryInfo ( dllDir ) } ) ;
while ( todo . Count > 0 )
{
var di = todo . Dequeue ( ) ;
foreach ( var disub in di . GetDirectories ( ) ) todo . Enqueue ( disub ) ;
foreach ( var fi in di . GetFiles ( "*.dll" ) )
RemoveMOTW ( fi . FullName ) ;
2014-11-06 19:04:51 +00:00
foreach ( var fi in di . GetFiles ( "*.exe" ) )
RemoveMOTW ( fi . FullName ) ;
2013-07-27 00:30:08 +00:00
}
}
2012-10-29 08:37:22 +00:00
#endif
2013-05-03 18:12:36 +00:00
private const UInt32 WM_DROPFILES = 0x0233 ;
private const UInt32 WM_COPYDATA = 0x004A ;
[DllImport("user32")]
public static extern bool ChangeWindowMessageFilter ( uint msg , ChangeWindowMessageFilterFlags flags ) ;
public enum ChangeWindowMessageFilterFlags : uint
{
Add = 1 , Remove = 2
} ;
2013-11-03 13:19:36 +00:00
public enum MessageFilterInfo : uint
{
None = 0 , AlreadyAllowed = 1 , AlreadyDisAllowed = 2 , AllowedHigher = 3
} ;
public enum ChangeWindowMessageFilterExAction : uint
{
Reset = 0 , Allow = 1 , DisAllow = 2
} ;
[StructLayout(LayoutKind.Sequential)]
public struct CHANGEFILTERSTRUCT
{
public uint size ;
public MessageFilterInfo info ;
}
2013-08-19 01:43:18 +00:00
}
2012-10-29 08:37:22 +00:00
2013-08-19 01:43:18 +00:00
class DiscoHawk
{
2015-07-08 07:56:59 +00:00
static List < string > FindCuesRecurse ( string dir )
2015-07-02 05:23:16 +00:00
{
List < string > ret = new List < string > ( ) ;
Queue < string > dpTodo = new Queue < string > ( ) ;
dpTodo . Enqueue ( dir ) ;
for ( ; ; )
{
string dpCurr ;
if ( dpTodo . Count = = 0 )
break ;
dpCurr = dpTodo . Dequeue ( ) ;
2015-07-08 07:56:59 +00:00
foreach ( var fi in new DirectoryInfo ( dpCurr ) . GetFiles ( "*.cue" ) )
2015-07-02 05:23:16 +00:00
{
2015-07-08 07:56:59 +00:00
ret . Add ( fi . FullName ) ;
}
2015-07-02 05:23:16 +00:00
Parallel . ForEach ( new DirectoryInfo ( dpCurr ) . GetDirectories ( ) , ( di ) = >
{
lock ( dpTodo )
dpTodo . Enqueue ( di . FullName ) ;
} ) ;
}
return ret ;
}
2013-08-19 01:43:18 +00:00
public void Run ( string [ ] args )
2011-05-08 09:07:46 +00:00
{
2015-06-23 18:57:11 +00:00
if ( args . Length = = 0 )
2011-08-07 03:21:03 +00:00
{
2011-09-01 01:24:26 +00:00
var dialog = new MainDiscoForm ( ) ;
2011-08-07 03:21:03 +00:00
dialog . ShowDialog ( ) ;
2011-08-07 09:05:10 +00:00
return ;
2011-08-07 03:21:03 +00:00
}
2015-06-23 18:57:11 +00:00
2015-07-02 05:23:16 +00:00
bool scanCues = false ;
string dirArg = null ;
2015-06-23 18:57:11 +00:00
string infile = null ;
var loadDiscInterface = DiscInterface . BizHawk ;
var compareDiscInterfaces = new List < DiscInterface > ( ) ;
bool hawk = false ;
int idx = 0 ;
while ( idx < args . Length )
2014-12-04 05:40:10 +00:00
{
2015-06-23 18:57:11 +00:00
string a = args [ idx + + ] ;
string au = a . ToUpperInvariant ( ) ;
if ( au = = "LOAD" )
loadDiscInterface = ( DiscInterface ) Enum . Parse ( typeof ( DiscInterface ) , args [ idx + + ] , true ) ;
else if ( au = = "COMPARE" )
compareDiscInterfaces . Add ( ( DiscInterface ) Enum . Parse ( typeof ( DiscInterface ) , args [ idx + + ] , true ) ) ;
else if ( au = = "HAWK" )
hawk = true ;
2015-07-02 05:23:16 +00:00
else if ( au = = "CUEDIR" )
{
dirArg = args [ idx + + ] ;
scanCues = true ;
}
2015-06-23 18:57:11 +00:00
else infile = a ;
2014-12-04 05:40:10 +00:00
}
2015-06-23 18:57:11 +00:00
2015-07-01 08:55:59 +00:00
if ( hawk )
{
2015-07-02 05:23:16 +00:00
if ( infile = = null )
return ;
2015-07-01 08:55:59 +00:00
//TODO - write it out
var dmj = new DiscMountJob { IN_DiscInterface = loadDiscInterface , IN_FromPath = infile } ;
dmj . Run ( ) ;
//var disc = dmj.OUT_Disc;
}
2015-06-23 18:57:11 +00:00
2015-07-02 05:23:16 +00:00
bool verbose = true ;
2015-06-23 18:57:11 +00:00
2015-07-02 05:23:16 +00:00
if ( scanCues )
{
verbose = false ;
2015-07-08 07:56:59 +00:00
var todo = FindCuesRecurse ( dirArg ) ;
2015-07-02 05:23:16 +00:00
var po = new ParallelOptions ( ) ;
var cts = new CancellationTokenSource ( ) ;
po . CancellationToken = cts . Token ;
po . MaxDegreeOfParallelism = 1 ;
2015-07-03 07:40:45 +00:00
//po.MaxDegreeOfParallelism = System.Environment.ProcessorCount - 2; //I'm disk or network bound, no sense hammering this
2015-07-02 05:23:16 +00:00
if ( po . MaxDegreeOfParallelism < 0 ) po . MaxDegreeOfParallelism = 1 ;
object olock = new object ( ) ;
int ctr = 0 ;
2015-07-03 07:40:45 +00:00
bool blocked = false ;
2015-07-02 05:23:16 +00:00
try
2015-07-01 08:55:59 +00:00
{
2015-07-02 05:23:16 +00:00
Parallel . ForEach ( todo , po , ( fp ) = >
{
lock ( olock )
{
ctr + + ;
int strlen = todo . Count . ToString ( ) . Length ;
string fmt = string . Format ( "{{0,{0}}}/{{1,{0}}} {{2}}" , strlen ) ;
Console . WriteLine ( fmt , ctr , todo . Count , Path . GetFileNameWithoutExtension ( fp ) ) ;
2015-07-03 07:40:45 +00:00
//if (fp.Contains("Break Out"))
// blocked = false;
2015-07-02 05:23:16 +00:00
}
2015-07-03 07:40:45 +00:00
if ( ! blocked )
foreach ( var cmpif in compareDiscInterfaces )
2015-07-02 05:23:16 +00:00
{
2015-07-03 07:40:45 +00:00
StringWriter sw = new StringWriter ( ) ;
bool success = CompareFile ( fp , loadDiscInterface , cmpif , verbose , cts , sw ) ;
if ( ! success )
{
lock ( Console . Out )
Console . Out . Write ( sw . ToString ( ) ) ;
cts . Cancel ( ) ;
return ;
}
2015-07-02 05:23:16 +00:00
}
} ) ;
2015-07-01 08:55:59 +00:00
}
2015-07-02 05:23:16 +00:00
catch ( AggregateException ae ) {
Console . WriteLine ( ae . ToString ( ) ) ;
}
2015-07-03 07:40:45 +00:00
catch ( OperationCanceledException oce )
{
Console . WriteLine ( oce . ToString ( ) ) ;
}
2015-07-02 05:23:16 +00:00
Console . WriteLine ( "--TERMINATED--" ) ;
return ;
}
if ( compareDiscInterfaces . Count ! = 0 )
{
StringWriter sw = new StringWriter ( ) ;
foreach ( var cmpif in compareDiscInterfaces )
CompareFile ( infile , loadDiscInterface , cmpif , verbose , null , sw ) ;
sw . Flush ( ) ;
string results = sw . ToString ( ) ;
var cr = new ComparisonResults ( ) ;
cr . textBox1 . Text = results ;
cr . ShowDialog ( ) ;
}
2015-07-01 08:55:59 +00:00
2015-07-02 05:23:16 +00:00
} //Run()
2015-06-23 18:57:11 +00:00
2015-07-02 05:23:16 +00:00
static bool CompareFile ( string infile , DiscInterface loadDiscInterface , DiscInterface cmpif , bool verbose , CancellationTokenSource cancelToken , StringWriter sw )
{
2015-07-03 07:40:45 +00:00
Disc src_disc = null , dst_disc = null ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
try
2015-07-02 05:23:16 +00:00
{
2015-07-03 07:40:45 +00:00
bool success = false ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
sw . WriteLine ( "BEGIN COMPARE: {0}\nSRC {1} vs DST {2}" , infile , loadDiscInterface , cmpif ) ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
//reload the original disc, with new policies as needed
var dmj = new DiscMountJob { IN_DiscInterface = loadDiscInterface , IN_FromPath = infile } ;
if ( cmpif = = DiscInterface . MednaDisc )
{
dmj . IN_DiscMountPolicy . CUE_PregapContradictionModeA = false ;
}
dmj . Run ( ) ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
src_disc = dmj . OUT_Disc ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
var dst_dmj = new DiscMountJob { IN_DiscInterface = cmpif , IN_FromPath = infile } ;
dst_dmj . Run ( ) ;
dst_disc = dst_dmj . OUT_Disc ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
var src_dsr = new DiscSectorReader ( src_disc ) ;
var dst_dsr = new DiscSectorReader ( dst_disc ) ;
2015-07-02 05:23:16 +00:00
2015-07-08 04:12:06 +00:00
var src_toc = src_disc . TOC ;
var dst_toc = dst_disc . TOC ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
var src_databuf = new byte [ 2448 ] ;
var dst_databuf = new byte [ 2448 ] ;
2015-07-02 05:23:16 +00:00
2015-07-08 04:12:06 +00:00
Action < DiscTOC . TOCItem > sw_dump_toc_one = ( item ) = >
2015-07-03 07:40:45 +00:00
{
if ( ! item . Exists )
sw . Write ( "(---missing---)" ) ;
else
2015-07-19 04:23:15 +00:00
sw . Write ( "({0:X2} - {1})" , ( byte ) item . Control , item . LBA ) ;
2015-07-03 07:40:45 +00:00
} ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
Action < int > sw_dump_toc = ( index ) = >
{
sw . Write ( "SRC TOC#{0,3} " , index ) ; sw_dump_toc_one ( src_toc . TOCItems [ index ] ) ; sw . WriteLine ( ) ;
sw . Write ( "DST TOC#{0,3} " , index ) ; sw_dump_toc_one ( dst_toc . TOCItems [ index ] ) ; sw . WriteLine ( ) ;
} ;
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
//verify sector count
2015-07-08 03:29:11 +00:00
if ( src_disc . Session1 . LeadoutLBA ! = dst_disc . Session1 . LeadoutLBA )
2015-06-23 18:57:11 +00:00
{
2015-07-08 03:29:11 +00:00
sw . Write ( "LeadoutTrack.LBA {0} vs {1}\n" , src_disc . Session1 . LeadoutTrack . LBA , dst_disc . Session1 . LeadoutTrack . LBA ) ;
2015-07-03 07:40:45 +00:00
goto SKIPPO ;
2015-06-23 18:57:11 +00:00
}
2015-07-03 07:40:45 +00:00
//verify TOC match
2015-07-08 04:12:06 +00:00
if ( src_disc . TOC . FirstRecordedTrackNumber ! = dst_disc . TOC . FirstRecordedTrackNumber
| | src_disc . TOC . LastRecordedTrackNumber ! = dst_disc . TOC . LastRecordedTrackNumber )
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
sw . WriteLine ( "Mismatch of RecordedTrackNumbers: {0}-{1} vs {2}-{3}" ,
2015-07-08 04:12:06 +00:00
src_disc . TOC . FirstRecordedTrackNumber , src_disc . TOC . LastRecordedTrackNumber ,
dst_disc . TOC . FirstRecordedTrackNumber , dst_disc . TOC . LastRecordedTrackNumber
2015-07-03 07:40:45 +00:00
) ;
goto SKIPPO ;
2015-06-23 18:57:11 +00:00
}
2015-07-02 05:23:16 +00:00
2015-07-03 07:40:45 +00:00
bool badToc = false ;
for ( int t = 0 ; t < 101 ; t + + )
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
if ( src_toc . TOCItems [ t ] . Exists ! = dst_toc . TOCItems [ t ] . Exists
| | src_toc . TOCItems [ t ] . Control ! = dst_toc . TOCItems [ t ] . Control
2015-07-19 04:23:15 +00:00
| | src_toc . TOCItems [ t ] . LBA ! = dst_toc . TOCItems [ t ] . LBA
2015-07-03 07:40:45 +00:00
)
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
sw . WriteLine ( "Mismatch in TOCItem" ) ;
sw_dump_toc ( t ) ;
badToc = true ;
2015-06-23 18:57:11 +00:00
}
}
2015-07-03 07:40:45 +00:00
if ( badToc )
goto SKIPPO ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
Action < string , int , byte [ ] , int , int > sw_dump_chunk_one = ( comment , lba , buf , addr , count ) = >
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
sw . Write ( "{0} - " , comment ) ;
for ( int i = 0 ; i < count ; i + + )
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
if ( i + addr > = buf . Length ) continue ;
sw . Write ( "{0:X2}{1}" , buf [ addr + i ] , ( i = = count - 1 ) ? " " : " " ) ;
2015-06-23 18:57:11 +00:00
}
2015-07-03 07:40:45 +00:00
sw . WriteLine ( ) ;
} ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
int [ ] offenders = new int [ 12 ] ;
Action < int , int , int , int , int > sw_dump_chunk = ( lba , dispaddr , addr , count , numoffenders ) = >
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
var hashedOffenders = new HashSet < int > ( ) ;
for ( int i = 0 ; i < numoffenders ; i + + ) hashedOffenders . Add ( offenders [ i ] ) ;
sw . Write ( " " ) ;
for ( int i = 0 ; i < count ; i + + ) sw . Write ( ( hashedOffenders . Contains ( dispaddr + i ) ) ? "vvv " : " " ) ;
sw . WriteLine ( ) ;
sw . Write ( " " ) ;
for ( int i = 0 ; i < count ; i + + ) sw . Write ( "{0:X3} " , dispaddr + i , ( i = = count - 1 ) ? " " : " " ) ;
sw . WriteLine ( ) ;
sw . Write ( " " ) ;
sw . Write ( new string ( '-' , count * 4 ) ) ;
sw . WriteLine ( ) ;
sw_dump_chunk_one ( string . Format ( "SRC #{0,6} ({1})" , lba , new Timestamp ( lba ) ) , lba , src_databuf , addr , count ) ;
sw_dump_chunk_one ( string . Format ( "DST #{0,6} ({1})" , lba , new Timestamp ( lba ) ) , lba , dst_databuf , addr , count ) ;
} ;
//verify each sector contents
2015-07-08 03:29:11 +00:00
int nSectors = src_disc . Session1 . LeadoutLBA ;
2015-07-03 07:40:45 +00:00
for ( int lba = - 150 ; lba < nSectors ; lba + + )
{
if ( verbose )
if ( lba % 1000 = = 0 )
2015-07-08 03:29:11 +00:00
Console . WriteLine ( "LBA {0} of {1}" , lba , nSectors ) ;
2015-07-03 07:40:45 +00:00
if ( cancelToken ! = null )
if ( cancelToken . Token . IsCancellationRequested )
return false ;
2015-07-08 21:52:21 +00:00
src_dsr . ReadLBA_2448 ( lba , src_databuf , 0 ) ;
dst_dsr . ReadLBA_2448 ( lba , dst_databuf , 0 ) ;
2015-07-03 07:40:45 +00:00
//check the header
for ( int b = 0 ; b < 16 ; b + + )
{
if ( src_databuf [ b ] ! = dst_databuf [ b ] )
{
sw . WriteLine ( "Mismatch in sector header at byte {0}" , b ) ;
offenders [ 0 ] = b ;
sw_dump_chunk ( lba , 0 , 0 , 16 , 1 ) ;
goto SKIPPO ;
}
}
//check userdata
for ( int b = 16 ; b < 2352 ; b + + )
2015-06-23 18:57:11 +00:00
{
if ( src_databuf [ b ] ! = dst_databuf [ b ] )
{
2015-07-03 07:40:45 +00:00
sw . Write ( "LBA {0} mismatch at userdata byte {1}; terminating sector cmp\n" , lba , b ) ;
goto SKIPPO ;
2015-06-23 18:57:11 +00:00
}
}
2015-07-03 07:40:45 +00:00
//check subchannels
for ( int c = 0 , b = 2352 ; c < 8 ; c + + )
2015-06-23 18:57:11 +00:00
{
2015-07-03 07:40:45 +00:00
int numOffenders = 0 ;
for ( int e = 0 ; e < 12 ; e + + , b + + )
{
if ( src_databuf [ b ] ! = dst_databuf [ b ] )
{
offenders [ numOffenders + + ] = e ;
}
}
if ( numOffenders ! = 0 )
{
sw . Write ( "LBA {0} mismatch(es) at subchannel {1}; terminating sector cmp\n" , lba , ( char ) ( 'P' + c ) ) ;
sw_dump_chunk ( lba , 0 , 2352 + c * 12 , 12 , numOffenders ) ;
goto SKIPPO ;
}
2015-06-24 01:11:06 +00:00
}
2015-07-02 05:23:16 +00:00
}
2015-06-24 01:11:06 +00:00
2015-07-03 07:40:45 +00:00
success = true ;
2015-06-24 01:11:06 +00:00
2015-07-03 07:40:45 +00:00
SKIPPO :
sw . WriteLine ( "END COMPARE" ) ;
sw . WriteLine ( "-----------------------------" ) ;
2015-06-23 18:57:11 +00:00
2015-07-03 07:40:45 +00:00
return success ;
}
finally
{
if ( src_disc ! = null )
src_disc . Dispose ( ) ;
if ( dst_disc ! = null )
dst_disc . Dispose ( ) ;
}
2015-07-02 05:23:16 +00:00
} //CompareFile
2015-06-23 18:57:11 +00:00
2015-07-02 05:23:16 +00:00
} //class DiscoHawk
2011-05-08 09:07:46 +00:00
2012-11-17 22:16:09 +00:00
}
//code to test ECM:
//static class test
//{
// public static void Shuffle<T>(this IList<T> list, Random rng)
// {
// int n = list.Count;
// while (n > 1)
// {
// n--;
// int k = rng.Next(n + 1);
// T value = list[k];
// list[k] = list[n];
// list[n] = value;
// }
// }
// public static void Test()
// {
// var plaindisc = BizHawk.DiscSystem.Disc.FromCuePath("d:\\ecmtest\\test.cue", BizHawk.MainDiscoForm.GetCuePrefs());
// var ecmdisc = BizHawk.DiscSystem.Disc.FromCuePath("d:\\ecmtest\\ecmtest.cue", BizHawk.MainDiscoForm.GetCuePrefs());
// //var prefs = new BizHawk.DiscSystem.CueBinPrefs();
// //prefs.AnnotateCue = false;
// //prefs.OneBlobPerTrack = false;
// //prefs.ReallyDumpBin = true;
// //prefs.SingleSession = true;
// //prefs.DumpToBitbucket = true;
// //var dump = ecmdisc.DumpCueBin("test", prefs);
// //dump.Dump("test", prefs);
// //var prefs = new BizHawk.DiscSystem.CueBinPrefs();
// //prefs.AnnotateCue = false;
// //prefs.OneBlobPerTrack = false;
// //prefs.ReallyDumpBin = true;
// //prefs.SingleSession = true;
// //var dump = ecmdisc.DumpCueBin("test", prefs);
// //dump.Dump(@"D:\ecmtest\myout", prefs);
// int seed = 102;
// for (; ; )
// {
// Console.WriteLine("running seed {0}", seed);
// Random r = new Random(seed);
// seed++;
// byte[] chunkbuf_corlet = new byte[2352 * 20];
// byte[] chunkbuf_mine = new byte[2352 * 20];
// int length = ecmdisc.LBACount * 2352;
// int counter = 0;
// List<Tuple<int, int>> testChunks = new List<Tuple<int, int>>();
// while (counter < length)
// {
// int chunk = r.Next(1, 2352 * 20);
// if (r.Next(20) == 0)
// chunk /= 100;
// if (r.Next(40) == 0)
// chunk = 0;
// if (counter + chunk > length)
// chunk = length - counter;
// testChunks.Add(new Tuple<int, int>(counter, chunk));
// counter += chunk;
// }
// testChunks.Shuffle(r);
// for (int t = 0; t < testChunks.Count; t++)
// {
// //Console.WriteLine("skank");
// var item = testChunks[t];
// //Console.WriteLine("chunk {0} of {3} is {1} bytes @ {2:X8}", t, item.Item2, item.Item1, testChunks.Count);
// plaindisc.ReadLBA_2352_Flat(item.Item1, chunkbuf_corlet, 0, item.Item2);
// ecmdisc.ReadLBA_2352_Flat(item.Item1, chunkbuf_mine, 0, item.Item2);
// for (int i = 0; i < item.Item2; i++)
// if (chunkbuf_corlet[i] != chunkbuf_mine[i])
// {
// Debug.Assert(false);
// }
// }
// }
// }
//}