changeset 184 | dbeaaaf8b2bb |
parent 182 | 1641047f1d9f |
child 361 | 95307fb1c3f8 |
183:ec2b02ea4c88 | 184:dbeaaaf8b2bb |
---|---|
50 |
50 |
51 static const char * const _filename_list[] = { |
51 static const char * const _filename_list[] = { |
52 "TRG1R.GRF", |
52 "TRG1R.GRF", |
53 "TRGIR.GRF", |
53 "TRGIR.GRF", |
54 "signalsw.grf", //0x1320 - 0x1405 inclusive |
54 "signalsw.grf", //0x1320 - 0x1405 inclusive |
55 // "openttd.grf", //0x1406 - |
55 // "openttd.grf", //0x1406 - |
56 NULL |
56 NULL |
57 }; |
57 }; |
58 |
58 |
59 static const char * const _landscape_filenames[] = { |
59 static const char * const _landscape_filenames[] = { |
60 "TRGCR.GRF", |
60 "TRGCR.GRF", |
91 if (_skip_sprites) { |
91 if (_skip_sprites) { |
92 if (_skip_sprites > 0) |
92 if (_skip_sprites > 0) |
93 _skip_sprites--; |
93 _skip_sprites--; |
94 deaf = 1; |
94 deaf = 1; |
95 } |
95 } |
96 |
96 |
97 type = FioReadByte(); |
97 type = FioReadByte(); |
98 if (type == 0xFF) { |
98 if (type == 0xFF) { |
99 /* We need to really skip only special sprites in the deaf |
99 /* We need to really skip only special sprites in the deaf |
100 * mode. It won't hurt to proceed regular sprites as usual |
100 * mode. It won't hurt to proceed regular sprites as usual |
101 * because if no special sprite referencing to them is |
101 * because if no special sprite referencing to them is |
106 } else { |
106 } else { |
107 DecodeSpecialSprite(_cur_grffile, num, load_index); |
107 DecodeSpecialSprite(_cur_grffile, num, load_index); |
108 } |
108 } |
109 return; |
109 return; |
110 } |
110 } |
111 |
111 |
112 _cur_sprite.info = type; |
112 _cur_sprite.info = type; |
113 #ifdef WANT_SPRITESIZES |
113 #ifdef WANT_SPRITESIZES |
114 _cur_sprite.height = FioReadByte(); |
114 _cur_sprite.height = FioReadByte(); |
115 _cur_sprite.width = FioReadWord(); |
115 _cur_sprite.width = FioReadWord(); |
116 _cur_sprite.x_offs = FioReadWord(); |
116 _cur_sprite.x_offs = FioReadWord(); |
144 { |
144 { |
145 byte type; |
145 byte type; |
146 byte *rel; |
146 byte *rel; |
147 int8 i; |
147 int8 i; |
148 int j, dist; |
148 int j, dist; |
149 |
149 |
150 type = FioReadByte(); |
150 type = FioReadByte(); |
151 /* We've decoded special sprites when reading headers. */ |
151 /* We've decoded special sprites when reading headers. */ |
152 if (type != 0xFF) { |
152 if (type != 0xFF) { |
153 /* read sprite hdr */ |
153 /* read sprite hdr */ |
154 *dest++ = type; |
154 *dest++ = type; |
171 *dest++ = FioReadByte(); |
171 *dest++ = FioReadByte(); |
172 } else { |
172 } else { |
173 dist = -(((i&7)<<8)|FioReadByte()); |
173 dist = -(((i&7)<<8)|FioReadByte()); |
174 i = -(i >> 3); |
174 i = -(i >> 3); |
175 num -= i; |
175 num -= i; |
176 |
176 |
177 rel = &dest[dist]; |
177 rel = &dest[dist]; |
178 while (i--) |
178 while (i--) |
179 *dest++ = *rel++; |
179 *dest++ = *rel++; |
180 } |
180 } |
181 } |
181 } |
207 _sprite_locked[load_index] = false; |
207 _sprite_locked[load_index] = false; |
208 #endif |
208 #endif |
209 |
209 |
210 #if defined(WANT_NEW_LRU) |
210 #if defined(WANT_NEW_LRU) |
211 _sprite_lru_new[load_index] = 0; |
211 _sprite_lru_new[load_index] = 0; |
212 #else |
212 #else |
213 _sprite_lru[load_index] = 0xFFFF; |
213 _sprite_lru[load_index] = 0xFFFF; |
214 _sprite_lru_cur[load_index] = 0; |
214 _sprite_lru_cur[load_index] = 0; |
215 #endif |
215 #endif |
216 |
216 |
217 return true; |
217 return true; |
280 bool b = LoadNextSprite(start, file_index); |
280 bool b = LoadNextSprite(start, file_index); |
281 assert(b); |
281 assert(b); |
282 } while (++start <= end); |
282 } while (++start <= end); |
283 } |
283 } |
284 } |
284 } |
285 } |
285 } |
286 |
286 |
287 typedef size_t CDECL fread_t(void*,size_t,size_t,FILE*); |
287 typedef size_t CDECL fread_t(void*,size_t,size_t,FILE*); |
288 |
288 |
289 static bool HandleCachedSpriteHeaders(const char *filename, bool read) |
289 static bool HandleCachedSpriteHeaders(const char *filename, bool read) |
290 { |
290 { |
396 static void CompactSpriteCache() |
396 static void CompactSpriteCache() |
397 { |
397 { |
398 byte *s, *t; |
398 byte *s, *t; |
399 size_t size, sizeb, cur_size; |
399 size_t size, sizeb, cur_size; |
400 int i; |
400 int i; |
401 |
401 |
402 DEBUG(spritecache, 2) ("compacting sprite cache, inuse=%d", GetSpriteCacheUsage()); |
402 DEBUG(spritecache, 2) ("compacting sprite cache, inuse=%d", GetSpriteCacheUsage()); |
403 |
403 |
404 s = _spritecache_ptr; |
404 s = _spritecache_ptr; |
405 |
405 |
406 while (true) { |
406 while (true) { |
407 size = S_DATA(s); |
407 size = S_DATA(s); |
408 |
408 |
409 // Only look for free blocks. |
409 // Only look for free blocks. |
410 if (size & S_FREE_MASK) { |
410 if (size & S_FREE_MASK) { |
411 size -= S_FREE_MASK; |
411 size -= S_FREE_MASK; |
412 // Since free blocks are automatically coalesced, this should hold true. |
412 // Since free blocks are automatically coalesced, this should hold true. |
413 assert(!(S_DATA(s+size) & S_FREE_MASK)); |
413 assert(!(S_DATA(s+size) & S_FREE_MASK)); |
414 |
414 |
415 // If the next block is the sentinel block, we can safely return |
415 // If the next block is the sentinel block, we can safely return |
416 if ( (sizeb=S_DATA(s + size)) == 0) |
416 if ( (sizeb=S_DATA(s + size)) == 0) |
417 break; |
417 break; |
418 |
418 |
419 // Locate the sprite number belonging to the next pointer. |
419 // Locate the sprite number belonging to the next pointer. |
425 #endif |
425 #endif |
426 |
426 |
427 // Offset the sprite pointer by the size of the free block |
427 // Offset the sprite pointer by the size of the free block |
428 _sprite_ptr[i] -= size; |
428 _sprite_ptr[i] -= size; |
429 |
429 |
430 // Move the memory |
430 // Move the memory |
431 memcpy_overlapping(s+S_HDRSIZE, s+S_HDRSIZE+size, sizeb - S_HDRSIZE ); |
431 memcpy_overlapping(s+S_HDRSIZE, s+S_HDRSIZE+size, sizeb - S_HDRSIZE ); |
432 |
432 |
433 // What we just did had the effect of swapping the allocated block with the free block, so we need to update |
433 // What we just did had the effect of swapping the allocated block with the free block, so we need to update |
434 // the block pointers. First update the allocated one. It is in use. |
434 // the block pointers. First update the allocated one. It is in use. |
435 S_DATA(s) = sizeb; |
435 S_DATA(s) = sizeb; |
436 |
436 |
437 // Then coalesce the free ones that follow. |
437 // Then coalesce the free ones that follow. |
438 s += sizeb; |
438 s += sizeb; |
439 while ((cur_size = S_DATA(s+size)) & S_FREE_MASK) |
439 while ((cur_size = S_DATA(s+size)) & S_FREE_MASK) |
440 size += cur_size - S_FREE_MASK; |
440 size += cur_size - S_FREE_MASK; |
441 S_DATA(s) = size + S_FREE_MASK; |
441 S_DATA(s) = size + S_FREE_MASK; |
483 #if defined(WANT_LOCKED) |
483 #if defined(WANT_LOCKED) |
484 _sprite_locked[i] || |
484 _sprite_locked[i] || |
485 #endif |
485 #endif |
486 _sprite_lru[i] < cur_lru) |
486 _sprite_lru[i] < cur_lru) |
487 continue; |
487 continue; |
488 |
488 |
489 // Found a sprite with a higher LRU value, then remember it. |
489 // Found a sprite with a higher LRU value, then remember it. |
490 if (_sprite_lru[i] != cur_lru) { |
490 if (_sprite_lru[i] != cur_lru) { |
491 cur_lru = _sprite_lru[i]; |
491 cur_lru = _sprite_lru[i]; |
492 best = i; |
492 best = i; |
493 |
493 |
549 cur_size -= S_FREE_MASK; |
549 cur_size -= S_FREE_MASK; |
550 |
550 |
551 // Now s points at a free block. |
551 // Now s points at a free block. |
552 // The block is exactly the size we need? |
552 // The block is exactly the size we need? |
553 if (cur_size != mem_req) { |
553 if (cur_size != mem_req) { |
554 |
554 |
555 // No.. is it too small? |
555 // No.. is it too small? |
556 if (cur_size < mem_req + S_HDRSIZE) |
556 if (cur_size < mem_req + S_HDRSIZE) |
557 break; |
557 break; |
558 |
558 |
559 // Block was big enough, and we need to inject a free block too. |
559 // Block was big enough, and we need to inject a free block too. |
565 |
565 |
566 _sprite_ptr[sprite] = (s += S_HDRSIZE); |
566 _sprite_ptr[sprite] = (s += S_HDRSIZE); |
567 |
567 |
568 FioSeekToFile(_sprite_file_pos[sprite]); |
568 FioSeekToFile(_sprite_file_pos[sprite]); |
569 ReadSprite(_sprite_size[sprite], s); |
569 ReadSprite(_sprite_size[sprite], s); |
570 |
570 |
571 // Patch the height to compensate for a TTD bug? |
571 // Patch the height to compensate for a TTD bug? |
572 if (sprite == 142) { s[1] = 10; } |
572 if (sprite == 142) { s[1] = 10; } |
573 |
573 |
574 // Return sprite ptr |
574 // Return sprite ptr |
575 return s; |
575 return s; |
578 // Reached sentinel, but no block found yet. Need to delete some old entries. |
578 // Reached sentinel, but no block found yet. Need to delete some old entries. |
579 if (cur_size == 0) { |
579 if (cur_size == 0) { |
580 DeleteEntryFromSpriteCache(); |
580 DeleteEntryFromSpriteCache(); |
581 goto restart; |
581 goto restart; |
582 } |
582 } |
583 |
583 |
584 s += cur_size; |
584 s += cur_size; |
585 } |
585 } |
586 } |
586 } |
587 |
587 |
588 #if defined(NEW_ROTATION) |
588 #if defined(NEW_ROTATION) |
626 MAP(4120, 4125, _fence_map) |
626 MAP(4120, 4125, _fence_map) |
627 return s; |
627 return s; |
628 } |
628 } |
629 #endif |
629 #endif |
630 |
630 |
631 byte *GetSpritePtr(uint sprite) |
631 byte *GetSpritePtr(uint sprite) |
632 { |
632 { |
633 byte *p; |
633 byte *p; |
634 |
634 |
635 assert(sprite < NUM_SPRITES); |
635 assert(sprite < NUM_SPRITES); |
636 |
636 |
648 |
648 |
649 // Check if the sprite is loaded already? |
649 // Check if the sprite is loaded already? |
650 p = _sprite_ptr[sprite]; |
650 p = _sprite_ptr[sprite]; |
651 if (p == NULL) |
651 if (p == NULL) |
652 p = LoadSpriteToMem(sprite); // No, need to load it. |
652 p = LoadSpriteToMem(sprite); // No, need to load it. |
653 return p; |
653 return p; |
654 } |
654 } |
655 |
655 |
656 byte _sprite_page_to_load = 0xFF; |
656 byte _sprite_page_to_load = 0xFF; |
657 |
657 |
658 static const char * const _cached_filenames[4] = { |
658 static const char * const _cached_filenames[4] = { |
678 |
678 |
679 static void LoadSpriteTables() |
679 static void LoadSpriteTables() |
680 { |
680 { |
681 int i,j; |
681 int i,j; |
682 |
682 |
683 /* load initial sprites */ |
683 /* |
684 * Note for developers: |
|
685 * Keep in mind that when you add a LoadGrfIndexed in the 'if'-section below |
|
686 * that you should also add the corresponding FioOpenFile to the 'else'-section |
|
687 * below. |
|
688 */ |
|
689 |
|
690 // Try to load the sprites from cache |
|
684 if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) { |
691 if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) { |
685 |
692 // We do not have the sprites in cache yet, or cache is disabled |
693 // So just load all files from disk.. |
|
694 |
|
686 int load_index = 0; |
695 int load_index = 0; |
687 for(i=0; _filename_list[i] != NULL; i++) { |
696 for(i=0; _filename_list[i] != NULL; i++) { |
688 load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i); |
697 load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i); |
689 } |
698 } |
690 |
699 |
691 LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++); |
700 LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++); |
692 |
701 |
693 { |
702 if (_sprite_page_to_load != 0) |
694 int l; |
703 LoadGrfIndexed(_landscape_filenames[_sprite_page_to_load-1], _landscape_spriteindexes[_sprite_page_to_load-1], i++); |
695 if ((l=_sprite_page_to_load) != 0) |
704 |
696 LoadGrfIndexed(_landscape_filenames[l-1], _landscape_spriteindexes[l-1], i++); |
|
697 } |
|
698 |
|
699 LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++); |
705 LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++); |
700 |
706 |
701 load_index = SPR_CANALS_BASE; |
707 load_index = SPR_CANALS_BASE; |
702 load_index += LoadGrfFile("canalsw.grf", load_index, i++); |
708 load_index += LoadGrfFile("canalsw.grf", load_index, i++); |
703 /* XXX: Only for debugging. Will be more generic. */ |
709 |
704 |
710 load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1; |
705 load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT+1; |
|
706 |
711 |
707 for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) |
712 for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) |
708 load_index += LoadGrfFile(_newgrf_files[j], load_index, i++); |
713 load_index += LoadGrfFile(_newgrf_files[j], load_index, i++); |
709 |
714 |
710 // load_index += LoadGrfFile("arcticseto.grf", load_index, i++); |
715 // If needed, save the cache to file |
711 // load_index += LoadGrfFile("tempsetpo.grf", load_index, i++); |
|
712 // load_index += LoadGrfFile("newshipso.grf", load_index, i++); |
|
713 //load_index += LoadGrfFile("brseto.grf", load_index, i++); |
|
714 |
|
715 HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false); |
716 HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false); |
716 } else { |
717 } else { |
718 // We have sprites cached. We just loaded the cached files |
|
719 // now we only have to open a file-pointer to all the original grf-files |
|
720 // This is very important. Not all sprites are in the cache. So sometimes |
|
721 // the game needs to load the sprite from disk. When the file is not |
|
722 // open it can not read. So all files that are in the 'if'-section |
|
723 // above should also be in this 'else'-section. |
|
724 // |
|
725 // NOTE: the order of the files must be identical as in the section above!! |
|
726 |
|
717 for(i=0; _filename_list[i] != NULL; i++) |
727 for(i=0; _filename_list[i] != NULL; i++) |
718 FioOpenFile(i,_filename_list[i]); |
728 FioOpenFile(i,_filename_list[i]); |
719 |
729 |
720 FioOpenFile(i, "openttd.grf"); |
730 FioOpenFile(i++, "openttd.grf"); |
721 FioOpenFile(i+1, "canalsw.grf"); |
731 |
722 |
|
723 if (_sprite_page_to_load != 0) |
732 if (_sprite_page_to_load != 0) |
724 FioOpenFile(i+2, _landscape_filenames[_sprite_page_to_load-1]); |
733 FioOpenFile(i++, _landscape_filenames[_sprite_page_to_load-1]); |
734 |
|
735 FioOpenFile(i++, "trkfoundw.grf"); |
|
736 FioOpenFile(i++, "canalsw.grf"); |
|
737 |
|
738 // FIXME: if a user changes his newgrf's, the cached-sprites gets |
|
739 // invalid. We should have some kind of check for this. |
|
740 // The best solution for this is to delete the cached-sprites.. but how |
|
741 // do we detect it? |
|
742 for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) |
|
743 FioOpenFile(i++, _newgrf_files[j]); |
|
725 } |
744 } |
726 |
745 |
727 _compact_cache_counter = 0; |
746 _compact_cache_counter = 0; |
728 } |
747 } |
729 |
748 |
742 } |
761 } |
743 |
762 |
744 |
763 |
745 void GfxLoadSprites() { |
764 void GfxLoadSprites() { |
746 static byte *_sprite_mem; |
765 static byte *_sprite_mem; |
747 |
766 |
748 // Need to reload the sprites only if the landscape changed |
767 // Need to reload the sprites only if the landscape changed |
749 if (_sprite_page_to_load != _opt.landscape) { |
768 if (_sprite_page_to_load != _opt.landscape) { |
750 _sprite_page_to_load = _opt.landscape; |
769 _sprite_page_to_load = _opt.landscape; |
751 |
770 |
752 // Sprite cache |
771 // Sprite cache |
791 sd->xsize = _sprite_xsize[sprite]; |
810 sd->xsize = _sprite_xsize[sprite]; |
792 sd->ysize = _sprite_ysize[sprite]; |
811 sd->ysize = _sprite_ysize[sprite]; |
793 */ |
812 */ |
794 return sd; |
813 return sd; |
795 } |
814 } |
796 |
815 |