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