mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-07 12:29:30 +00:00
better 2mg handling
This commit is contained in:
parent
f0c714e241
commit
52cfdebb63
|
@ -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)
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user