dmolony-DiskBrowser/src/com/bytezone/diskbrowser/applefile/SegmentHeader.java

374 lines
12 KiB
Java

package com.bytezone.diskbrowser.applefile;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
public class SegmentHeader
// -----------------------------------------------------------------------------------//
{
int bytecnt;
int resspc;
int length;
int kind1;
String kindWhereText;
boolean kindReload;
boolean kindAbsoluteBank;
boolean kindSpecialMemory;
boolean kindPosIndependent;
boolean kindPrivate;
boolean kindStatic;
int lablen;
int numlen;
int version;
int banksize;
int kind2;
int unused;
int org;
int align;
int numsex;
int lcbank;
int segnum;
int entry;
int dispname;
int dispdata;
String loadname;
String segname;
boolean debug = false;
// ---------------------------------------------------------------------------------//
public SegmentHeader (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
bytecnt = Utility.getLong (buffer, offset);
resspc = Utility.getLong (buffer, offset + 4);
length = Utility.getLong (buffer, offset + 8);
kind1 = buffer[offset + 12] & 0xFF;
lablen = buffer[offset + 13] & 0xFF;
numlen = buffer[offset + 14] & 0xFF;
version = buffer[offset + 15] & 0xFF;
banksize = Utility.getLong (buffer, offset + 16);
kind2 = Utility.getShort (buffer, offset + 20);
unused = Utility.getShort (buffer, offset + 22);
org = Utility.getLong (buffer, offset + 24);
align = Utility.getLong (buffer, offset + 28);
numsex = buffer[offset + 32] & 0xFF;
lcbank = buffer[offset + 33] & 0xFF;
segnum = Utility.getShort (buffer, offset + 34);
entry = Utility.getLong (buffer, offset + 36);
dispname = Utility.getShort (buffer, offset + 40);
dispdata = Utility.getShort (buffer, offset + 42);
decodeKind ();
if (buffer[offset + dispname] == 0)
loadname = "";
else
loadname = new String (buffer, offset + dispname, 10);
if (lablen == 0)
segname = HexFormatter.getPascalString (buffer, offset + dispname + 10);
else
segname = "not finished";
if (debug)
System.out.println (this);
int ptr = offset + dispdata;
while (true)
{
int recType = buffer[ptr] & 0xFF;
// System.out.printf ("%04X = %02X%n", ptr, recType);
if (recType > 0 && recType <= 0xDF)
{
if (debug)
{
System.out.printf ("Const: %02X%n", recType);
System.out.println (HexFormatter.format (buffer, ptr, recType + 1, ptr));
}
ptr += recType + 1;
continue;
}
if (debug)
System.out.printf ("%02X ", recType);
switch (recType)
{
case 0x00: // END
if (debug)
System.out.println ("END");
break;
case 0xE0: // ALIGN
if (debug)
System.out.printf ("ALIGN:%n");
break;
case 0xE1: // ORG
if (debug)
System.out.printf ("ORG:%n");
break;
case 0xE2: // RELOC
int bytesRelocated = buffer[ptr + 1] & 0xFF;
int bitShift = buffer[ptr + 2] & 0xFF;
int segmentOffset = Utility.getLong (buffer, ptr + 3);
int value = Utility.getLong (buffer, ptr + 7);
if (debug)
System.out.printf ("RELOC: %02X %02X %08X %08X%n", bytesRelocated, bitShift,
segmentOffset, value);
ptr += 11;
continue;
case 0xE3: // INTERSEG
int count1 = buffer[ptr + 1] & 0xFF;
int count2 = buffer[ptr + 2] & 0xFF;
int operandOffset = Utility.getLong (buffer, ptr + 3);
int fileNo = Utility.getShort (buffer, ptr + 7);
int segNo = Utility.getShort (buffer, ptr + 9);
int subroutineOffset = Utility.getLong (buffer, ptr + 11);
if (debug)
System.out.printf ("INTERSEG: %02X %02X %08X %04X %04X %08X%n", count1,
count2, operandOffset, fileNo, segNo, subroutineOffset);
ptr += 15;
break;
case 0xE4: // USING
if (debug)
System.out.printf ("USING:%n");
break;
case 0xE5: // STRONG
if (debug)
System.out.printf ("STRONG:%n");
break;
case 0xE6: // GLOBAL
if (debug)
System.out.printf ("GLOBAL:%n");
break;
case 0xE7: // GEQU
if (debug)
System.out.printf ("GEQU:%n");
break;
case 0xE8: // MEM
if (debug)
System.out.printf ("MEM:%n");
break;
case 0xEB: // EXPR
if (debug)
System.out.printf ("EXPR:%n");
break;
case 0xEC: // ZEXPR
if (debug)
System.out.printf ("ZEXPR:%n");
break;
case 0xED: // BEXPR
if (debug)
System.out.printf ("BEXPR:%n");
break;
case 0xEE: // RELEXPR
if (debug)
System.out.printf ("RELEXPR:%n");
break;
case 0xEF: // LOCAL
if (debug)
System.out.printf ("LOCAL:%n");
break;
case 0xF0: // EQU
String label = HexFormatter.getPascalString (buffer, ptr + 1);
if (debug)
System.out.printf ("EQU: %s%n", label);
break;
case 0xF1: // DS
if (debug)
System.out.printf ("DS:%n");
break;
case 0xF2: // LCONST
int constLength = Utility.getLong (buffer, ptr + 1);
if (debug)
System.out.printf ("Const: %04X%n", constLength);
ptr += constLength + 5;
continue;
case 0xF3: // LEXPR
if (debug)
System.out.printf ("LEXPR:%n");
break;
case 0xF4: // ENTRY
if (debug)
System.out.printf ("ENTRY:%n");
break;
case 0xF5: // cRELOC
int cBytesRelocated = buffer[ptr + 1] & 0xFF;
int cBitShift = buffer[ptr + 2] & 0xFF;
int cSegmentOffset = Utility.getShort (buffer, ptr + 3);
int cValue = Utility.getShort (buffer, ptr + 5);
if (debug)
System.out.printf ("cRELOC: %02X %02X %08X %08X%n", cBytesRelocated,
cBitShift, cSegmentOffset, cValue);
ptr += 7;
continue;
case 0xF6: // cINTERSEG
int cCount1 = buffer[ptr + 1] & 0xFF;
int cCount2 = buffer[ptr + 2] & 0xFF;
int cOperandOffset = Utility.getShort (buffer, ptr + 3);
int cSegNo = buffer[ptr + 5] & 0xFF;
int cSubroutineOffset = Utility.getShort (buffer, ptr + 6);
if (debug)
System.out.printf ("cINTERSEG: %02X %02X %04X %02X %04X%n", cCount1, cCount2,
cOperandOffset, cSegNo, cSubroutineOffset);
ptr += 8;
continue;
case 0xF7: // SUPER
int superLength = Utility.getLong (buffer, ptr + 1);
int recordType = buffer[ptr + 5] & 0xFF;
if (debug)
System.out.printf ("Super type %02X%n", recordType);
ptr += superLength + 5;
continue;
default:
System.out.printf ("Unknown record type: %02X%n", recType);
break;
}
if (debug)
System.out.println ();
break;
}
}
// ---------------------------------------------------------------------------------//
private void decodeKind ()
// ---------------------------------------------------------------------------------//
{
int segType;
int segAttr;
if (version < 2) // 8 bits
{
segType = kind1 & 0x1F;
segAttr = kind1 & 0xE0;
}
else // 16 bits
{
segType = kind2 & 0x001F;
segAttr = kind2 >>> 8;
}
kindReload = (segAttr & 0x04) != 0;
kindAbsoluteBank = (segAttr & 0x08) != 0;
kindSpecialMemory = (segAttr & 0x10) == 0;
kindPosIndependent = (segAttr & 0x20) != 0;
kindPrivate = (segAttr & 0x40) != 0;
kindStatic = (segAttr & 0x80) == 0;
kindWhereText = switch (segType)
{
case 0x00 -> "Code Segment";
case 0x01 -> "Data Segment";
case 0x02 -> "Jump Table Segment";
case 0x04 -> "Pathname Segment";
case 0x08 -> "Library Dictionary Segment";
case 0x10 -> "Initialization Segment";
case 0x11 -> "Absolute Bank Segment";
case 0x12 -> "Direct Page / Stack Segment";
default -> "Unknown";
};
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Byte count ......... %08X%n", bytecnt));
text.append (String.format ("Reserved space ..... %08X%n", resspc));
text.append (String.format ("Length ............. %08X%n", length));
text.append (String.format ("Kind v1 ............ %02X%n", kind1));
if (version < 2)
{
text.append (String.format (" Type ............. %s%n", kindWhereText));
text.append (
String.format (" Position ind ..... %s%n", kindPosIndependent ? "Yes" : "No"));
text.append (
String.format (" Private .......... %s%n", kindPrivate ? "Yes" : "No"));
text.append (
String.format (" Static/Dynamic ... %s%n", kindStatic ? "Static" : "Dynamic"));
}
text.append (String.format ("Label length ....... %02X%n", lablen));
text.append (String.format ("Number length ...... %02X%n", numlen));
text.append (String.format ("Version ............ %02X%n", version));
text.append (String.format ("Bank size .......... %08X%n", banksize));
text.append (String.format ("Kind v2 ............ %04X%n", kind2));
if (version >= 2)
{
text.append (String.format (" Type ............. %s%n", kindWhereText));
text.append (
String.format (" Reload ........... %s%n", kindReload ? "Yes" : "No"));
text.append (
String.format (" Absolute Bank .... %s%n", kindAbsoluteBank ? "Yes" : "No"));
text.append (
String.format (" Special Memory ... %s%n", kindSpecialMemory ? "Yes" : "No"));
text.append (
String.format (" Position ind ..... %s%n", kindPosIndependent ? "Yes" : "No"));
text.append (
String.format (" Private .......... %s%n", kindPrivate ? "Yes" : "No"));
text.append (
String.format (" Static/Dynamic ... %s%n", kindStatic ? "Static" : "Dynamic"));
}
text.append (String.format ("Unused ............. %04X%n", unused));
text.append (String.format ("Org ................ %08X%n", org));
text.append (String.format ("Align .............. %08X%n", align));
text.append (String.format ("Number sex ......... %02X%n", numsex));
text.append (String.format ("LC Bank ............ %02X%n", lcbank));
text.append (String.format ("Segment number ..... %04X%n", segnum));
text.append (String.format ("Entry .............. %08X%n", entry));
text.append (String.format ("Disp name .......... %04X%n", dispname));
text.append (String.format ("Disp data .......... %04X%n", dispdata));
text.append (String.format ("Load name .......... %s%n", loadname));
text.append (String.format ("Segment name ....... %s%n", segname));
return text.toString ();
}
}