spritecache.c
changeset 2014 0230ed9186bc
parent 1891 92a3b0aa0946
child 2015 3eec709611f8
equal deleted inserted replaced
2013:1b80954e9594 2014:0230ed9186bc
    29 static int _skip_specials;
    29 static int _skip_specials;
    30 uint16 _custom_sprites_base;
    30 uint16 _custom_sprites_base;
    31 static Sprite _cur_sprite;
    31 static Sprite _cur_sprite;
    32 
    32 
    33 
    33 
    34 static byte *_sprite_ptr[NUM_SPRITES];
    34 static void* _sprite_ptr[NUM_SPRITES];
    35 static uint16 _sprite_size[NUM_SPRITES];
    35 static uint16 _sprite_size[NUM_SPRITES];
    36 static uint32 _sprite_file_pos[NUM_SPRITES];
    36 static uint32 _sprite_file_pos[NUM_SPRITES];
    37 
    37 
    38 // This one is probably not needed.
    38 // This one is probably not needed.
    39 #if defined(WANT_LOCKED)
    39 #if defined(WANT_LOCKED)
   146 			}
   146 			}
   147 		}
   147 		}
   148 	}
   148 	}
   149 }
   149 }
   150 
   150 
   151 static void ReadSprite(SpriteID id, void *buffer)
   151 static void* AllocSprite(size_t);
       
   152 
       
   153 static void* ReadSprite(SpriteID id)
   152 {
   154 {
   153 	uint num = _sprite_size[id];
   155 	uint num = _sprite_size[id];
   154 	byte type;
   156 	byte type;
   155 	byte* dest;
   157 
       
   158 	DEBUG(spritecache, 9) ("load sprite %d", id);
   156 
   159 
   157 	if (_sprite_file_pos[id] == 0) {
   160 	if (_sprite_file_pos[id] == 0) {
   158 		error(
   161 		error(
   159 			"Tried to load non-existing sprite #%d.\n"
   162 			"Tried to load non-existing sprite #%d.\n"
   160 			"Probable cause: Wrong/missing NewGRFs",
   163 			"Probable cause: Wrong/missing NewGRFs",
   163 	}
   166 	}
   164 
   167 
   165 	FioSeekToFile(_sprite_file_pos[id]);
   168 	FioSeekToFile(_sprite_file_pos[id]);
   166 
   169 
   167 	type = FioReadByte();
   170 	type = FioReadByte();
   168 	/* We've decoded special sprites when reading headers. */
   171 	if (type == 0xFF) {
   169 	if (type != 0xFF) {
   172 		byte* dest = AllocSprite(num);
   170 		/* read sprite hdr */
   173 
   171 		Sprite* sprite = buffer;
   174 		_sprite_ptr[id] = dest;
   172 		sprite->info = type;
   175 		FioReadBlock(dest, num);
   173 		sprite->height = FioReadByte();
   176 
   174 		if (id == 142) sprite->height = 10; // Compensate for a TTD bug
   177 		return dest;
   175 		sprite->width = FioReadWord();
   178 	} else {
       
   179 		uint height = FioReadByte();
       
   180 		uint width  = FioReadWord();
       
   181 		Sprite* sprite;
       
   182 		byte* dest;
       
   183 
       
   184 		num = (type & 0x02) ? width * height : num - 8;
       
   185 		sprite = AllocSprite(sizeof(*sprite) + num);
       
   186 		_sprite_ptr[id] = sprite;
       
   187 		sprite->info   = type;
       
   188 		sprite->height = (id != 142) ? height : 10;
       
   189 		sprite->width  = width;
   176 		sprite->x_offs = FioReadWord();
   190 		sprite->x_offs = FioReadWord();
   177 		sprite->y_offs = FioReadWord();
   191 		sprite->y_offs = FioReadWord();
       
   192 
   178 		dest = sprite->data;
   193 		dest = sprite->data;
   179 		num -= 8;
       
   180 	} else {
       
   181 		dest = buffer;
       
   182 	}
       
   183 
       
   184 	if (type & 2) {
       
   185 		for (; num > 0; --num)
       
   186 			*dest++ = FioReadByte();
       
   187 	} else {
       
   188 		while (num > 0) {
   194 		while (num > 0) {
   189 			int8 i = FioReadByte();
   195 			int8 i = FioReadByte();
   190 
   196 
   191 			if (i >= 0) {
   197 			if (i >= 0) {
   192 				num -= i;
   198 				num -= i;
   193 				for (; i > 0; --i)
   199 				for (; i > 0; --i) *dest++ = FioReadByte();
   194 					*dest++ = FioReadByte();
       
   195 			} else {
   200 			} else {
   196 				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
   201 				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
   197 
   202 
   198 				i = -(i >> 3);
   203 				i = -(i >> 3);
   199 				num -= i;
   204 				num -= i;
   200 
   205 
   201 				for (; i > 0; --i)
   206 				for (; i > 0; --i) *dest++ = *rel++;
   202 					*dest++ = *rel++;
       
   203 			}
   207 			}
   204 		}
   208 		}
       
   209 
       
   210 		return sprite;
   205 	}
   211 	}
   206 }
   212 }
   207 
   213 
   208 
   214 
   209 static bool LoadNextSprite(int load_index, byte file_index)
   215 static bool LoadNextSprite(int load_index, byte file_index)
   497 
   503 
   498 	for (s = _spritecache_ptr; s->size != 0;) {
   504 	for (s = _spritecache_ptr; s->size != 0;) {
   499 		if (s->size & S_FREE_MASK) {
   505 		if (s->size & S_FREE_MASK) {
   500 			MemBlock* next = NextBlock(s);
   506 			MemBlock* next = NextBlock(s);
   501 			MemBlock temp;
   507 			MemBlock temp;
   502 			byte** i;
   508 			void** i;
   503 
   509 
   504 			// Since free blocks are automatically coalesced, this should hold true.
   510 			// Since free blocks are automatically coalesced, this should hold true.
   505 			assert(!(next->size & S_FREE_MASK));
   511 			assert(!(next->size & S_FREE_MASK));
   506 
   512 
   507 			// If the next block is the sentinel block, we can safely return
   513 			// If the next block is the sentinel block, we can safely return
   604 			}
   610 			}
   605 		}
   611 		}
   606 	}
   612 	}
   607 }
   613 }
   608 
   614 
   609 static byte *LoadSpriteToMem(SpriteID sprite)
   615 static void* AllocSprite(size_t mem_req)
   610 {
   616 {
   611 	size_t mem_req;
   617 	mem_req += sizeof(MemBlock);
   612 
       
   613 	DEBUG(spritecache, 9) ("load sprite %d", sprite);
       
   614 
       
   615 	// Number of needed bytes
       
   616 	mem_req = sizeof(MemBlock) + _sprite_size[sprite];
       
   617 
   618 
   618 	/* Align this to an uint32 boundary. This also makes sure that the 2 least
   619 	/* Align this to an uint32 boundary. This also makes sure that the 2 least
   619 	 * bits are not used, so we could use those for other things. */
   620 	 * bits are not used, so we could use those for other things. */
   620 	mem_req = (mem_req + sizeof(uint32) - 1) & ~(sizeof(uint32) - 1);
   621 	mem_req = (mem_req + sizeof(uint32) - 1) & ~(sizeof(uint32) - 1);
   621 
   622 
   636 					// Do we need to inject a free block too?
   637 					// Do we need to inject a free block too?
   637 					if (cur_size != mem_req) {
   638 					if (cur_size != mem_req) {
   638 						NextBlock(s)->size = (cur_size - mem_req) | S_FREE_MASK;
   639 						NextBlock(s)->size = (cur_size - mem_req) | S_FREE_MASK;
   639 					}
   640 					}
   640 
   641 
   641 					_sprite_ptr[sprite] = s->data;
       
   642 
       
   643 					ReadSprite(sprite, s->data);
       
   644 
       
   645 					// Return sprite ptr
       
   646 					return s->data;
   642 					return s->data;
   647 				}
   643 				}
   648 			}
   644 			}
   649 		}
   645 		}
   650 
   646 
   696 }
   692 }
   697 #endif
   693 #endif
   698 
   694 
   699 const void *GetRawSprite(SpriteID sprite)
   695 const void *GetRawSprite(SpriteID sprite)
   700 {
   696 {
   701 	byte *p;
   697 	void* p;
   702 
   698 
   703 	assert(sprite < NUM_SPRITES);
   699 	assert(sprite < NUM_SPRITES);
   704 
   700 
   705 #if defined(NEW_ROTATION)
   701 #if defined(NEW_ROTATION)
   706 	sprite = RotateSprite(sprite);
   702 	sprite = RotateSprite(sprite);
   712 #else
   708 #else
   713 	_sprite_lru_cur[sprite]	= ++_sprite_lru_counter;
   709 	_sprite_lru_cur[sprite]	= ++_sprite_lru_counter;
   714 	_sprite_lru[sprite] = 0;
   710 	_sprite_lru[sprite] = 0;
   715 #endif
   711 #endif
   716 
   712 
   717 	// Check if the sprite is loaded already?
       
   718 	p = _sprite_ptr[sprite];
   713 	p = _sprite_ptr[sprite];
   719 	if (p == NULL)
   714 	// Load the sprite, if it is not loaded, yet
   720 		p = LoadSpriteToMem(sprite);  // No, need to load it.
   715 	if (p == NULL) p = ReadSprite(sprite);
   721 	return p;
   716 	return p;
   722 }
   717 }
   723 
   718 
   724 byte _sprite_page_to_load = 0xFF;
   719 byte _sprite_page_to_load = 0xFF;
   725 
   720