source: trunk/UDecode.pas

Last change on this file was 4, checked in by chronos, 8 years ago
  • Added: Not finished class for loading WSA files.
File size: 6.0 KB
Line 
1unit UDecode;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, Types;
9
10function Format80(Source: TByteDynArray): TByteDynArray;
11function Format40(Source: TByteDynArray): TByteDynArray;
12function Format20(Source: TByteDynArray): TByteDynArray;
13
14
15implementation
16
17// LCW decoder
18function Format80(Source: TByteDynArray): TByteDynArray;
19var
20 Flag: Byte;
21 Size: Word;
22 Offset: Word;
23 SourceIndex: Integer;
24 DestIndex: Integer;
25begin
26 SourceIndex := 0;
27 DestIndex := 0;
28 SetLength(Result, Length(Source));
29 while SourceIndex < Length(Source) do begin
30 Flag := Source[SourceIndex];
31 Inc(SourceIndex);
32
33 // Short move, relative
34 if ((Flag and $80) = 0) then begin
35 Size := (Flag shr 4) + 3;
36 Offset := ((Flag and $f) shl 8) or Source[SourceIndex];
37 Inc(SourceIndex);
38
39 // This decoder assumes memcpy. As some platforms implement memcpy as memmove, this is much safer
40 if (DestIndex + Size) >= Length(Result) then
41 SetLength(Result, DestIndex + Size + 1);
42 while Size > 0 do begin
43 Result[DestIndex] := Result[DestIndex - Offset];
44 Inc(DestIndex);
45 Dec(Size);
46 end;
47 Continue;
48 end;
49
50 // Exit
51 if (Flag = $80) then Break;
52
53 // Long set
54 if (Flag = $fe) then begin
55 Size := Source[SourceIndex] or (Source[SourceIndex + 1] shl 8);
56 Inc(SourceIndex, 2);
57
58 if (DestIndex + Size) >= Length(Result) then
59 SetLength(Result, DestIndex + Size + 1);
60 FillChar(Result[DestIndex], Size, Source[SourceIndex]);
61 Inc(SourceIndex);
62 Inc(DestIndex, Size);
63 Continue;
64 end;
65
66 // Long move, absolute
67 if (Flag = $ff) then begin
68 Size := Source[SourceIndex] or (Source[SourceIndex + 1] shl 8);
69 Inc(SourceIndex, 2);
70 Offset := Source[SourceIndex] or(Source[SourceIndex + 1] shl 8);
71 Inc(SourceIndex, 2);
72
73 if (DestIndex + Size) >= Length(Result) then
74 SetLength(Result, DestIndex + Size + 1);
75 // This decoder assumes memcpy. As some platforms implement memcpy as memmove, this is much safer
76 while Size > 0 do begin
77 Result[DestIndex] := Result[Offset];
78 Inc(DestIndex);
79 Inc(Offset);
80 Dec(Size);
81 end;
82 Continue;
83 end;
84
85 // Short move, absolute
86 if ((Flag and $40) <> 0) then begin
87 Size := (Flag and $3f) + 3;
88 Offset := Source[SourceIndex] or (Source[SourceIndex + 1] shl 8);
89 Inc(SourceIndex, 2);
90
91 // This decoder assumes memcpy. As some platforms implement memcpy as memmove, this is much safer
92 if (DestIndex + Size) >= Length(Result) then
93 SetLength(Result, DestIndex + Size + 1);
94 while Size > 0 do begin
95 Result[DestIndex] := Result[Offset];
96 Inc(DestIndex);
97 Inc(Offset);
98 Dec(Size);
99 end;
100 Continue;
101 end;
102
103 // Short copy
104 begin
105 Size := Flag and $3f;
106
107 // This decoder assumes memcpy. As some platforms implement memcpy as memmove, this is much safer
108 if (DestIndex + Size) >= Length(Result) then
109 SetLength(Result, DestIndex + Size + 1);
110 while Size > 0 do begin
111 Result[DestIndex] := Source[SourceIndex];
112 Inc(DestIndex);
113 Inc(SourceIndex);
114 Dec(Size);
115 end;
116 Continue;
117 end;
118 end;
119end;
120
121// XORDelta decoder
122function Format40(Source: TByteDynArray): TByteDynArray;
123var
124 Flag: Word;
125 SourceIndex: Integer;
126 DestIndex: Integer;
127begin
128 SourceIndex := 0;
129 DestIndex := 0;
130 SetLength(Result, Length(Source));
131 while True do begin
132 Flag := Source[SourceIndex];
133 Inc(SourceIndex);
134
135 if Flag = 0 then begin
136 Flag := Source[SourceIndex];
137 if (DestIndex + Flag) >= Length(Result) then
138 SetLength(Result, DestIndex + Flag + 1);
139 while Flag > 0 do begin
140 Result[DestIndex] := Result[DestIndex] xor Source[SourceIndex];
141 Inc(DestIndex);
142 Dec(Flag);
143 end;
144 Inc(SourceIndex);
145 Continue;
146 end;
147
148 if (Flag and $80) = 0 then begin
149 if (DestIndex + Flag) >= Length(Result) then
150 SetLength(Result, DestIndex + Flag + 1);
151 while Flag > 0 do begin
152 Result[DestIndex] := Result[DestIndex] xor Source[SourceIndex];
153 Inc(DestIndex);
154 Inc(SourceIndex);
155 Dec(Flag);
156 end;
157 Continue;
158 end;
159
160 if Flag <> $80 then begin
161 DestIndex := DestIndex + (Flag and $7F);
162 Continue;
163 end;
164
165 Flag := Source[SourceIndex] or (Source[SourceIndex] shl 8);
166 Inc(SourceIndex, 2);
167
168 if Flag = 0 then Break;
169
170 if (Flag and $8000) = 0 then begin
171 Inc(DestIndex, Flag);
172 Continue;
173 end;
174
175 if (Flag and $4000) = 0 then begin
176 Flag := Flag and $3FFF;
177 if (DestIndex + Flag) >= Length(Result) then
178 SetLength(Result, DestIndex + Flag + 1);
179 while Flag > 0 do begin
180 Result[DestIndex] := Result[DestIndex] xor Source[SourceIndex];
181 Inc(DestIndex);
182 Inc(SourceIndex);
183 Dec(Flag);
184 end;
185 Continue;
186 end;
187
188 Flag := Flag and $3FFF;
189 if (DestIndex + Flag) >= Length(Result) then
190 SetLength(Result, DestIndex + Flag + 1);
191 while Flag > 0 do begin
192 Result[DestIndex] := Result[DestIndex] xor Source[SourceIndex];
193 Inc(DestIndex);
194 Dec(Flag);
195 end;
196 Inc(SourceIndex);
197 Continue;
198 end;
199end;
200
201function Format20(Source: TByteDynArray): TByteDynArray;
202var
203 D: Byte;
204 Count: Integer;
205 SourceIndex: Integer;
206 DestIndex: Integer;
207begin
208 SourceIndex := 0;
209 DestIndex := 0;
210 SetLength(Result, Length(Source));
211 while SourceIndex < Length(Source) do begin
212 D := Source[SourceIndex];
213 Inc(SourceIndex);
214 if D = 0 then begin
215 if SourceIndex >= Length(Source) then
216 Break;
217 Count := Source[SourceIndex];
218 if Count = 0 then Break;
219 Inc(SourceIndex);
220 if (DestIndex + Count) >= Length(Result) then
221 SetLength(Result, DestIndex + Count + 1);
222 FillChar(Result[DestIndex], Count, 0);
223 Inc(DestIndex, Count);
224 end else begin
225 if DestIndex >= Length(Result) then
226 SetLength(Result, DestIndex + 1);
227 Result[DestIndex] := D;
228 Inc(DestIndex);
229 end;
230 end;
231end;
232
233
234end.
235
Note: See TracBrowser for help on using the repository browser.