mirror of https://github.com/OpenTTD/OpenTTD
(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
parent
b29556e6b5
commit
a06b2fdc44
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;
|
||||||
sprite->info = type;
|
FioReadBlock(dest, num);
|
||||||
sprite->height = FioReadByte();
|
|
||||||
if (id == 142) sprite->height = 10; // Compensate for a TTD bug
|
return dest;
|
||||||
sprite->width = FioReadWord();
|
} 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->height = (id != 142) ? height : 10;
|
||||||
|
sprite->width = width;
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue