diff --git a/src/com/bytezone/diskbrowser/applefile/HiResImage.java b/src/com/bytezone/diskbrowser/applefile/HiResImage.java index b097f08..c61593f 100644 --- a/src/com/bytezone/diskbrowser/applefile/HiResImage.java +++ b/src/com/bytezone/diskbrowser/applefile/HiResImage.java @@ -62,10 +62,10 @@ public abstract class HiResImage extends AbstractFile System.out.println ("aux 1 - " + name); } - if (auxType == 2) - { - System.out.println ("aux 2 - " + name); - } + // if (auxType == 2) + // { + // System.out.println ("aux 2 - " + name); + // } } } @@ -224,8 +224,8 @@ public abstract class HiResImage extends AbstractFile int ptr = 0, newPtr = 0; while (ptr < buffer.length) { - int type = (buffer[ptr] & 0xC0) >> 6; - int count = (buffer[ptr++] & 0x3F) + 1; + int type = (buffer[ptr] & 0xC0) >> 6; // 0-3 + int count = (buffer[ptr++] & 0x3F) + 1; // 1-64 switch (type) { diff --git a/src/com/bytezone/diskbrowser/applefile/IconFile.java b/src/com/bytezone/diskbrowser/applefile/IconFile.java index 9a13e93..48f286f 100644 --- a/src/com/bytezone/diskbrowser/applefile/IconFile.java +++ b/src/com/bytezone/diskbrowser/applefile/IconFile.java @@ -219,19 +219,29 @@ public class IconFile extends AbstractFile DataBuffer dataBuffer = image.getRaster ().getDataBuffer (); int element = 0; + // System.out.println ("*** " + dataBuffer.getSize ()); + // System.out.printf ("width %d height %d%n", iconWidth, iconHeight); + // System.out.printf ("icon image length %d%n", iconImage.length); int rowBytes = (iconWidth - 1) / 2 + 1; if (true) for (int i = 0; i < iconImage.length; i += rowBytes) { - for (int j = i, max = i + rowBytes; j < max; j++) + int max = Math.min (i + rowBytes, dataBuffer.getSize ()); + // System.out.printf ("max %d%n", max); + for (int j = i; j < max; j++) { int left = (byte) ((iconImage[j] & 0xF0) >>> 4); int right = (byte) (iconImage[j] & 0x0F); int maskLeft = (byte) ((iconMask[j] & 0xF0) >>> 4); int maskRight = (byte) (iconMask[j] & 0x0F); - dataBuffer.setElem (element++, colours[left & maskLeft]); - dataBuffer.setElem (element++, colours[right & maskRight]); + + // see WhatIsThe2gs/System 6 and Free Games.hdv/SWAREGAME.ICONS + if (element < dataBuffer.getSize ()) + { + dataBuffer.setElem (element++, colours[left & maskLeft]); + dataBuffer.setElem (element++, colours[right & maskRight]); + } } } } diff --git a/src/com/bytezone/diskbrowser/applefile/PaintFile.java b/src/com/bytezone/diskbrowser/applefile/PaintFile.java new file mode 100644 index 0000000..388c07d --- /dev/null +++ b/src/com/bytezone/diskbrowser/applefile/PaintFile.java @@ -0,0 +1,261 @@ +package com.bytezone.diskbrowser.applefile; + +import java.util.ArrayList; +import java.util.List; + +import com.bytezone.diskbrowser.utilities.HexFormatter; + +public class PaintFile extends HiResImage +{ + List blocks = new ArrayList (); + + public PaintFile (String name, byte[] buffer, int fileType, int auxType) + { + super (name, buffer, fileType, auxType); + + int ptr = 0; + while (ptr < buffer.length) + { + int len = HexFormatter.unsignedLong (buffer, ptr); + int nameLen = buffer[ptr + 4] & 0xFF; + String kind = HexFormatter.getPascalString (buffer, ptr + 4); + byte[] data = new byte[Math.min (len - (nameLen + 5), buffer.length - ptr)]; + System.arraycopy (buffer, ptr, data, 0, data.length); + + if ("MAIN".equals (kind)) + blocks.add (new Main (kind, data)); + else + blocks.add (new Block (kind, data)); + + ptr += len; + } + } + + @Override + protected void createMonochromeImage () + { + } + + @Override + protected void createColourImage () + { + } + + @Override + public String getText () + { + StringBuilder text = new StringBuilder (super.getText ()); + text.append ("\n\n"); + + for (Block block : blocks) + { + text.append (block); + text.append ("\n\n"); + } + + text.deleteCharAt (text.length () - 1); + text.deleteCharAt (text.length () - 1); + + return text.toString (); + } + + class Block + { + String kind; + byte[] data; + + public Block (String kind, byte[] data) + { + this.kind = kind; + this.data = data; + } + + @Override + public String toString () + { + StringBuilder text = new StringBuilder (); + + text.append (String.format ("Kind ...... %s%n%n", kind)); + text.append (HexFormatter.format (data)); + + return text.toString (); + } + } + + class Main extends Block + { + int masterMode; + int pixelsPerScanLine; + int numColorTables; + ColorTable[] colorTables; + int numScanLines; + DirEntry[] scanLineDirectory; + byte[][] packedScanLines; + + public Main (String kind, byte[] data) + { + super (kind, data); + + int ptr = 5 + kind.length (); + masterMode = HexFormatter.unsignedShort (data, ptr); + pixelsPerScanLine = HexFormatter.unsignedShort (data, ptr + 2); + numColorTables = HexFormatter.unsignedShort (data, ptr + 4); + + ptr += 6; + colorTables = new ColorTable[numColorTables]; + for (int i = 0; i < numColorTables; i++) + { + colorTables[i] = new ColorTable (i, data, ptr); + ptr += 32; + } + + numScanLines = HexFormatter.unsignedShort (data, ptr); + scanLineDirectory = new DirEntry[numScanLines]; + packedScanLines = new byte[numScanLines][]; + + ptr += 2; + for (int i = 0; i < numScanLines; i++) + { + DirEntry dirEntry = new DirEntry (data, ptr); + scanLineDirectory[i] = dirEntry; + packedScanLines[i] = new byte[dirEntry.numBytes]; + ptr += 4; + } + + for (int i = 0; i < numScanLines; i++) + { + int len = scanLineDirectory[i].numBytes; + if (ptr + len > data.length) + break; + + System.arraycopy (data, ptr, packedScanLines[i], 0, len); + ptr += len; + } + } + + @Override + public String toString () + { + StringBuilder text = new StringBuilder (); + + text.append (String.format ("Kind ................. %s%n", kind)); + text.append (String.format ("MasterMode ........... %04X%n", masterMode)); + text.append (String.format ("PixelsPerScanLine .... %d%n", pixelsPerScanLine)); + text.append (String.format ("NumColorTables ....... %d%n", numColorTables)); + text.append (String.format ("NumScanLines ......... %d%n%n", numScanLines)); + + text.append ("Color Tables\n"); + text.append ("------------\n\n"); + + text.append (" # "); + for (int i = 0; i < 16; i++) + text.append (String.format (" %02X ", i)); + text.deleteCharAt (text.length () - 1); + text.deleteCharAt (text.length () - 1); + text.append ("\n---"); + for (int i = 0; i < 16; i++) + text.append (" ---- "); + text.deleteCharAt (text.length () - 1); + text.append ("\n"); + for (ColorTable colorTable : colorTables) + { + text.append (colorTable.toLine ()); + text.append ("\n"); + } + + text.append ("\nScan Lines\n"); + text.append ("----------\n\n"); + + text.append (" # Mode Packed Data\n"); + text.append ("--- ---- ---------------------------------------------"); + text.append ("------------------------------------------\n"); + for (int i = 0; i < scanLineDirectory.length; i++) + { + DirEntry dirEntry = scanLineDirectory[i]; + byte[] packedScanLine = packedScanLines[i]; + text.append (String.format ("%3d %2d ", i, dirEntry.mode)); + text.append (HexFormatter.getHexString (packedScanLine)); + text.append ("\n"); + } + + return text.toString (); + } + } + + class ColorTable + { + int id; + ColorEntry[] entries = new ColorEntry[16]; + + public ColorTable (int id, byte[] data, int offset) + { + this.id = id; + for (int i = 0; i < 16; i++) + { + entries[i] = new ColorEntry (data, offset); + offset += 2; + } + } + + String toLine () + { + + StringBuilder text = new StringBuilder (); + + text.append (String.format (" %X", id)); + for (int i = 0; i < 16; i++) + text.append (String.format (" %04X", entries[i].value)); + + return text.toString (); + } + + @Override + public String toString () + { + StringBuilder text = new StringBuilder (); + + text.append (String.format ("%2d ColorTable%n", id)); + for (int i = 0; i < 8; i++) + text.append (String.format (" %2d: %04X", i, entries[i].value)); + text.append ("\n"); + for (int i = 8; i < 16; i++) + text.append (String.format (" %2d: %04X", i, entries[i].value)); + + return text.toString (); + } + } + + class ColorEntry + { + int value; // 0RGB + + public ColorEntry (byte[] data, int offset) + { + value = HexFormatter.unsignedShort (data, offset); + } + + @Override + public String toString () + { + return String.format ("ColorEntry: %04X", value); + } + } + + class DirEntry + { + int numBytes; + int mode; + + public DirEntry (byte[] data, int offset) + { + numBytes = HexFormatter.unsignedShort (data, offset); + mode = HexFormatter.unsignedShort (data, offset + 2); + } + + @Override + public String toString () + { + return String.format ("Bytes: %5d, mode: %02X", numBytes, mode); + } + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/prodos/FileEntry.java b/src/com/bytezone/diskbrowser/prodos/FileEntry.java index ed74a28..f4d6691 100755 --- a/src/com/bytezone/diskbrowser/prodos/FileEntry.java +++ b/src/com/bytezone/diskbrowser/prodos/FileEntry.java @@ -354,7 +354,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants file = new IconFile (name, exactBuffer); break; case FILE_TYPE_PNT: - file = new OriginalHiResImage (name, exactBuffer, fileType, auxType); + if (auxType == 2) + file = new PaintFile (name, exactBuffer, fileType, auxType); + else + file = new OriginalHiResImage (name, exactBuffer, fileType, auxType); break; case FILE_TYPE_PIC: file = new OriginalHiResImage (name, exactBuffer, fileType, auxType); @@ -383,6 +386,12 @@ class FileEntry extends CatalogEntry implements ProdosConstants private byte[] getExactBuffer (byte[] buffer) { + if (buffer.length < endOfFile) + { + System.out.println ("Buffer shorter than EOF in " + name); + System.out.printf (" buffer %,d, eof %,d%n", buffer.length, endOfFile); + } + byte[] exactBuffer; if (buffer.length < endOfFile) { diff --git a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java index 3bbbf18..95ff855 100755 --- a/src/com/bytezone/diskbrowser/utilities/HexFormatter.java +++ b/src/com/bytezone/diskbrowser/utilities/HexFormatter.java @@ -15,6 +15,11 @@ public class HexFormatter return format (buffer, 0, buffer.length); } + public static String formatNoHeader (byte[] buffer) + { + return formatNoHeader (buffer, 0, buffer.length); + } + public static String format (byte[] buffer, int offset, int length) { return format (buffer, offset, length, true, 0); @@ -331,9 +336,14 @@ public class HexFormatter return val; } + // public static int signedShort (byte[] buffer, int ptr) + // { + // return (short) (((buffer[ptr] & 0xFF) << 8) | (buffer[ptr + 1] & 0xFF)); + // } + public static int signedShort (byte[] buffer, int ptr) { - return (short) (((buffer[ptr] & 0xFF) << 8) | (buffer[ptr + 1] & 0xFF)); + return (short) ((buffer[ptr] & 0xFF) | ((buffer[ptr + 1] & 0xFF) << 8)); } public static int getShortBigEndian (byte[] buffer, int ptr)