dmolony-DiskBrowser/src/com/bytezone/diskbrowser/disk/DiskFactory.java
2016-11-28 11:45:17 +11:00

511 lines
14 KiB
Java
Executable File

package com.bytezone.diskbrowser.disk;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.GZIPInputStream;
import com.bytezone.diskbrowser.cpm.CPMDisk;
import com.bytezone.diskbrowser.dos.DosDisk;
import com.bytezone.diskbrowser.infocom.InfocomDisk;
import com.bytezone.diskbrowser.pascal.PascalDisk;
import com.bytezone.diskbrowser.prodos.ProdosDisk;
import com.bytezone.diskbrowser.utilities.FileFormatException;
import com.bytezone.diskbrowser.utilities.NuFX;
import com.bytezone.diskbrowser.wizardry.Wizardry4BootDisk;
import com.bytezone.diskbrowser.wizardry.WizardryScenarioDisk;
public class DiskFactory
{
private static boolean debug = false;
private DiskFactory ()
{
}
public static FormattedDisk createDisk (File file)
{
return createDisk (file.getAbsolutePath ());
}
public static FormattedDisk createDisk (String path)
{
if (debug)
System.out.println ("Factory : " + path);
File file = new File (path);
if (!file.exists ())
return null;
String suffix = path.substring (path.lastIndexOf (".") + 1).toLowerCase ();
Boolean compressed = false;
Path p = Paths.get (path);
if (suffix.equals ("sdk"))
{
try
{
NuFX nuFX = new NuFX (p);
File tmp = File.createTempFile ("sdk", null);
FileOutputStream fos = new FileOutputStream (tmp);
fos.write (nuFX.getBuffer ());
fos.close ();
tmp.deleteOnExit ();
file = tmp;
suffix = "dsk";
compressed = true;
}
catch (IOException e)
{
e.printStackTrace ();
return null;
}
catch (FileFormatException e)
{
return null;
}
}
else if (suffix.equals ("gz")) // will be .dsk.gz
{
try
{
InputStream in = new GZIPInputStream (new FileInputStream (path));
File tmp = File.createTempFile ("gzip", null);
FileOutputStream fos = new FileOutputStream (tmp);
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read (buffer)) > 0)
fos.write (buffer, 0, bytesRead);
fos.close ();
in.close ();
tmp.deleteOnExit ();
file = tmp;
suffix = "dsk";
compressed = true;
}
catch (IOException e)
{
e.printStackTrace ();
return null;
}
}
FormattedDisk disk = null;
FormattedDisk disk2 = null;
if (suffix.equals ("hdv"))
{
ProdosDisk prodosDisk = checkHardDisk (file);
if (prodosDisk != null)
return prodosDisk;
disk2 = check2mgDisk (file);
if (disk2 != null)
return disk2;
AppleDisk appleDisk = new AppleDisk (file, (int) file.length () / 4096, 8);
return new DataDisk (appleDisk);
}
if (suffix.equals ("2mg"))
{
disk2 = check2mgDisk (file);
if (disk2 != null)
return disk2;
AppleDisk appleDisk = new AppleDisk (file, (int) file.length () / 4096, 8);
return new DataDisk (appleDisk);
}
if (((suffix.equals ("po") || suffix.equals ("dsk")) && file.length () > 143360))
{
if (debug)
System.out.println ("Checking po or dsk hard drive: " + file.length ());
disk = checkHardDisk (file);
if (disk != null)
{
if (compressed)
disk.setOriginalPath (p);
return disk;
}
if (debug)
System.out.println ("Creating a data disk from bad length");
try
{
AppleDisk appleDisk = new AppleDisk (file, (int) file.length () / 4096, 8);
if (debug)
System.out.println ("created");
return new DataDisk (appleDisk);
}
catch (FileFormatException e)
{
if (debug)
System.out.println ("Creating AppleDisk failed");
return null;
}
}
if (suffix.equals ("v2d"))
{
// Disk disk = checkV2DDisk (file);
// return disk2;
checkV2DDisk (file);
return null;
}
long length = file.length ();
if (length == 116480) // 13 sector disk
{
if (!suffix.equals ("d13"))
System.out.printf ("%s should have a d13 suffix%n", file.getName ());
AppleDisk appleDisk = new AppleDisk (file, 35, 13);
disk = checkDos (appleDisk);
return disk == null ? new DataDisk (appleDisk) : disk;
}
if (length != 143360)
{
System.out.printf ("%s: invalid file length : %,d%n", file.getName (),
file.length ());
return null;
}
AppleDisk appleDisk16 = new AppleDisk (file, 35, 16);
AppleDisk appleDisk8 = new AppleDisk (file, 35, 8);
if (true)
{
long checksum = appleDisk16.getBootChecksum ();
if (checksum == 3176296590L || checksum == 108825457L || checksum == 1439356606L
|| checksum == 1550012074L || checksum == 1614602459L || checksum == 940889336L
|| checksum == 990032697 || checksum == 2936955085L || checksum == 1348415927L
|| checksum == 3340889101L || checksum == 18315788L || checksum == 993895235L)
{
disk = checkDos (appleDisk16);
disk2 = checkProdos (appleDisk8);
if (disk2 != null && disk != null)
disk = new DualDosDisk (disk, disk2);
}
else if (checksum == 1737448647L || checksum == 170399908L)
{
disk = checkProdos (appleDisk8);
disk2 = checkDos (appleDisk16);
if (disk2 != null && disk != null)
disk = new DualDosDisk (disk, disk2);
}
else if (checksum == 2803644711L || checksum == 3317783349L
|| checksum == 1728863694L || checksum == 198094178L)
{
// disk = checkPascalDisk (file);
disk = checkPascalDisk (appleDisk8);
}
else if (checksum == 3028642627L || checksum == 2070151659L)
disk = checkInfocomDisk (appleDisk16);
// else if (checksum == 1212926910L || checksum == 1365043894L
// || checksum == 2128073918L)
// disk = checkCPMDisk (file);
// System.out.println (checksum);
if (disk != null)
{
if (compressed)
disk.setOriginalPath (p);
return disk;
}
// empty boot sector
if (checksum != 227968344L && false)
System.out.println ("Unknown checksum : " + checksum + " : " + path);
}
if (suffix.equals ("dsk") || suffix.equals ("do"))
{
disk = checkDos (appleDisk16);
if (disk == null)
disk = checkProdos (appleDisk8);
else
{
if (debug)
System.out.println ("Checking DualDos disk");
disk2 = checkProdos (appleDisk8);
if (disk2 != null)
disk = new DualDosDisk (disk, disk2);
}
}
else if (suffix.equals ("po"))
{
disk = checkProdos (appleDisk8);
if (disk == null)
disk = checkDos (appleDisk16);
}
if (disk == null)
disk = checkPascalDisk (appleDisk8);
if (disk == null)
disk = checkCPMDisk (appleDisk16);
if (disk == null)
{
disk2 = checkInfocomDisk (appleDisk16);
if (disk2 != null)
disk = disk2;
}
if (disk == null)
disk = new DataDisk (appleDisk16);
if (debug)
System.out.println (
"Factory creating disk : " + disk.getDisk ().getFile ().getAbsolutePath ());
if (disk != null && compressed)
disk.setOriginalPath (p);
return disk;
}
// private static DosDisk checkDos (File file)
private static DosDisk checkDos (AppleDisk disk)
{
if (debug)
System.out.println ("Checking DOS disk");
try
{
// int sectors = file.length () == 143360 ? 16 : 13;
// AppleDisk disk = new AppleDisk (file, 35, sectors);
if (DosDisk.isCorrectFormat (disk))
return new DosDisk (disk);
}
catch (Exception e)
{
}
if (debug)
System.out.println ("Not a DOS disk");
return null;
}
// private static ProdosDisk checkProdos (File file)
private static ProdosDisk checkProdos (AppleDisk disk)
{
if (debug)
System.out.println ("Checking Prodos disk");
try
{
// AppleDisk disk = new AppleDisk (file, 35, 8);
if (ProdosDisk.isCorrectFormat (disk))
return new ProdosDisk (disk);
}
catch (Exception e)
{
}
if (debug)
System.out.println ("Not a Prodos disk");
return null;
}
private static ProdosDisk checkHardDisk (File file)
{
if (debug)
{
System.out.println ("\nChecking Prodos hard disk");
System.out.printf ("Total blocks : %f%n", (float) file.length () / 512);
System.out.printf ("Total tracks : %f%n", (float) file.length () / 4096);
System.out.printf ("File length : %d%n", file.length ());
System.out.println ();
}
// assumes a sector is 512 bytes
if ((file.length () % 512) != 0)
{
if (debug)
System.out.printf ("file length not divisible by 512 : %,d%n%n", file.length ());
return null;
}
// assumes a track is 4096 bytes
// if ((file.length () % 4096) != 0)
// {
// if (debug)
// System.out.printf ("file length not divisible by 4096 : %d%n%n", file.length ());
// return null;
// }
try
{
// truncate the file if necessary
AppleDisk disk = new AppleDisk (file, (int) file.length () / 4096, 8);
if (ProdosDisk.isCorrectFormat (disk))
{
if (debug)
{
System.out.println ("Yay, it's a prodos hard disk");
System.out.println (disk);
}
return new ProdosDisk (disk);
}
}
catch (Exception e)
{
// e.printStackTrace ();
System.out.println (e);
}
if (debug)
System.out.println ("Not a Prodos hard disk\n");
return null;
}
private static FormattedDisk check2mgDisk (File file)
{
if (debug)
System.out.println ("Checking Prodos 2mg disk");
try
{
AppleDisk disk = new AppleDisk (file, 0, 0);
if (ProdosDisk.isCorrectFormat (disk))
return new ProdosDisk (disk);
}
catch (Exception e)
{
}
if (debug)
System.out.println ("Not a Prodos 2mg disk");
return null;
}
// private static FormattedDisk checkPascalDisk (File file)
private static FormattedDisk checkPascalDisk (AppleDisk disk)
{
if (debug)
System.out.println ("Checking Pascal disk");
// AppleDisk disk = new AppleDisk (file, 35, 8);
File file = disk.getFile ();
if (!PascalDisk.isCorrectFormat (disk, debug))
return null;
if (debug)
System.out.println ("Pascal disk OK - Checking Wizardry disk");
if (WizardryScenarioDisk.isWizardryFormat (disk, debug))
return new WizardryScenarioDisk (disk);
if (debug)
System.out.println ("Not a Wizardry 1-3 disk");
// check for compressed disk
if (file.getName ().endsWith (".tmp"))
return new PascalDisk (disk); // complicated joining up compressed disks
if (Wizardry4BootDisk.isWizardryIVorV (disk, debug))
{
String fileName = file.getAbsolutePath ().toLowerCase ();
int pos = file.getAbsolutePath ().indexOf ('.');
char c = fileName.charAt (pos - 1);
String suffix = fileName.substring (pos + 1);
int requiredDisks = c == '1' ? 6 : c == 'a' ? 10 : 0;
if (requiredDisks > 0)
{
// collect extra data disks
AppleDisk[] disks = new AppleDisk[requiredDisks];
disks[0] = new AppleDisk (file, 256, 8); // will become a PascalDisk
disks[0].setInterleave (1);
disks[1] = new AppleDisk (file, 256, 8); // will remain a DataDisk
disks[1].setInterleave (1);
if (pos > 0 && requiredDisks > 0)
{
if (collectDataDisks (file.getAbsolutePath (), pos, disks))
return new Wizardry4BootDisk (disks);
}
}
}
if (debug)
System.out.println ("Not a Wizardry IV disk");
PascalDisk pascalDisk = new PascalDisk (disk);
return pascalDisk;
}
private static boolean collectDataDisks (String fileName, int dotPos, AppleDisk[] disks)
{
char c = fileName.charAt (dotPos - 1);
String suffix = fileName.substring (dotPos + 1);
for (int i = 2; i < disks.length; i++)
{
String old = new String (c + "." + suffix);
String rep = new String ((char) (c + i - 1) + "." + suffix);
// System.out.printf ("[%s] [%s]%n", old, rep);
File f = new File (fileName.replace (old, rep));
// System.out.println (f);
if (!f.exists () || !f.isFile ())
return false;
AppleDisk dataDisk = new AppleDisk (f, 35, 8);
dataDisk.setInterleave (1);
disks[i] = dataDisk;
}
return true;
}
private static V2dDisk checkV2DDisk (File file)
{
// System.out.println ("possible V2D disk");
new V2dDisk (file);
return null;
}
// private static InfocomDisk checkInfocomDisk (File file)
private static InfocomDisk checkInfocomDisk (AppleDisk disk)
{
if (debug)
System.out.println ("Checking Infocom disk");
// AppleDisk disk = new AppleDisk (file, 35, 16);
if (InfocomDisk.isCorrectFormat (disk))
return new InfocomDisk (disk);
if (debug)
System.out.println ("Not an InfocomDisk disk");
return null;
}
// private static CPMDisk checkCPMDisk (File file)
private static CPMDisk checkCPMDisk (AppleDisk disk)
{
if (debug)
System.out.println ("Checking CPM disk");
// AppleDisk disk = new AppleDisk (file, 35, 16);
if (CPMDisk.isCorrectFormat (disk))
return new CPMDisk (disk);
if (debug)
System.out.println ("Not a CPM disk");
return null;
}
}