changeset 19036:ca6c588c2baa draft

(svn r23893) -Change: [NewGRF] Extended chunked sprite encoding to work for bigger sprites.
author michi_cc <michi_cc@openttd.org>
date Sat, 04 Feb 2012 19:21:32 +0000
parents 9b9d6d0f3a48
children 3ddfadaa6d86
files src/spriteloader/grf.cpp
diffstat 1 files changed, 29 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/spriteloader/grf.cpp
+++ b/src/spriteloader/grf.cpp
@@ -61,9 +61,10 @@
  * @param num Size of the decompressed sprite.
  * @param type Type of the encoded sprite.
  * @param zoom_lvl Requested zoom level.
+ * @param container_format Container format of the GRF this sprite is in.
  * @return True if the sprite was successfully loaded.
  */
-bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, int64 num, byte type, ZoomLevel zoom_lvl)
+bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type, int64 num, byte type, ZoomLevel zoom_lvl, byte container_format)
 {
 	AutoFreePtr<byte> dest_orig(MallocT<byte>(num));
 	byte *dest = dest_orig;
@@ -105,24 +106,40 @@
 		for (int y = 0; y < sprite->height; y++) {
 			bool last_item = false;
 			/* Look up in the header-table where the real data is stored for this row */
-			int offset = (dest_orig[y * 2 + 1] << 8) | dest_orig[y * 2];
+			int offset;
+			if (container_format >= 2 && num > UINT16_MAX) {
+				offset = (dest_orig[y * 4 + 3] << 24) | (dest_orig[y * 4 + 2] << 16) | (dest_orig[y * 4 + 1] << 8) | dest_orig[y * 4];
+			} else {
+				offset = (dest_orig[y * 2 + 1] << 8) | dest_orig[y * 2];
+			}
 
 			/* Go to that row */
 			dest = dest_orig + offset;
 
 			do {
-				if (dest + 2 > dest_orig + dest_size) {
+				if (dest + (container_format >= 2 && sprite->width > 256 ? 4 : 2) > dest_orig + dest_size) {
 					return WarnCorruptSprite(file_slot, file_pos, __LINE__);
 				}
 
 				SpriteLoader::CommonPixel *data;
-				/* Read the header:
-				 *  0 .. 14  - length
-				 *  15       - last_item
-				 *  16 .. 31 - transparency bytes */
-				last_item  = ((*dest) & 0x80) != 0;
-				int length =  (*dest++) & 0x7F;
-				int skip   =   *dest++;
+				/* Read the header. */
+				int length, skip;
+				if (container_format >= 2 && sprite->width > 256) {
+					/*  0 .. 14  - length
+					 *  15       - last_item
+					 *  16 .. 31 - transparency bytes */
+					last_item = (dest[1] & 0x80) != 0;
+					length    = ((dest[1] & 0x7F) << 8) | dest[0];
+					skip      = (dest[3] << 8) | dest[2];
+					dest += 4;
+				} else {
+					/*  0 .. 6  - length
+					 *  7       - last_item
+					 *  8 .. 15 - transparency bytes */
+					last_item  = ((*dest) & 0x80) != 0;
+					length =  (*dest++) & 0x7F;
+					skip   =   *dest++;
+				}
 
 				data = &sprite->data[y * sprite->width + skip];
 
@@ -194,7 +211,7 @@
 	 * In case it is uncompressed, the size is 'num' - 8 (header-size). */
 	num = (type & 0x02) ? sprite[zoom_lvl].width * sprite[zoom_lvl].height : num - 8;
 
-	if (DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, num, type, zoom_lvl)) return 1 << zoom_lvl;
+	if (DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, num, type, zoom_lvl, 1)) return 1 << zoom_lvl;
 
 	return 0;
 }
@@ -245,7 +262,7 @@
 			 * otherwise we can calculate it from the image dimensions. */
 			uint decomp_size = (type & 0x08) ? FioReadDword() : sprite[zoom_lvl].width * sprite[zoom_lvl].height;
 
-			bool valid = DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, decomp_size, type, zoom_lvl);
+			bool valid = DecodeSingleSprite(&sprite[zoom_lvl], file_slot, file_pos, sprite_type, decomp_size, type, zoom_lvl, 2);
 			if (FioGetPos() != start_pos + num) {
 				WarnCorruptSprite(file_slot, file_pos, __LINE__);
 				return 0;