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