grf.cpp
Go to the documentation of this file.00001
00002
00005 #include "../stdafx.h"
00006 #include "../gfx_func.h"
00007 #include "../fileio_func.h"
00008 #include "../debug.h"
00009 #include "../core/alloc_func.hpp"
00010 #include "../strings_func.h"
00011 #include "table/strings.h"
00012 #include "../gui.h"
00013 #include "grf.hpp"
00014
00023 static bool WarnCorruptSprite(uint8 file_slot, size_t file_pos, int line)
00024 {
00025 static byte warning_level = 0;
00026 if (warning_level == 0) {
00027 SetDParamStr(0, FioGetFilename(file_slot));
00028 ShowErrorMessage(INVALID_STRING_ID, STR_NEWGRF_ERROR_CORRUPT_SPRITE, 0, 0);
00029 }
00030 DEBUG(sprite, warning_level, "[%i] Loading corrupted sprite from %s at position %i", line, FioGetFilename(file_slot), (int)file_pos);
00031 warning_level = 6;
00032 return false;
00033 }
00034
00035 bool SpriteLoaderGrf::LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, size_t file_pos, SpriteType sprite_type)
00036 {
00037
00038 FioSeekToFile(file_slot, file_pos);
00039
00040
00041 int num = FioReadWord();
00042 byte type = FioReadByte();
00043
00044
00045 if (type == 0xFF) return false;
00046
00047 sprite->height = FioReadByte();
00048 sprite->width = FioReadWord();
00049 sprite->x_offs = FioReadWord();
00050 sprite->y_offs = FioReadWord();
00051
00052
00053
00054 num = (type & 0x02) ? sprite->width * sprite->height : num - 8;
00055
00056 byte *dest_orig = AllocaM(byte, num);
00057 byte *dest = dest_orig;
00058 const int dest_size = num;
00059
00060
00061 while (num > 0) {
00062 int8 code = FioReadByte();
00063
00064 if (code >= 0) {
00065
00066 int size = (code == 0) ? 0x80 : code;
00067 num -= size;
00068 if (num < 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00069 for (; size > 0; size--) {
00070 *dest = FioReadByte();
00071 dest++;
00072 }
00073 } else {
00074
00075 const uint data_offset = ((code & 7) << 8) | FioReadByte();
00076 if (dest - data_offset < dest_orig) return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00077 int size = -(code >> 3);
00078 num -= size;
00079 if (num < 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00080 for (; size > 0; size--) {
00081 *dest = *(dest - data_offset);
00082 dest++;
00083 }
00084 }
00085 }
00086
00087 if (num != 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00088
00089 sprite->data = CallocT<SpriteLoader::CommonPixel>(sprite->width * sprite->height);
00090
00091
00092 if (type & 0x08) {
00093 for (int y = 0; y < sprite->height; y++) {
00094 bool last_item = false;
00095
00096 int offset = (dest_orig[y * 2 + 1] << 8) | dest_orig[y * 2];
00097
00098
00099 dest = dest_orig + offset;
00100
00101 do {
00102 if (dest + 2 > dest_orig + dest_size) {
00103 free(sprite->data);
00104 return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00105 }
00106
00107 SpriteLoader::CommonPixel *data;
00108
00109
00110
00111
00112 last_item = ((*dest) & 0x80) != 0;
00113 int length = (*dest++) & 0x7F;
00114 int skip = *dest++;
00115
00116 data = &sprite->data[y * sprite->width + skip];
00117
00118 if (skip + length > sprite->width || dest + length > dest_orig + dest_size) {
00119 free(sprite->data);
00120 return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00121 }
00122
00123 for (int x = 0; x < length; x++) {
00124 data->m = ((sprite_type == ST_NORMAL && _palette_remap_grf[file_slot]) ? _palette_remap[*dest] : *dest);
00125 dest++;
00126 data++;
00127 }
00128 } while (!last_item);
00129 }
00130 } else {
00131 if (dest_size < sprite->width * sprite->height) {
00132 free(sprite->data);
00133 return WarnCorruptSprite(file_slot, file_pos, __LINE__);
00134 }
00135
00136 if (dest_size > sprite->width * sprite->height) {
00137 static byte warning_level = 0;
00138 DEBUG(sprite, warning_level, "Ignoring %i unused extra bytes from the sprite from %s at position %i", dest_size - sprite->width * sprite->height, FioGetFilename(file_slot), (int)file_pos);
00139 warning_level = 6;
00140 }
00141
00142 dest = dest_orig;
00143
00144 for (int i = 0; i < sprite->width * sprite->height; i++) {
00145 sprite->data[i].m = ((sprite_type == ST_NORMAL && _palette_remap_grf[file_slot]) ? _palette_remap[dest[i]] : dest[i]);
00146 }
00147 }
00148
00149
00150 for (int i = 0; i < sprite->width * sprite->height; i++)
00151 if (sprite->data[i].m != 0) sprite->data[i].a = 0xFF;
00152
00153 return true;
00154 }