Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
bchannel.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/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : W3D Tools *
24 * *
25 * $Archive:: /Commando/Code/Tools/max2w3d/bchannel.cpp $*
26 * *
27 * $Author:: Greg_h $*
28 * *
29 * $Modtime:: 10/30/00 5:25p $*
30 * *
31 * $Revision:: 6 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#include "bchannel.h"
38#include "w3d_file.h"
39#include "logdlg.h"
40#include "exportlog.h"
41
42
44(
45 uint32 id,
46 int maxframes,
47 uint32 chntype,
48 bool default_val
49) :
50 ID(id),
51 ChannelType(chntype),
52 MaxFrames(maxframes),
53 IsEmpty(true),
54 DefaultVal(default_val),
55 Data(maxframes),
56 Begin(0),
57 End(0)
58{
59 // start "Begin" at the end of the array, whenever we set a value
60 // at an index less than "Begin", we push "Begin" back.
61 Begin = MaxFrames;
62 End = 0;
63}
64
66{
67}
68
69void BitChannelClass::Set_Bit(int frameidx,bool bit)
70{
71 assert(frameidx >= 0);
72 assert(frameidx < MaxFrames);
73
74 Data[frameidx] = bit;
75
76 if (!is_default(bit)) {
77 IsEmpty = false;
78 }
79}
80
82{
83 for (int i=0; i<bits.Length(); i++) {
84 Set_Bit(i,bits[i]);
85 }
86}
87
88
89bool BitChannelClass::Get_Bit(int frameidx)
90{
91 assert(frameidx >= 0);
92 assert(frameidx < MaxFrames);
93
94 return Data[frameidx];
95}
96
97
98bool BitChannelClass::Save(ChunkSaveClass & csave, bool compress)
99{
100 if (IsEmpty) return true;
101
102 if (compress) {
103 // Save the Channel Data Compressed
104 // TIMECODED
106 return false;
107 }
108
109 uint32 channelsize = sizeof(W3dTimeCodedBitChannelStruct);
110 uint32 packetsize = sizeof(uint32);
111
112 channelsize += packetsize * MaxFrames;
113 channelsize -= sizeof(uint32);
114
115 W3dTimeCodedBitChannelStruct * chn = (W3dTimeCodedBitChannelStruct *)malloc(channelsize);
116
117 if (chn == NULL) {
118 return false;
119 }
120
121 chn->NumTimeCodes = MaxFrames;
122 chn->Pivot = ID;
123 chn->Flags = ChannelType;
124 chn->DefaultVal = DefaultVal;
125
126 // copy data into the channel struct, in timecoded raw format
127
128 for (uint32 fcount=0; fcount < chn->NumTimeCodes; fcount++) {
129
130 if (Get_Bit(fcount)) {
131 chn->Data[fcount] = fcount | W3D_TIMECODED_BIT_MASK;
132 }
133 else {
134 chn->Data[fcount] = fcount;
135 }
136 }
137
138 // Compress the new structure
139
140 BitChannelClass::compress( chn );
141
142 float originalchannelsize = channelsize;
143
144 // Update Channel Size
145 channelsize = sizeof(W3dTimeCodedBitChannelStruct);
146 channelsize += packetsize * chn->NumTimeCodes;
147 channelsize -= sizeof(uint32);
148
149 float percent = (((float) channelsize) / originalchannelsize) * 100.0f;
150
151 ExportLog::printf("%.0f", percent);
152
153
154 // save
155
156 if (csave.Write(chn,channelsize) != channelsize) {
157 return false;
158 }
159
160 if (chn != NULL) {
161 free(chn);
162 }
163
164 if (!csave.End_Chunk()) {
165 return false;
166 }
167
168 }
169 else {
170 // Stock Raw Save
172 return false;
173 }
174
175 compute_range();
176
177 int numbits = End - Begin + 1;
178 assert(numbits > 0);
179 int numbytes = (numbits + 7) / 8;
180
181 unsigned int channelsize = sizeof(W3dBitChannelStruct);
182 channelsize += numbytes - 1; // one byte inside the W3dBitChannelStruct...
183
184 W3dBitChannelStruct * chn = (W3dBitChannelStruct *)malloc(channelsize);
185
186 if (chn == NULL) {
187 return false;
188 }
189
190 chn->FirstFrame = Begin;
191 chn->LastFrame = End;
192 chn->Flags = ChannelType;
193 chn->Pivot = ID;
194 chn->DefaultVal = DefaultVal;
195
196 uint8 * bits = (uint8 *)&(chn->Data[0]);
197
198 for (int fcount=0; fcount < End-Begin+1; fcount++) {
199 ::Set_Bit(bits,fcount,Get_Bit(Begin + fcount));
200 }
201
202 if (csave.Write(chn,channelsize) != channelsize) {
203 return false;
204 }
205
206 if (chn != NULL) {
207 free(chn);
208 }
209
210 if (!csave.End_Chunk()) {
211 return false;
212 }
213
214 }
215
216 return true;
217}
218
219
220bool BitChannelClass::is_default(bool bit)
221{
222 return (bit == DefaultVal);
223}
224
225void BitChannelClass::compute_range(void)
226{
227 Begin = 0;
228 while ((Begin < MaxFrames) && (is_default(Get_Bit(Begin)))) {
229 Begin++;
230 }
231
232 End = MaxFrames-1;
233 while ((End >= 0) && (is_default(Get_Bit(End)))) {
234 End--;
235 }
236} // compute_range
237
238
239//
240// find a packet that isn't needed, and return the index
241// if all packets are necessary, then return back PACKETS_ALL_USEFUL
242// a useless packet is defined, as a packet that can be recreated
243//
244#define PACKETS_ALL_USEFUL (0xFFFFFFFF)
245//
246uint32 BitChannelClass::find_useless_packet(W3dTimeCodedBitChannelStruct * c)
247{
248
249 assert( c ); // make sure pointer exists
250 assert( c->NumTimeCodes ); // make sure some packets exist
251
252 if (c->NumTimeCodes > 2) {
253
254 for(uint32 try_idx = 0; try_idx < (c->NumTimeCodes - 1); try_idx++) {
255
256 if ((c->Data[try_idx] & W3D_TIMECODED_BIT_MASK) ==
257 (c->Data[try_idx+1] & W3D_TIMECODED_BIT_MASK)) {
258 return(try_idx + 1);
259 }
260
261 } // for
262 }
263
264 return( PACKETS_ALL_USEFUL );
265
266} // find_useless_packet
267
268
269//
270// Remove a packet from a W3dTimeCodedBitChannelStruct
271//
272void BitChannelClass::remove_packet(W3dTimeCodedBitChannelStruct * c, uint32 packet_idx)
273{
274 assert( c );
275 assert( c->NumTimeCodes > 1 );
276
277 uint32 packet_size = 1;
278 uint32 packet_len = packet_size * sizeof(uint32);
279
280 uint32 *src, *dst;
281
282 dst = (uint32 *) &c->Data[ packet_size * packet_idx ];
283 src = (uint32 *) &c->Data[ packet_size * (packet_idx + 1) ];
284
285 uint32 copy_length = (c->NumTimeCodes - (packet_idx + 1)) * packet_len;
286
287 if (copy_length) {
288
289 memcpy(dst, src, copy_length);
290
291 }
292
293 // Decrement Packet Count
294 c->NumTimeCodes--;
295
296} // remove_packet
297
298//
299// Take a non-compressed TimeCoded Bit Channel
300// and compress the packets
301//
302void BitChannelClass::compress(W3dTimeCodedBitChannelStruct * c)
303{
304 while(1) {
305
306 uint32 idx = find_useless_packet( c );
307
308 if (PACKETS_ALL_USEFUL == idx) break;
309
310 remove_packet( c, idx );
311
312 }
313
314} // compress
315
316
317
318
319// EOF - bchannel.cpp
#define NULL
Definition BaseType.h:92
#define W3D_TIMECODED_BIT_MASK
Definition w3d_file.h:1490
@ W3D_CHUNK_BIT_CHANNEL
Definition w3d_file.h:404
@ W3D_CHUNK_COMPRESSED_BIT_CHANNEL
Definition w3d_file.h:409
unsigned long uint32
Definition bittype.h:46
unsigned char uint8
Definition bittype.h:44
@ true
Definition bool.h:59
#define PACKETS_ALL_USEFUL
Definition bchannel.cpp:244
void Set_Bit(int framenumber, bool bit)
Definition bchannel.cpp:69
bool Save(ChunkSaveClass &csave, bool compress)
Definition bchannel.cpp:98
BitChannelClass(void)
Definition motchan.cpp:211
~BitChannelClass(void)
Definition motchan.cpp:234
void Set_Bits(BooleanVectorClass &bits)
Definition bchannel.cpp:81
WWINLINE int Get_Bit(int frame) const
Definition motchan.h:191
int Length(void)
Definition Vector.H:984
uint32 Write(const void *buf, uint32 nbytes)
Definition chunkio.cpp:264
bool Begin_Chunk(uint32 id)
Definition chunkio.cpp:108
bool End_Chunk()
Definition chunkio.cpp:148
static void printf(char *,...)
int percent
Definition patch.cpp:426