better 2mg handling

This commit is contained in:
Denis Molony 2016-02-24 13:13:52 +11:00
parent f0c714e241
commit 52cfdebb63
5 changed files with 123 additions and 36 deletions

View File

@ -6,8 +6,8 @@ import java.util.GregorianCalendar;
public class HexFormatter
{
private static String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B",
"C", "D", "E", "F" };
private static String[] hex =
{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
private static MathContext mathContext = new MathContext (9);
public static String format (byte[] buffer)
@ -31,13 +31,13 @@ public class HexFormatter
}
public static String formatNoHeader (byte[] buffer, int offset, int length,
int startingAddress)
int startingAddress)
{
return format (buffer, offset, length, false, startingAddress);
}
public static String format (byte[] buffer, int offset, int length, boolean header,
int startingAddress)
int startingAddress)
{
StringBuffer line = new StringBuffer ();
int[] freq = new int[256];
@ -106,7 +106,8 @@ public class HexFormatter
if (freq[i] > 0)
{
totalBits += (Integer.bitCount (i) * freq[i]);
line.append (String.format ("%02X %3d %d%n", i, freq[i], Integer.bitCount (i)));
line.append (String.format ("%02X %3d %d%n", i, freq[i],
Integer.bitCount (i)));
}
line.append (String.format ("%nTotal bits : %d%n", totalBits));
}
@ -221,7 +222,7 @@ public class HexFormatter
}
public static String getHexStringReversed (byte[] buffer, int offset, int length,
boolean space)
boolean space)
{
StringBuilder hex = new StringBuilder ();
for (int i = length - 1; i >= 0; i--)
@ -356,8 +357,8 @@ public class HexFormatter
int exponent = HexFormatter.intValue (buffer[offset]) - 0x80;
int mantissa =
(buffer[offset + 1] & 0x7F) * 0x1000000 + intValue (buffer[offset + 2]) * 0x10000
+ intValue (buffer[offset + 3]) * 0x100 + intValue (buffer[offset + 4]);
(buffer[offset + 1] & 0x7F) * 0x1000000 + intValue (buffer[offset + 2]) * 0x10000
+ intValue (buffer[offset + 3]) * 0x100 + intValue (buffer[offset + 4]);
int weight1 = 1;
long weight2 = 2147483648L;
@ -381,9 +382,8 @@ public class HexFormatter
if (exponent == 0)
return 0.0;
int mantissa =
(buffer[ptr + 1] & 0x7F) << 24 | (buffer[ptr + 2] & 0xFF) << 16
| (buffer[ptr + 3] & 0xFF) << 8 | (buffer[ptr + 4] & 0xFF);
int mantissa = (buffer[ptr + 1] & 0x7F) << 24 | (buffer[ptr + 2] & 0xFF) << 16
| (buffer[ptr + 3] & 0xFF) << 8 | (buffer[ptr + 4] & 0xFF);
boolean negative = (buffer[ptr + 1] & 0x80) > 0;
double value = 0.5;
for (int i = 2, weight = 0x40000000; i <= 32; i++, weight >>>= 1)

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.FileFormatException;
import com.bytezone.diskbrowser.HexFormatter;
import com.bytezone.diskbrowser.applefile.AppleFileSource;
@ -24,6 +25,7 @@ public class AppleDisk implements Disk
public final File path;
private final byte[] diskBuffer; // contains the disk contents in memory
private int skip = 0;
private final int tracks; // usually 35 for floppy disks
private int sectors; // 8 or 16
@ -48,6 +50,8 @@ public class AppleDisk implements Disk
private ActionListener actionListenerList;
private List<DiskAddress> blockList;
private final boolean debug = false;
public AppleDisk (File path, int tracks, int sectors) throws FileFormatException
{
assert (path.exists ()) : "No such path :" + path.getAbsolutePath ();
@ -55,19 +59,64 @@ public class AppleDisk implements Disk
assert (path.length () <= Integer.MAX_VALUE) : "File too large";
assert (path.length () != 0) : "File empty";
int skip = 0;
String name = path.getName ();
int pos = name.lastIndexOf ('.');
if (pos > 0 && name.substring (pos + 1).equalsIgnoreCase ("2mg"))
byte[] buffer = getPrefix (path); // HDV could be a 2mg
String prefix = new String (buffer, 0, 4);
if ((pos > 0 && name.substring (pos + 1).equalsIgnoreCase ("2mg"))
|| "2IMG".equals (prefix))
// if ("2IMG".equals (prefix))
{
byte[] buffer = getPrefix (path);
this.blocks = HexFormatter.intValue (buffer[20], buffer[21]); // 1600
this.sectorSize = 512;
this.trackSize = 8 * sectorSize;
tracks = this.blocks / 8;
sectors = 8;
skip = HexFormatter.intValue (buffer[8], buffer[9]);
if (debug)
System.out.println (Utility.toHex (buffer));
// http://apple2.org.za/gswv/a2zine/Docs/DiskImage_2MG_Info.txt
if ("2IMG".equals (prefix))
{
if (debug)
{
String creator = new String (buffer, 4, 4);
System.out.printf ("Prefix : %s%n", prefix);
System.out.printf ("Creator : %s%n", creator);
int headerSize = Utility.getWord (buffer, 8);
System.out.printf ("Header : %d%n", headerSize);
int version = Utility.getWord (buffer, 10);
System.out.printf ("Version : %d%n", version);
System.out.printf ("Format : %02X%n", buffer[12]);
}
int diskData = Utility.getLong (buffer, 28);
if (debug)
System.out.printf ("Data size : %08X (%,d)%n", diskData, diskData);
blocks = HexFormatter.intValue (buffer[20], buffer[21]); // 1600
if (debug)
System.out.printf ("Blocks : %,d%n", blocks);
int format = buffer[12] & 0xFF;
// if (blocks == 0 && format == 1)
{
this.blocks = diskData / 4096 * 8; // reduces blocks to a legal multiple
if (debug)
System.out.printf ("Blocks : %,d%n", blocks);
}
this.sectorSize = 512;
this.trackSize = 8 * sectorSize;
skip = Utility.getWord (buffer, 8);
tracks = blocks / 8; // change parameter
sectors = 8; // change parameter
}
else
{
System.out.println ("Not a 2mg file");
this.blocks = (int) path.length () / 4096 * 8; // reduces blocks to a legal multiple
this.sectorSize = 512;
this.trackSize = sectors * sectorSize;
}
}
else if (pos > 0 && name.substring (pos + 1).equalsIgnoreCase ("HDV"))
{
@ -84,6 +133,9 @@ public class AppleDisk implements Disk
if (false)
{
System.out.println ();
System.out.printf ("File name : %s%n", path.getName ());
System.out.printf ("File size : %,d%n", path.length ());
System.out.println ("Tracks : " + tracks);
System.out.println ("Sectors : " + sectors);
System.out.println ("Blocks : " + blocks);
@ -108,6 +160,12 @@ public class AppleDisk implements Disk
diskBuffer = new byte[tracks * sectors * sectorSize];
hasData = new boolean[blocks];
if (debug)
{
System.out.printf ("DiskBuffer size : %,d%n", diskBuffer.length);
System.out.printf ("Skip size : %,d%n", skip);
}
try
{
BufferedInputStream file = new BufferedInputStream (new FileInputStream (path));
@ -139,14 +197,18 @@ public class AppleDisk implements Disk
e.printStackTrace ();
System.exit (1);
}
return buffer;
}
private void checkSectorsForData ()
{
blockList = null; // force blockList to be rebuilt with the correct number/size of blocks
// force blockList to be rebuilt with the correct number/size of blocks
blockList = null;
for (DiskAddress da : this)
{
// System.out.println (da);
byte[] buffer = readSector (da);
hasData[da.getBlock ()] = false;
for (int i = 0; i < sectorSize; i++)
@ -430,6 +492,7 @@ public class AppleDisk implements Disk
for (int block = 0; block < blocks; block++)
blockList.add (new AppleDiskAddress (block, this));
}
return blockList.iterator ();
}

View File

@ -99,12 +99,29 @@ public class DiskFactory
FormattedDisk disk2 = null;
if (suffix.equals ("hdv"))
return checkHardDisk (file);
{
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"))
return check2mgDisk (file);
{
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 () > 116480))
if (((suffix.equals ("po") || suffix.equals ("dsk")) && file.length () > 143360))
{
disk = checkHardDisk (file);
@ -114,6 +131,11 @@ public class DiskFactory
disk.setOriginalPath (p);
return disk;
}
else
{
AppleDisk appleDisk = new AppleDisk (file, (int) file.length () / 4096, 8);
return new DataDisk (appleDisk);
}
}
long length = file.length ();
@ -267,8 +289,8 @@ public class DiskFactory
if ((file.length () % 512) != 0)
{
if (debug)
System.out.printf ("file length not divisible by 512 : %d%n%", file.length ());
return null;
System.out.printf ("file length not divisible by 512 : %,d%n", file.length ());
// return null;
}
// assumes a track is 4096 bytes
@ -301,7 +323,7 @@ public class DiskFactory
}
if (debug)
System.out.println ("Not a Prodos hard disk");
System.out.println ("Not a Prodos hard disk\n");
return null;
}
@ -322,6 +344,7 @@ public class DiskFactory
}
if (debug)
System.out.println ("Not a Prodos 2mg disk");
return null;
}

