|
shedevr.org.ru Группа перевода приставочных игр "ШЕДЕВР"
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Shiru
Зарегистрирован: 25.10.2006 Сообщения: 295 Откуда: Russia, Moscow
|
Добавлено: Пн Окт 22, 2007 10:20 pm Заголовок сообщения: Сжатие графики |
|
|
Вопрос не имеет отношения к переводам игр, но, думаю, местные ромхакеры могут на него ответить.
Ищутся алгоритмы и процедуры сжатия графики, для которых написаны упаковщики (и распаковщики). В основном интересуют алгоритмы, распаковывающие графику непосредственно в видеопамять, без буфера в основной памяти (большого, по крайней мере) - когда распаковщик не использует уже распакованные данные (как LZ-подобные алгоритмы), или использует только небольшую их часть. Самые простейшие реализации RLE, конечно, не интересуют.
Нужно это для нахождения наиболее эффективного алгоритма для последующего использования в homebrew-разработках для SMD (м.б. и для других платформ). Требуется наличие исходного кода пакера-депакера на любом языке. Предполагаю, что у тех, кто занимался заменой сжатой графики в играх, найдётся что-нибудь подходящее. |
|
Вернуться к началу |
|
|
HoRRoR RRC2008
Зарегистрирован: 21.06.2006 Сообщения: 2341 Откуда: Ростов-на-Дону
|
Добавлено: Пн Окт 22, 2007 10:46 pm Заголовок сообщения: |
|
|
У Джинна есть отличные коды, но без его согласия выкладывать не буду.
Вот, например, процедуры распаковки/запаковки LZ77. Алгоритм оперирует Word'ами:
Код: |
Procedure UnPack(var Buffer: Pointer);
var BW: pointer; B: ^byte; W, Pos, RPos, WPos: ^Word; CByte, Size, CurSize: DWord;
DW: ^DWord; Flag: Boolean;
n, m: Integer; Back, TW: Word;
Count: byte;
begin
CurSize:=0;
DW:=Addr(Buffer^);
Inc(DW);
Size:=DW^;
GetMem(BW,Size);
Inc(DW);
Pos:=Addr(Buffer^);
WPos:=Addr(BW^);
While CurSize<Size do
begin
CByte:=DW^;
Pos:=Addr(DW^);
Inc(Pos,2);
Inc(DW,17);
For n:=0 to 31 do
begin
If CurSize>Size then break;
Flag:=Boolean((CByte shr n) and 1); //Выдвигаем байт
If Flag=True then //Просто копируем
begin
WPos^:=Pos^;
Inc(Wpos); Inc(Pos); Inc(CurSize,2);
end else
begin
B:=Addr(Pos^);
Count:=B^;
Back:=B^;
Inc(B);
TW:=B^;
Back:=(Back SHR 5)+(TW SHL 3);
Count:= Count SHL 3;
Count:= Count SHR 3;
If Back=0 then Back:=$7FF;
RPos:=Addr(WPos^);
Inc(RPos, -Back);
For m:=0 to Count+1 do
begin
If Back*2<=CurSize then
begin
WPos^:=RPos^;
Inc(WPos); Inc(RPos); Inc(CurSize, 2);
end else
begin
WPos^:=0;
Inc(WPos); Inc(RPos); Inc(CurSize, 2);
end;
end;
Inc(Pos);
end;
end;
end;
FreeMem(Buffer);
Buffer:=BW;
end;
|
Запаковка вроде работает, но игра не всегда принимает:
Код: |
Function Pack(var Buf: Pointer; Size: Integer; Lev: Word): Integer;
var BW: Pointer; W: ^Word; B: ^Byte; DW: ^DWord; CurSize, ASize: DWord;
Pos, CPos, CRPos, BPos, RPos, WPos: ^Word; BestRes: Word; lv, Cnt: Integer;
n,m,l: Integer;
UDWord: ^DWord;
begin
GetMem(BW, Size+(Size div 64)+8);
Pos:=Addr(Buf^);
Inc(Pos,$800);
WPos:=Addr(BW^);
WPos^:=$7057; Inc(WPos); WPos^:=$3631; Inc(Wpos);
WPos^:=Size AND $0000FFFF; Inc(WPos); WPos^:=Size SHR 16; Inc(WPos);
CurSize:=0;
ASize:=8;
While CurSize<Size do
begin
UDWord:=Addr(WPos^);
UDWord^:=0;
Inc(WPos,2);
Inc(ASize,4);
For n:=0 to 31 do
begin
UDWord^:=UDWord^ SHR 1;
BestRes:=0;
//-
RPos:=Addr(Pos^);
If CurSize<lev*2 then lv:=CurSize div 2+8 else lv:=lev;
Inc(RPos, -lv);
For m:=0 to lv-1 do
begin
If BestRes>=32 then break;
If RPos^=Pos^ then
begin
CPos:=Addr(Pos^);
CRPos:= Addr(RPos^);
Inc(CPos); Inc(CRPos);
Cnt:=1;
While (CPos^=CRPos^) and (Cnt<=32) and (CRPos<>Pos) and (CurSize+Cnt<Size) do
begin
Inc(CPos); Inc(CRPos); Inc(Cnt);
end;
If {Integer(CRPos)-Integer(RPos)+1}Cnt>=BestRes then
begin
BestRes:=Cnt{Integer(CRPos)-Integer(RPos)-1};
BPos:=Addr(RPos^);
end;
end;
Inc(RPos);
end;
//If BestRes>=31 then WriteLn(IntToStr(BestRes));
If BestRes>1 Then
begin
WPos^:=(((Integer(Pos)-Integer(BPos){-1}) div 2) SHL 5)+BestRes-2;
Inc(WPos);
Inc(CurSize,(BestRes-1)*2);
Inc(ASize,2);
Inc(Pos, BestRes);
end else
begin
Inc(UDWord^,$80000000);
WPos^:=Pos^;
Inc(WPos); Inc(Pos);
Inc(ASize,2); Inc(CurSize,2);
end;
//WriteLn(IntToHex(UDWord^,8));
If CurSize>Size then break;
end;
end;
Result:=ASize;
FreeMem(Buf);
Buf:=BW;
end;
|
Ещё есть процедуры на VB, но это были пробы пера. Вроде и на Дельфи ещё были... Если найду - выложу.
--
З.Ы. Посмотрел я на этот свой недавний код (который чуть выше)... Мда... Сейчас бы сделал намного лучше и оптимальней. _________________ Работаю за деньги
KILL ALL HUMANS!!!!!111 |
|
Вернуться к началу |
|
|
Djinn RRC2008
Зарегистрирован: 16.03.2004 Сообщения: 633 Откуда: Москва
|
Добавлено: Чт Ноя 01, 2007 7:04 pm Заголовок сообщения: |
|
|
Huffman на GBA
Распаковка:
Код: |
Function HuffDecompress(Var Source, Dest): Integer;
Var
Src, Dst, Header, TreeSize, TreeStart, Mask, Data, RootNode: DWord;
CurrentNode, WriteValue, HalfLen, Value, Pos, ByteShift: DWord;
ByteCount: Integer; WriteData: Boolean; Len: Integer;
begin
LastHufSize := 0;
Src := DWord(Addr(Source));
Dst := DWord(Addr(Dest));
Header := PDWord(Src)^;
Inc(Src, 4);
Inc(LastHufSize, 4);
TreeSize := PByte(Src)^;
TreeStart := Src + 1;
Inc(Src, (TreeSize + 1) shl 1);
Inc(LastHufSize, (TreeSize + 1) shl 1);
Len := Header shr 8;
Result := Len;
Mask := $80000000;
Data := PDWord(Src)^;
Inc(Src, 4);
Inc(LastHufSize, 4);
Pos := 0;
RootNode := PByte(TreeStart)^;
CurrentNode := RootNode;
WriteData := False;
ByteShift := 0;
ByteCount := 0;
WriteValue := 0;
if Header and $0F = 8 then
begin
While Len > 0 do
begin
If Pos = 0 then Inc(Pos) Else Inc(Pos, (((CurrentNode and $3F) + 1) shl 1));
If Data and Mask <> 0 then
begin
If CurrentNode and $40 <> 0 then WriteData := True;
CurrentNode := PByte(TreeStart + Pos + 1)^;
end Else
begin
If CurrentNode and $80 <> 0 then WriteData := True;
CurrentNode := PByte(TreeStart + Pos)^;
end;
If WriteData then
begin
WriteValue := WriteValue or (CurrentNode shl ByteShift);
Inc(ByteCount);
Inc(ByteShift, 8);
Pos := 0;
CurrentNode := RootNode;
WriteData := False;
If ByteCount = 4 then
begin
ByteCount := 0;
ByteShift := 0;
PDWord(Dst)^ := WriteValue;
WriteValue := 0;
Inc(Dst, 4);
Dec(Len, 4);
end;
end;
Mask := Mask shr 1;
If Mask = 0 then
begin
Mask := $80000000;
Data := PDWord(Src)^;
Inc(Src, 4);
Inc(LastHufSize, 4);
end;
end;
end Else
begin
HalfLen := 0;
Value := 0;
While Len > 0 do
begin
If Pos = 0 then Inc(Pos) Else Inc(Pos, (((CurrentNode and $3F) + 1) shl 1));
If Data and Mask <> 0 then
begin
If CurrentNode and $40 <> 0 then WriteData := True;
CurrentNode := PByte(TreeStart + Pos + 1)^;
end Else
begin
If CurrentNode and $80 <> 0 then WriteData := True;
CurrentNode := PByte(TreeStart + Pos)^;
end;
If WriteData then
begin
If HalfLen = 0 then
Value := Value or CurrentNode Else
Value := Value or (CurrentNode shl 4);
Inc(HalfLen, 4);
If HalfLen = 8 then
begin
WriteValue := WriteValue or (Value shl ByteShift);
Inc(ByteCount);
Inc(ByteShift, 8);
HalfLen := 0;
Value := 0;
If ByteCount = 4 then
begin
ByteCount := 0;
ByteShift := 0;
PDWord(Dst)^ := WriteValue;
WriteValue := 0;
Inc(Dst, 4);
Dec(Len, 4);
end;
end;
Pos := 0;
CurrentNode := RootNode;
WriteData := False;
end;
Mask := Mask shr 1;
If Mask = 0 then
begin
Mask := $80000000;
Data := PDWord(Src)^;
Inc(Src, 4);
Inc(LastHufSize, 4);
end;
end;
end;
end;
|
Упаковка:
Код: | Type
PFreq = ^TFreq;
TFreq = Record
Count: Integer;
Code: Integer;
HCode: DWord;
LRbit: DWord;
Pos: Integer;
Left: PFreq;
Right: PFreq;
Next: PFreq;
end;
TFreqs = Class
Root: PFreq;
Count: Integer;
Constructor Create;
Function Add: PFreq;
Function MakeParent: Boolean;
Destructor Destroy; override;
end;
Constructor TFreqs.Create;
begin
Root := NIL;
Count := 0;
end;
Function TFreqs.Add: PFreq;
begin
New(Result);
FillChar(Result^, SizeOf(TFreq), 0);
Result^.Code := -1;
Result^.Next := Root;
Root := Result;
Inc(Count);
end;
Destructor TFreqs.Destroy;
Procedure FreeNodes(Node: PFreq);
begin
If Node <> NIL then
begin
FreeNodes(Node^.Left);
FreeNodes(Node^.Right);
Dispose(Node^.Left);
Dispose(Node^.Right);
end;
end;
Var N: PFreq;
begin
While Root <> NIL do
begin
With Root^ do
begin
N := Next;
FreeNodes(Left);
Dispose(Left);
FreeNodes(Right);
Dispose(Right);
end;
Dispose(Root);
Root := N;
end;
Count := 0;
Inherited Destroy;
end;
Function TFreqs.MakeParent: Boolean;
Function FindMin: PFreq;
Var I: Integer; P, N: PFreq;
begin
I := $7FFFFFFF;
N := Root;
P := NIL;
While N <> NIL do With N^ do
begin
If I > Count then
begin
I := Count;
P := N;
end;
N := Next;
end;
N := Root;
If N = P then
begin
Root := N^.Next;
P^.Next := NIL;
Dec(Count);
Result := P;
Exit;
end;
While N <> NIL do
begin
If P = N^.Next then
begin
N^.Next := P^.Next;
P^.Next := NIL;
Dec(Count);
Result := P;
Exit;
end;
N := N^.Next;
end;
Result := NIL;
end;
Var A, B, N: PFreq;
begin
Result := False;
A := FindMin;
B := FindMin;
If B = NIL then
begin
Root := A;
Exit;
end;
If Root <> NIL then With Add^ do
begin
Left := B;
Right := A;
Code := -1;
Count := A^.Count + B^.Count;
Result := True;
end Else
begin
New(N);
FillChar(N^, SizeOf(TFreq), 0);
With N^ do
begin
Left := B;
Right := A;
Code := -1;
Count := A^.Count + B^.Count;
end;
Root := N;
Inc(Count);
Result := False;
end;
end;
Var HVar: Boolean;
Function CreateTree(Var Dest; Root: PFreq): DWord;
Function NodePos(L, R: PFreq; Pos: DWord): DWord;
begin
If L <> NIL then
begin
L^.Pos := Pos;
R^.Pos := Pos + 1;
Result := NodePos(R^.Left, R^.Right, NodePos(L^.Left, L^.Right, Pos + 2));
end Else Result := Pos;
end;
Var B: PBytes;
Procedure PutNode(N: PFreq);
Var I: Integer;
begin
If HVar then Exit;
If N <> NIL then With N^ do
begin
If Code = -1 then
begin
I := (Left^.Pos - (Pos - Integer(not Odd(Pos)))) shr 1 - 1;
If I > $3F then
begin
HVar := True;
Exit;
end;
B^[Pos] := I + Byte(Left^.Left = NIL) shl 7 +
Byte(Right^.Left = NIL) shl 6;
end Else
B^[Pos] := Code;
PutNode(Left);
PutNode(Right);
end;
end;
begin
Result := 0;
If Root = NIL then Exit;
With Root^ do
begin
Pos := 0;
Result := NodePos(Left, Right, 1);
end;
B := Addr(Dest);
HVar := False;
PutNode(Root);
If HVar then Result := 0;
end;
Function HuffCompress(Var Source, Dest; SrcLen: Integer; Bit8: Boolean): Integer;
Var Codes: Array[Byte] of Packed Record Code: DWord; Size: DWord end;
Procedure AnalizeCodes(Node: PFreq; A, B: Integer);
Var I: Integer;
begin
I := Node^.Code;
If I <> -1 then
begin
Codes[I].Size := A;
Codes[I].Code := B;
end;
With Node^ do
begin
HCode := B;
If Left = NIL then Exit;
Left^.LRbit := 1;
Right^.LRbit := 0;
AnalizeCodes(Left, A + 1, B + B);
AnalizeCodes(Right, A + 1, (B + B) or 1);
end;
end;
Var
S: PBytes; Dst: DWord; I: Integer; Bit: DWord;
Frs: TFreqs; Freqs: Array[Byte] of DWord; DataSize, Old: DWord;
Header: DWord Absolute Dest; TSZ: PByte; NCount: Integer;
MasX: DWord;
Procedure AddCode(aCode: Byte);
Var Mask: DWord;
begin
With Codes[aCode] do
begin
Mask := 1 shl (Size - 1);
While Mask > 0 do
begin
If aCode and Mask = 0 then
PDWord(DST)^ := PDWord(DST)^ and not MasX Else
PDWord(DST)^ := PDWord(DST)^ or MasX;
Mask := Mask shr 1;
MasX := MasX shr 1;
If MasX = 0 then
begin
Inc(Dst, 4);
MasX := $80000000;
end;
end;
Inc(Bit, Size);
If Bit div 32 > Old then
begin
Inc(DataSize, 4);
Old := Bit div 32;
end;
end;
end;
begin
FillChar(Freqs, SizeOf(Freqs), 0);
S := Addr(Source);
Dst := DWord(Addr(Dest));
Frs := TFreqs.Create;
If not Bit8 then
begin
For I := 0 to SrcLen - 1 do
begin
Inc(Freqs[S^[I] and $0F]);
Inc(Freqs[S^[I] shr 4]);
end;
end Else For I := 0 to SrcLen - 1 do Inc(Freqs[S^[I]]);
With Frs do
begin
For I := 0 to 255 do If Freqs[I] <> 0 then With Add^ do
begin
Code := I;
Count := Freqs[I];
end;
While MakeParent do;
FillChar(Codes, SizeOf(Codes), 0);
AnalizeCodes(Root, 0, 0);
Header := SrcLen shl 8 + $24;
If Bit8 then Inc(Header, 4);
Inc(Dst, 4);
Tsz := PByte(Dst);
NCount := CreateTree(Pointer(Dst + 1)^, Root) + 1;
While NCount mod 4 > 0 do Inc(NCount);
Inc(Dst, NCount);
NCount := NCount shr 1 - 1;
If not HVar and (NCount <= 255) then
begin
Tsz^ := NCount;
Result := (NCount + 1) shl 1 + 4;
Bit := 0; DataSize := 4; Old := 0;
MasX := $80000000;
If Bit8 then For I := 0 to SrcLen - 1 do AddCode(S^[I]) Else
For I := 0 to SrcLen - 1 do
begin
AddCode(S^[I] and $0F);
AddCode(S^[I] shr 4);
end;
Inc(Result, DataSize);
end Else Result := 0;
end;
Frs.Free;
end; |
|
|
Вернуться к началу |
|
|
HoRRoR RRC2008
Зарегистрирован: 21.06.2006 Сообщения: 2341 Откуда: Ростов-на-Дону
|
|
Вернуться к началу |
|
|
org
Зарегистрирован: 03.10.2007 Сообщения: 6
|
Добавлено: Ср Дек 19, 2007 3:24 pm Заголовок сообщения: |
|
|
Алгоритм сжатия 'SZP' (модифицированный вариант LZ), используемый на Gamecube:
Код: | #define SZP_ALLOC malloc
#define SZP_FREE free
#define SZP_MAGIC (('0'<<24)+('y'<<16)+('a'<<8)+'Y') // Yay0
typedef struct SZP_S // Szp Header.
{
u32 check;
u32 decodedSize;
u32 linkOffset;
u32 chunkOffset;
#pragma warning (disable: 4200)
u32 flagTable[];
} SZP_S;
// Encodes a data range in a SZP block.
// In: Memory mapped source buffer and its length in bytes.
// Out: Pre-allocated destination buffer (recommended length is twice as source),
// compressed buffer length in bytes.
void SZP_Compress(void *dest, int *encodedSize, void *src, int srcLen)
{
#define OFSBITS 12
u8 * decodedBuffer = (u8 *)src, *encodedBuffer = (u8 *)dest;
u32 decodedSize = srcLen;
u8 * decPtr, * decEndPtr;
SZP_S * header;
// masks buffer
u32 maskMaxSize = (decodedSize + 32) >> 3; // 1 bit per byte
u32 maskSize = 0;
u32 maskBitCount = 0, mask = 0;
u32 * maskBuffer, * maskPtr, * maskEndPtr;
// links buffer
u32 linkMaxSize = decodedSize;
u32 linkSize = 0;
u16 link = 0;
u16 linkOffset;
u16 * linkBuffer, * linkPtr, * linkEndPtr;
u16 maxOffset = 1 << OFSBITS;
u16 minCount = 3, maxCount = 273;
// chunks buffer
u32 chunkMaxSize = decodedSize;
u32 chunkSize = 0;
u8 chunk = 0;
u8 * chunkBuffer, * chunkPtr, * chunkEndPtr;
u8 *windowPtr;
int windowLen = 0, length, maxlen;
// Re-allocate memory needed
maskBuffer = (u32 *) SZP_ALLOC(maskMaxSize);
linkBuffer = (u16 *) SZP_ALLOC(linkMaxSize);
chunkBuffer = (u8 *) SZP_ALLOC(chunkMaxSize);
if (maskBuffer == NULL || linkBuffer == NULL || chunkBuffer == NULL) {
SZP_FREE(maskBuffer);
SZP_FREE(linkBuffer);
SZP_FREE(chunkBuffer);
return;
}
memset(maskBuffer, 0, maskMaxSize);
//memset(linkBuffer, 0, linkMaxSize); // Unnecessary.
//memset(chunkBuffer, 0, chunkMaxSize);
//set pointers
decPtr = decodedBuffer;
decEndPtr = decPtr + decodedSize;
maskPtr = maskBuffer;
maskEndPtr = (u32 *)((u8 *)maskPtr + maskMaxSize);
linkPtr = linkBuffer;
linkEndPtr = (u16 *)((u8 *)linkPtr + linkMaxSize);
chunkPtr = chunkBuffer;
chunkEndPtr = chunkPtr + chunkMaxSize;
windowPtr = decPtr;
// start enconding
while (decPtr < decEndPtr) {
if(windowLen >= (1 << OFSBITS))
{
windowLen = windowLen - (1 << OFSBITS);
windowPtr = decPtr - windowLen;
}
if((decEndPtr - decPtr) < maxCount) maxCount = (decEndPtr - decPtr);
// Scan through the window.
maxlen = 0;
for(int i=0; i<windowLen; i++)
{
for(length=0; length<(windowLen-i) && length<maxCount; length++)
{
if(decPtr[length] != windowPtr[length+i]) break;
}
if(length > maxlen)
{
maxlen = length;
linkOffset = windowLen - i;
}
}
length = maxlen;
mask <<= 1;
if(length >= minCount) // Add Link
{
link = (linkOffset - 1) & 0x0FFF;
if (length < 18) {
link |= ((length - 2) << 12) ;
}
else{
// store current count as a chunk.
*chunkPtr++ = (u8)(length - 18);
}
*linkPtr++ = Swap16(link);
decPtr += length;
windowLen += length;
}
else // Add single byte, increase Window.
{
*chunkPtr++ = *decPtr++;
windowLen++;
mask |= 1;
}
maskBitCount++;
if (maskBitCount == 32) {
// store current mask
*maskPtr = Swap32(mask);
maskPtr++;
maskBitCount = 0;
}
}
//flush mask
if (maskBitCount > 0) {
mask <<= (32 - maskBitCount);
// store current mask
*maskPtr = Swap32(mask);
maskPtr++;
maskBitCount = 0;
}
// now join all pieces
maskSize = (u32)((u8 *)maskPtr - (u8 *)maskBuffer);
linkSize = (u32)((u8 *)linkPtr - (u8 *)linkBuffer);
chunkSize = (u32)((u8 *)chunkPtr - (u8 *)chunkBuffer);
*encodedSize = sizeof(SZP_S) + maskSize + linkSize + chunkSize;
header = (SZP_S *)encodedBuffer;
// swap arch. dependent data
header->check = SZP_MAGIC;
header->decodedSize = Swap32(decodedSize);
header->linkOffset = Swap32(sizeof(SZP_S) + maskSize);
header->chunkOffset = Swap32(sizeof(SZP_S) + maskSize + linkSize);
// copy all buffer to final buffer
memcpy((u8 *)header + sizeof(SZP_S), maskBuffer, maskSize);
memcpy((u8 *)header + sizeof(SZP_S) + maskSize, linkBuffer, linkSize);
memcpy((u8 *)header + sizeof(SZP_S) + maskSize + linkSize, chunkBuffer, chunkSize);
SZP_FREE(maskBuffer);
SZP_FREE(linkBuffer);
SZP_FREE(chunkBuffer);
}
// Decodes an SZP block. Decoding is incredibly fast!
// In: Memory mapped compressed buffer and its length in bytes.
// Out: Pre-allocated destination buffer (length can be obtained from buffer's
// header), decompressed buffer length in bytes.
void SZP_Decompress(void *dest, int *destLen, void *src, int srcLen)
{
u8 * encodedBuffer = (u8 *)src;
SZP_S * header;
u8 * decodedBuffer;
u32 decodedBytes, decodedSize, linkOffset, chunkOffset;
u32 mask, maskBitsLeft, maskOffset;
u32 aux;
header = (SZP_S *)encodedBuffer;
decodedSize = Swap32(header->decodedSize); // size of decoded data
linkOffset = Swap32(header->linkOffset); // link table
chunkOffset = Swap32(header->chunkOffset); // byte chunks and count modifiers
decodedBytes = 0; // current offset in dest buffer
maskBitsLeft = 0; // mask bit counter
maskOffset = 16; // current offset in mask table
decodedBuffer = (u8 *)dest;
//memset(decodedBuffer, 0, decodedSize);
*destLen = decodedSize;
do
{
// if all bits are done, get next mask
if(maskBitsLeft == 0)
{
// read word from mask data block
mask = Swap32(*(u32 *)(encodedBuffer + maskOffset));
maskOffset += 4;
maskBitsLeft = 32; // bit counter
}
// if next bit is set, chunk is non-linked
if(mask & 0x80000000)
{
// get next byte
*(u8 *)(decodedBuffer + decodedBytes) = *(u8 *)(encodedBuffer + chunkOffset);
chunkOffset++, decodedBytes++;
}
// do copy, otherwise
else
{
u16 link;
u32 count;
u8 * pointer;
// read 16-bit from link table
link = Swap16(*(u16 *)(encodedBuffer + linkOffset));
linkOffset += 2;
// 'offset'
pointer = decodedBuffer + decodedBytes - ( (link & 0xfff) + 1);
// 'count'
count = link >> 12;
if(count == 0)
{
// get 'count' from chunks table
count = *(u8 *)(encodedBuffer + chunkOffset) + 18;
chunkOffset++;
}
else count += 2;
// do block copy
for(aux=0; aux<count; aux++)
{
*(u8 *)(decodedBuffer + decodedBytes) = *pointer;
decodedBytes++, pointer++;
}
}
// next bit in mask
mask <<= 1;
maskBitsLeft--;
} while(decodedBytes < decodedSize);
} |
|
|
Вернуться к началу |
|
|
|
|
Вы не можете начинать темы Вы можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
Powered by phpBB © 2001, 2005 phpBB Group
|