mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2025-02-18 05:30:29 +00:00
new pascal Relocator
This commit is contained in:
parent
cf833ab7d7
commit
e911fae830
@ -4,66 +4,79 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
public class PascalCode extends AbstractFile implements PascalConstants, Iterable<PascalSegment>
|
public class PascalCode extends AbstractFile
|
||||||
|
implements PascalConstants, Iterable<PascalSegment>
|
||||||
{
|
{
|
||||||
List<PascalSegment> segments = new ArrayList<PascalSegment> (16);
|
List<PascalSegment> segments = new ArrayList<PascalSegment> (16);
|
||||||
String codeName;
|
String codeName;
|
||||||
String comment;
|
String comment;
|
||||||
|
|
||||||
public static void print ()
|
public static void print ()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 216; i++)
|
for (int i = 0; i < 216; i++)
|
||||||
System.out.printf ("%3d %d %3s %s%n", i + 128, PascalConstants.mnemonicSize[i],
|
System.out.printf ("%3d %d %3s %s%n", i + 128, PascalConstants.mnemonicSize[i],
|
||||||
PascalConstants.mnemonics[i], PascalConstants.descriptions[i]);
|
PascalConstants.mnemonics[i], PascalConstants.descriptions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PascalCode (String name, byte[] buffer)
|
public PascalCode (String name, byte[] buffer)
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
int nonameCounter = 0;
|
int nonameCounter = 0;
|
||||||
|
|
||||||
// Build segment list (up to 16 segments)
|
// Build segment list (up to 16 segments)
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
codeName = HexFormatter.getString (buffer, 0x40 + i * 8, 8).trim ();
|
codeName = HexFormatter.getString (buffer, 0x40 + i * 8, 8).trim ();
|
||||||
int size = HexFormatter.intValue (buffer[i * 4 + 2], buffer[i * 4 + 3]);
|
int size = HexFormatter.intValue (buffer[i * 4 + 2], buffer[i * 4 + 3]);
|
||||||
if (size > 0)
|
System.out.printf ("%s %s %d %n", HexFormatter.getHexString (buffer, i * 4, 4),
|
||||||
{
|
codeName, size);
|
||||||
if (codeName.length () == 0)
|
if (size > 0)
|
||||||
codeName = "<NULL" + nonameCounter++ + ">";
|
{
|
||||||
segments.add (new PascalSegment (codeName, buffer, i));
|
if (codeName.length () == 0)
|
||||||
}
|
codeName = "<NULL" + nonameCounter++ + ">";
|
||||||
}
|
try
|
||||||
comment = HexFormatter.getPascalString (buffer, 0x1B0);
|
{
|
||||||
}
|
segments.add (new PascalSegment (codeName, buffer, i));
|
||||||
|
}
|
||||||
|
catch (FileFormatException e)
|
||||||
|
{
|
||||||
|
System.out.println ("Bad segment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comment = HexFormatter.getPascalString (buffer, 0x1B0);
|
||||||
|
}
|
||||||
|
|
||||||
public String getText ()
|
@Override
|
||||||
{
|
public String getText ()
|
||||||
StringBuilder text = new StringBuilder (getHeader ());
|
{
|
||||||
|
StringBuilder text = new StringBuilder (getHeader ());
|
||||||
|
|
||||||
text.append ("Segment Dictionary\n==================\n\n");
|
text.append ("Segment Dictionary\n==================\n\n");
|
||||||
|
|
||||||
text.append ("Slot Addr Len Len Name Kind"
|
text.append ("Slot Addr Len Len Name Kind"
|
||||||
+ " Text Seg# Mtyp Vers I/S\n");
|
+ " Text Seg# Mtyp Vers I/S\n");
|
||||||
text.append ("---- ---- ----- ----- -------- ---------------"
|
text.append ("---- ---- ----- ----- -------- ---------------"
|
||||||
+ " ---- ---- ---- ---- ---\n");
|
+ " ---- ---- ---- ---- ---\n");
|
||||||
|
|
||||||
for (PascalSegment segment : segments)
|
for (PascalSegment segment : segments)
|
||||||
text.append (segment.toText () + "\n");
|
text.append (segment.toText () + "\n");
|
||||||
text.append ("\nComment : " + comment + "\n\n");
|
text.append ("\nComment : " + comment + "\n\n");
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHeader ()
|
private String getHeader ()
|
||||||
{
|
{
|
||||||
return "Name : " + name + "\n\n";
|
return "Name : " + name + "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<PascalSegment> iterator ()
|
@Override
|
||||||
{
|
public Iterator<PascalSegment> iterator ()
|
||||||
return segments.iterator ();
|
{
|
||||||
}
|
return segments.iterator ();
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,323 +7,331 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
|
|
||||||
public class PascalCodeStatement implements PascalConstants
|
public class PascalCodeStatement implements PascalConstants
|
||||||
{
|
{
|
||||||
private static final String[] compValue =
|
private static final String[] compValue =
|
||||||
{ "invalid", "", "REAL", "", "STR", "", "BOOL", "", "POWR", "", "BYT", "", "WORD" };
|
{ "invalid", "", "REAL", "", "STR", "", "BOOL", "", "POWR", "", "BYT", "", "WORD" };
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int val;
|
int val;
|
||||||
int p1, p2, p3;
|
int p1, p2, p3;
|
||||||
String mnemonic;
|
String mnemonic;
|
||||||
String extras = "";
|
String extras = "";
|
||||||
String description;
|
String description;
|
||||||
String text;
|
String text;
|
||||||
int ptr; // temp
|
int ptr; // temp
|
||||||
byte[] buffer;
|
byte[] buffer;
|
||||||
boolean jumpTarget;
|
boolean jumpTarget;
|
||||||
List<Jump> jumps = new ArrayList<Jump> ();
|
List<Jump> jumps = new ArrayList<Jump> ();
|
||||||
|
|
||||||
public PascalCodeStatement (byte[] buffer, int ptr, int procPtr)
|
public PascalCodeStatement (byte[] buffer, int ptr, int procPtr)
|
||||||
{
|
{
|
||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
length = 1;
|
length = 1;
|
||||||
val = buffer[ptr] & 0xFF;
|
val = buffer[ptr] & 0xFF;
|
||||||
if (val <= 127)
|
if (val <= 127)
|
||||||
{
|
{
|
||||||
mnemonic = "SLDC";
|
mnemonic = "SLDC";
|
||||||
extras = "#" + val;
|
extras = "#" + val;
|
||||||
description = "Short load constant - push #" + val;
|
description = "Short load constant - push #" + val;
|
||||||
}
|
}
|
||||||
else if (val >= 248)
|
else if (val >= 248)
|
||||||
{
|
{
|
||||||
mnemonic = "SIND";
|
mnemonic = "SIND";
|
||||||
extras = "#" + (val - 248);
|
extras = "#" + (val - 248);
|
||||||
description = "Short index load - push word *ToS + #" + (val - 248);
|
description = "Short index load - push word *ToS + #" + (val - 248);
|
||||||
}
|
}
|
||||||
else if (val >= 232)
|
else if (val >= 232)
|
||||||
{
|
{
|
||||||
mnemonic = "SLDO";
|
mnemonic = "SLDO";
|
||||||
extras = "#" + (val - 231);
|
extras = "#" + (val - 231);
|
||||||
description = "Short load global - push BASE + #" + (val - 231);
|
description = "Short load global - push BASE + #" + (val - 231);
|
||||||
}
|
}
|
||||||
else if (val >= 216)
|
else if (val >= 216)
|
||||||
{
|
{
|
||||||
mnemonic = "SLDL";
|
mnemonic = "SLDL";
|
||||||
extras = "#" + (val - 215);
|
extras = "#" + (val - 215);
|
||||||
description = "Short load local - push MP + #" + (val - 215);
|
description = "Short load local - push MP + #" + (val - 215);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mnemonic = mnemonics[val - 128];
|
mnemonic = mnemonics[val - 128];
|
||||||
description = descriptions[val - 128];
|
description = descriptions[val - 128];
|
||||||
|
|
||||||
length = mnemonicSize[val - 128];
|
length = mnemonicSize[val - 128];
|
||||||
if (length != 1)
|
if (length != 1)
|
||||||
{
|
{
|
||||||
switch (val)
|
switch (val)
|
||||||
{
|
{
|
||||||
// W1, W2, W3, <table> - word aligned case jump
|
// W1, W2, W3, <table> - word aligned case jump
|
||||||
case 172: //XJP
|
case 172: //XJP
|
||||||
int padding = (ptr % 2) == 0 ? 1 : 0;
|
int padding = (ptr % 2) == 0 ? 1 : 0;
|
||||||
p1 = getWord (buffer, ptr + padding + 1);
|
p1 = getWord (buffer, ptr + padding + 1);
|
||||||
p2 = getWord (buffer, ptr + padding + 3);
|
p2 = getWord (buffer, ptr + padding + 3);
|
||||||
p3 = getWord (buffer, ptr + padding + 5);
|
p3 = getWord (buffer, ptr + padding + 5);
|
||||||
length = (p2 - p1 + 1) * 2 + 7 + padding;
|
length = (p2 - p1 + 1) * 2 + 7 + padding;
|
||||||
setParameters (p1, p2, String.format ("%04X", p3));
|
setParameters (p1, p2, String.format ("%04X", p3));
|
||||||
int v = p1;
|
int v = p1;
|
||||||
int min = ptr + padding + 7;
|
int min = ptr + padding + 7;
|
||||||
int max = min + (p2 - p1) * 2;
|
int max = min + (p2 - p1) * 2;
|
||||||
for (int i = min; i <= max; i += 2)
|
for (int i = min; i <= max; i += 2)
|
||||||
{
|
{
|
||||||
jumps.add (new Jump (i, i - HexFormatter.intValue (buffer[i], buffer[i + 1]), v++));
|
jumps.add (new Jump (i,
|
||||||
}
|
i - HexFormatter.intValue (buffer[i], buffer[i + 1]), v++));
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// UB, <block> - word aligned
|
// UB, <block> - word aligned
|
||||||
case 179: //LDC
|
case 179: //LDC
|
||||||
p1 = buffer[ptr + 1] & 0xFF;
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
padding = ptr % 2 == 0 ? 0 : 1;
|
padding = ptr % 2 == 0 ? 0 : 1;
|
||||||
length = p1 * 2 + padding + 2;
|
length = p1 * 2 + padding + 2;
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// UB, <chars>
|
// UB, <chars>
|
||||||
case 166: // LSA
|
case 166: // LSA
|
||||||
case 208: // LPA
|
case 208: // LPA
|
||||||
p1 = buffer[ptr + 1] & 0xFF;
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
length = p1 + 2;
|
length = p1 + 2;
|
||||||
if (val == 166)
|
if (val == 166)
|
||||||
{
|
{
|
||||||
text = HexFormatter.getPascalString (buffer, ptr + 1);
|
text = HexFormatter.getPascalString (buffer, ptr + 1);
|
||||||
description += ": " + text;
|
description += ": " + text;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// W
|
// W
|
||||||
case 199: // LDCI
|
case 199: // LDCI
|
||||||
p1 = getWord (buffer, ptr + 1);
|
p1 = getWord (buffer, ptr + 1);
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// B
|
// B
|
||||||
case 162: // INC
|
case 162: // INC
|
||||||
case 163: // IND
|
case 163: // IND
|
||||||
case 164: // IXA
|
case 164: // IXA
|
||||||
case 165: // LAO
|
case 165: // LAO
|
||||||
case 168: // MOV
|
case 168: // MOV
|
||||||
case 169: // LDO
|
case 169: // LDO
|
||||||
case 171: // SRO
|
case 171: // SRO
|
||||||
case 198: // LLA
|
case 198: // LLA
|
||||||
case 202: // LDL
|
case 202: // LDL
|
||||||
case 204: // STL
|
case 204: // STL
|
||||||
case 213: // BPT
|
case 213: // BPT
|
||||||
length = getLengthOfB (buffer[ptr + 1]) + 1;
|
length = getLengthOfB (buffer[ptr + 1]) + 1;
|
||||||
p1 = getValueOfB (buffer, ptr + 1, length - 1);
|
p1 = getValueOfB (buffer, ptr + 1, length - 1);
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// DB, B or UB, B
|
// DB, B or UB, B
|
||||||
case 157: // LDE
|
case 157: // LDE
|
||||||
case 167: // LAE
|
case 167: // LAE
|
||||||
case 178: // LDA
|
case 178: // LDA
|
||||||
case 182: // LOD
|
case 182: // LOD
|
||||||
case 184: // STR
|
case 184: // STR
|
||||||
case 209: // STE
|
case 209: // STE
|
||||||
length = getLengthOfB (buffer[ptr + 2]) + 2;
|
length = getLengthOfB (buffer[ptr + 2]) + 2;
|
||||||
p1 = buffer[ptr + 1] & 0xFF;
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
p2 = getValueOfB (buffer, ptr + 2, length - 2);
|
p2 = getValueOfB (buffer, ptr + 2, length - 2);
|
||||||
setParameters (p1, p2);
|
setParameters (p1, p2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// UB1, UB2
|
// UB1, UB2
|
||||||
case 192: // IXP
|
case 192: // IXP
|
||||||
case 205: // CXP
|
case 205: // CXP
|
||||||
p1 = buffer[ptr + 1] & 0xFF;
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
p2 = buffer[ptr + 2] & 0xFF;
|
p2 = buffer[ptr + 2] & 0xFF;
|
||||||
setParameters (p1, p2);
|
setParameters (p1, p2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// SB or DB
|
// SB or DB
|
||||||
case 161: // FJP
|
case 161: // FJP
|
||||||
case 173: // RNP
|
case 173: // RNP
|
||||||
case 185: // UJP
|
case 185: // UJP
|
||||||
case 193: // RBP
|
case 193: // RBP
|
||||||
case 211: // EFJ
|
case 211: // EFJ
|
||||||
case 212: // NFJ
|
case 212: // NFJ
|
||||||
p1 = buffer[ptr + 1];
|
p1 = buffer[ptr + 1];
|
||||||
if (val == 173 || val == 193) // return from procedure
|
if (val == 173 || val == 193) // return from procedure
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
else if (p1 < 0)
|
else if (p1 < 0)
|
||||||
{
|
{
|
||||||
// look up jump table entry
|
// look up jump table entry
|
||||||
int address = procPtr + p1;
|
int address = procPtr + p1;
|
||||||
int ptr2 = address - ((buffer[address + 1] & 0xFF) * 256 + (buffer[address] & 0xFF));
|
int ptr2 = address
|
||||||
extras = String.format ("$%04X", ptr2);
|
- ((buffer[address + 1] & 0xFF) * 256 + (buffer[address] & 0xFF));
|
||||||
jumps.add (new Jump (ptr, ptr2));
|
extras = String.format ("$%04X", ptr2);
|
||||||
}
|
jumps.add (new Jump (ptr, ptr2));
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
int address = ptr + length + p1;
|
{
|
||||||
extras = String.format ("$%04X", address);
|
int address = ptr + length + p1;
|
||||||
jumps.add (new Jump (ptr, address));
|
extras = String.format ("$%04X", address);
|
||||||
}
|
jumps.add (new Jump (ptr, address));
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// UB
|
// UB
|
||||||
case 160: // AOJ
|
case 160: // AOJ
|
||||||
case 170: // SAS
|
case 170: // SAS
|
||||||
case 174: // CIP
|
case 174: // CIP
|
||||||
case 188: // LDM
|
case 188: // LDM
|
||||||
case 189: // STM
|
case 189: // STM
|
||||||
case 194: // CBP
|
case 194: // CBP
|
||||||
case 206: // CLP
|
case 206: // CLP
|
||||||
case 207: // CGP
|
case 207: // CGP
|
||||||
p1 = buffer[ptr + 1] & 0xFF;
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// CSP
|
// CSP
|
||||||
case 158:
|
case 158:
|
||||||
p1 = buffer[ptr + 1];
|
p1 = buffer[ptr + 1] & 0xFF;
|
||||||
description = "Call standard procedure - " + CSP[p1];
|
if (p1 < CSP.length)
|
||||||
break;
|
description = "Call standard procedure - " + CSP[p1];
|
||||||
|
else
|
||||||
|
description = "Call standard procedure - index out of bounds";
|
||||||
|
break;
|
||||||
|
|
||||||
// Non-integer comparisons
|
// Non-integer comparisons
|
||||||
case 175:
|
case 175:
|
||||||
case 176:
|
case 176:
|
||||||
case 177:
|
case 177:
|
||||||
case 180:
|
case 180:
|
||||||
case 181:
|
case 181:
|
||||||
case 183:
|
case 183:
|
||||||
p1 = buffer[ptr + 1]; // 2/4/6/8/10/12
|
p1 = buffer[ptr + 1] & 0xFF; // 2/4/6/8/10/12
|
||||||
if (p1 < 0 || p1 >= compValue.length)
|
if (p1 < 0 || p1 >= compValue.length)
|
||||||
{
|
{
|
||||||
System.out.printf ("%d %d %d%n", val, p1, ptr);
|
System.out.printf ("%d %d %d%n", val, p1, ptr);
|
||||||
mnemonic += "******************************";
|
mnemonic += "******************************";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mnemonic += compValue[p1];
|
mnemonic += compValue[p1];
|
||||||
if (p1 == 10 || p1 == 12)
|
if (p1 == 10 || p1 == 12)
|
||||||
{
|
{
|
||||||
length = getLengthOfB (buffer[ptr + 2]) + 2;
|
length = getLengthOfB (buffer[ptr + 2]) + 2;
|
||||||
p2 = getValueOfB (buffer, ptr + 2, length - 2);
|
p2 = getValueOfB (buffer, ptr + 2, length - 2);
|
||||||
setParameters (p2);
|
setParameters (p2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
System.out.println ("Forgot : " + val);
|
System.out.println ("Forgot : " + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getWord (byte[] buffer, int ptr)
|
private int getWord (byte[] buffer, int ptr)
|
||||||
{
|
{
|
||||||
return (buffer[ptr + 1] & 0xFF) * 256 + (buffer[ptr] & 0xFF);
|
return (buffer[ptr + 1] & 0xFF) * 256 + (buffer[ptr] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getLengthOfB (byte b)
|
private int getLengthOfB (byte b)
|
||||||
{
|
{
|
||||||
return (b & 0x80) == 0x80 ? 2 : 1;
|
return (b & 0x80) == 0x80 ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getValueOfB (byte[] buffer, int ptr, int length)
|
private int getValueOfB (byte[] buffer, int ptr, int length)
|
||||||
{
|
{
|
||||||
if (length == 2)
|
if (length == 2)
|
||||||
return (buffer[ptr] & 0x7F) * 256 + (buffer[ptr + 1] & 0xFF);
|
return (buffer[ptr] & 0x7F) * 256 + (buffer[ptr + 1] & 0xFF);
|
||||||
return buffer[ptr] & 0xFF;
|
return buffer[ptr] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setParameters (int p1)
|
private void setParameters (int p1)
|
||||||
{
|
{
|
||||||
description = description.replaceFirst (":1", p1 + "");
|
description = description.replaceFirst (":1", p1 + "");
|
||||||
extras = "#" + p1;
|
extras = "#" + p1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setParameters (int p1, int p2)
|
private void setParameters (int p1, int p2)
|
||||||
{
|
{
|
||||||
setParameters (p1);
|
setParameters (p1);
|
||||||
extras += ", #" + p2;
|
extras += ", #" + p2;
|
||||||
description = description.replaceFirst (":2", p2 + "");
|
description = description.replaceFirst (":2", p2 + "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setParameters (int p1, int p2, String p3)
|
private void setParameters (int p1, int p2, String p3)
|
||||||
{
|
{
|
||||||
setParameters (p1, p2);
|
setParameters (p1, p2);
|
||||||
description = description.replaceFirst (":3", p3);
|
description = description.replaceFirst (":3", p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString ()
|
@Override
|
||||||
{
|
public String toString ()
|
||||||
String hex = getHex (buffer, ptr, length > 4 ? 4 : length);
|
{
|
||||||
StringBuilder text = new StringBuilder ();
|
String hex = getHex (buffer, ptr, length > 4 ? 4 : length);
|
||||||
text.append (String.format ("%2s%05X: %-11s %-6s %-8s %s%n", jumpTarget ? "->" : "", ptr,
|
StringBuilder text = new StringBuilder ();
|
||||||
hex, mnemonic, extras, description));
|
text.append (String.format ("%2s%05X: %-11s %-6s %-8s %s%n",
|
||||||
if (length > 4)
|
jumpTarget ? "->" : "", ptr, hex, mnemonic, extras,
|
||||||
{
|
description));
|
||||||
int bytesLeft = length - 4;
|
if (length > 4)
|
||||||
int jmp = 0;
|
{
|
||||||
int p = ptr + 4;
|
int bytesLeft = length - 4;
|
||||||
while (bytesLeft > 0)
|
int jmp = 0;
|
||||||
{
|
int p = ptr + 4;
|
||||||
String line = getHex (buffer, p, (bytesLeft > 4) ? 4 : bytesLeft);
|
while (bytesLeft > 0)
|
||||||
text.append (" " + line);
|
{
|
||||||
if (jumps.size () > 0)
|
String line = getHex (buffer, p, (bytesLeft > 4) ? 4 : bytesLeft);
|
||||||
{
|
text.append (" " + line);
|
||||||
if (jmp < jumps.size ())
|
if (jumps.size () > 0)
|
||||||
text.append (" " + jumps.get (jmp++));
|
{
|
||||||
if (jmp < jumps.size ())
|
if (jmp < jumps.size ())
|
||||||
text.append (" " + jumps.get (jmp++));
|
text.append (" " + jumps.get (jmp++));
|
||||||
}
|
if (jmp < jumps.size ())
|
||||||
text.append ("\n");
|
text.append (" " + jumps.get (jmp++));
|
||||||
bytesLeft -= 4;
|
}
|
||||||
p += 4;
|
text.append ("\n");
|
||||||
}
|
bytesLeft -= 4;
|
||||||
}
|
p += 4;
|
||||||
return text.toString ();
|
}
|
||||||
}
|
}
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
private String getHex (byte[] buffer, int offset, int length)
|
private String getHex (byte[] buffer, int offset, int length)
|
||||||
{
|
{
|
||||||
if ((offset + length) >= buffer.length)
|
if ((offset + length) >= buffer.length)
|
||||||
{
|
{
|
||||||
System.out.println ("too many");
|
System.out.println ("too many");
|
||||||
return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||||
}
|
}
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
text.append (String.format ("%02X ", buffer[offset + i]));
|
text.append (String.format ("%02X ", buffer[offset + i]));
|
||||||
if (text.length () > 0)
|
if (text.length () > 0)
|
||||||
text.deleteCharAt (text.length () - 1);
|
text.deleteCharAt (text.length () - 1);
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Jump
|
class Jump
|
||||||
{
|
{
|
||||||
int addressFrom;
|
int addressFrom;
|
||||||
int addressTo;
|
int addressTo;
|
||||||
boolean caseJump;
|
boolean caseJump;
|
||||||
int caseValue;
|
int caseValue;
|
||||||
|
|
||||||
public Jump (int addressFrom, int addressTo)
|
public Jump (int addressFrom, int addressTo)
|
||||||
{
|
{
|
||||||
this.addressFrom = addressFrom;
|
this.addressFrom = addressFrom;
|
||||||
this.addressTo = addressTo;
|
this.addressTo = addressTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Jump (int addressFrom, int addressTo, int value)
|
public Jump (int addressFrom, int addressTo, int value)
|
||||||
{
|
{
|
||||||
this (addressFrom, addressTo);
|
this (addressFrom, addressTo);
|
||||||
this.caseValue = value;
|
this.caseValue = value;
|
||||||
this.caseJump = true;
|
this.caseJump = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString ()
|
@Override
|
||||||
{
|
public String toString ()
|
||||||
if (caseJump)
|
{
|
||||||
return String.format ("%3d: %04X", caseValue, addressTo);
|
if (caseJump)
|
||||||
return String.format ("%04X", addressTo);
|
return String.format ("%3d: %04X", caseValue, addressTo);
|
||||||
}
|
return String.format ("%04X", addressTo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,117 +2,91 @@ package com.bytezone.diskbrowser.applefile;
|
|||||||
|
|
||||||
public interface PascalConstants
|
public interface PascalConstants
|
||||||
{
|
{
|
||||||
static String[] mnemonics =
|
static String[] mnemonics =
|
||||||
{ "ABI", "ABR", "ADI", "ADR", "LAND", "DIF", "DVI", "DVR", "CHK", "FLO", "FLT",
|
{ "ABI", "ABR", "ADI", "ADR", "LAND", "DIF", "DVI", "DVR", "CHK", "FLO", "FLT",
|
||||||
"INN", "INT", "LOR", "MODI", "MPI", "MPR", "NGI", "NGR", "LNOT", "SRS", "SBI",
|
"INN", "INT", "LOR", "MODI", "MPI", "MPR", "NGI", "NGR", "LNOT", "SRS", "SBI",
|
||||||
"SBR", "SGS", "SQI", "SQR", "STO", "IXS", "UNI", "LDE", "CSP", "LDCN", "ADJ",
|
"SBR", "SGS", "SQI", "SQR", "STO", "IXS", "UNI", "LDE", "CSP", "LDCN", "ADJ",
|
||||||
"FJP", "INC", "IND", "IXA", "LAO", "LSA", "LAE", "MOV", "LDO", "SAS", "SRO", "XJP",
|
"FJP", "INC", "IND", "IXA", "LAO", "LSA", "LAE", "MOV", "LDO", "SAS", "SRO",
|
||||||
"RNP", "CIP", "EQU", "GEQ", "GRT", "LDA", "LDC", "LEQ", "LES", "LOD", "NEQ", "STR",
|
"XJP", "RNP", "CIP", "EQU", "GEQ", "GRT", "LDA", "LDC", "LEQ", "LES", "LOD",
|
||||||
"UJP", "LDP", "STP", "LDM", "STM", "LDB", "STB", "IXP", "RBP", "CBP", "EQUI",
|
"NEQ", "STR", "UJP", "LDP", "STP", "LDM", "STM", "LDB", "STB", "IXP", "RBP",
|
||||||
"GEQI", "GRTI", "LLA", "LDCI", "LEQI", "LESI", "LDL", "NEQI", "STL", "CXP", "CLP",
|
"CBP", "EQUI", "GEQI", "GRTI", "LLA", "LDCI", "LEQI", "LESI", "LDL", "NEQI",
|
||||||
"CGP", "LPA", "STE", "???", "EFJ", "NFJ", "BPT", "XIT", "NOP" };
|
"STL", "CXP", "CLP", "CGP", "LPA", "STE", "???", "EFJ", "NFJ", "BPT", "XIT",
|
||||||
|
"NOP" };
|
||||||
|
|
||||||
static int[] mnemonicSize =
|
static int[] mnemonicSize =
|
||||||
//
|
//
|
||||||
// 128 - 155
|
// 128 - 155
|
||||||
// 156 - 183
|
// 156 - 183
|
||||||
// 184 - 211
|
// 184 - 211
|
||||||
// 212 - 239
|
// 212 - 239
|
||||||
// 240 - 255
|
// 240 - 255
|
||||||
|
|
||||||
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 3, 2, 1, 2, 2, 2, 2, 2, 2, 0, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 3, 0, 2, 2, 3, 2,
|
1, 1, 3, 2, 1, 2, 2, 2, 2, 2, 2, 0, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 3, 0, 2, 2,
|
||||||
3, 2, 1, 1, 2, 2, 1, 1, 3, 2, 2, 1, 1, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 2, 0, 3, 1, 2,
|
3, 2, 3, 2, 1, 1, 2, 2, 1, 1, 3, 2, 2, 1, 1, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 2, 0,
|
||||||
2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
3, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
static String[] descriptions =
|
static String[] descriptions =
|
||||||
{
|
{ "Absolute value of integer - push ABS(ToS)",
|
||||||
"Absolute value of integer - push ABS(ToS)",
|
"Absolute value of real - push abs((real)ToS)", "Add integers (tos + tos-1)",
|
||||||
"Absolute value of real - push abs((real)ToS)",
|
"Add reals - push ToS + ToS-1", "Logical AND",
|
||||||
"Add integers (tos + tos-1)",
|
"Set difference - push difference of sets ToS-1 and ToS",
|
||||||
"Add reals - push ToS + ToS-1",
|
"Divide integers - push ToS-1 / ToS", "Divide reals - push ToS-1 / ToS",
|
||||||
"Logical AND",
|
"Check subrange bounds - assert ToS-1 <= ToS-2 <= ToS, pop ToS, pop ToS-1",
|
||||||
"Set difference - push difference of sets ToS-1 and ToS",
|
"Float next-to-ToS - push integer ToS-1 after converting to a real",
|
||||||
"Divide integers - push ToS-1 / ToS",
|
"Float ToS - push integer ToS after converting to a float",
|
||||||
"Divide reals - push ToS-1 / ToS",
|
"Set Membership - if int ToS-1 is in set ToS, push true, else push false",
|
||||||
"Check subrange bounds - assert ToS-1 <= ToS-2 <= ToS, pop ToS, pop ToS-1",
|
"Set Intersection - push TOS AND TOS-1", "Logical OR",
|
||||||
"Float next-to-ToS - push integer ToS-1 after converting to a real",
|
"Modulo integers - push ToS-1 % ToS", "Multiply TOS by TOS-1",
|
||||||
"Float ToS - push integer ToS after converting to a float",
|
"Multiply reals - push ToS-1 * ToS",
|
||||||
"Set Membership - if int ToS-1 is in set ToS, push true, else push false",
|
"Negate Integer - push two's complement of ToS",
|
||||||
"Set Intersection - push TOS AND TOS-1",
|
"Negate real - push -((real)ToS)", "Logical Not - push one's complement of ToS",
|
||||||
"Logical OR",
|
"Build a subrange set", "Subtract Integers push ToS-1 - ToS",
|
||||||
"Modulo integers - push ToS-1 % ToS",
|
"Subtract reals - push ToS-1 - ToS", "Build a singleton set",
|
||||||
"Multiply TOS by TOS-1",
|
"Square integer - push ToS ^ 2", "Square real - push ToS ^ 2",
|
||||||
"Multiply reals - push ToS-1 * ToS",
|
"Store indirect word - store ToS into word pointed to by ToS-1",
|
||||||
"Negate Integer - push two's complement of ToS",
|
"Index string array - push &(*ToS-1 + ToS)",
|
||||||
"Negate real - push -((real)ToS)",
|
"Set union - push union of sets ToS OR ToS-1",
|
||||||
"Logical Not - push one's complement of ToS",
|
"Load extended word - push word at segment :1+:2",
|
||||||
"Build a subrange set",
|
"Call Standard Procedure #:1 - ", "Load Constant NIL", "Adjust set",
|
||||||
"Subtract Integers push ToS-1 - ToS",
|
"Jump if ToS false", "Increment field ptr - push ToS+:1",
|
||||||
"Subtract reals - push ToS-1 - ToS",
|
"Static index and load word", "Compute word pointer from ToS-1 + ToS * :1 words",
|
||||||
"Build a singleton set",
|
"Load Global - push (BASE+:1)", "Load constant string address",
|
||||||
"Square integer - push ToS ^ 2",
|
"Load extended address - push address of word at segment :1+:2",
|
||||||
"Square real - push ToS ^ 2",
|
"Move words - transfer :1 words from *ToS to *ToS-1",
|
||||||
"Store indirect word - store ToS into word pointed to by ToS-1",
|
"Load Global Word - push BASE+:1", "String Assign", "Store TOS into BASE+:1",
|
||||||
"Index string array - push &(*ToS-1 + ToS)",
|
"Case Jump - :1::2, Error: :3", "Return from non-base procedure (pass :1 words)",
|
||||||
"Set union - push union of sets ToS OR ToS-1",
|
"Call intermediate procedure #:1", "ToS-1 == ToS", "ToS-1 >= ToS", "ToS-1 > ToS",
|
||||||
"Load extended word - push word at segment :1+:2",
|
"Load Intermediate Address - push :1th activation record +:2 bytes",
|
||||||
"Call Standard Procedure #:1 - ",
|
"Load multi-word constant - :1 words", "ToS-1 <= ToS", "ToS-1 < ToS",
|
||||||
"Load Constant NIL",
|
"Load Intermediate Word - push :1th activation record +:2 bytes", "ToS-1 <> ToS",
|
||||||
"Adjust set",
|
"Store intermediate word - store TOS into :2, traverse :1", "Unconditional jump",
|
||||||
"Jump if ToS false",
|
"Load Packed Field - push *ToS", "Store into packed field",
|
||||||
"Increment field ptr - push ToS+:1",
|
"Load multiple words - push block of unsigned bytes at *ToS",
|
||||||
"Static index and load word",
|
"Store multiple words - store block of UB at ToS to *ToS-1",
|
||||||
"Compute word pointer from ToS-1 + ToS * :1 words",
|
"Load Byte - index the byte pointer ToS-1 by integer index ToS and push that byte",
|
||||||
"Load Global - push (BASE+:1)",
|
"Store Byte - index the byte pointer ToS-2 by integer index ToS-1 and move ToS to that location",
|
||||||
"Load constant string address",
|
"Index packed array - do complicated stuff with :1 and :2",
|
||||||
"Load extended address - push address of word at segment :1+:2",
|
"Return from base procedure (pass :1 words)",
|
||||||
"Move words - transfer :1 words from *ToS to *ToS-1",
|
"Call Base Procedure :1 at lex level -1 or 0", "Compare Integer : ToS-1 = ToS",
|
||||||
"Load Global Word - push BASE+:1",
|
"Compare Integer : TOS-1 >= TOS", "Compare Integer : TOS-1 > ToS",
|
||||||
"String Assign",
|
"Load Local Address - push MP+:1", "Load Word - push #:1",
|
||||||
"Store TOS into BASE+:1",
|
"Compare Integer : TOS-1 <= TOS", "Compare Integer : TOS-1 < ToS",
|
||||||
"Case Jump - :1::2, Error: :3",
|
"Load Local Word - push MP+:1", "Compare Integer : TOS-1 <> TOS",
|
||||||
"Return from non-base procedure (pass :1 words)",
|
"Store Local Word - store ToS into MP+:1",
|
||||||
"Call intermediate procedure #:1",
|
"Call external procedure #:2 in segment #:1", "Call local procedure #:1",
|
||||||
"ToS-1 == ToS",
|
"Call global procedure #:1", "Load a packed array - use :1 and :2",
|
||||||
"ToS-1 >= ToS",
|
"Store extended word - store ToS into word at segment :1+:2", "210 ",
|
||||||
"ToS-1 > ToS",
|
"Equal false jump - jump :1 if ToS-1 <> ToS",
|
||||||
"Load Intermediate Address - push :1th activation record +:2 bytes",
|
"Not equal false jump - jump :1 if ToS-1 == ToS",
|
||||||
"Load multi-word constant - :1 words",
|
"Breakpoint - not used (does NOP)", "Exit OS - cold boot", "No-op" };
|
||||||
"ToS-1 <= ToS",
|
|
||||||
"ToS-1 < ToS",
|
|
||||||
"Load Intermediate Word - push :1th activation record +:2 bytes",
|
|
||||||
"ToS-1 <> ToS",
|
|
||||||
"Store intermediate word - store TOS into :2, traverse :1",
|
|
||||||
"Unconditional jump",
|
|
||||||
"Load Packed Field - push *ToS",
|
|
||||||
"Store into packed field",
|
|
||||||
"Load multiple words - push block of unsigned bytes at *ToS",
|
|
||||||
"Store multiple words - store block of UB at ToS to *ToS-1",
|
|
||||||
"Load Byte - index the byte pointer ToS-1 by integer index ToS and push that byte",
|
|
||||||
"Store Byte - index the byte pointer ToS-2 by integer index ToS-1 and move ToS to that location",
|
|
||||||
"Index packed array - do complicated stuff with :1 and :2",
|
|
||||||
"Return from base procedure (pass :1 words)",
|
|
||||||
"Call Base Procedure :1 at lex level -1 or 0", "Compare Integer : ToS-1 = ToS",
|
|
||||||
"Compare Integer : TOS-1 >= TOS", "Compare Integer : TOS-1 > ToS",
|
|
||||||
"Load Local Address - push MP+:1", "Load Word - push #:1",
|
|
||||||
"Compare Integer : TOS-1 <= TOS", "Compare Integer : TOS-1 < ToS",
|
|
||||||
"Load Local Word - push MP+:1", "Compare Integer : TOS-1 <> TOS",
|
|
||||||
"Store Local Word - store ToS into MP+:1",
|
|
||||||
"Call external procedure #:2 in segment #:1", "Call local procedure #:1",
|
|
||||||
"Call global procedure #:1", "Load a packed array - use :1 and :2",
|
|
||||||
"Store extended word - store ToS into word at segment :1+:2", "210 ",
|
|
||||||
"Equal false jump - jump :1 if ToS-1 <> ToS",
|
|
||||||
"Not equal false jump - jump :1 if ToS-1 == ToS",
|
|
||||||
"Breakpoint - not used (does NOP)", "Exit OS - cold boot", "No-op" };
|
|
||||||
|
|
||||||
static String[] CSP =
|
static String[] CSP =
|
||||||
{ "000", "NEW", "MVL", "MVR", "EXIT", "", "", "IDS", "TRS", "TIM", "FLC", "SCN", "",
|
{ "000", "NEW", "MVL", "MVR", "EXIT", "", "", "IDS", "TRS", "TIM", "FLC", "SCN", "",
|
||||||
"", "", "", "", "", "", "", "", "021", "TNC", "RND", "", "", "", "", "", "", "",
|
"", "", "", "", "", "", "", "", "021", "TNC", "RND", "", "", "", "", "", "", "",
|
||||||
"MRK", "RLS", "33", "34", "POT", "36", "37", "38", "39", "40" };
|
"MRK", "RLS", "33", "34", "POT", "36", "37", "38", "39", "40" };
|
||||||
|
|
||||||
static String[] SegmentKind =
|
static String[] SegmentKind = { "Linked", "HostSeg", "SegProc", "UnitSeg", "SeprtSeg",
|
||||||
{ "Linked", "HostSeg", "SegProc", "UnitSeg", "SeprtSeg", "UnlinkedIntrins",
|
"UnlinkedIntrins", "LinkedIntrins", "DataSeg" };
|
||||||
"LinkedIntrins", "DataSeg" };
|
|
||||||
}
|
}
|
@ -8,168 +8,183 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
|
|
||||||
public class PascalProcedure
|
public class PascalProcedure
|
||||||
{
|
{
|
||||||
// all procedures have these fields
|
// all procedures have these fields
|
||||||
byte[] buffer;
|
byte[] buffer;
|
||||||
int procOffset;
|
int procOffset;
|
||||||
int offset;
|
int offset;
|
||||||
int slot;
|
int slot;
|
||||||
boolean valid;
|
boolean valid;
|
||||||
|
|
||||||
// only valid procedures have these fields
|
// only valid procedures have these fields
|
||||||
int procedureNo;
|
int procedureNo;
|
||||||
int procLevel;
|
int procLevel;
|
||||||
int codeStart;
|
int codeStart;
|
||||||
int codeEnd;
|
int codeEnd;
|
||||||
int parmSize;
|
int parmSize;
|
||||||
int dataSize;
|
int dataSize;
|
||||||
List<PascalCodeStatement> statements = new ArrayList<PascalCodeStatement> ();
|
List<PascalCodeStatement> statements = new ArrayList<PascalCodeStatement> ();
|
||||||
AssemblerProgram assembler;
|
AssemblerProgram assembler;
|
||||||
int jumpTable = -8;
|
int jumpTable = -8;
|
||||||
|
|
||||||
public PascalProcedure (byte[] buffer, int slot)
|
public PascalProcedure (byte[] buffer, int slot)
|
||||||
{
|
{
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
int p = buffer.length - 2 - slot * 2;
|
int p = buffer.length - 2 - slot * 2;
|
||||||
offset = HexFormatter.intValue (buffer[p], buffer[p + 1]);
|
offset = HexFormatter.intValue (buffer[p], buffer[p + 1]);
|
||||||
procOffset = p - offset;
|
procOffset = p - offset;
|
||||||
valid = procOffset > 0;
|
valid = procOffset > 0;
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
procedureNo = buffer[procOffset] & 0xFF;
|
procedureNo = buffer[procOffset] & 0xFF;
|
||||||
procLevel = buffer[procOffset + 1];
|
procLevel = buffer[procOffset + 1];
|
||||||
codeStart = HexFormatter.intValue (buffer[procOffset - 2], buffer[procOffset - 1]);
|
codeStart = HexFormatter.intValue (buffer[procOffset - 2], buffer[procOffset - 1]);
|
||||||
codeEnd = HexFormatter.intValue (buffer[procOffset - 4], buffer[procOffset - 3]);
|
codeEnd = HexFormatter.intValue (buffer[procOffset - 4], buffer[procOffset - 3]);
|
||||||
parmSize = HexFormatter.intValue (buffer[procOffset - 6], buffer[procOffset - 5]);
|
parmSize = HexFormatter.intValue (buffer[procOffset - 6], buffer[procOffset - 5]);
|
||||||
dataSize = HexFormatter.intValue (buffer[procOffset - 8], buffer[procOffset - 7]);
|
dataSize = HexFormatter.intValue (buffer[procOffset - 8], buffer[procOffset - 7]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decode ()
|
private void decode ()
|
||||||
{
|
{
|
||||||
if (statements.size () > 0 || assembler != null)
|
if (statements.size () > 0 || assembler != null)
|
||||||
return;
|
return;
|
||||||
int ptr = procOffset - codeStart - 2;
|
int ptr = procOffset - codeStart - 2;
|
||||||
int max = procOffset + jumpTable;
|
int max = procOffset + jumpTable;
|
||||||
|
|
||||||
if (codeEnd == 0)
|
if (codeEnd == 0)
|
||||||
{
|
{
|
||||||
int len = codeStart + jumpTable + 2;
|
int len = codeStart + jumpTable + 2;
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
byte[] asmBuf = new byte[len];
|
byte[] asmBuf = new byte[len];
|
||||||
System.arraycopy (buffer, ptr, asmBuf, 0, len);
|
System.arraycopy (buffer, ptr, asmBuf, 0, len);
|
||||||
assembler = new AssemblerProgram ("Proc", asmBuf, ptr);
|
assembler = new AssemblerProgram ("Proc", asmBuf, ptr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ptr < max)
|
while (ptr < max)
|
||||||
{
|
{
|
||||||
PascalCodeStatement cs = new PascalCodeStatement (buffer, ptr, procOffset);
|
System.out.printf ("ptr:%d, max:%d, buf:%d %n", ptr, max, buffer.length);
|
||||||
if (cs.length <= 0)
|
if (ptr >= buffer.length || ptr < 0)
|
||||||
{
|
{
|
||||||
System.out.println ("error - length <= 0 : " + cs);
|
System.out.println ("Ptr outside buffer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
statements.add (cs);
|
PascalCodeStatement cs = new PascalCodeStatement (buffer, ptr, procOffset);
|
||||||
if (cs.val == 185 || cs.val == 161)
|
if (cs.length <= 0)
|
||||||
if (cs.p1 < jumpTable)
|
{
|
||||||
{
|
System.out.println ("error - length <= 0 : " + cs);
|
||||||
jumpTable = cs.p1;
|
break;
|
||||||
max = procOffset + jumpTable;
|
}
|
||||||
}
|
statements.add (cs);
|
||||||
ptr += cs.length;
|
if (cs.val == 185 || cs.val == 161)
|
||||||
}
|
if (cs.p1 < jumpTable)
|
||||||
|
{
|
||||||
|
jumpTable = cs.p1;
|
||||||
|
max = procOffset + jumpTable;
|
||||||
|
}
|
||||||
|
ptr += cs.length;
|
||||||
|
}
|
||||||
|
|
||||||
// Tidy up left-over bytes at the end
|
// Tidy up left-over bytes at the end
|
||||||
if (statements.size () > 1)
|
if (statements.size () > 1)
|
||||||
{
|
{
|
||||||
PascalCodeStatement lastStatement = statements.get (statements.size () - 1);
|
PascalCodeStatement lastStatement = statements.get (statements.size () - 1);
|
||||||
PascalCodeStatement secondLastStatement = statements.get (statements.size () - 2);
|
PascalCodeStatement secondLastStatement = statements.get (statements.size () - 2);
|
||||||
if (lastStatement.val == 0
|
if (lastStatement.val == 0 && (secondLastStatement.val == 0xD6
|
||||||
&& (secondLastStatement.val == 0xD6 || secondLastStatement.val == 0xC1 || secondLastStatement.val == 0xAD))
|
|| secondLastStatement.val == 0xC1 || secondLastStatement.val == 0xAD))
|
||||||
statements.remove (statements.size () - 1);
|
statements.remove (statements.size () - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark statements that are jump targets
|
// Mark statements that are jump targets
|
||||||
int actualEnd = procOffset - codeEnd - 4;
|
int actualEnd = procOffset - codeEnd - 4;
|
||||||
for (PascalCodeStatement cs : statements)
|
for (PascalCodeStatement cs : statements)
|
||||||
{
|
{
|
||||||
if (cs.ptr == actualEnd)
|
if (cs.ptr == actualEnd)
|
||||||
{
|
{
|
||||||
cs.jumpTarget = true;
|
cs.jumpTarget = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (Jump cj : cs.jumps)
|
for (Jump cj : cs.jumps)
|
||||||
for (PascalCodeStatement cs2 : statements)
|
for (PascalCodeStatement cs2 : statements)
|
||||||
if (cs2.ptr == cj.addressTo)
|
if (cs2.ptr == cj.addressTo)
|
||||||
{
|
{
|
||||||
cs2.jumpTarget = true;
|
cs2.jumpTarget = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PascalCodeStatement> extractStrings ()
|
public List<PascalCodeStatement> extractStrings ()
|
||||||
{
|
{
|
||||||
decode ();
|
decode ();
|
||||||
List<PascalCodeStatement> strings = new ArrayList<PascalCodeStatement> ();
|
List<PascalCodeStatement> strings = new ArrayList<PascalCodeStatement> ();
|
||||||
for (PascalCodeStatement cs : statements)
|
for (PascalCodeStatement cs : statements)
|
||||||
if (cs.val == 166)
|
if (cs.val == 166)
|
||||||
strings.add (cs);
|
strings.add (cs);
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString ()
|
@Override
|
||||||
{
|
public String toString ()
|
||||||
if (!valid)
|
{
|
||||||
return "";
|
if (!valid)
|
||||||
decode ();
|
return "";
|
||||||
|
decode ();
|
||||||
|
|
||||||
StringBuilder text = new StringBuilder ("\nProcedure Header\n================\n\n");
|
StringBuilder text = new StringBuilder ("\nProcedure Header\n================\n\n");
|
||||||
|
|
||||||
if (false)
|
if (false)
|
||||||
text.append (HexFormatter.format (buffer, procOffset + jumpTable, 2 - jumpTable) + "\n\n");
|
text.append (HexFormatter.format (buffer, procOffset + jumpTable, 2 - jumpTable)
|
||||||
|
+ "\n\n");
|
||||||
|
|
||||||
text.append (String.format ("Level.......%5d %02X%n", procLevel, procLevel & 0xFF));
|
text.append (String.format ("Level.......%5d %02X%n", procLevel,
|
||||||
text.append (String.format ("Proc no.....%5d %02X%n", procedureNo, procedureNo));
|
procLevel & 0xFF));
|
||||||
text.append (String.format ("Code entry..%5d %04X (%04X - %04X = %04X)%n", codeStart,
|
text.append (String.format ("Proc no.....%5d %02X%n", procedureNo, procedureNo));
|
||||||
codeStart, (procOffset - 2), codeStart, (procOffset - codeStart - 2)));
|
text.append (String.format ("Code entry..%5d %04X (%04X - %04X = %04X)%n",
|
||||||
text.append (String.format ("Code exit...%5d %04X", codeEnd, codeEnd));
|
codeStart, codeStart, (procOffset - 2), codeStart,
|
||||||
if (codeEnd > 0)
|
(procOffset - codeStart - 2)));
|
||||||
text.append (String.format (" (%04X - %04X = %04X)%n", (procOffset - 4), codeEnd,
|
text.append (String.format ("Code exit...%5d %04X", codeEnd, codeEnd));
|
||||||
(procOffset - codeEnd - 4)));
|
if (codeEnd > 0)
|
||||||
else
|
text.append (String.format (" (%04X - %04X = %04X)%n", (procOffset - 4), codeEnd,
|
||||||
text.append (String.format ("%n"));
|
(procOffset - codeEnd - 4)));
|
||||||
text.append (String.format ("Parm size...%5d %04X%n", parmSize, parmSize));
|
else
|
||||||
text.append (String.format ("Data size...%5d %04X%n%n", dataSize, dataSize));
|
text.append (String.format ("%n"));
|
||||||
|
text.append (String.format ("Parm size...%5d %04X%n", parmSize, parmSize));
|
||||||
|
text.append (String.format ("Data size...%5d %04X%n%n", dataSize, dataSize));
|
||||||
|
|
||||||
text.append ("Procedure Code\n==============\n\n");
|
text.append ("Procedure Code\n==============\n\n");
|
||||||
|
|
||||||
int ptr = procOffset - codeStart - 2;
|
int ptr = procOffset - codeStart - 2;
|
||||||
if (false)
|
if (false)
|
||||||
text.append (HexFormatter.format (buffer, ptr, codeStart + jumpTable + 2) + "\n\n");
|
text.append (HexFormatter.format (buffer, ptr, codeStart + jumpTable + 2) + "\n\n");
|
||||||
|
|
||||||
if (codeEnd == 0)
|
if (codeEnd == 0)
|
||||||
text.append (assembler.getAssembler () + "\n");
|
{
|
||||||
else
|
if (assembler != null)
|
||||||
{
|
text.append (assembler.getAssembler () + "\n");
|
||||||
for (PascalCodeStatement cs : statements)
|
else
|
||||||
text.append (cs);
|
text.append ("Null assembler in PascalProcedure");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (PascalCodeStatement cs : statements)
|
||||||
|
text.append (cs);
|
||||||
|
|
||||||
if (jumpTable < -8 && false)
|
if (jumpTable < -8 && false)
|
||||||
{
|
{
|
||||||
text.append ("\nJump table:\n");
|
text.append ("\nJump table:\n");
|
||||||
for (int i = procOffset + jumpTable; i < procOffset - 8; i += 2)
|
for (int i = procOffset + jumpTable; i < procOffset - 8; i += 2)
|
||||||
{
|
{
|
||||||
ptr = i - ((buffer[i + 1] & 0xFF) * 256 + (buffer[i] & 0xFF));
|
ptr = i - ((buffer[i + 1] & 0xFF) * 256 + (buffer[i] & 0xFF));
|
||||||
text.append (String.format ("%05X : %02X %02X --> %04X%n", i, buffer[i], buffer[i + 1],
|
text.append (String.format ("%05X : %02X %02X --> %04X%n", i, buffer[i],
|
||||||
ptr));
|
buffer[i + 1], ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,19 +33,22 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
this.size = HexFormatter.intValue (fullBuffer[seq * 4 + 2], fullBuffer[seq * 4 + 3]);
|
this.size = HexFormatter.intValue (fullBuffer[seq * 4 + 2], fullBuffer[seq * 4 + 3]);
|
||||||
this.segmentNoHeader = fullBuffer[0x100 + seq * 2];
|
this.segmentNoHeader = fullBuffer[0x100 + seq * 2];
|
||||||
|
|
||||||
segKind =
|
segKind = HexFormatter.intValue (fullBuffer[0xC0 + seq * 2],
|
||||||
HexFormatter.intValue (fullBuffer[0xC0 + seq * 2], fullBuffer[0xC0 + seq * 2 + 1]);
|
fullBuffer[0xC0 + seq * 2 + 1]);
|
||||||
textAddress =
|
textAddress = HexFormatter.intValue (fullBuffer[0xE0 + seq * 2],
|
||||||
HexFormatter.intValue (fullBuffer[0xE0 + seq * 2], fullBuffer[0xE0 + seq * 2 + 1]);
|
fullBuffer[0xE0 + seq * 2 + 1]);
|
||||||
int flags = fullBuffer[0x101 + seq * 2] & 0xFF;
|
int flags = fullBuffer[0x101 + seq * 2] & 0xFF;
|
||||||
machineType = flags & 0x0F;
|
machineType = flags & 0x0F;
|
||||||
version = (flags & 0xD0) >> 5;
|
version = (flags & 0xD0) >> 5;
|
||||||
intrinsSegs1 =
|
intrinsSegs1 = HexFormatter.intValue (fullBuffer[0x120 + seq * 4],
|
||||||
HexFormatter.intValue (fullBuffer[0x120 + seq * 4], fullBuffer[0x120 + seq * 4 + 1]);
|
fullBuffer[0x120 + seq * 4 + 1]);
|
||||||
intrinsSegs2 = HexFormatter.intValue (fullBuffer[0x120 + seq * 4 + 2],
|
intrinsSegs2 = HexFormatter.intValue (fullBuffer[0x120 + seq * 4 + 2],
|
||||||
fullBuffer[0x120 + seq * 4 + 3]);
|
fullBuffer[0x120 + seq * 4 + 3]);
|
||||||
|
|
||||||
int offset = blockNo * 512;
|
int offset = blockNo * 512;
|
||||||
|
// System.out.printf ("Seq:%d, block:%d, size:%d, seg:%d, kind:%d, address:%d %n", seq,
|
||||||
|
// blockNo, size, segmentNoHeader, segKind, textAddress);
|
||||||
|
// System.out.println (HexFormatter.format (fullBuffer));
|
||||||
if (offset < fullBuffer.length)
|
if (offset < fullBuffer.length)
|
||||||
{
|
{
|
||||||
buffer = new byte[size]; // replaces this.buffer with the segment buffer only
|
buffer = new byte[size]; // replaces this.buffer with the segment buffer only
|
||||||
@ -57,11 +60,12 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
System.out.printf ("Zero segment header in %s seq %d%n", name, seq);
|
System.out.printf ("Zero segment header in %s seq %d%n", name, seq);
|
||||||
else if (segmentNoBody != segmentNoHeader)
|
else if (segmentNoBody != segmentNoHeader)
|
||||||
System.out.println ("Segment number mismatch : " + segmentNoBody + " / "
|
System.out.println ("Segment number mismatch : " + segmentNoBody + " / "
|
||||||
+ segmentNoHeader);
|
+ segmentNoHeader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
System.out.println ("Error in blocksize for pascal disk");
|
System.out.printf ("Error in blocksize %,d > %,d for pascal disk%n", offset,
|
||||||
|
fullBuffer.length);
|
||||||
throw new FileFormatException ("Error in PascalSegment");
|
throw new FileFormatException ("Error in PascalSegment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,10 +80,10 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
|
|
||||||
public String toText ()
|
public String toText ()
|
||||||
{
|
{
|
||||||
return String.format (
|
return String
|
||||||
" %2d %02X %04X %,6d %-8s %-15s %3d %3d %d %d %d %d",
|
.format (" %2d %02X %04X %,6d %-8s %-15s %3d %3d %d %d %d %d",
|
||||||
slot, blockNo, size, size, name, SegmentKind[segKind], textAddress,
|
slot, blockNo, size, size, name, SegmentKind[segKind], textAddress,
|
||||||
segmentNoHeader, machineType, version, intrinsSegs1, intrinsSegs2);
|
segmentNoHeader, machineType, version, intrinsSegs1, intrinsSegs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,9 +95,9 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
String title = "Segment - " + name;
|
String title = "Segment - " + name;
|
||||||
text.append (title + "\n"
|
text.append (title + "\n"
|
||||||
+ "===============================".substring (0, title.length ()) + "\n\n");
|
+ "===============================".substring (0, title.length ()) + "\n\n");
|
||||||
String warning =
|
String warning =
|
||||||
segmentNoBody == segmentNoHeader ? "" : " (" + segmentNoHeader + " in header)";
|
segmentNoBody == segmentNoHeader ? "" : " (" + segmentNoHeader + " in header)";
|
||||||
text.append (String.format ("Address........ %02X%n", blockNo));
|
text.append (String.format ("Address........ %02X%n", blockNo));
|
||||||
text.append (String.format ("Length......... %04X%n", buffer.length));
|
text.append (String.format ("Length......... %04X%n", buffer.length));
|
||||||
text.append (String.format ("Machine type... %d%n", machineType));
|
text.append (String.format ("Machine type... %d%n", machineType));
|
||||||
@ -116,11 +120,12 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
int address = size - procedure.slot * 2 - 2;
|
int address = size - procedure.slot * 2 - 2;
|
||||||
text.append (String.format (
|
text.append (String.format (
|
||||||
" %2d %04X %3d %04X %04X %04X "
|
" %2d %04X %3d %04X %04X %04X "
|
||||||
+ "%04X (%04X - %04X = %04X)%n",
|
+ "%04X (%04X - %04X = %04X)%n",
|
||||||
procedure.procedureNo, procedure.offset,
|
procedure.procedureNo, procedure.offset,
|
||||||
procedure.procLevel, procedure.codeStart,
|
procedure.procLevel, procedure.codeStart,
|
||||||
procedure.codeEnd, procedure.parmSize, procedure.dataSize,
|
procedure.codeEnd, procedure.parmSize,
|
||||||
address, procedure.offset, procedure.procOffset));
|
procedure.dataSize, address, procedure.offset,
|
||||||
|
procedure.procOffset));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
text.append (String.format (" %2d %04X%n", procedure.slot, procedure.offset));
|
text.append (String.format (" %2d %04X%n", procedure.slot, procedure.offset));
|
||||||
@ -131,7 +136,8 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||||||
{
|
{
|
||||||
List<PascalCodeStatement> strings = pp.extractStrings ();
|
List<PascalCodeStatement> strings = pp.extractStrings ();
|
||||||
for (PascalCodeStatement cs : strings)
|
for (PascalCodeStatement cs : strings)
|
||||||
text.append (String.format (" %2d %04X %s%n", pp.procedureNo, cs.ptr, cs.text));
|
text.append (String.format (" %2d %04X %s%n", pp.procedureNo, cs.ptr,
|
||||||
|
cs.text));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PascalProcedure procedure : procedures)
|
for (PascalProcedure procedure : procedures)
|
||||||
|
107
src/com/bytezone/diskbrowser/applefile/Relocator.java
Normal file
107
src/com/bytezone/diskbrowser/applefile/Relocator.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package com.bytezone.diskbrowser.applefile;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
public class Relocator extends AbstractFile
|
||||||
|
{
|
||||||
|
private final int checkByte;
|
||||||
|
private final List<DiskRecord> diskRecords = new ArrayList<DiskRecord> ();
|
||||||
|
|
||||||
|
public Relocator (String name, byte[] buffer)
|
||||||
|
{
|
||||||
|
super (name, buffer);
|
||||||
|
|
||||||
|
checkByte = HexFormatter.intValue (buffer[0], buffer[1]);
|
||||||
|
|
||||||
|
int ptr = 2; // skip checkByte
|
||||||
|
|
||||||
|
while (buffer[ptr] != 0)
|
||||||
|
{
|
||||||
|
DiskRecord diskRecord = new DiskRecord (buffer, ptr);
|
||||||
|
diskRecords.add (diskRecord);
|
||||||
|
ptr += diskRecord.size ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText ()
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
text.append ("Pascal Relocator\n\n");
|
||||||
|
text.append (String.format ("Check byte..... %04X%n%n", checkByte));
|
||||||
|
|
||||||
|
for (DiskRecord diskRecord : diskRecords)
|
||||||
|
{
|
||||||
|
text.append (diskRecord);
|
||||||
|
text.append ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DiskRecord
|
||||||
|
{
|
||||||
|
int diskNumber;
|
||||||
|
int diskSegments;
|
||||||
|
List<Segment> segments = new ArrayList<Segment> ();
|
||||||
|
|
||||||
|
public DiskRecord (byte[] buffer, int ptr)
|
||||||
|
{
|
||||||
|
diskNumber = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
|
diskSegments = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 4]);
|
||||||
|
|
||||||
|
ptr += 4;
|
||||||
|
for (int i = 0; i < diskSegments; i++)
|
||||||
|
{
|
||||||
|
segments.add (new Segment (buffer, ptr));
|
||||||
|
ptr += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int size ()
|
||||||
|
{
|
||||||
|
return 4 + segments.size () * 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
StringBuilder text = new StringBuilder ();
|
||||||
|
|
||||||
|
text.append (String.format ("Disk number.... %04X%n", diskNumber));
|
||||||
|
text.append (String.format ("Segments....... %04X%n%n", diskSegments));
|
||||||
|
text.append ("Segment Logical Physical Length\n");
|
||||||
|
|
||||||
|
int count = 1;
|
||||||
|
for (Segment segment : segments)
|
||||||
|
text.append (String.format (" %02X %s %n", count++, segment));
|
||||||
|
|
||||||
|
return text.toString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Segment
|
||||||
|
{
|
||||||
|
int logicalBlock;
|
||||||
|
int physicalBlock;
|
||||||
|
int segmentLength;
|
||||||
|
|
||||||
|
public Segment (byte[] buffer, int ptr)
|
||||||
|
{
|
||||||
|
logicalBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
|
physicalBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||||
|
segmentLength = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return String.format (" %04X %04X %04X", logicalBlock, physicalBlock,
|
||||||
|
segmentLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -384,6 +384,7 @@ public class AppleDisk implements Disk
|
|||||||
if (!isValidAddress (block))
|
if (!isValidAddress (block))
|
||||||
{
|
{
|
||||||
System.out.println ("Invalid block : " + block);
|
System.out.println ("Invalid block : " + block);
|
||||||
|
// assert false;
|
||||||
return null;
|
return null;
|
||||||
// return new AppleDiskAddress (this, 0); this was looping 26/07/2016
|
// return new AppleDiskAddress (this, 0); this was looping 26/07/2016
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import com.bytezone.diskbrowser.wizardry.WizardryScenarioDisk;
|
|||||||
|
|
||||||
public class DiskFactory
|
public class DiskFactory
|
||||||
{
|
{
|
||||||
private static boolean debug = false;
|
private static boolean debug = true;
|
||||||
|
|
||||||
private DiskFactory ()
|
private DiskFactory ()
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,6 @@ import com.bytezone.common.State;
|
|||||||
public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitListener
|
public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitListener
|
||||||
{
|
{
|
||||||
private static final String windowTitle = "Apple ][ Disk Browser";
|
private static final String windowTitle = "Apple ][ Disk Browser";
|
||||||
// private static final String PREFS_FULL_SCREEN = "full screen";
|
|
||||||
private final Preferences prefs = Preferences.userNodeForPackage (this.getClass ());
|
private final Preferences prefs = Preferences.userNodeForPackage (this.getClass ());
|
||||||
private WindowSaver windowSaver;
|
private WindowSaver windowSaver;
|
||||||
|
|
||||||
@ -127,9 +126,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||||||
|
|
||||||
pack ();
|
pack ();
|
||||||
|
|
||||||
// prefs.addPreferenceChangeListener (catalogPanel);
|
|
||||||
// prefs.addPreferenceChangeListener (dataPanel);
|
|
||||||
|
|
||||||
// restore the menuHandler items before they are referenced
|
// restore the menuHandler items before they are referenced
|
||||||
quitAction.restore ();
|
quitAction.restore ();
|
||||||
|
|
||||||
@ -164,6 +160,7 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||||||
@Override
|
@Override
|
||||||
public void quit (Preferences preferences)
|
public void quit (Preferences preferences)
|
||||||
{
|
{
|
||||||
|
windowSaver = new WindowSaver (prefs, this, "DiskBrowser");
|
||||||
windowSaver.saveWindow ();
|
windowSaver.saveWindow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.bytezone.diskbrowser.gui;
|
package com.bytezone.diskbrowser.gui;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@ -23,6 +24,8 @@ public class WindowSaver
|
|||||||
prefs.putInt (key + "Y", frame.getY ());
|
prefs.putInt (key + "Y", frame.getY ());
|
||||||
prefs.putInt (key + "Height", frame.getHeight ());
|
prefs.putInt (key + "Height", frame.getHeight ());
|
||||||
prefs.putInt (key + "Width", frame.getWidth ());
|
prefs.putInt (key + "Width", frame.getWidth ());
|
||||||
|
System.out.printf ("Saving x:%d, y:%d, w:%d, h:%d%n", frame.getX (), frame.getY (),
|
||||||
|
frame.getWidth (), frame.getHeight ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean restoreWindow ()
|
public boolean restoreWindow ()
|
||||||
@ -32,19 +35,24 @@ public class WindowSaver
|
|||||||
int height = prefs.getInt (key + "Height", -1);
|
int height = prefs.getInt (key + "Height", -1);
|
||||||
int width = prefs.getInt (key + "Width", -1);
|
int width = prefs.getInt (key + "Width", -1);
|
||||||
|
|
||||||
|
Dimension screen = java.awt.Toolkit.getDefaultToolkit ().getScreenSize ();
|
||||||
|
|
||||||
if (width < 0) // nothing to restore
|
if (width < 0) // nothing to restore
|
||||||
{
|
{
|
||||||
|
frame.setLocation (100, 100);
|
||||||
|
frame.setSize (1000, 600);
|
||||||
frame.setLocationRelativeTo (null); // centre
|
frame.setLocationRelativeTo (null); // centre
|
||||||
// frame.centerOnScreen ();
|
System.out.printf ("Creating x:%d, y:%d, w:%d, h:%d%n", x, y, width, height);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// frame.setX (x);
|
System.out.printf ("w:%d, sw:%f%n", width, screen.getWidth ());
|
||||||
// frame.setY (y);
|
if (width > screen.getWidth () - 15)
|
||||||
// frame.setHeight (height);
|
width = (int) (screen.getWidth () - 15);
|
||||||
// frame.setWidth (width);
|
|
||||||
frame.setLocation (x, y);
|
|
||||||
frame.setSize (width, height);
|
frame.setSize (width, height);
|
||||||
|
frame.setLocation (x, y);
|
||||||
|
System.out.printf ("Restoring x:%d, y:%d, w:%d, h:%d%n", x, y, width, height);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,12 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||||||
abstract class CatalogEntry implements AppleFileSource
|
abstract class CatalogEntry implements AppleFileSource
|
||||||
{
|
{
|
||||||
protected final PascalDisk parent;
|
protected final PascalDisk parent;
|
||||||
String name;
|
protected final String name;
|
||||||
int firstBlock;
|
int firstBlock;
|
||||||
int lastBlock; // block AFTER last used block
|
int lastBlock; // block AFTER last used block
|
||||||
int fileType;
|
int fileType;
|
||||||
GregorianCalendar date;
|
GregorianCalendar date;
|
||||||
|
int bytesUsedInLastBlock;
|
||||||
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
List<DiskAddress> blocks = new ArrayList<DiskAddress> ();
|
||||||
AbstractFile file;
|
AbstractFile file;
|
||||||
|
|
||||||
@ -28,13 +29,21 @@ abstract class CatalogEntry implements AppleFileSource
|
|||||||
|
|
||||||
firstBlock = HexFormatter.intValue (buffer[0], buffer[1]);
|
firstBlock = HexFormatter.intValue (buffer[0], buffer[1]);
|
||||||
lastBlock = HexFormatter.intValue (buffer[2], buffer[3]);
|
lastBlock = HexFormatter.intValue (buffer[2], buffer[3]);
|
||||||
// fileType = HexFormatter.intValue (buffer[4], buffer[5]);
|
fileType = HexFormatter.intValue (buffer[4], buffer[5]);
|
||||||
fileType = buffer[4] & 0x0F;
|
// fileType = buffer[4] & 0x0F;
|
||||||
name = HexFormatter.getPascalString (buffer, 6);
|
name = HexFormatter.getPascalString (buffer, 6);
|
||||||
|
bytesUsedInLastBlock = HexFormatter.intValue (buffer[16], buffer[17]);
|
||||||
|
|
||||||
Disk disk = parent.getDisk ();
|
Disk disk = parent.getDisk ();
|
||||||
for (int i = firstBlock; i < lastBlock; i++)
|
for (int i = firstBlock; i < lastBlock; i++)
|
||||||
|
{
|
||||||
|
if (i >= 280)
|
||||||
|
{
|
||||||
|
System.out.printf ("CatalogEntry: block >= 280%n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
blocks.add (disk.getDiskAddress (i));
|
blocks.add (disk.getDiskAddress (i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,10 @@ class FileEntry extends CatalogEntry
|
|||||||
date = HexFormatter.getPascalDate (buffer, 24);
|
date = HexFormatter.getPascalDate (buffer, 24);
|
||||||
|
|
||||||
for (int i = firstBlock; i < lastBlock; i++)
|
for (int i = firstBlock; i < lastBlock; i++)
|
||||||
|
{
|
||||||
|
if (i >= 280)
|
||||||
|
break;
|
||||||
|
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
@ -46,6 +50,7 @@ class FileEntry extends CatalogEntry
|
|||||||
parent.sectorTypes[i] = parent.dataSector;
|
parent.sectorTypes[i] = parent.dataSector;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -58,30 +63,32 @@ class FileEntry extends CatalogEntry
|
|||||||
|
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
case 3:
|
|
||||||
file = new PascalText (name, buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
file = new PascalCode (name, buffer);
|
file = new PascalCode (name, buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
file = new PascalText (name, buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
file = new PascalInfo (name, buffer);
|
file = new PascalInfo (name, buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: // volume
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5: // data
|
case 5: // data
|
||||||
if (name.equals ("SYSTEM.CHARSET"))
|
if (name.equals ("SYSTEM.CHARSET"))
|
||||||
file = new Charset (name, buffer);
|
file = new Charset (name, buffer);
|
||||||
else if (name.equals ("WT")) // only testing
|
// else if (name.equals ("WT")) // only testing
|
||||||
file = new WizardryTitle (name, buffer);
|
// file = new WizardryTitle (name, buffer);
|
||||||
|
else if (name.equals ("SYSTEM.RELOC"))
|
||||||
|
file = new Relocator (name, buffer);
|
||||||
else
|
else
|
||||||
file = new DefaultAppleFile (name, buffer);
|
file = new DefaultAppleFile (name, buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0: // volume
|
||||||
|
break;
|
||||||
|
|
||||||
default: // unknown
|
default: // unknown
|
||||||
file = new DefaultAppleFile (name, buffer);
|
file = new DefaultAppleFile (name, buffer);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.bytezone.diskbrowser.pascal;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
@ -19,11 +20,11 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
{
|
{
|
||||||
static final int CATALOG_ENTRY_SIZE = 26;
|
static final int CATALOG_ENTRY_SIZE = 26;
|
||||||
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
||||||
private final VolumeEntry volume;
|
private final VolumeEntry volumeEntry;
|
||||||
private final PascalCatalogSector diskCatalogSector;
|
private final PascalCatalogSector diskCatalogSector;
|
||||||
|
|
||||||
final String[] fileTypes =
|
final String[] fileTypes =
|
||||||
{ "Volume", "Xdsk", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
{ "Volume", "Xdsk", "Code", "Text", "Info", "Data", "Graf", "Foto", "SecureDir" };
|
||||||
|
|
||||||
SectorType diskBootSector = new SectorType ("Boot", Color.lightGray);
|
SectorType diskBootSector = new SectorType ("Boot", Color.lightGray);
|
||||||
SectorType catalogSector = new SectorType ("Catalog", Color.magenta);
|
SectorType catalogSector = new SectorType ("Catalog", Color.magenta);
|
||||||
@ -56,7 +57,7 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
byte[] data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
System.arraycopy (buffer, 0, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
|
|
||||||
volume = new VolumeEntry (this, data);
|
volumeEntry = new VolumeEntry (this, data);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
if (!disk.isSectorEmpty (i))
|
if (!disk.isSectorEmpty (i))
|
||||||
@ -69,7 +70,7 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
freeBlocks.set (i, true);
|
freeBlocks.set (i, true);
|
||||||
|
|
||||||
List<DiskAddress> sectors = new ArrayList<DiskAddress> ();
|
List<DiskAddress> sectors = new ArrayList<DiskAddress> ();
|
||||||
for (int i = 2; i < volume.lastBlock; i++)
|
for (int i = 2; i < volumeEntry.lastBlock; i++)
|
||||||
{
|
{
|
||||||
DiskAddress da = disk.getDiskAddress (i);
|
DiskAddress da = disk.getDiskAddress (i);
|
||||||
if (!disk.isSectorEmpty (da))
|
if (!disk.isSectorEmpty (da))
|
||||||
@ -82,34 +83,34 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
diskCatalogSector = new PascalCatalogSector (disk, buffer, sectors);
|
diskCatalogSector = new PascalCatalogSector (disk, buffer, sectors);
|
||||||
|
|
||||||
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
||||||
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volume);
|
DefaultMutableTreeNode volumeNode = new DefaultMutableTreeNode (volumeEntry);
|
||||||
root.add (volumeNode);
|
root.add (volumeNode);
|
||||||
|
|
||||||
// read the catalog
|
// read the catalog
|
||||||
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
||||||
for (int i = 2; i < volume.lastBlock; i++)
|
for (int i = 2; i < volumeEntry.lastBlock; i++)
|
||||||
addresses.add (disk.getDiskAddress (i));
|
addresses.add (disk.getDiskAddress (i));
|
||||||
buffer = disk.readSectors (addresses);
|
buffer = disk.readSectors (addresses);
|
||||||
|
|
||||||
// loop through each catalog entry (what if there are deleted files?)
|
// loop through each catalog entry (what if there are deleted files?)
|
||||||
for (int i = 1; i <= volume.totalFiles; i++)
|
for (int i = 1; i <= volumeEntry.totalFiles; i++)
|
||||||
{
|
{
|
||||||
int ptr = i * CATALOG_ENTRY_SIZE;
|
int ptr = i * CATALOG_ENTRY_SIZE;
|
||||||
data = new byte[CATALOG_ENTRY_SIZE];
|
data = new byte[CATALOG_ENTRY_SIZE];
|
||||||
|
|
||||||
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
System.arraycopy (buffer, ptr, data, 0, CATALOG_ENTRY_SIZE);
|
||||||
FileEntry fe = new FileEntry (this, data);
|
FileEntry fileEntry = new FileEntry (this, data);
|
||||||
fileEntries.add (fe);
|
fileEntries.add (fileEntry);
|
||||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fe);
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode (fileEntry);
|
||||||
|
|
||||||
if (fe.fileType == 2) // PascalCode
|
if (fileEntry.fileType == 2) // PascalCode
|
||||||
{
|
{
|
||||||
node.setAllowsChildren (true);
|
node.setAllowsChildren (true);
|
||||||
PascalCode pc = (PascalCode) fe.getDataSource ();
|
PascalCode pascalCode = (PascalCode) fileEntry.getDataSource ();
|
||||||
for (PascalSegment ps : pc)
|
for (PascalSegment pascalSegment : pascalCode)
|
||||||
{
|
{
|
||||||
DefaultMutableTreeNode segmentNode =
|
DefaultMutableTreeNode segmentNode = new DefaultMutableTreeNode (
|
||||||
new DefaultMutableTreeNode (new PascalCodeObject (this, ps, fe.firstBlock));
|
new PascalCodeObject (this, pascalSegment, fileEntry.firstBlock));
|
||||||
node.add (segmentNode);
|
node.add (segmentNode);
|
||||||
segmentNode.setAllowsChildren (false);
|
segmentNode.setAllowsChildren (false);
|
||||||
}
|
}
|
||||||
@ -118,7 +119,7 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
node.setAllowsChildren (false);
|
node.setAllowsChildren (false);
|
||||||
|
|
||||||
volumeNode.add (node);
|
volumeNode.add (node);
|
||||||
for (int j = fe.firstBlock; j < fe.lastBlock; j++)
|
for (int j = fileEntry.firstBlock; j < fileEntry.lastBlock; j++)
|
||||||
freeBlocks.set (j, false);
|
freeBlocks.set (j, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,9 +129,10 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
|
|
||||||
public static boolean isCorrectFormat (AppleDisk disk, boolean debug)
|
public static boolean isCorrectFormat (AppleDisk disk, boolean debug)
|
||||||
{
|
{
|
||||||
disk.setInterleave (1);
|
disk.setInterleave (1); // should only ever be Prodos
|
||||||
if (checkFormat (disk, debug))
|
if (checkFormat (disk, debug))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
disk.setInterleave (0);
|
disk.setInterleave (0);
|
||||||
if (checkFormat (disk, debug))
|
if (checkFormat (disk, debug))
|
||||||
return true;
|
return true;
|
||||||
@ -141,8 +143,8 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
public static boolean checkFormat (AppleDisk disk, boolean debug)
|
public static boolean checkFormat (AppleDisk disk, boolean debug)
|
||||||
{
|
{
|
||||||
byte[] buffer = disk.readSector (2);
|
byte[] buffer = disk.readSector (2);
|
||||||
if (debug)
|
// if (debug)
|
||||||
System.out.println (HexFormatter.format (buffer));
|
// System.out.println (HexFormatter.format (buffer));
|
||||||
int nameLength = HexFormatter.intValue (buffer[6]);
|
int nameLength = HexFormatter.intValue (buffer[6]);
|
||||||
if (nameLength < 1 || nameLength > 7)
|
if (nameLength < 1 || nameLength > 7)
|
||||||
{
|
{
|
||||||
@ -166,6 +168,14 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
return false; // will only work for floppies!
|
return false; // will only work for floppies!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int blocks = HexFormatter.intValue (buffer[14], buffer[15]);
|
||||||
|
if (blocks > 280)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
System.out.printf ("Blocks > 280: %d%n", blocks);
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
|
||||||
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
List<DiskAddress> addresses = new ArrayList<DiskAddress> ();
|
||||||
for (int i = 2; i < to; i++)
|
for (int i = 2; i < to; i++)
|
||||||
addresses.add (disk.getDiskAddress (i));
|
addresses.add (disk.getDiskAddress (i));
|
||||||
@ -185,27 +195,21 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
for (int i = 1; i <= files; i++)
|
for (int i = 1; i <= files; i++)
|
||||||
{
|
{
|
||||||
int ptr = i * 26;
|
int ptr = i * 26;
|
||||||
int a = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
int firstBlock = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
|
||||||
int b = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
int lastBlock = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||||
int c = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
int kind = HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]);
|
||||||
if (b < a)
|
if (lastBlock < firstBlock)
|
||||||
return false;
|
return false;
|
||||||
if (c == 0)
|
if (kind == 0)
|
||||||
return false;
|
return false;
|
||||||
nameLength = HexFormatter.intValue (buffer[ptr + 6]);
|
nameLength = HexFormatter.intValue (buffer[ptr + 6]);
|
||||||
if (nameLength < 1 || nameLength > 15)
|
if (nameLength < 1 || nameLength > 15)
|
||||||
return false;
|
return false;
|
||||||
|
int lastByte = HexFormatter.intValue (buffer[ptr + 22], buffer[ptr + 23]);
|
||||||
|
GregorianCalendar date = HexFormatter.getPascalDate (buffer, 24);
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out.printf ("%4d %4d %d %s%n", a, b, c,
|
System.out.printf ("%4d %4d %d %-15s %d %s%n", firstBlock, lastBlock, kind,
|
||||||
new String (buffer, ptr + 7, nameLength));
|
new String (buffer, ptr + 7, nameLength), lastByte, date);
|
||||||
}
|
|
||||||
|
|
||||||
int blocks = HexFormatter.intValue (buffer[14], buffer[15]);
|
|
||||||
if (blocks > 280)
|
|
||||||
{
|
|
||||||
if (debug)
|
|
||||||
System.out.printf ("Blocks > 280: %d%n", blocks);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -254,13 +258,16 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
{
|
{
|
||||||
String newLine = String.format ("%n");
|
String newLine = String.format ("%n");
|
||||||
String newLine2 = newLine + newLine;
|
String newLine2 = newLine + newLine;
|
||||||
String line = "---- --------------- ---- -------- ------- ---- ----" + newLine;
|
String line =
|
||||||
String date = volume.date == null ? "--" : df.format (volume.date.getTime ());
|
"---- --------------- ---- -------- ------- ---- ----" + newLine;
|
||||||
|
String date =
|
||||||
|
volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ());
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
text.append ("Disk : " + disk.getFile ().getAbsolutePath () + newLine2);
|
text.append ("Disk : " + disk.getFile ().getAbsolutePath () + newLine2);
|
||||||
text.append ("Volume : " + volume.name + newLine);
|
text.append ("Volume : " + volumeEntry.name + newLine);
|
||||||
text.append ("Date : " + date + newLine2);
|
text.append ("Date : " + date + newLine2);
|
||||||
text.append ("Blks Name Type Date Length Frst Last" + newLine);
|
text.append ("Blks Name Type Date Length Frst Last"
|
||||||
|
+ newLine);
|
||||||
text.append (line);
|
text.append (line);
|
||||||
|
|
||||||
int usedBlocks = 6;
|
int usedBlocks = 6;
|
||||||
@ -271,14 +278,15 @@ public class PascalDisk extends AbstractFormattedDisk
|
|||||||
usedBlocks += size;
|
usedBlocks += size;
|
||||||
date = ce.date == null ? "--" : df.format (ce.date.getTime ());
|
date = ce.date == null ? "--" : df.format (ce.date.getTime ());
|
||||||
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
||||||
text.append (String.format (" %3d %-15s %s %8s %,8d $%03X $%03X%n", size,
|
text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X%n", size,
|
||||||
ce.name, fileTypes[ce.fileType], date, bytes, ce.firstBlock,
|
ce.name, fileTypes[ce.fileType], date, bytes,
|
||||||
ce.lastBlock));
|
ce.firstBlock, ce.lastBlock));
|
||||||
}
|
}
|
||||||
text.append (line);
|
text.append (line);
|
||||||
text.append (String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
text.append (String.format (
|
||||||
(volume.totalBlocks - usedBlocks), usedBlocks,
|
"Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
||||||
volume.totalBlocks));
|
(volumeEntry.totalBlocks - usedBlocks), usedBlocks,
|
||||||
return new DefaultAppleFileSource (volume.name, text.toString (), this);
|
volumeEntry.totalBlocks));
|
||||||
|
return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,15 +8,26 @@ class VolumeEntry extends CatalogEntry
|
|||||||
{
|
{
|
||||||
final int totalFiles;
|
final int totalFiles;
|
||||||
final int totalBlocks;
|
final int totalBlocks;
|
||||||
|
final int block1; // first block on the disk (usually 0)
|
||||||
|
final int lastDirectoryBlock; // (plus 1) (usually 6)
|
||||||
|
final int recordType; // 0 = directory
|
||||||
|
final int nameLength;
|
||||||
|
final String name;
|
||||||
|
|
||||||
public VolumeEntry (PascalDisk parent, byte[] buffer)
|
public VolumeEntry (PascalDisk parent, byte[] buffer)
|
||||||
{
|
{
|
||||||
super (parent, buffer);
|
super (parent, buffer);
|
||||||
|
|
||||||
totalBlocks = HexFormatter.intValue (buffer[14], buffer[15]);
|
block1 = HexFormatter.intValue (buffer[0], buffer[1]); // 0
|
||||||
|
lastDirectoryBlock = HexFormatter.intValue (buffer[2], buffer[3]); // 6
|
||||||
|
recordType = HexFormatter.intValue (buffer[4], buffer[5]); // 0
|
||||||
|
nameLength = buffer[6] & 0xFF;
|
||||||
|
name = HexFormatter.getPascalString (buffer, 6); // 06-0D
|
||||||
|
totalBlocks = HexFormatter.intValue (buffer[14], buffer[15]); // 280
|
||||||
totalFiles = HexFormatter.intValue (buffer[16], buffer[17]);
|
totalFiles = HexFormatter.intValue (buffer[16], buffer[17]);
|
||||||
firstBlock = HexFormatter.intValue (buffer[18], buffer[19]);
|
firstBlock = HexFormatter.intValue (buffer[18], buffer[19]); // 0
|
||||||
date = HexFormatter.getPascalDate (buffer, 20);
|
date = HexFormatter.getPascalDate (buffer, 20); // 2 bytes
|
||||||
|
// bytes 0x16 - 0x19 are unused
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user