2 |
2 |
3 /** @file spritecache.cpp */ |
3 /** @file spritecache.cpp */ |
4 |
4 |
5 #include "stdafx.h" |
5 #include "stdafx.h" |
6 #include "openttd.h" |
6 #include "openttd.h" |
|
7 #include "variables.h" |
|
8 #include "string.h" |
7 #include "debug.h" |
9 #include "debug.h" |
8 #include "functions.h" |
10 #include "functions.h" |
9 #include "macros.h" |
11 #include "macros.h" |
10 #include "spritecache.h" |
12 #include "spritecache.h" |
11 #include "table/sprites.h" |
13 #include "table/sprites.h" |
12 #include "fileio.h" |
14 #include "fileio.h" |
13 #include "helpers.hpp" |
15 #include "helpers.hpp" |
14 #include "spriteloader/grf.hpp" |
16 #include "spriteloader/grf.hpp" |
15 #include "blitter/blitter.hpp" |
17 #ifdef WITH_PNG |
|
18 #include "spriteloader/png.hpp" |
|
19 #endif /* WITH_PNG */ |
|
20 #include "blitter/factory.hpp" |
16 |
21 |
17 /* Default of 4MB spritecache */ |
22 /* Default of 4MB spritecache */ |
18 uint _sprite_cache_size = 4; |
23 uint _sprite_cache_size = 4; |
19 |
24 |
20 |
25 |
21 struct SpriteCache { |
26 struct SpriteCache { |
22 void *ptr; |
27 void *ptr; |
23 uint32 file_pos; |
28 uint32 file_pos; |
24 int16 lru; |
29 int16 lru; |
|
30 uint32 id; |
|
31 const char *grf_name; |
25 }; |
32 }; |
26 |
33 |
27 |
34 |
28 static uint _spritecache_items = 0; |
35 static uint _spritecache_items = 0; |
29 static SpriteCache *_spritecache = NULL; |
36 static SpriteCache *_spritecache = NULL; |
128 DEBUG(sprite, 1, "Tried to load non-existing sprite #%d. Probable cause: Wrong/missing NewGRFs", id); |
135 DEBUG(sprite, 1, "Tried to load non-existing sprite #%d. Probable cause: Wrong/missing NewGRFs", id); |
129 |
136 |
130 /* SPR_IMG_QUERY is a BIG FAT RED ? */ |
137 /* SPR_IMG_QUERY is a BIG FAT RED ? */ |
131 id = SPR_IMG_QUERY; |
138 id = SPR_IMG_QUERY; |
132 file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos; |
139 file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos; |
|
140 } |
|
141 |
|
142 if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) { |
|
143 #ifdef WITH_PNG |
|
144 /* Try loading 32bpp graphics in case we are 32bpp output */ |
|
145 SpriteLoaderPNG sprite_loader; |
|
146 SpriteLoader::Sprite sprite; |
|
147 |
|
148 if (sprite_loader.LoadSprite(&sprite, sc->grf_name, sc->id)) { |
|
149 sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite); |
|
150 free(sprite.data); |
|
151 |
|
152 return sc->ptr; |
|
153 } |
|
154 /* If the PNG couldn't be loaded, fall back to 8bpp grfs */ |
|
155 #else |
|
156 static bool show_once = true; |
|
157 if (show_once) { |
|
158 DEBUG(misc, 0, "You are running a 32bpp blitter, but this build is without libpng support; falling back to 8bpp graphics"); |
|
159 show_once = false; |
|
160 } |
|
161 #endif /* WITH_PNG */ |
133 } |
162 } |
134 |
163 |
135 FioSeekToFile(file_pos); |
164 FioSeekToFile(file_pos); |
136 |
165 |
137 /* Read the size and type */ |
166 /* Read the size and type */ |
138 int num = FioReadWord(); |
167 int num = FioReadWord(); |
139 byte type = FioReadByte(); |
168 byte type = FioReadByte(); |
140 /* Type 0xFF indicates either a colormap or some other non-sprite info */ |
169 /* Type 0xFF indicates either a colormap or some other non-sprite info */ |
141 if (type == 0xFF) { |
170 if (type == 0xFF) { |
|
171 if (real_sprite) { |
|
172 static byte warning_level = 0; |
|
173 DEBUG(sprite, warning_level, "Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id); |
|
174 warning_level = 6; |
|
175 if (id == SPR_IMG_QUERY) error("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?"); |
|
176 return (void*)GetSprite(SPR_IMG_QUERY); |
|
177 } |
|
178 |
142 byte *dest = (byte *)AllocSprite(num); |
179 byte *dest = (byte *)AllocSprite(num); |
143 |
180 |
144 sc->ptr = dest; |
181 sc->ptr = dest; |
145 FioReadBlock(dest, num); |
182 FioReadBlock(dest, num); |
146 |
183 |
147 return dest; |
184 return sc->ptr; |
|
185 } |
|
186 /* Ugly hack to work around the problem that the old landscape |
|
187 * generator assumes that those sprites are stored uncompressed in |
|
188 * the memory, and they are only read directly by the code, never |
|
189 * send to the blitter. So do not send it to the blitter (which will |
|
190 * result in a data array in the format the blitter likes most), but |
|
191 * read the data directly from disk and store that as sprite. |
|
192 * Ugly: yes. Other solution: no. Blame the original author or |
|
193 * something ;) The image should really have been a data-stream |
|
194 * (so type = 0xFF basicly). */ |
|
195 if (id >= 4845 && id <= 4881) { |
|
196 uint height = FioReadByte(); |
|
197 uint width = FioReadWord(); |
|
198 Sprite *sprite; |
|
199 byte *dest; |
|
200 |
|
201 num = width * height; |
|
202 sprite = (Sprite *)AllocSprite(sizeof(*sprite) + num); |
|
203 sc->ptr = sprite; |
|
204 sprite->height = height; |
|
205 sprite->width = width; |
|
206 sprite->x_offs = FioReadWord(); |
|
207 sprite->y_offs = FioReadWord(); |
|
208 |
|
209 dest = sprite->data; |
|
210 while (num > 0) { |
|
211 int8 i = FioReadByte(); |
|
212 if (i >= 0) { |
|
213 num -= i; |
|
214 for (; i > 0; --i) *dest++ = FioReadByte(); |
|
215 } else { |
|
216 const byte* rel = dest - (((i & 7) << 8) | FioReadByte()); |
|
217 i = -(i >> 3); |
|
218 num -= i; |
|
219 for (; i > 0; --i) *dest++ = *rel++; |
|
220 } |
|
221 } |
|
222 |
|
223 return sc->ptr; |
|
224 } |
|
225 |
|
226 if (!real_sprite) { |
|
227 static byte warning_level = 0; |
|
228 DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id); |
|
229 warning_level = 6; |
148 } |
230 } |
149 |
231 |
150 SpriteLoaderGrf sprite_loader; |
232 SpriteLoaderGrf sprite_loader; |
151 SpriteLoader::Sprite sprite; |
233 SpriteLoader::Sprite sprite; |
152 |
234 |
153 if (!sprite_loader.LoadSprite(&sprite, file_pos)) return NULL; |
235 if (!sprite_loader.LoadSprite(&sprite, sc->grf_name, file_pos)) return NULL; |
154 if (id == 142) sprite.height = 10; // Compensate for a TTD bug |
236 if (id == 142) sprite.height = 10; // Compensate for a TTD bug |
155 sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite); |
237 sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite); |
156 free(sprite.data); |
238 free(sprite.data); |
157 |
239 |
158 return sc->ptr; |
240 return sc->ptr; |
159 } |
241 } |
160 |
242 |
161 |
243 |
162 bool LoadNextSprite(int load_index, byte file_index) |
244 bool LoadNextSprite(int load_index, byte file_index, uint file_sprite_id) |
163 { |
245 { |
164 SpriteCache *sc; |
246 SpriteCache *sc; |
165 uint32 file_pos = FioGetPos() | (file_index << 24); |
247 uint32 file_pos = FioGetPos() | (file_index << 24); |
166 |
248 |
167 if (!ReadSpriteHeaderSkipData()) return false; |
249 if (!ReadSpriteHeaderSkipData()) return false; |