package com.bytezone.diskbrowser.disk; import java.io.*; import java.nio.file.Path; import java.nio.file.Paths; import java.util.zip.GZIPInputStream; import com.bytezone.diskbrowser.FileFormatException; import com.bytezone.diskbrowser.NuFX; 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.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.equalsIgnoreCase ("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.equalsIgnoreCase ("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")) return checkHardDisk (file); if (suffix.equals ("2mg")) return check2mgDisk (file); // if (((suffix.equals ("po") || suffix.equals ("dsk")) && file.length () > 116480)) if (((suffix.equals ("po") || suffix.equals ("dsk")) && file.length () > 143360)) { disk = checkHardDisk (file); if (disk != null) { if (compressed) disk.setOriginalPath (p); return disk; } } long length = file.length (); if (length != 143360 && length != 116480) { System.out.println ("invalid file length : " + file.length ()); return null; } int sectors = file.length () == 143360 ? 16 : 13; if (true) { AppleDisk appleDisk = new AppleDisk (file, 35, sectors); long checksum = appleDisk.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 (file); disk2 = checkProdos (file); if (disk2 != null && disk != null) disk = new DualDosDisk (disk, disk2); } else if (checksum == 1737448647L || checksum == 170399908L) { disk = checkProdos (file); disk2 = checkDos (file); if (disk2 != null && disk != null) disk = new DualDosDisk (disk, disk2); } else if (checksum == 2803644711L || checksum == 3317783349L || checksum == 1728863694L || checksum == 198094178L) disk = checkPascalDisk (file); else if (checksum == 3028642627L || checksum == 2070151659L) disk = checkInfocomDisk (file); else if (checksum == 1212926910L || checksum == 1365043894L) disk = checkCPMDisk (file); 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") || suffix.equals ("d13")) { disk = checkDos (file); if (disk == null) disk = checkProdos (file); else if (sectors == 16) { if (debug) System.out.println ("Checking DualDos disk"); disk2 = checkProdos (file); if (disk2 != null) disk = new DualDosDisk (disk, disk2); } } else if (suffix.equals ("po")) { disk = checkProdos (file); if (disk == null) disk = checkDos (file); } if (disk == null) disk = checkPascalDisk (file); if (disk == null) { disk2 = checkInfocomDisk (file); if (disk2 != null) disk = disk2; } if (disk == null) disk = new DataDisk (new AppleDisk (file, 35, 16)); 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) { 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) { 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%", 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 ()); // int usableLength = (int) (file.length () / 4096); // } // return null; // } try { 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 (); } if (debug) System.out.println ("Not a Prodos hard disk"); 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) { if (debug) System.out.println ("Checking Pascal disk"); AppleDisk disk = new AppleDisk (file, 35, 8); 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 disk"); return new PascalDisk (disk); } private static InfocomDisk checkInfocomDisk (File file) { 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) { 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; } }