From 24daee5319843cd53f320778aa6e9d5d1ee11ee2 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Tue, 23 Jun 2020 14:23:53 +1000 Subject: [PATCH] new ExoBuffer --- .../diskbrowser/applefile/ExoBuffer.java | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 src/com/bytezone/diskbrowser/applefile/ExoBuffer.java diff --git a/src/com/bytezone/diskbrowser/applefile/ExoBuffer.java b/src/com/bytezone/diskbrowser/applefile/ExoBuffer.java new file mode 100644 index 0000000..c3948f5 --- /dev/null +++ b/src/com/bytezone/diskbrowser/applefile/ExoBuffer.java @@ -0,0 +1,347 @@ +package com.bytezone.diskbrowser.applefile; + +// pack::: ~/exomizer-3.0.2/src/exomizer mem -q -P23 -lnone LODE148@0x4000 -o LODE148c +// unpack: ~/exomizer-3.0.2/src/exomizer raw -d -b -P23 LODE148c,0,-2 -o LODE148x + +// -----------------------------------------------------------------------------------// +public class ExoBuffer +// -----------------------------------------------------------------------------------// +{ + private static int PBIT_BITS_ORDER_BE = 0; + private static int PBIT_BITS_COPY_GT_7 = 1; + private static int PBIT_IMPL_1LITERAL = 2; + private static int PBIT_BITS_ALIGN_START = 3; + private static int PBIT_4_OFFSET_TABLES = 4; + + private static int PFLAG_BITS_ORDER_BE = (1 << PBIT_BITS_ORDER_BE); + private static int PFLAG_BITS_COPY_GT_7 = (1 << PBIT_BITS_COPY_GT_7); + private static int PFLAG_IMPL_1LITERAL = (1 << PBIT_IMPL_1LITERAL); + private static int PFLAG_BITS_ALIGN_START = (1 << PBIT_BITS_ALIGN_START); + private static int PFLAG_4_OFFSET_TABLES = (1 << PBIT_4_OFFSET_TABLES); + + byte[] outBuffer = new byte[8192]; + + // ---------------------------------------------------------------------------------// + public ExoBuffer (byte[] inBuffer) + // ---------------------------------------------------------------------------------// + { + reverse (inBuffer); + DecCtx decCtx = new DecCtx (); + decCtxInit (decCtx, inBuffer, outBuffer, 23); + // tableDump (decCtx.table); + decCtxDecrunch (decCtx); + + reverse (outBuffer); + // System.out.println (HexFormatter.format (outBuffer)); + } + + private void reverse (byte[] inBuffer) + { + int lo = 0; + int hi = inBuffer.length - 1; + while (lo < hi) + { + byte temp = inBuffer[lo]; + inBuffer[lo] = inBuffer[hi]; + inBuffer[hi] = temp; + ++lo; + --hi; + } + } + + // ---------------------------------------------------------------------------------// + public byte[] getExpandedBuffer () + // ---------------------------------------------------------------------------------// + { + return outBuffer; + } + + // ---------------------------------------------------------------------------------// + private int bitBufRotate (DecCtx decCtx, int carry) + // ---------------------------------------------------------------------------------// + { + int carryOut; + + if ((decCtx.flagsProto & PFLAG_BITS_ORDER_BE) != 0) + { + carryOut = (decCtx.bitBuffer & 0x80) == 0 ? 0 : 1; + decCtx.bitBuffer = (decCtx.bitBuffer << 1) & 0xFF; + + if (carry != 0) + decCtx.bitBuffer |= 0x01; + } + else + { + carryOut = decCtx.bitBuffer & 0x01; + decCtx.bitBuffer = (decCtx.bitBuffer >>> 1) & 0xFF; + + if (carry != 0) + decCtx.bitBuffer |= 0x80; + } + + return carryOut; + } + + // ---------------------------------------------------------------------------------// + private int getByte (DecCtx decCtx) + // ---------------------------------------------------------------------------------// + { + decCtx.bitsRead += 8; + int c = decCtx.inBuffer[decCtx.inPos++] & 0xFF; + return c; + } + + // ---------------------------------------------------------------------------------// + private int getBits (DecCtx decCtx, int count) + // ---------------------------------------------------------------------------------// + { + int byteCopy = 0; + int value = 0; + + if ((decCtx.flagsProto & PFLAG_BITS_COPY_GT_7) != 0) + { + while (count > 7) + { + byteCopy = count >>> 3; + count &= 7; + } + } + + while (count-- > 0) + { + int carry = bitBufRotate (decCtx, 0); + + if (decCtx.bitBuffer == 0) + { + decCtx.bitBuffer = getByte (decCtx); + decCtx.bitsRead -= 8; + carry = bitBufRotate (decCtx, 1); + } + value <<= 1; + value |= carry; + decCtx.bitsRead++; + } + + while (byteCopy-- > 0) + { + value <<= 8; + value |= getByte (decCtx); + } + + return value; + } + + // ---------------------------------------------------------------------------------// + private int getGammaCode (DecCtx decCtx) + // ---------------------------------------------------------------------------------// + { + int gammaCode = 0; + + while (getBits (decCtx, 1) == 0) + ++gammaCode; + + return gammaCode; + } + + // ---------------------------------------------------------------------------------// + private int getCooked (DecCtx decCtx, int index) + // ---------------------------------------------------------------------------------// + { + int base = decCtx.table.tableLo[index] | (decCtx.table.tableHi[index] << 8); + return base + getBits (decCtx, decCtx.table.tableBi[index]); + } + + // ---------------------------------------------------------------------------------// + private void tableInit (DecCtx decCtx, DecTable decTable) + // ---------------------------------------------------------------------------------// + { + int end; + int a = 0; + int b = 0; + + decTable.tableBit[0] = 2; + decTable.tableBit[1] = 4; + decTable.tableBit[2] = 4; + + if ((decCtx.flagsProto & PFLAG_4_OFFSET_TABLES) != 0) + { + end = 68; + + decTable.tableBit[3] = 4; + + decTable.tableOff[0] = 64; + decTable.tableOff[1] = 48; + decTable.tableOff[2] = 32; + decTable.tableOff[3] = 16; + } + else + { + end = 52; + + decTable.tableOff[0] = 48; + decTable.tableOff[1] = 32; + decTable.tableOff[2] = 16; + } + + for (int i = 0; i < end; i++) + { + if ((i & 0x0F) != 0) + a += (1 << b); + else + a = 1; + + decTable.tableLo[i] = a & 0xFF; + decTable.tableHi[i] = a >>> 8; + + if ((decCtx.flagsProto & PFLAG_BITS_COPY_GT_7) != 0) + { + b = getBits (decCtx, 3); + b |= getBits (decCtx, 1) << 3; + } + else + b = getBits (decCtx, 4); + + decTable.tableBi[i] = b; + } + } + + // ---------------------------------------------------------------------------------// + private void tableDump (DecTable table) + // ---------------------------------------------------------------------------------// + { + for (int i = 0; i < 16; i++) + System.out.printf ("%X", table.tableBi[i]); + + for (int j = 0; j < 3; j++) + { + System.out.printf (","); + int start = table.tableOff[j]; + int end = start + (1 << table.tableBit[j]); + for (int i = start; i < end; i++) + System.out.printf ("%X", table.tableBi[i]); + } + System.out.println (); + } + + // ---------------------------------------------------------------------------------// + private void decCtxInit (DecCtx decCtx, byte[] inBuffer, byte[] outBuffer, int flags) + // ---------------------------------------------------------------------------------// + { + decCtx.bitsRead = 0; + + decCtx.inBuffer = inBuffer; + decCtx.inEnd = inBuffer.length; + + decCtx.inPos = 2; + decCtx.flagsProto = flags; + + decCtx.outBuffer = outBuffer; + decCtx.outPos = 0; + + if ((decCtx.flagsProto & PFLAG_BITS_ALIGN_START) != 0) + decCtx.bitBuffer = 0; + else + decCtx.bitBuffer = getByte (decCtx); + + tableInit (decCtx, decCtx.table); + } + + // ---------------------------------------------------------------------------------// + private void decCtxDecrunch (DecCtx decCtx) + // ---------------------------------------------------------------------------------// + { + int len; + int offset; + int i; + int val; + int src = 0; + int literal; + int threshold = (decCtx.flagsProto & PFLAG_4_OFFSET_TABLES) != 0 ? 4 : 3; + + if ((decCtx.flagsProto & PFLAG_IMPL_1LITERAL) != 0) + { + len = 1; + literal = 1; + src = literal (decCtx, len, literal, src); + } + + while (true) + { + literal = 0; + + if (getBits (decCtx, 1) != 0) + { + len = 1; + literal = 1; + src = literal (decCtx, len, literal, src); + continue; + } + + val = getGammaCode (decCtx); + + if (val == 16) + break; + + if (val == 17) + { + len = getBits (decCtx, 16); + literal = 1; + src = literal (decCtx, len, literal, src); + continue; + } + + len = getCooked (decCtx, val); + i = (len > threshold ? threshold : len) - 1; + val = decCtx.table.tableOff[i] + getBits (decCtx, decCtx.table.tableBit[i]); + offset = getCooked (decCtx, val); + + src = decCtx.outPos - offset; + + src = literal (decCtx, len, literal, src); + } + } + + // ---------------------------------------------------------------------------------// + private int literal (DecCtx decCtx, int len, int literal, int src) + // ---------------------------------------------------------------------------------// + { + assert len > 0; + do + { + int val = literal == 0 ? decCtx.outBuffer[src++] : getByte (decCtx); + decCtx.outBuffer[decCtx.outPos++] = (byte) (val & 0xFF); + + } while (--len > 0); + + return src; + } + + // ---------------------------------------------------------------------------------// + class DecCtx + // ---------------------------------------------------------------------------------// + { + int inPos; + int inEnd; + int outPos; + + byte[] inBuffer; + byte[] outBuffer; + + int bitBuffer; + + DecTable table = new DecTable (); + int bitsRead; + int flagsProto; + } + + // ---------------------------------------------------------------------------------// + class DecTable + // ---------------------------------------------------------------------------------// + { + int tableBit[] = new int[8]; + int tableOff[] = new int[8]; + int tableBi[] = new int[100]; + int tableLo[] = new int[100]; + int tableHi[] = new int[100]; + } +}