View File

@ -82,7 +82,7 @@ class DiskAndFileSelector
FileNodeSelectedEvent e = new FileNodeSelectedEvent (this, node);
e.redo = redo;
FileNodeSelectionListener[] listeners =
(listenerList.getListeners (FileNodeSelectionListener.class));
(listenerList.getListeners (FileNodeSelectionListener.class));
for (FileNodeSelectionListener listener : listeners)
listener.fileNodeSelected (e);
}
@ -91,7 +91,7 @@ class DiskAndFileSelector
{
if (disk == currentDisk)
{
System.out.println ("Disk event duplicated");
// System.out.println ("Disk event duplicated");
return;
}
@ -104,7 +104,7 @@ class DiskAndFileSelector
DiskSelectedEvent e = new DiskSelectedEvent (this, disk);
e.redo = redo;
DiskSelectionListener[] listeners =
(listenerList.getListeners (DiskSelectionListener.class));
(listenerList.getListeners (DiskSelectionListener.class));
for (DiskSelectionListener listener : listeners)
listener.diskSelected (e);
currentDisk = disk;
@ -131,7 +131,7 @@ class DiskAndFileSelector
FileSelectedEvent e = new FileSelectedEvent (this, file);
e.redo = redo;
FileSelectionListener[] listeners =
(listenerList.getListeners (FileSelectionListener.class));
(listenerList.getListeners (FileSelectionListener.class));
for (FileSelectionListener listener : listeners)
listener.fileSelected (e);
}

