Woz 3.5" disks, display preferences

This commit is contained in:
Denis Molony 2019-09-05 06:44:43 +10:00
parent 696393799a
commit 19386e5c8e
17 changed files with 364 additions and 109 deletions

View File

@ -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 (' ');

View File

@ -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<Integer, String> equates;
private final int loadAddress;
@ -26,8 +27,6 @@ public class AssemblerProgram extends AbstractFile
private List<Integer> entryPoints;
private List<StringLocation> 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,

View File

@ -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)

View File

@ -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);

View File

@ -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");

View File

@ -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)

View File

@ -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 ();
}

View File

@ -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 ();

View File

@ -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;
// ---------------------------------------------------------------------------------//
}

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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 ();
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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<Sector> 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<Sector>
// ---------------------------------------------------------------------------------//
{
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;
}
}
}