diff --git a/src/com/bytezone/diskbrowser/applefile/HiResImage.java b/src/com/bytezone/diskbrowser/applefile/HiResImage.java index 0184c8a..676ab93 100644 --- a/src/com/bytezone/diskbrowser/applefile/HiResImage.java +++ b/src/com/bytezone/diskbrowser/applefile/HiResImage.java @@ -16,9 +16,10 @@ import com.bytezone.diskbrowser.utilities.Utility; public abstract class HiResImage extends AbstractFile // -----------------------------------------------------------------------------------// { - static final String[] auxTypes = { "Paintworks Packed SHR Image", - "Packed Super Hi-Res Image", "Super Hi-Res Image (Apple Preferred Format)", - "Packed QuickDraw II PICT File", "Packed Super Hi-Res 3200 color image" }; + static final String[] auxTypes = + { "Paintworks Packed SHR Image", "Packed Super Hi-Res Image", + "Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File", + "Packed Super Hi-Res 3200 color image", "DreamGraphix" }; static final int COLOR_TABLE_SIZE = 32; static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256; static final int COLOR_TABLE_OFFSET_AUX_2 = 32_000; @@ -57,7 +58,7 @@ public abstract class HiResImage extends AbstractFile // $C0 PNT $1000 // $C0 PNT $8000 Drawplus? Paintworks Gold? // $C0 PNT $8001 GTv background picture - // $C0 PNT $8005 DreamGraphix document + // $C0 PNT $8005 DreamGraphix document SHRPictureFile2 // $C0 PNT $8006 GIF // ---- ---- ------ -------------------------------------- ------------------------ // * $C1 PIC $0000 IIGS Super Hi-Res Image SHRPictureFile2 @@ -296,7 +297,10 @@ public abstract class HiResImage extends AbstractFile break; case ProdosConstants.FILE_TYPE_PNT: // 0xC0 - auxText = auxType > 4 ? "Unknown aux: " + auxType : auxTypes[auxType]; + if (auxType == 0x8005) + auxText = auxTypes[5]; + else + auxText = auxType > 4 ? "Unknown aux: " + auxType : auxTypes[auxType]; break; case ProdosConstants.FILE_TYPE_PIC: // 0xC1 diff --git a/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java b/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java index 086e5a1..e591c68 100644 --- a/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java +++ b/src/com/bytezone/diskbrowser/applefile/SHRPictureFile2.java @@ -5,6 +5,7 @@ import java.awt.image.DataBuffer; import java.util.ArrayList; import java.util.List; +import com.bytezone.diskbrowser.nufx.LZW3; import com.bytezone.diskbrowser.prodos.ProdosConstants; import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.Utility; @@ -144,6 +145,36 @@ public class SHRPictureFile2 extends HiResImage break; + case 0x8005: + int ptr = buffer.length - 17; + + int imageType = Utility.getShort (buffer, ptr); + int imageHeight = Utility.getShort (buffer, ptr + 2); + int imageWidth = Utility.getShort (buffer, ptr + 4); + + String id = HexFormatter.getPascalString (buffer, ptr + 6); + assert "DreamWorld".equals (id); + + int expectedLen = 32000 + 512; + if (imageType == 0) // 256 colours + expectedLen += (256 + 512); + else // 3200 colours + expectedLen += 6400; + + byte[] dstBuffer = new byte[expectedLen + 1024]; + LZW3 lzw3 = new LZW3 (); + int bytes = lzw3.unpack (buffer, dstBuffer, expectedLen); + buffer = dstBuffer; + + colorTables = new ColorTable[imageHeight]; + for (int i = 0; i < colorTables.length; i++) + { + colorTables[i] = new ColorTable (i, this.buffer, 32000 + i * COLOR_TABLE_SIZE); + colorTables[i].reverse (); + } + + break; + default: System.out.printf ("%s: PNT unknown aux: %04X%n", name, auxType); failureReason = "unknown PNT aux"; diff --git a/src/com/bytezone/diskbrowser/nufx/LZW.java b/src/com/bytezone/diskbrowser/nufx/LZW.java index 868dc76..c307698 100644 --- a/src/com/bytezone/diskbrowser/nufx/LZW.java +++ b/src/com/bytezone/diskbrowser/nufx/LZW.java @@ -90,7 +90,7 @@ abstract class LZW } bitsLeft--; - boolean bit = ((byteBuffer << bitsLeft) & 0x80) == 0x80; + boolean bit = ((byteBuffer << bitsLeft) & 0x80) != 0; return bit; } diff --git a/src/com/bytezone/diskbrowser/nufx/LZW3.java b/src/com/bytezone/diskbrowser/nufx/LZW3.java new file mode 100644 index 0000000..907e9b9 --- /dev/null +++ b/src/com/bytezone/diskbrowser/nufx/LZW3.java @@ -0,0 +1,160 @@ +package com.bytezone.diskbrowser.nufx; + +// DreamGraphix LZW +// code ported from CiderPress' DreamGraphix::UnpackDG() +// -----------------------------------------------------------------------------------// +public class LZW3 +// -----------------------------------------------------------------------------------// +{ + static final int[] bitMasks = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1FF, 0x3FF, 0x7FF, 0xFFF }; + static final int CLEAR_CODE = 256; + static final int EOF_CODE = 257; + static final int FIRST_FREE_CODE = 258; + + int nBitMod1; + int nBitMask; + int finChar; + int oldCode; + int inCode; + int freeCode; + int maxCode; + int k; + + int bitOffset; + + int[] hashNext = new int[4096]; + int[] hashChar = new int[4096]; + + int ptr = 0; + int iCode; + int[] stack = new int[32768]; + int stackIdx = 0; + + byte[] srcBuf; + byte[] dstBuf; + + // ---------------------------------------------------------------------------------// + public int unpack (byte[] src, byte[] dst, int max) + // ---------------------------------------------------------------------------------// + { + assert max <= dst.length; + + srcBuf = src; + dstBuf = dst; + + initTable (); + + bitOffset = 0; + + int a = 0; + int y = 0; + + while (true) + { + if (ptr > max) + { + System.out.println ("LZW3 overrun"); + return -1; + } + + readCode (); // sets iCode + + if (iCode == EOF_CODE) + break; + + if (iCode == CLEAR_CODE) + { + initTable (); + readCode (); // sets iCode + + oldCode = iCode; + k = iCode; + finChar = iCode; + dstBuf[ptr++] = (byte) iCode; + continue; + } + + a = inCode = iCode; + + if (iCode >= freeCode) + { + stack[stackIdx++] = finChar; + a = oldCode; + } + + while (a >= 256) + { + y = a; + a = hashChar[y]; + stack[stackIdx++] = a; + a = hashNext[y]; + } + +// a &= 0xFF; // should already be in 8 bits + finChar = a; + k = a; + y = 0; + + dstBuf[ptr + y++] = (byte) a; + + while (stackIdx > 0) + { + a = stack[--stackIdx]; + dstBuf[ptr + y++] = (byte) a; + } + + ptr += y; + + addCode (); + + oldCode = inCode; + + if (freeCode < maxCode) + continue; + + if (nBitMod1 == 12) + continue; + + nBitMod1++; + nBitMask = bitMasks[nBitMod1]; + maxCode <<= 1; + } + + return ptr; + } + + // ---------------------------------------------------------------------------------// + private void initTable () + // ---------------------------------------------------------------------------------// + { + nBitMod1 = 9; + nBitMask = bitMasks[nBitMod1]; + maxCode = 1 << nBitMod1; + freeCode = FIRST_FREE_CODE; + } + + // ---------------------------------------------------------------------------------// + private void readCode () + // ---------------------------------------------------------------------------------// + { + int bitIdx = bitOffset & 0x07; + int byteIdx = bitOffset >>> 3; // no sign extension + + iCode = srcBuf[byteIdx] & 0xFF | (srcBuf[byteIdx + 1] & 0xFF) << 8 + | (srcBuf[byteIdx + 2] & 0xFF) << 16; + + iCode >>>= bitIdx; + iCode &= nBitMask; + + bitOffset += nBitMod1; + } + + // ---------------------------------------------------------------------------------// + private void addCode () + // ---------------------------------------------------------------------------------// + { + hashChar[freeCode] = k; + hashNext[freeCode] = oldCode; + freeCode++; + } +} diff --git a/src/com/bytezone/diskbrowser/nufx/NuFX.java b/src/com/bytezone/diskbrowser/nufx/NuFX.java index 6cb8cde..a00d3f1 100644 --- a/src/com/bytezone/diskbrowser/nufx/NuFX.java +++ b/src/com/bytezone/diskbrowser/nufx/NuFX.java @@ -59,9 +59,7 @@ public class NuFX { masterHeader = new MasterHeader (buffer); - int dataPtr = 48; - if (masterHeader.bin2) - dataPtr += 128; + int dataPtr = masterHeader.bin2 ? 176 : 48; if (debug) System.out.printf ("%s%n%n", masterHeader);