View File

@ -27,7 +27,7 @@ class VolumeDirectoryHeader extends DirectoryHeader
totalBlocks = HexFormatter.intValue (entryBuffer[37], entryBuffer[38]);
if (totalBlocks == 0xFFFF | totalBlocks == 0x7FFF)
totalBlocks = (int) disk.getFile ().length () / 4096 * 8; // ignore extra bytes
// totalBitMapBlocks = (totalBlocks * 8 - 1) / 4096 + 1;
// totalBitMapBlocks = (totalBlocks * 8 - 1) / 4096 + 1;
totalBitMapBlocks = (totalBlocks - 1) / 512 + 1;
int block = 2;
@ -56,8 +56,9 @@ class VolumeDirectoryHeader extends DirectoryHeader
}
block = 0;
int max = (totalBlocks - 1) / 8 + 1; // bytes required for sector map
// int max = (disk.getTotalBlocks () - 1) / 8 + 1; // bytes required for sector map
// int max = (totalBlocks - 1) / 8 + 1; // bytes required for sector map
// nb disk may be truncated, so use actual number of blocks
int max = (disk.getTotalBlocks () - 1) / 8 + 1; // bytes required for sector map
for (int i = 0; i < max; i++)
{
@ -99,7 +100,7 @@ class VolumeDirectoryHeader extends DirectoryHeader
offset += 507;
}
return new ProdosDirectory (parentDisk, name, fullBuffer, totalBlocks, freeBlocks,
usedBlocks);
usedBlocks);
}
@Override