This is my fixed Carmack decompressor:I wrote:I'm trying to read Galaxy levels, but I'm having some trouble with decompression. (It doesn't help that there is no consistent information on the web, except the uberobscure mobydoc.txt.)
I know I need to de-Carmackize first, and I get a chunk of length 6536 for Keen 4's game maps. That length checks out with what's reported in the file. However, when I then un-RLEW it (with the flag provided in MAPHEAD, $CD $AB = 43981), I get a massive chunk of length 106618, far larger than the prescribed size of 8052. My RLEW decompressor works with Vorticons levels, but what it produces here is insanely incorrect.
When I resave the mal-loaded levels, TOM can open them and not Keen. When TOM opens them, it's OK for a while and then starts looking like this:
Notice that the infoplane is OK, probably because it's sparse. This makes me suspect that badness only starts happening after a Carmack far pointer.
Code: Select all
Sub DecompressCarmack(Data As IO.Stream, Output As IO.Stream)
Dim opos As UInteger = Output.Position
Do Until Data.Position = Data.Length
Dim w As UShort = ReadUShort(Data)
Dim f As Byte() = UShortToByte(w)
If f(0) = 0 And (f(1) = 167 Or f(1) = 168) Then
Output.Write({f(1), Data.ReadByte}, 0, 2)
Else
If f(1) = 167 Then
Dim o As Byte = ReadByte(Data)
Dim cpos As UInteger = Output.Position
Output.Position -= (2 * o)
Dim buf((2 * f(0)) - 1) As Byte
Output.Read(buf, 0, 2 * f(0))
Output.Position = cpos
Output.Write(buf, 0, 2 * f(0))
ElseIf f(1) = 168 Then
Dim l As UShort = ReadUShort(Data)
Dim cpos As UInteger = Output.Position
Output.Position = opos + (2 * l)
Dim buf((2 * f(0)) - 1) As Byte
Output.Read(buf, 0, 2 * f(0))
Output.Position = cpos
Output.Write(buf, 0, 2 * f(0))
Else
WriteUShort(Output, w)
End If
End If
Loop
End Sub
Code: Select all
Sub DecompressRLEW(Data As IO.Stream, Flag As UShort, Output As IO.Stream)
Dim current As UShort
Dim count As UShort
Do
current = ReadUShort(Data)
If current = Flag Then
count = ReadUShort(Data)
current = ReadUShort(Data)
For z = 1 To count
WriteUShort(Output, current)
Next
Else
WriteUShort(Output, current)
End If
Loop Until Data.Position = Data.Length
End Sub
FleexyI wrote:Any help is appreciated, and I release these (probably flawed) implementations into the public domain.