• Popular Now

• 15
• 15
• 11
• 9
• 10

Archived

This topic is now archived and is closed to further replies.

C&C Format80 conversion - Porting Pascal to C

This topic is 5108 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

struct SHP_IMAGEHEADER
{
BYTE cType;
BYTE cReserved0;
BYTE cHeight;
BYTE cWidth;
BYTE cReserved1;
BYTE cHeight0;
WORD wSize;
WORD wChecksum;
};

struct SHP_IMAGE
{
SHP_IMAGE() { Data = NULL; } // Constructor

BYTE           *Data;
};

void ReadImage(ifstream &File, DWORD Offset, SHP_IMAGE &Image)
{
File.seekg(Offset + 2);

// Allocate memory for the data

Image.Data = new BYTE[Image.Header.wSize - 10];
}

And this is my decode function:
void DecodeFormat80(SHP_IMAGE &Image, BYTE *Destination)
{
BYTE *Source;
BYTE *Dest;
BYTE  Com;
int   SP = 0;
int   DP = 0;
int   Posit = 0;
int   Count = 0;

Source = Image.Data;
Dest   = Destination;

{
Com = Source[SP];
SP++;

switch (Com >> 7)
{
case 0:
Count = ((Com & 0x7F) >> 4) + 3;
Posit = ((Com & 0x0F) << 8) + Source[SP];
++SP;
Posit = DP - Posit;
for (int i = Posit; i < Posit+Count; ++i)
{
Dest[DP] = Dest[i];
++DP;
}break;

case 1:
switch ((Com & 0x40) >> 6)
{
case 0:
Count = Com & 0x3F;
if (Count == 0) break; // EOF Marker

for (int i = 0; i < Count; ++i)
{
Dest[DP] = Source[SP];
++DP; ++ SP;
}break;

case 1:
Count = Com & 0x3F;
if (Count < 0x3E)
{
Count += 3;
Posit = (WORD)Source[SP];
Source += 2;
for (int i = Posit; i < Posit+Count; ++i)
{
Dest[DP] = Dest[i];
DP++;
}
}
else if (Count == 0x3F)
{
Count = WORD(Source[SP]);
Posit = WORD(Source[SP+2]);
SP += 4;
for (int i = Posit; i < Posit + Count; ++i)
{
Dest[DP] = Dest[i];
DP++;
}
}
else
{
BYTE Color;
Count = (WORD)Source[SP];
SP += 2;
Color = Source[SP];
for (int i = 0; i < Count; ++i)
{
Dest[DP] = Color;
DP++;
}
}break; // case 1:

} // switch (b6)

break;
} // switch (Command)

}
}

Toolmaker
-Earth is 98% full. Please delete anybody you can.

Share on other sites
As I have replied to you before, I took a quick look. The problem is that you are looping while (SP < Image.Header.cWidth * Image.Header.cHeight) and of course there''s not that many bytes in the compressed data. And even the uncompressed data offly have that many BITS. You don''t know how many bytes there is in the compressed data(source) before, so nake it an endless loop.

You probably added it because it wouldn''t break out right? That''s because you copied the source slightly wrong compare
case 0:    Count = Com & 0x3F;    if (Count == 0) break; // EOF Marker	    for (int i = 0; i < Count; ++i)    {         Dest[DP] = Source[SP];				           ++DP; ++ SP;    }break;

to
0 : begin  {Copy as is command (1)}    Count:=Com and \$3F;  {mask 2 topmost bits}    if Count=0 then break; {EOF marker}    for i:=1 to Count do    begin        Dest[DP]:=Source[SP];        Inc(DP);        Inc(SP);    end;end;

In the pascal source the break statement breaks out of the whole loop, while it only breaks out of the switch statement for you. So, that''s what you need to fix

Share on other sites
I changed that code, but that''s actually not the problem. The problem is, when I decompress the first file(I never get any further anyway), the data read starts with 0x00 0x00. This results in Command 0 and the posit to be -128 + 3(Posit = 0 - 128 + 3) and a count of 3 aswell. I have no clue what I am doing wrong here...

Toolmaker

-Earth is 98% full. Please delete anybody you can.

Share on other sites
Hm... I don''t see how you can get that

Count = ((Com & 0x7F) >> 4) + 3;
should give
((0x00 & 07F) >> 4) + 3
= (0x00 >> 4) + 3
= 3

Posit = ((Com & 0x0F) << 8) + Source[SP];
should give
((0x00 & 0x0F) << 8) + 0x00
=((0x00) << 8) +0x00
=0x00 + 0x00
=0

Posit = DP - Posit;
=0-0
=0

So this would copy 3 bytes in the destination buffer, starting at position 0 to position 0. In other words the only thing it does is incresing the destination pointer by 3. Which may or may not be right.

Allthough not documented there, it''s possible that 0x00 as the first byte just means start of the commands, so try starting from source position 1 or maybe 2, by setting SP at the start

Share on other sites
Well, after a few days I finally got back to coding. However, it still won''t work. I changed everything to WORDs since I was using signed ints. Obviously, that doesn''t cause the problem. I took the 2 second image from the file.

It would run the first case right after start. This are the results:

Count = ((Com & 0x7F) >> 4) + 3;              // Count = 3Posit = ((Com & 0x0F) << 8) + Source[SP];     // Posit = 133 ???++SP;                                         // SP = 2Posit = DP - Posit;                           // Posit = 65403

The rest is predictable, ie, not worky...

Toolmaker

-Earth is 98% full. Please delete anybody you can.