saveload.c
changeset 2041 8b8899617403
parent 2026 02dfa0aa2c2f
child 2051 44b6b091beb3
equal deleted inserted replaced
2040:907b217a026a 2041:8b8899617403
   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;