(svn r2522) Reorganize sprite load and decompression in order to remove a special case from the sprite blitter, which decompressed certain sprites every time when blitting them
This commit is contained in:
		
							
								
								
									
										32
									
								
								gfx.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								gfx.c
									
									
									
									
									
								
							@@ -1376,38 +1376,6 @@ static void GfxMainBlitter(const Sprite* sprite, int x, int y, int mode)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		bp.start_x = start_x;
 | 
							bp.start_x = start_x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (info&2) {
 | 
					 | 
				
			||||||
			int totpix = bp.height_org * bp.width_org;
 | 
					 | 
				
			||||||
			byte *dst = (byte*)alloca(totpix);
 | 
					 | 
				
			||||||
			const byte *src = bp.sprite_org;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			bp.sprite = dst + (bp.sprite - bp.sprite_org);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			while (totpix != 0) {
 | 
					 | 
				
			||||||
				signed char b;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				assert(totpix > 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				b = *src++;
 | 
					 | 
				
			||||||
				if (b >= 0) {
 | 
					 | 
				
			||||||
					uint count = b;
 | 
					 | 
				
			||||||
					uint i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					for (i = 0; i != count; i++) dst[i] = src[i];
 | 
					 | 
				
			||||||
					dst += count;
 | 
					 | 
				
			||||||
					src += count;
 | 
					 | 
				
			||||||
					totpix -= count;
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					const byte *tmp = dst - (((b & 7) << 8) | *src++);
 | 
					 | 
				
			||||||
					uint count = -(b >> 3);
 | 
					 | 
				
			||||||
					uint i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					for (i = 0; i != count; i++) dst[i] = tmp[i];
 | 
					 | 
				
			||||||
					dst += count;
 | 
					 | 
				
			||||||
					totpix -= count;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		zf_uncomp[dpi->zoom](&bp);
 | 
							zf_uncomp[dpi->zoom](&bp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,7 @@ uint16 _custom_sprites_base;
 | 
				
			|||||||
static Sprite _cur_sprite;
 | 
					static Sprite _cur_sprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static byte *_sprite_ptr[NUM_SPRITES];
 | 
					static void* _sprite_ptr[NUM_SPRITES];
 | 
				
			||||||
static uint16 _sprite_size[NUM_SPRITES];
 | 
					static uint16 _sprite_size[NUM_SPRITES];
 | 
				
			||||||
static uint32 _sprite_file_pos[NUM_SPRITES];
 | 
					static uint32 _sprite_file_pos[NUM_SPRITES];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,11 +148,14 @@ static void ReadSpriteHeaderSkipData(int num, int load_index)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ReadSprite(SpriteID id, void *buffer)
 | 
					static void* AllocSprite(size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void* ReadSprite(SpriteID id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint num = _sprite_size[id];
 | 
						uint num = _sprite_size[id];
 | 
				
			||||||
	byte type;
 | 
						byte type;
 | 
				
			||||||
	byte* dest;
 | 
					
 | 
				
			||||||
 | 
						DEBUG(spritecache, 9) ("load sprite %d", id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_sprite_file_pos[id] == 0) {
 | 
						if (_sprite_file_pos[id] == 0) {
 | 
				
			||||||
		error(
 | 
							error(
 | 
				
			||||||
@@ -165,43 +168,46 @@ static void ReadSprite(SpriteID id, void *buffer)
 | 
				
			|||||||
	FioSeekToFile(_sprite_file_pos[id]);
 | 
						FioSeekToFile(_sprite_file_pos[id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type = FioReadByte();
 | 
						type = FioReadByte();
 | 
				
			||||||
	/* We've decoded special sprites when reading headers. */
 | 
						if (type == 0xFF) {
 | 
				
			||||||
	if (type != 0xFF) {
 | 
							byte* dest = AllocSprite(num);
 | 
				
			||||||
		/* read sprite hdr */
 | 
					
 | 
				
			||||||
		Sprite* sprite = buffer;
 | 
							_sprite_ptr[id] = dest;
 | 
				
			||||||
 | 
							FioReadBlock(dest, num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return dest;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							uint height = FioReadByte();
 | 
				
			||||||
 | 
							uint width  = FioReadWord();
 | 
				
			||||||
 | 
							Sprite* sprite;
 | 
				
			||||||
 | 
							byte* dest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							num = (type & 0x02) ? width * height : num - 8;
 | 
				
			||||||
 | 
							sprite = AllocSprite(sizeof(*sprite) + num);
 | 
				
			||||||
 | 
							_sprite_ptr[id] = sprite;
 | 
				
			||||||
		sprite->info   = type;
 | 
							sprite->info   = type;
 | 
				
			||||||
		sprite->height = FioReadByte();
 | 
							sprite->height = (id != 142) ? height : 10;
 | 
				
			||||||
		if (id == 142) sprite->height = 10; // Compensate for a TTD bug
 | 
							sprite->width  = width;
 | 
				
			||||||
		sprite->width = FioReadWord();
 | 
					 | 
				
			||||||
		sprite->x_offs = FioReadWord();
 | 
							sprite->x_offs = FioReadWord();
 | 
				
			||||||
		sprite->y_offs = FioReadWord();
 | 
							sprite->y_offs = FioReadWord();
 | 
				
			||||||
		dest = sprite->data;
 | 
					 | 
				
			||||||
		num -= 8;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		dest = buffer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (type & 2) {
 | 
							dest = sprite->data;
 | 
				
			||||||
		for (; num > 0; --num)
 | 
					 | 
				
			||||||
			*dest++ = FioReadByte();
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		while (num > 0) {
 | 
							while (num > 0) {
 | 
				
			||||||
			int8 i = FioReadByte();
 | 
								int8 i = FioReadByte();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (i >= 0) {
 | 
								if (i >= 0) {
 | 
				
			||||||
				num -= i;
 | 
									num -= i;
 | 
				
			||||||
				for (; i > 0; --i)
 | 
									for (; i > 0; --i) *dest++ = FioReadByte();
 | 
				
			||||||
					*dest++ = FioReadByte();
 | 
					 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
 | 
									const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				i = -(i >> 3);
 | 
									i = -(i >> 3);
 | 
				
			||||||
				num -= i;
 | 
									num -= i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for (; i > 0; --i)
 | 
									for (; i > 0; --i) *dest++ = *rel++;
 | 
				
			||||||
					*dest++ = *rel++;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return sprite;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -499,7 +505,7 @@ static void CompactSpriteCache(void)
 | 
				
			|||||||
		if (s->size & S_FREE_MASK) {
 | 
							if (s->size & S_FREE_MASK) {
 | 
				
			||||||
			MemBlock* next = NextBlock(s);
 | 
								MemBlock* next = NextBlock(s);
 | 
				
			||||||
			MemBlock temp;
 | 
								MemBlock temp;
 | 
				
			||||||
			byte** i;
 | 
								void** i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Since free blocks are automatically coalesced, this should hold true.
 | 
								// Since free blocks are automatically coalesced, this should hold true.
 | 
				
			||||||
			assert(!(next->size & S_FREE_MASK));
 | 
								assert(!(next->size & S_FREE_MASK));
 | 
				
			||||||
@@ -606,14 +612,9 @@ static void DeleteEntryFromSpriteCache(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static byte *LoadSpriteToMem(SpriteID sprite)
 | 
					static void* AllocSprite(size_t mem_req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t mem_req;
 | 
						mem_req += sizeof(MemBlock);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	DEBUG(spritecache, 9) ("load sprite %d", sprite);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Number of needed bytes
 | 
					 | 
				
			||||||
	mem_req = sizeof(MemBlock) + _sprite_size[sprite];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Align this to an uint32 boundary. This also makes sure that the 2 least
 | 
						/* Align this to an uint32 boundary. This also makes sure that the 2 least
 | 
				
			||||||
	 * bits are not used, so we could use those for other things. */
 | 
						 * bits are not used, so we could use those for other things. */
 | 
				
			||||||
@@ -638,11 +639,6 @@ static byte *LoadSpriteToMem(SpriteID sprite)
 | 
				
			|||||||
						NextBlock(s)->size = (cur_size - mem_req) | S_FREE_MASK;
 | 
											NextBlock(s)->size = (cur_size - mem_req) | S_FREE_MASK;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					_sprite_ptr[sprite] = s->data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					ReadSprite(sprite, s->data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					// Return sprite ptr
 | 
					 | 
				
			||||||
					return s->data;
 | 
										return s->data;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -698,7 +694,7 @@ static uint RotateSprite(uint s)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const void *GetRawSprite(SpriteID sprite)
 | 
					const void *GetRawSprite(SpriteID sprite)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	byte *p;
 | 
						void* p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	assert(sprite < NUM_SPRITES);
 | 
						assert(sprite < NUM_SPRITES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -714,10 +710,9 @@ const void *GetRawSprite(SpriteID sprite)
 | 
				
			|||||||
	_sprite_lru[sprite] = 0;
 | 
						_sprite_lru[sprite] = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check if the sprite is loaded already?
 | 
					 | 
				
			||||||
	p = _sprite_ptr[sprite];
 | 
						p = _sprite_ptr[sprite];
 | 
				
			||||||
	if (p == NULL)
 | 
						// Load the sprite, if it is not loaded, yet
 | 
				
			||||||
		p = LoadSpriteToMem(sprite);  // No, need to load it.
 | 
						if (p == NULL) p = ReadSprite(sprite);
 | 
				
			||||||
	return p;
 | 
						return p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@ typedef struct Sprite {
 | 
				
			|||||||
	int16 y_offs;
 | 
						int16 y_offs;
 | 
				
			||||||
	byte data[VARARRAY_SIZE];
 | 
						byte data[VARARRAY_SIZE];
 | 
				
			||||||
} Sprite;
 | 
					} Sprite;
 | 
				
			||||||
assert_compile(sizeof(Sprite) == 8);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
	int xoffs, yoffs;
 | 
						int xoffs, yoffs;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user