150 */ |
150 */ |
151 static uint SlReadSimpleGamma(void) |
151 static uint SlReadSimpleGamma(void) |
152 { |
152 { |
153 uint i = SlReadByte(); |
153 uint i = SlReadByte(); |
154 if (HASBIT(i, 7)) { |
154 if (HASBIT(i, 7)) { |
155 i = (i << 8) + SlReadByte(); |
155 i &= ~0x80; |
156 CLRBIT(i, 15); |
156 if (HASBIT(i, 6)) { |
|
157 i &= ~0x40; |
|
158 if (HASBIT(i, 5)) { |
|
159 i &= ~0x20; |
|
160 if (HASBIT(i, 4)) |
|
161 SlError("Unsupported gamma"); |
|
162 i = (i << 8) | SlReadByte(); |
|
163 } |
|
164 i = (i << 8) | SlReadByte(); |
|
165 } |
|
166 i = (i << 8) | SlReadByte(); |
157 } |
167 } |
158 return i; |
168 return i; |
159 } |
169 } |
160 |
170 |
161 /** |
171 /** |
162 * Write the header descriptor of an object or an array. |
172 * Write the header descriptor of an object or an array. |
163 * If the element is bigger than 127, use 2 bytes for saving |
173 * If the element is bigger than 127, use 2 bytes for saving |
164 * and use the highest byte of the first written one as a notice |
174 * and use the highest byte of the first written one as a notice |
165 * that the length consists of 2 bytes. The length is fixed to a |
175 * that the length consists of 2 bytes, etc.. like this: |
166 * maximum of 16384 since any higher value will have bit 15 set |
176 * 0xxxxxxx |
167 * and the notice, would obfuscate the real value |
177 * 10xxxxxx xxxxxxxx |
|
178 * 110xxxxx xxxxxxxx xxxxxxxx |
|
179 * 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx |
168 * @param i Index being written |
180 * @param i Index being written |
169 * @todo the maximum of 16384 can easily be reached with vehicles, so raise this artificial limit |
181 */ |
170 */ |
182 |
171 static void SlWriteSimpleGamma(uint i) |
183 static void SlWriteSimpleGamma(uint i) |
172 { |
184 { |
173 assert(i < (1 << 14)); |
|
174 |
|
175 if (i >= (1 << 7)) { |
185 if (i >= (1 << 7)) { |
176 SlWriteByte((byte)((1 << 7) | (i >> 8))); |
186 if (i >= (1 << 14)) { |
177 SlWriteByte((byte)i); |
187 if (i >= (1 << 21)) { |
178 } else |
188 assert(i < (1 << 28)); |
179 SlWriteByte(i); |
189 SlWriteByte((byte)0xE0 | (i>>24)); |
180 } |
190 SlWriteByte((byte)(i>>16)); |
181 |
191 } else { |
182 /** Return if the length will use up 1 or two bytes in a savegame */ |
192 SlWriteByte((byte)0xC0 | (i>>16)); |
183 static inline uint SlGetGammaLength(uint i) {return (i >= (1 << 7)) ? 2 : 1;} |
193 } |
|
194 SlWriteByte((byte)(i>>8)); |
|
195 } else { |
|
196 SlWriteByte((byte)(0x80 | (i>>8))); |
|
197 } |
|
198 } |
|
199 SlWriteByte(i); |
|
200 } |
|
201 |
|
202 /** Return how many bytes used to encode a gamma value */ |
|
203 static inline uint SlGetGammaLength(uint i) { |
|
204 return 1 + (i >= (1 << 7)) + (i >= (1 << 14)) + (i >= (1 << 21)); |
|
205 } |
184 |
206 |
185 static inline int SlReadSparseIndex(void) {return SlReadSimpleGamma();} |
207 static inline int SlReadSparseIndex(void) {return SlReadSimpleGamma();} |
186 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);} |
208 static inline void SlWriteSparseIndex(uint index) {SlWriteSimpleGamma(index);} |
187 |
209 |
188 static inline int SlReadArrayLength(void) {return SlReadSimpleGamma();} |
210 static inline int SlReadArrayLength(void) {return SlReadSimpleGamma();} |
239 switch (_sl.need_length) { |
261 switch (_sl.need_length) { |
240 case NL_WANTLENGTH: |
262 case NL_WANTLENGTH: |
241 _sl.need_length = NL_NONE; |
263 _sl.need_length = NL_NONE; |
242 switch (_sl.block_mode) { |
264 switch (_sl.block_mode) { |
243 case CH_RIFF: |
265 case CH_RIFF: |
244 // Really simple to write a RIFF length :) |
266 // Ugly encoding of >16M RIFF chunks |
245 SlWriteUint32(length); |
267 // The lower 24 bits are normal |
|
268 // The uppermost 4 bits are bits 24:27 |
|
269 assert(length < (1<<28)); |
|
270 SlWriteUint32((length & 0xFFFFFF) | ((length >> 24) << 28)); |
246 break; |
271 break; |
247 case CH_ARRAY: |
272 case CH_ARRAY: |
248 assert(_sl.last_array_index <= _sl.array_index); |
273 assert(_sl.last_array_index <= _sl.array_index); |
249 while (++_sl.last_array_index <= _sl.array_index) |
274 while (++_sl.last_array_index <= _sl.array_index) |
250 SlWriteArrayLength(1); |
275 SlWriteArrayLength(1); |
612 ch->load_proc(); |
637 ch->load_proc(); |
613 break; |
638 break; |
614 case CH_SPARSE_ARRAY: |
639 case CH_SPARSE_ARRAY: |
615 ch->load_proc(); |
640 ch->load_proc(); |
616 break; |
641 break; |
617 case CH_RIFF: |
642 default: |
618 // Read length |
643 if ((m & 0xF) == CH_RIFF) { |
619 len = SlReadByte() << 16; |
644 // Read length |
620 len += SlReadUint16(); |
645 len = (SlReadByte() << 16) | ((m >> 4) << 24); |
621 _sl.obj_len = len; |
646 len += SlReadUint16(); |
622 endoffs = SlGetOffs() + len; |
647 _sl.obj_len = len; |
623 ch->load_proc(); |
648 endoffs = SlGetOffs() + len; |
624 assert(SlGetOffs() == endoffs); |
649 ch->load_proc(); |
|
650 assert(SlGetOffs() == endoffs); |
|
651 } else { |
|
652 SlError("Invalid chunk type"); |
|
653 } |
625 break; |
654 break; |
626 default: NOT_REACHED(); |
|
627 } |
655 } |
628 } |
656 } |
629 |
657 |
630 /* Stub Chunk handlers to only calculate length and do nothing else */ |
658 /* Stub Chunk handlers to only calculate length and do nothing else */ |
631 static ChunkSaveLoadProc *_tmp_proc_1; |
659 static ChunkSaveLoadProc *_tmp_proc_1; |