Skip to content

Commit

Permalink
Add PackBytes-compressed hgr and dhgr
Browse files Browse the repository at this point in the history
For file types FOT/$4000 and FOT/$4001.
  • Loading branch information
fadden committed Dec 30, 2023
1 parent aa03936 commit f8b5c50
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
26 changes: 24 additions & 2 deletions FileConv/Gfx/DoubleHiRes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ internal enum ColorConvMode {

private const int PAGE_SIZE = 8192;
private const int EXPECTED_LEN = PAGE_SIZE * 2;
private const int MIN_PB_LEN = ((EXPECTED_LEN + 255) / 256) * 2;
private const int MAX_PB_LEN = EXPECTED_LEN; // assume compression succeeded
private const int NUM_ROWS = 192;
private const int PIXELS_PER_ROW = 560;
private const int NUM_COLORS = 16;
Expand All @@ -83,7 +85,17 @@ public DoubleHiRes(FileAttribs attrs, Stream? dataStream, Stream? rsrcStream,
}

protected override Applicability TestApplicability() {
if (DataStream == null || DataStream.Length != EXPECTED_LEN) {
if (DataStream == null || IsRawDOS) {
return Applicability.Not;
}
// Check for PackBytes-compressed hi-res.
if (FileAttrs.FileType == FileAttribs.FILE_TYPE_FOT && FileAttrs.AuxType == 0x4001 &&
DataStream.Length >= MIN_PB_LEN && DataStream.Length <= MAX_PB_LEN) {
return Applicability.Probably; // 0x4001 is PackBytes-compressed dhgr
}

// Primary indicator is file length. Must be $2000.
if (DataStream.Length != EXPECTED_LEN) {
return Applicability.Not;
}
if (FileAttrs.FileType == FileAttribs.FILE_TYPE_BIN) {
Expand All @@ -109,7 +121,17 @@ public override IConvOutput ConvertFile(Dictionary<string, string> options) {

byte[] fullBuf = new byte[EXPECTED_LEN];
DataStream.Position = 0;
DataStream.ReadExactly(fullBuf, 0, Math.Min(EXPECTED_LEN, (int)DataStream.Length));
if (FileAttrs.FileType == FileAttribs.FILE_TYPE_FOT && FileAttrs.AuxType == 0x4001) {
byte[] tmpBuf = new byte[DataStream.Length];
DataStream.ReadExactly(tmpBuf, 0, tmpBuf.Length);
int outLen = ApplePack.UnpackBytes(tmpBuf, 0, tmpBuf.Length, fullBuf, 0,
out bool decompErr);
if (decompErr || outLen != EXPECTED_LEN) {
return new ErrorText("Unable to decompress data.");
}
} else {
DataStream.ReadExactly(fullBuf, 0, Math.Min(EXPECTED_LEN, (int)DataStream.Length));
}

ColorConvMode convMode =
OptToEnum(GetStringOption(options, OPT_CONV, CONV_MODE_LATCHED));
Expand Down
40 changes: 37 additions & 3 deletions FileConv/Gfx/HiRes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public class HiRes : Converter {
private const int MIN_LEN = EXPECTED_LEN - 8;
private const int MAX_LEN = EXPECTED_LEN + 1;

private const int MIN_PB_LEN = ((EXPECTED_LEN + 255) / 256) * 2;
private const int MAX_PB_LEN = EXPECTED_LEN; // assume compression succeeded


private HiRes() { }

Expand All @@ -61,6 +64,12 @@ protected override Applicability TestApplicability() {
if (DataStream == null || IsRawDOS) {
return Applicability.Not;
}
// Check for PackBytes-compressed hi-res.
if (FileAttrs.FileType == FileAttribs.FILE_TYPE_FOT && FileAttrs.AuxType == 0x4000 &&
DataStream.Length >= MIN_PB_LEN && DataStream.Length <= MAX_PB_LEN) {
return Applicability.Probably; // 0x4000 is PackBytes-compressed hgr
}

// Primary indicator is file length. $1ffc, $1ff8, $2000 are most common.
if (DataStream.Length < MIN_LEN || DataStream.Length > MAX_LEN) {
return Applicability.Not;
Expand Down Expand Up @@ -88,11 +97,36 @@ public override IConvOutput ConvertFile(Dictionary<string, string> options) {
Debug.Assert(DataStream != null);

byte[] fullBuf = new byte[EXPECTED_LEN];
DataStream.Position = 0;
DataStream.ReadExactly(fullBuf, 0, Math.Min(EXPECTED_LEN, (int)DataStream.Length));
bool isCompressed =
(FileAttrs.FileType == FileAttribs.FILE_TYPE_FOT && FileAttrs.AuxType == 0x4000);
bool badComp = false;
if (isCompressed) {
DataStream.Position = 0;
byte[] tmpBuf = new byte[DataStream.Length];
DataStream.ReadExactly(tmpBuf, 0, tmpBuf.Length);
int outLen = ApplePack.UnpackBytes(tmpBuf, 0, tmpBuf.Length, fullBuf, 0,
out bool decompErr);
if (decompErr || outLen < MIN_LEN) {
if (DataStream.Length >= MIN_LEN && DataStream.Length <= MAX_LEN) {
// Retry as uncompressed.
badComp = true;
isCompressed = false;
} else {
return new ErrorText("Unable to decompress data.");
}
}
}
if (!isCompressed) {
DataStream.Position = 0;
DataStream.ReadExactly(fullBuf, 0, Math.Min(EXPECTED_LEN, (int)DataStream.Length));
}

bool doMonochrome = GetBoolOption(options, OPT_BW, false);
return ConvertBuffer(fullBuf, Palette8.Palette_HiRes, doMonochrome);
IConvOutput output = ConvertBuffer(fullBuf, Palette8.Palette_HiRes, doMonochrome);
if (badComp) {
output.Notes.AddW("File aux type is incorrect (not compressed)");
}
return output;
}

#region Common
Expand Down

0 comments on commit f8b5c50

Please sign in to comment.