Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
refencode.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19// Copyright (C) Electronic Arts Canada Inc. 1995-2002. All rights reserved.
20
21#ifndef __REFWRITE
22#define __REFWRITE 1
23
24#include <string.h>
25#include "codex.h"
26#include "refcodex.h"
27
28/****************************************************************/
29/* Internal Functions */
30/****************************************************************/
31
32static unsigned int matchlen(unsigned char *s,unsigned char *d, unsigned int maxmatch)
33{
34 unsigned int current;
35
36 for (current=0; current<maxmatch && *s++==*d++; ++current)
37 ;
38
39 return(current);
40}
41
42#define HASH(cptr) (int)((((unsigned int)(unsigned char)cptr[0]<<8) | ((unsigned int)(unsigned char)cptr[2])) ^ ((unsigned int)(unsigned char)cptr[1]<<4))
43
44static int refcompress(unsigned char *from, int len, unsigned char *dest, int maxback, int quick)
45{
46 unsigned int tlen;
47 unsigned int tcost;
48// unsigned int ccost; // context cost
49 unsigned int run;
50 unsigned int toffset;
51 unsigned int boffset;
52 unsigned int blen;
53 unsigned int bcost;
54 unsigned int mlen;
55 unsigned char *tptr;
56 unsigned char *cptr;
57 unsigned char *to;
58 unsigned char *rptr;
59 int countliterals=0;
60 int countshort=0;
61 int countint=0;
62 int countvint=0;
63 int hash;
64 int hoffset;
65 int minhoffset;
66 int i;
67 int *link;
68 int *hashtbl;
69
70 to = dest;
71 run = 0;
72 cptr = rptr = from;
73
74 if ((unsigned int)maxback > (unsigned int)131071)
75 maxback = 131071;
76
77 hashtbl = (int *) galloc(65536L*sizeof(int));
78 if (!hashtbl)
79 return(0);
80 link = (int *) galloc(131072L*sizeof(int));
81 if (!link)
82 return(0);
83
84 memset(hashtbl,-1,65536L*sizeof(int));
85
86 len -= 4;
87 while (len>=0)
88 {
89 boffset = 0;
90 blen = 2;
91 bcost = 2;
92// ccost = 0;
93 mlen = qmin(len,1028);
94 tptr=cptr-1;
95 hash = HASH(cptr);
96 hoffset = hashtbl[hash];
97 minhoffset = qmax(cptr-from-131071,0);
98
99
100 if (hoffset>=minhoffset)
101 {
102 do
103 {
104 tptr = from+hoffset;
105 if (cptr[blen]==tptr[blen])
106 {
107 tlen = matchlen(cptr,tptr,mlen);
108 if (tlen > blen)
109 {
110 toffset = (cptr-1)-tptr;
111 if (toffset<1024 && tlen<=10) /* two byte int form */
112 tcost = 2;
113 else if (toffset<16384 && tlen<=67) /* three byte int form */
114 tcost = 3;
115 else /* four byte very int form */
116 tcost = 4;
117
118 if (tlen-tcost+4 > blen-bcost+4)
119 {
120 blen = tlen;
121 bcost = tcost;
122 boffset = toffset;
123 if (blen>=1028) break;
124 }
125 }
126 }
127 } while ((hoffset = link[hoffset&131071]) >= minhoffset);
128 }
129
130// ccost = 0;
131// if ((run<4) && ((run+blen)>=4))
132// ccost = 1; // extra packet cost to switch out of literal into reference
133
134// if (bcost>blen || (blen<=2 && bcost==blen && !ccost) || (len<4))
135 if (bcost>=blen || len<4)
136 {
137 hoffset = (cptr-from);
138 link[hoffset&131071] = hashtbl[hash];
139 hashtbl[hash] = hoffset;
140
141 ++run;
142 ++cptr;
143 --len;
144 }
145 else
146 {
147 while (run>3) /* literal block of data */
148 {
149 tlen = qmin(112,run&~3);
150 run -= tlen;
151 *to++ = (unsigned char) (0xe0+(tlen>>2)-1);
152 memcpy(to,rptr,tlen);
153 rptr += tlen;
154 to += tlen;
155 ++countliterals;
156 }
157 if (bcost==2) /* two byte int form */
158 {
159 *to++ = (unsigned char) (((boffset>>8)<<5) + ((blen-3)<<2) + run);
160 *to++ = (unsigned char) boffset;
161 ++countshort;
162 }
163 else if (bcost==3) /* three byte int form */
164 {
165 *to++ = (unsigned char) (0x80 + (blen-4));
166 *to++ = (unsigned char) ((run<<6) + (boffset>>8));
167 *to++ = (unsigned char) boffset;
168 ++countint;
169 }
170 else /* four byte very int form */
171 {
172 *to++ = (unsigned char) (0xc0 + ((boffset>>16)<<4) + (((blen-5)>>8)<<2) + run);
173 *to++ = (unsigned char) (boffset>>8);
174 *to++ = (unsigned char) (boffset);
175 *to++ = (unsigned char) (blen-5);
176 ++countvint;
177 }
178 if (run)
179 {
180 memcpy(to, rptr, run);
181 to += run;
182 run = 0;
183 }
184
185 if (quick)
186 {
187 hoffset = (cptr-from);
188 link[hoffset&131071] = hashtbl[hash];
189 hashtbl[hash] = hoffset;
190 cptr += blen;
191 }
192 else
193 {
194 for (i=0; i < (int)blen; ++i)
195 {
196 hash = HASH(cptr);
197 hoffset = (cptr-from);
198 link[hoffset&131071] = hashtbl[hash];
199 hashtbl[hash] = hoffset;
200 ++cptr;
201 }
202 }
203
204 rptr = cptr;
205 len -= blen;
206 }
207 }
208 len += 4;
209 run += len;
210 while (run>3) /* no match at end, use literal */
211 {
212 tlen = qmin(112,run&~3);
213 run -= tlen;
214 *to++ = (unsigned char) (0xe0+(tlen>>2)-1);
215 memcpy(to,rptr,tlen);
216 rptr += tlen;
217 to += tlen;
218 }
219
220 *to++ = (unsigned char) (0xfc+run); /* end of stream command + 0..3 literal */
221 if (run)
222 {
223 memcpy(to,rptr,run);
224 to += run;
225 }
226
227 gfree(link);
228 gfree(hashtbl);
229 return(to-dest);
230}
231
232
233/****************************************************************/
234/* Encode Function */
235/****************************************************************/
236
237int GCALL REF_encode(void *compresseddata, const void *source, int sourcesize, int *opts)
238{
239 int maxback=131072;
240 int quick=0;
241 int plen;
242 int hlen;
243
244
245 /* simple fb6 header */
246
247 if (sourcesize>0xffffff) // 32 bit header required
248 {
249 gputm(compresseddata, (unsigned int) 0x90fb, 2);
250 gputm((char *)compresseddata+2, (unsigned int) sourcesize, 4);
251 hlen = 6L;
252 }
253 else
254 {
255 gputm(compresseddata, (unsigned int) 0x10fb, 2);
256 gputm((char *)compresseddata+2, (unsigned int) sourcesize, 3);
257 hlen = 5L;
258 }
259 plen = hlen+refcompress((unsigned char *)source, sourcesize, (unsigned char *)compresseddata+hlen, maxback, quick);
260 return(plen);
261}
262
263#endif
264
#define gfree
Definition gimex.h:360
#define galloc
Definition gimex.h:356
#define GCALL
Definition codex.h:81
#define qmax(a, b)
Definition huffcodex.h:67
#define qmin(a, b)
Definition huffcodex.h:63
#define HASH(cptr)
Definition refencode.cpp:42
int GCALL REF_encode(void *compresseddata, const void *source, int sourcesize, int *opts)