diff --git a/src/com/bytezone/diskbrowser/applefile/ApplesoftBasicProgram.java b/src/com/bytezone/diskbrowser/applefile/ApplesoftBasicProgram.java index 626cd4d..00c7d9f 100644 --- a/src/com/bytezone/diskbrowser/applefile/ApplesoftBasicProgram.java +++ b/src/com/bytezone/diskbrowser/applefile/ApplesoftBasicProgram.java @@ -556,7 +556,7 @@ public class ApplesoftBasicProgram extends BasicProgram this.length = length; byte b = buffer[startPtr]; - if (isToken (b)) + if (isHighBitSet (b)) { switch (b) { @@ -637,7 +637,7 @@ public class ApplesoftBasicProgram extends BasicProgram private boolean isImpliedGoto () { byte b = buffer[startPtr]; - if (isToken (b)) + if (isHighBitSet (b)) return false; return (isDigit (b)); } @@ -677,7 +677,7 @@ public class ApplesoftBasicProgram extends BasicProgram { // ignore first byte, check the rest for tokens for (int p = startPtr + 1, max = startPtr + length; p < max; p++) - if (isToken (buffer[p])) + if (isHighBitSet (buffer[p])) return true; return false; } @@ -740,7 +740,7 @@ public class ApplesoftBasicProgram extends BasicProgram for (int p = startPtr; p <= max; p++) { byte b = buffer[p]; - if (isToken (b)) + if (isHighBitSet (b)) { if (line.length () > 0 && line.charAt (line.length () - 1) != ' ') line.append (' '); diff --git a/src/com/bytezone/diskbrowser/applefile/AssemblerProgram.java b/src/com/bytezone/diskbrowser/applefile/AssemblerProgram.java index ee716c9..b64b544 100755 --- a/src/com/bytezone/diskbrowser/applefile/AssemblerProgram.java +++ b/src/com/bytezone/diskbrowser/applefile/AssemblerProgram.java @@ -9,13 +9,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import com.bytezone.common.Utility; import com.bytezone.diskbrowser.gui.AssemblerPreferences; import com.bytezone.diskbrowser.gui.DiskBrowser; import com.bytezone.diskbrowser.utilities.HexFormatter; public class AssemblerProgram extends AbstractFile { + static AssemblerPreferences assemblerPreferences; // set by MenuHandler + private static Map equates; private final int loadAddress; @@ -26,8 +27,6 @@ public class AssemblerProgram extends AbstractFile private List entryPoints; private List stringLocations; - static AssemblerPreferences assemblerPreferences; - public static void setAssemblerPreferences (AssemblerPreferences assemblerPreferences) { AssemblerProgram.assemblerPreferences = assemblerPreferences; @@ -81,6 +80,7 @@ public class AssemblerProgram extends AbstractFile { if (buffer == null) return "No buffer"; + if (assembler == null) this.assembler = new AssemblerProgram (name, buffer, loadAddress); @@ -94,19 +94,25 @@ public class AssemblerProgram extends AbstractFile return assembler.getText () + "\n\n" + assemblerProgram.getText (); } - @Override - public String getText () + private void addHeader (StringBuilder pgm) { - StringBuilder pgm = new StringBuilder (); - pgm.append (String.format ("Name : %s%n", name)); pgm.append (String.format ("Length : $%04X (%,d)%n", buffer.length, buffer.length)); pgm.append (String.format ("Load at : $%04X (%,d)%n", loadAddress, loadAddress)); if (executeOffset > 0) pgm.append (String.format ("Entry : $%04X%n", (loadAddress + executeOffset))); - pgm.append ("\n"); + } + + @Override + public String getText () + { + StringBuilder pgm = new StringBuilder (); + + if (assemblerPreferences.showHeader) + addHeader (pgm); + pgm.append (getListing ()); if (assemblerPreferences.showStrings) @@ -250,7 +256,7 @@ public class AssemblerProgram extends AbstractFile { int address = stringLocation.offset + loadAddress; text.append (String.format ("%s %04X - %04X %s %n", - entryPoints.contains (stringLocation.offset + loadAddress) ? "*" : " ", address, + entryPoints.contains (stringLocation.offset) ? "*" : " ", address, address + stringLocation.length, stringLocation)); } @@ -266,19 +272,8 @@ public class AssemblerProgram extends AbstractFile stringLocations = new ArrayList<> (); int start = 0; - int max = buffer.length - 2; for (int ptr = 0; ptr < buffer.length; ptr++) { - if ((buffer[ptr] == (byte) 0xBD // LDA Absolute,X - || buffer[ptr] == (byte) 0xB9 // LDA Absolute,Y - || buffer[ptr] == (byte) 0xAD) // LDA Absolute - && (ptr < max)) - { - int address = Utility.getWord (buffer, ptr + 1); - if (address >= loadAddress && address < loadAddress + buffer.length) - entryPoints.add (address); - } - if ((buffer[ptr] & 0x80) != 0) // hi bit set continue; @@ -290,6 +285,15 @@ public class AssemblerProgram extends AbstractFile if (buffer.length - start > 3) stringLocations.add (new StringLocation (start, buffer.length - 1)); + + int max = buffer.length - 2; + for (StringLocation stringLocation : stringLocations) + for (int ptr = 0; ptr < max; ptr++) + if (stringLocation.matches (buffer, ptr)) + { + entryPoints.add (stringLocation.offset); + break; + } } private String getArrow (AssemblerStatement cmd) @@ -350,6 +354,7 @@ public class AssemblerProgram extends AbstractFile class StringLocation { int offset; + byte hi, lo; int length; boolean zeroTerminated; boolean lowTerminated; @@ -364,12 +369,20 @@ public class AssemblerProgram extends AbstractFile { offset = first; length = last - offset + 1; - int end = last + 1; zeroTerminated = end < buffer.length && buffer[end] == 0; lowTerminated = end < buffer.length && buffer[end] >= 32 && buffer[end] < 127; - hasLengthByte = first > 0 && (buffer[first] & 0xFF) == length; + + if (first > 0 && (buffer[first] & 0xFF) == length + 1) + { + hasLengthByte = true; + --offset; + ++length; + } + + hi = (byte) ((offset + loadAddress) >>> 8); + lo = (byte) ((offset + loadAddress) & 0x00FF); for (int i = offset; i < offset + length; i++) { @@ -389,11 +402,21 @@ public class AssemblerProgram extends AbstractFile } } + boolean matches (byte[] buffer, int ptr) + { + return lo == buffer[ptr] && hi == buffer[ptr + 1]; + } + boolean likelyString () { return spaces > 0 || letters > punctuation; } + public String address () + { + return String.format ("%04X %02X %02X", offset, hi, lo); + } + public String toStatisticsString () { return String.format ("%2d, %2d, %2d, %2d, %2d", digits, letters, punctuation, diff --git a/src/com/bytezone/diskbrowser/applefile/BasicProgram.java b/src/com/bytezone/diskbrowser/applefile/BasicProgram.java index 6ea2aac..8c42d22 100644 --- a/src/com/bytezone/diskbrowser/applefile/BasicProgram.java +++ b/src/com/bytezone/diskbrowser/applefile/BasicProgram.java @@ -9,11 +9,11 @@ public abstract class BasicProgram extends AbstractFile static final byte ASCII_SEMI_COLON = 0x3B; static final byte ASCII_CARET = 0x5E; - static BasicPreferences basicPreferences; + static BasicPreferences basicPreferences; // set by MenuHandler public static void setBasicPreferences (BasicPreferences basicPreferences) { - ApplesoftBasicProgram.basicPreferences = basicPreferences; + BasicProgram.basicPreferences = basicPreferences; } public BasicProgram (String name, byte[] buffer) @@ -21,14 +21,15 @@ public abstract class BasicProgram extends AbstractFile super (name, buffer); } - boolean isToken (byte value) + boolean isHighBitSet (byte value) { return (value & 0x80) != 0; } boolean isControlCharacter (byte value) { - return (value & 0xFF) < 32; + int val = value & 0xFF; + return val > 0 && val < 32; } boolean isDigit (byte value) diff --git a/src/com/bytezone/diskbrowser/applefile/BasicProgramGS.java b/src/com/bytezone/diskbrowser/applefile/BasicProgramGS.java index 6f1eaff..29b0665 100644 --- a/src/com/bytezone/diskbrowser/applefile/BasicProgramGS.java +++ b/src/com/bytezone/diskbrowser/applefile/BasicProgramGS.java @@ -136,7 +136,7 @@ public class BasicProgramGS extends BasicProgram while (ptr < max) { byte b1 = buffer[ptr++]; - if (isToken (b1)) + if (isHighBitSet (b1)) ptr = tokenOrNumber (b1, text, ptr); else text.append ((b1 & 0xFF) < 32 ? '.' : (char) b1); diff --git a/src/com/bytezone/diskbrowser/applefile/BootSector.java b/src/com/bytezone/diskbrowser/applefile/BootSector.java index cff44e9..3122c02 100644 --- a/src/com/bytezone/diskbrowser/applefile/BootSector.java +++ b/src/com/bytezone/diskbrowser/applefile/BootSector.java @@ -10,6 +10,7 @@ public class BootSector extends AbstractSector private static final byte[] skew = { 0x00, 0x0D, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01, 0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x0F }; private static final int SKEW_OFFSET = 0x4D; + private static final int SKEW_OFFSET_2 = 0x3C; // DOS 4.x AssemblerProgram assembler1; AssemblerProgram assembler2; @@ -34,7 +35,7 @@ public class BootSector extends AbstractSector if (assembler1 == null) { - int flag = buffer[0] & 0xFF; + int flag = buffer[0] & 0xFF; // how many blocks to load if (flag == 1) // apple II { if (matches (buffer, SKEW_OFFSET, skew)) @@ -53,8 +54,8 @@ public class BootSector extends AbstractSector } else // apple III (SOS) { - byte[] newBuffer = new byte[buffer.length * 2]; - System.arraycopy (buffer, 0, newBuffer, 0, buffer.length); + // byte[] newBuffer = new byte[buffer.length * 2]; + // System.arraycopy (buffer, 0, newBuffer, 0, buffer.length); // byte[] buf = disk.readSector (1); // System.arraycopy (buf, 0, newBuffer, buf.length, buf.length); @@ -66,6 +67,7 @@ public class BootSector extends AbstractSector } text.append (assembler1.getText ()); + if (assembler2 != null) { text.append ("\n\n"); diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index 8c3da9c..cd83519 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -247,13 +247,30 @@ public class DiskFactory if (wozFile.getSectorsPerTrack () == 16) { - AppleDisk appleDisk256 = new AppleDisk (wozFile, wozFile.getTracks (), 16); - disk = checkDos (appleDisk256); - if (disk == null) - disk = checkProdos (new AppleDisk (wozFile, 35, 8)); - if (disk == null) - disk = new DataDisk (appleDisk256); + if (wozFile.getDiskType () == 2) + { + if (debug) + System.out.println ("Checking woz 3.5"); + AppleDisk disk800 = new AppleDisk (wozFile, 200, 8); + if (ProdosDisk.isCorrectFormat (disk800)) + { + if (debug) + System.out.println (" --> PRODOS hard disk"); + return new ProdosDisk (disk800); + } + disk = new DataDisk (disk800); + } + else + { + AppleDisk appleDisk256 = new AppleDisk (wozFile, wozFile.getTracks (), 16); + disk = checkDos (appleDisk256); + if (disk == null) + disk = checkProdos (new AppleDisk (wozFile, 35, 8)); + if (disk == null) + disk = new DataDisk (appleDisk256); + } } + return disk; } catch (Exception e) diff --git a/src/com/bytezone/diskbrowser/gui/AssemblerPreferences.java b/src/com/bytezone/diskbrowser/gui/AssemblerPreferences.java index 21d3ee9..598033e 100644 --- a/src/com/bytezone/diskbrowser/gui/AssemblerPreferences.java +++ b/src/com/bytezone/diskbrowser/gui/AssemblerPreferences.java @@ -5,6 +5,7 @@ public class AssemblerPreferences public boolean showTargets = true; public boolean showStrings = true; public boolean offsetFromZero = false; + public boolean showHeader = true; @Override public String toString () @@ -14,6 +15,7 @@ public class AssemblerPreferences text.append (String.format ("Show targets .......... %s%n", showTargets)); text.append (String.format ("Show strings .......... %s%n", showStrings)); text.append (String.format ("Offset from zero ...... %s%n", offsetFromZero)); + text.append (String.format ("Show header ........... %s%n", showHeader)); return text.toString (); } diff --git a/src/com/bytezone/diskbrowser/gui/MenuHandler.java b/src/com/bytezone/diskbrowser/gui/MenuHandler.java index 94e0c60..ec14c8f 100755 --- a/src/com/bytezone/diskbrowser/gui/MenuHandler.java +++ b/src/com/bytezone/diskbrowser/gui/MenuHandler.java @@ -35,6 +35,7 @@ public class MenuHandler private static final String PREFS_SHOW_ASSEMBLER_TARGETS = "showAssemblerTargets"; private static final String PREFS_SHOW_ASSEMBLER_STRINGS = "showAssemblerStrings"; + private static final String PREFS_SHOW_ASSEMBLER_HEADER = "showAssemblerHeader"; // private static final String PREFS_DEBUGGING = "debugging"; private static final String PREFS_PALETTE = "palette"; @@ -99,6 +100,7 @@ public class MenuHandler // Assembler menu items final JMenuItem showAssemblerTargetsItem = new JCheckBoxMenuItem ("Show targets"); final JMenuItem showAssemblerStringsItem = new JCheckBoxMenuItem ("Show strings"); + final JMenuItem showAssemblerHeaderItem = new JCheckBoxMenuItem ("Show header"); ButtonGroup paletteGroup = new ButtonGroup (); @@ -174,6 +176,7 @@ public class MenuHandler assemblerMenu.add (showAssemblerTargetsItem); assemblerMenu.add (showAssemblerStringsItem); + assemblerMenu.add (showAssemblerHeaderItem); ActionListener basicPreferencesAction = new ActionListener () { @@ -204,6 +207,7 @@ public class MenuHandler showAssemblerTargetsItem.addActionListener (assemblerPreferencesAction); showAssemblerStringsItem.addActionListener (assemblerPreferencesAction); + showAssemblerHeaderItem.addActionListener (assemblerPreferencesAction); helpMenu.add (new JMenuItem (new EnvironmentAction ())); @@ -255,6 +259,7 @@ public class MenuHandler { assemblerPreferences.showTargets = showAssemblerTargetsItem.isSelected (); assemblerPreferences.showStrings = showAssemblerStringsItem.isSelected (); + assemblerPreferences.showHeader = showAssemblerHeaderItem.isSelected (); AssemblerProgram.setAssemblerPreferences (assemblerPreferences); } @@ -323,6 +328,7 @@ public class MenuHandler showAssemblerTargetsItem.isSelected ()); prefs.putBoolean (PREFS_SHOW_ASSEMBLER_STRINGS, showAssemblerStringsItem.isSelected ()); + prefs.putBoolean (PREFS_SHOW_ASSEMBLER_HEADER, showAssemblerHeaderItem.isSelected ()); } @Override @@ -334,6 +340,7 @@ public class MenuHandler showFreeSectorsItem.setSelected (prefs.getBoolean (PREFS_SHOW_FREE_SECTORS, false)); colourQuirksItem.setSelected (prefs.getBoolean (PREFS_COLOUR_QUIRKS, false)); monochromeItem.setSelected (prefs.getBoolean (PREFS_MONOCHROME, false)); + // debuggingItem.setSelected (prefs.getBoolean (PREFS_DEBUGGING, false)); splitRemarkItem.setSelected (prefs.getBoolean (PREFS_SPLIT_REMARKS, false)); @@ -348,6 +355,8 @@ public class MenuHandler .setSelected (prefs.getBoolean (PREFS_SHOW_ASSEMBLER_TARGETS, true)); showAssemblerStringsItem .setSelected (prefs.getBoolean (PREFS_SHOW_ASSEMBLER_STRINGS, true)); + showAssemblerHeaderItem + .setSelected (prefs.getBoolean (PREFS_SHOW_ASSEMBLER_HEADER, true)); setBasicPreferences (); setAssemblerPreferences (); diff --git a/src/com/bytezone/diskbrowser/nib/ByteTranslator.java b/src/com/bytezone/diskbrowser/nib/ByteTranslator.java index 913e0b7..9105dd9 100644 --- a/src/com/bytezone/diskbrowser/nib/ByteTranslator.java +++ b/src/com/bytezone/diskbrowser/nib/ByteTranslator.java @@ -1,8 +1,14 @@ package com.bytezone.diskbrowser.nib; -public interface ByteTranslator +// -----------------------------------------------------------------------------------// +interface ByteTranslator +// -----------------------------------------------------------------------------------// { + // ---------------------------------------------------------------------------------// abstract byte encode (byte b); + // ---------------------------------------------------------------------------------// + // ---------------------------------------------------------------------------------// abstract byte decode (byte b) throws DiskNibbleException; + // ---------------------------------------------------------------------------------// } diff --git a/src/com/bytezone/diskbrowser/nib/ByteTranslator5and3.java b/src/com/bytezone/diskbrowser/nib/ByteTranslator5and3.java index 540424a..f3ae938 100644 --- a/src/com/bytezone/diskbrowser/nib/ByteTranslator5and3.java +++ b/src/com/bytezone/diskbrowser/nib/ByteTranslator5and3.java @@ -1,6 +1,8 @@ package com.bytezone.diskbrowser.nib; -public class ByteTranslator5and3 implements ByteTranslator +// -----------------------------------------------------------------------------------// +class ByteTranslator5and3 implements ByteTranslator +// -----------------------------------------------------------------------------------// { // 32 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) private static byte[] writeTranslateTable5and3 = @@ -11,14 +13,16 @@ public class ByteTranslator5and3 implements ByteTranslator (byte) 0xEE, (byte) 0xEF, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xFA, (byte) 0xFB, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; - private static byte[] readTranslateTable5and3 = new byte[85]; // skip first 171 blanks + private static final int SKIP = 0xAB; + private static byte[] readTranslateTable5and3 = new byte[256 - SKIP]; + private static boolean debug = false; static { for (int i = 0; i < writeTranslateTable5and3.length; i++) { - int j = (writeTranslateTable5and3[i] & 0xFF) - 0xAB; // skip first 171 blanks + int j = (writeTranslateTable5and3[i] & 0xFF) - SKIP; // skip first 171 blanks readTranslateTable5and3[j] = (byte) (i + 1); // offset by 1 to avoid zero if (debug) System.out.printf ("%02X %02X %02X%n", i, writeTranslateTable5and3[i], j); @@ -38,24 +42,20 @@ public class ByteTranslator5and3 implements ByteTranslator } // ---------------------------------------------------------------------------------// - // encode - // ---------------------------------------------------------------------------------// - @Override public byte encode (byte b) + // ---------------------------------------------------------------------------------// { System.out.println ("encode() not written"); return 0; } // ---------------------------------------------------------------------------------// - // decode - // ---------------------------------------------------------------------------------// - @Override public byte decode (byte b) throws DiskNibbleException + // ---------------------------------------------------------------------------------// { - int val = (b & 0xFF) - 0xAB; // 0 - 84 + int val = (b & 0xFF) - SKIP; // 0 - 84 if (val < 0 || val > 84) throw new DiskNibbleException ("5&3 val: " + val); byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits) diff --git a/src/com/bytezone/diskbrowser/nib/ByteTranslator6and2.java b/src/com/bytezone/diskbrowser/nib/ByteTranslator6and2.java index 6ba6c6e..30dbaa2 100644 --- a/src/com/bytezone/diskbrowser/nib/ByteTranslator6and2.java +++ b/src/com/bytezone/diskbrowser/nib/ByteTranslator6and2.java @@ -1,6 +1,8 @@ package com.bytezone.diskbrowser.nib; -public class ByteTranslator6and2 implements ByteTranslator +// -----------------------------------------------------------------------------------// +class ByteTranslator6and2 implements ByteTranslator +// -----------------------------------------------------------------------------------// { // 64 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) private static byte[] writeTranslateTable6and2 = @@ -17,35 +19,36 @@ public class ByteTranslator6and2 implements ByteTranslator (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xF9, (byte) 0xFA, (byte) 0xFB, (byte) 0xFC, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; - private static byte[] readTranslateTable6and2 = new byte[106]; // skip first 150 blanks + private static final int SKIP = 0x96; + private static byte[] readTranslateTable6and2 = new byte[256 - SKIP]; static { for (int i = 0; i < writeTranslateTable6and2.length; i++) { - int j = (writeTranslateTable6and2[i] & 0xFF) - 0x96; // skip first 150 blanks + int j = (writeTranslateTable6and2[i] & 0xFF) - SKIP; // skip first 150 blanks readTranslateTable6and2[j] = (byte) (i + 1); // offset by 1 to avoid zero } + + if (false) + for (int i = 0; i < readTranslateTable6and2.length; i++) + System.out.printf ("%02X %02X%n", i + SKIP, readTranslateTable6and2[i] - 1); } // ---------------------------------------------------------------------------------// - // encode - // ---------------------------------------------------------------------------------// - @Override public byte encode (byte b) + // ---------------------------------------------------------------------------------// { return writeTranslateTable6and2[(b & 0xFC)]; } // ---------------------------------------------------------------------------------// - // decode - // ---------------------------------------------------------------------------------// - @Override public byte decode (byte b) throws DiskNibbleException + // ---------------------------------------------------------------------------------// { - int val = (b & 0xFF) - 0x96; // 0 - 105 + int val = (b & 0xFF) - SKIP; // 0 - 105 if (val < 0 || val > 105) throw new DiskNibbleException ("6&2 val: " + val); byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits) diff --git a/src/com/bytezone/diskbrowser/nib/DiskNibbleException.java b/src/com/bytezone/diskbrowser/nib/DiskNibbleException.java index 760a614..b35344f 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskNibbleException.java +++ b/src/com/bytezone/diskbrowser/nib/DiskNibbleException.java @@ -1,16 +1,22 @@ package com.bytezone.diskbrowser.nib; -public class DiskNibbleException extends Exception +// -----------------------------------------------------------------------------------// +class DiskNibbleException extends Exception +// -----------------------------------------------------------------------------------// { String message; + // ---------------------------------------------------------------------------------// public DiskNibbleException (String message) + // ---------------------------------------------------------------------------------// { this.message = message; } + // ---------------------------------------------------------------------------------// @Override public String toString () + // ---------------------------------------------------------------------------------// { return message; } diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader.java b/src/com/bytezone/diskbrowser/nib/DiskReader.java index ca34dae..3444a64 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader.java @@ -1,14 +1,15 @@ package com.bytezone.diskbrowser.nib; -// ---------------------------------------------------------------------------------// -public abstract class DiskReader -// ---------------------------------------------------------------------------------// +// -----------------------------------------------------------------------------------// +abstract class DiskReader +// -----------------------------------------------------------------------------------// { static final int BLOCK_SIZE = 256; static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; static DiskReader reader13; static DiskReader reader16; + static DiskReader readerGRC; final int sectorsPerTrack; @@ -23,21 +24,26 @@ public abstract class DiskReader static DiskReader getInstance (int sectors) // ---------------------------------------------------------------------------------// { - if (sectors == 13) + switch (sectors) { - if (reader13 == null) - reader13 = new DiskReader13Sector (); - return reader13; - } + case 13: + if (reader13 == null) + reader13 = new DiskReader13Sector (); + return reader13; - if (sectors == 16) - { - if (reader16 == null) - reader16 = new DiskReader16Sector (); - return reader16; - } + case 16: + if (reader16 == null) + reader16 = new DiskReader16Sector (); + return reader16; - return null; + case 0: + if (readerGRC == null) + readerGRC = new DiskReaderGRC (); + return readerGRC; + + default: + return null; + } } // ---------------------------------------------------------------------------------// @@ -55,7 +61,5 @@ public abstract class DiskReader abstract byte[] encodeSector (byte[] buffer); - // abstract void storeBuffer (RawDiskSector diskSector, byte[] diskBuffer); - abstract int expectedDataSize (); } diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java b/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java index 0f41feb..12d851b 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader13Sector.java @@ -1,7 +1,7 @@ package com.bytezone.diskbrowser.nib; // -----------------------------------------------------------------------------------// -public class DiskReader13Sector extends DiskReader +class DiskReader13Sector extends DiskReader // -----------------------------------------------------------------------------------// { private static final int RAW_BUFFER_SIZE = 410; diff --git a/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java b/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java index c586a91..646088a 100644 --- a/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java +++ b/src/com/bytezone/diskbrowser/nib/DiskReader16Sector.java @@ -1,7 +1,7 @@ package com.bytezone.diskbrowser.nib; // -----------------------------------------------------------------------------------// -public class DiskReader16Sector extends DiskReader +class DiskReader16Sector extends DiskReader // -----------------------------------------------------------------------------------// { private static final int RAW_BUFFER_SIZE = 342; diff --git a/src/com/bytezone/diskbrowser/nib/DiskReaderGRC.java b/src/com/bytezone/diskbrowser/nib/DiskReaderGRC.java new file mode 100644 index 0000000..87600cf --- /dev/null +++ b/src/com/bytezone/diskbrowser/nib/DiskReaderGRC.java @@ -0,0 +1,99 @@ +package com.bytezone.diskbrowser.nib; + +// -----------------------------------------------------------------------------------// +public class DiskReaderGRC extends DiskReader +// -----------------------------------------------------------------------------------// +{ + private final ByteTranslator byteTranslator = new ByteTranslator6and2 (); + + // ---------------------------------------------------------------------------------// + DiskReaderGRC () + // ---------------------------------------------------------------------------------// + { + super (0); + } + + // ---------------------------------------------------------------------------------// + @Override + byte[] decodeSector (byte[] buffer, int ptr) throws DiskNibbleException + // ---------------------------------------------------------------------------------// + { + byte[] outBuffer = new byte[BLOCK_SIZE * 2 + 12]; // 524 bytes + int outPtr = 0; + + int[] checksums = new int[3]; + + for (int j = 0; j < 175; j++) + { + checksums[0] = (checksums[0] & 0xFF) << 1; // ROL + if ((checksums[0] > 0xFF)) + ++checksums[0]; + + byte d3 = byteTranslator.decode (buffer[ptr++]); // composite byte + byte d0 = byteTranslator.decode (buffer[ptr++]); + byte d1 = byteTranslator.decode (buffer[ptr++]); + + byte b0 = (byte) ((d0 & 0x3F) | ((d3 & 0x30) << 2)); + byte b1 = (byte) ((d1 & 0x3F) | ((d3 & 0x0C) << 4)); + + outBuffer[outPtr++] = checksum (b0, checksums, 0, 2); + outBuffer[outPtr++] = checksum (b1, checksums, 2, 1); + + if (j < 174) + { + byte d2 = byteTranslator.decode (buffer[ptr++]); + byte b2 = (byte) ((d2 & 0x3F) | ((d3 & 0x03) << 6)); + outBuffer[outPtr++] = checksum (b2, checksums, 1, 0); + } + } + + byte d3 = byteTranslator.decode (buffer[ptr++]); // composite byte + byte d0 = byteTranslator.decode (buffer[ptr++]); + byte d1 = byteTranslator.decode (buffer[ptr++]); + byte d2 = byteTranslator.decode (buffer[ptr++]); + + byte b0 = (byte) ((d0 & 0x3F) | ((d3 & 0x30) << 2)); + byte b1 = (byte) ((d1 & 0x3F) | ((d3 & 0x0C) << 4)); + byte b2 = (byte) ((d2 & 0x3F) | ((d3 & 0x03) << 6)); + + if ((checksums[0] & 0xFF) != (b2 & 0xFF) // + || (checksums[1] & 0xFF) != (b1 & 0xFF) // + || (checksums[2] & 0xFF) != (b0 & 0xFF)) + throw new DiskNibbleException ("Checksum failed"); + + return outBuffer; + } + + // ---------------------------------------------------------------------------------// + private byte checksum (byte b, int[] checksums, int c1, int c2) + // ---------------------------------------------------------------------------------// + { + int val = (b ^ checksums[c1]) & 0xFF; + checksums[c2] += val; + + if (checksums[c1] > 0xFF) + { + ++checksums[c2]; + checksums[c1] &= 0xFF; + } + + return (byte) val; + } + + // ---------------------------------------------------------------------------------// + @Override + byte[] encodeSector (byte[] buffer) + // ---------------------------------------------------------------------------------// + { + return null; + } + + // ---------------------------------------------------------------------------------// + @Override + int expectedDataSize () + // ---------------------------------------------------------------------------------// + { + assert false; + return 0; + } +} diff --git a/src/com/bytezone/diskbrowser/nib/WozFile.java b/src/com/bytezone/diskbrowser/nib/WozFile.java index 381d365..a36de9b 100644 --- a/src/com/bytezone/diskbrowser/nib/WozFile.java +++ b/src/com/bytezone/diskbrowser/nib/WozFile.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -44,6 +45,8 @@ public class WozFile private final boolean debug1 = false; private final boolean showTracks = false; + private final ByteTranslator6and2 byteTranslator6and2 = new ByteTranslator6and2 (); + // ---------------------------------------------------------------------------------// public WozFile (File file) throws DiskNibbleException // ---------------------------------------------------------------------------------// @@ -101,7 +104,23 @@ public class WozFile diskBuffer = new byte[tracks.size () * diskSectors * SECTOR_SIZE]; for (Track track : tracks) - track.pack (diskBuffer); + track.packType1 (diskBuffer); + } + else if (info.diskType == 2) // 3.5" + { + List sectors = new ArrayList<> (); + for (Track track : tracks) + sectors.addAll (track.sectors); + Collections.sort (sectors); + + diskBuffer = new byte[800 * info.sides * SECTOR_SIZE * 2]; + ptr = 0; + + for (Sector sector : sectors) + { + sector.pack (diskBuffer, ptr); + ptr += 512; + } } } @@ -112,6 +131,13 @@ public class WozFile return diskBuffer; } + // ---------------------------------------------------------------------------------// + public int getDiskType () + // ---------------------------------------------------------------------------------// + { + return info.diskType; + } + // ---------------------------------------------------------------------------------// public int getTracks () // ---------------------------------------------------------------------------------// @@ -368,9 +394,6 @@ public class WozFile this.rawBuffer = rawBuffer; this.trackNo = trackNo; - // if (debug1) - // System.out.println (HexFormatter.format (rawBuffer, ptr, 1024, ptr)); - if (info.wozVersion == 1) { bytesUsed = val16 (rawBuffer, ptr + DATA_SIZE); @@ -413,18 +436,21 @@ public class WozFile break; Sector sector = new Sector (this, offset); - checkDuplicates (sector); + if (isDuplicate (sector)) + break; sectors.add (sector); } } // ---------------------------------------------------------------------------------// - private void checkDuplicates (Sector newSector) + private boolean isDuplicate (Sector newSector) // ---------------------------------------------------------------------------------// { for (Sector sector : sectors) - if (sector.isDuplicate (newSector)) - System.out.printf ("Duplicate: %s%n", newSector); + if (sector.sectorNo == newSector.sectorNo) + return true; + + return false; } // ---------------------------------------------------------------------------------// @@ -483,7 +509,7 @@ public class WozFile return; int max = (bitCount - 1) / 8 + 1; - max += 520; + max += 600; newBuffer = new byte[max]; for (int i = 0; i < max; i++) @@ -509,7 +535,7 @@ public class WozFile } // ---------------------------------------------------------------------------------// - void pack (byte[] diskBuffer) throws DiskNibbleException + void packType1 (byte[] diskBuffer) throws DiskNibbleException // ---------------------------------------------------------------------------------// { int ndx = diskSectors == 13 ? 0 : 1; @@ -517,8 +543,29 @@ public class WozFile for (Sector sector : sectors) if (sector.dataOffset > 0) - sector.pack (diskReader, diskBuffer, SECTOR_SIZE - * (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo])); + { + byte[] decodedBuffer = + diskReader.decodeSector (newBuffer, sector.dataOffset + 3); + int ptr = SECTOR_SIZE + * (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]); + System.arraycopy (decodedBuffer, 0, diskBuffer, ptr, decodedBuffer.length); + } + } + + // ---------------------------------------------------------------------------------// + int packType2 (byte[] diskBuffer, int ptr) throws DiskNibbleException + // ---------------------------------------------------------------------------------// + { + DiskReader diskReader = DiskReader.getInstance (0); + for (Sector sector : sectors) + if (sector.dataOffset > 0) + { + byte[] decodedBuffer = + diskReader.decodeSector (newBuffer, sector.dataOffset + 4); + System.arraycopy (decodedBuffer, 12, diskBuffer, ptr, 512); + ptr += 512; + } + return ptr; } // ---------------------------------------------------------------------------------// @@ -552,11 +599,11 @@ public class WozFile } // ---------------------------------------------------------------------------------// - public class Sector + public class Sector implements Comparable // ---------------------------------------------------------------------------------// { private final Track track; - private final int trackNo, sectorNo, volume, checksum; + private int trackNo, sectorNo, volume, checksum; private final int addressOffset; private int dataOffset; @@ -566,10 +613,37 @@ public class WozFile { this.track = track; - volume = decode4and4 (track.newBuffer, addressOffset + 3); - trackNo = decode4and4 (track.newBuffer, addressOffset + 5); - sectorNo = decode4and4 (track.newBuffer, addressOffset + 7); - checksum = decode4and4 (track.newBuffer, addressOffset + 9); + if (info.diskType == 1) + { + volume = decode4and4 (track.newBuffer, addressOffset + 3); + trackNo = decode4and4 (track.newBuffer, addressOffset + 5); + sectorNo = decode4and4 (track.newBuffer, addressOffset + 7); + checksum = decode4and4 (track.newBuffer, addressOffset + 9); + } + else + { + // http://apple2.guidero.us/doku.php/articles/iicplus_smartport_secrets + // SWIM Chip User's Ref pp 6 + // uPD72070.pdf + try + { + int b1 = byteTranslator6and2.decode (track.newBuffer[addressOffset + 3]); + sectorNo = byteTranslator6and2.decode (track.newBuffer[addressOffset + 4]); + int b3 = byteTranslator6and2.decode (track.newBuffer[addressOffset + 5]); + int format = byteTranslator6and2.decode (track.newBuffer[addressOffset + 6]); + checksum = byteTranslator6and2.decode (track.newBuffer[addressOffset + 7]); + + trackNo = (b1 & 0x3F) | ((b3 & 0x1F) << 6); + volume = (b3 & 0x20) >>> 5; // side + + int chk = b1 ^ sectorNo ^ b3 ^ format; + assert chk == checksum; + } + catch (DiskNibbleException e) + { + e.printStackTrace (); + } + } // int epiloguePtr = track.findNext (epilogue, addressOffset + 11); // assert epiloguePtr == addressOffset + 11; @@ -581,18 +655,13 @@ public class WozFile } // ---------------------------------------------------------------------------------// - boolean isDuplicate (Sector sector) + void pack (byte[] diskBuffer, int ptr) throws DiskNibbleException // ---------------------------------------------------------------------------------// { - return this.sectorNo == sector.sectorNo; - } + DiskReader diskReader = DiskReader.getInstance (0); - // ---------------------------------------------------------------------------------// - void pack (DiskReader diskReader, byte[] buffer, int ptr) throws DiskNibbleException - // ---------------------------------------------------------------------------------// - { - byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 3); - System.arraycopy (decodedBuffer, 0, buffer, ptr, decodedBuffer.length); + byte[] decodedBuffer = diskReader.decodeSector (track.newBuffer, dataOffset + 4); + System.arraycopy (decodedBuffer, 12, diskBuffer, ptr, 512); } // ---------------------------------------------------------------------------------// @@ -600,10 +669,24 @@ public class WozFile public String toString () // ---------------------------------------------------------------------------------// { + String fld = info.diskType == 1 ? "Vol" : info.diskType == 2 ? "Sde" : "???"; String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset); + return String.format ( - "Vol: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", volume, + "%s: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", fld, volume, trackNo, sectorNo, checksum, addressOffset, dataOffsetText); } + + // ---------------------------------------------------------------------------------// + @Override + public int compareTo (Sector o) + // ---------------------------------------------------------------------------------// + { + if (this.trackNo != o.trackNo) + return this.trackNo - o.trackNo; + if (this.volume != o.volume) + return this.volume - o.volume; + return this.sectorNo - o.sectorNo; + } } }