Ticket #8910: kyra_thumbnail_v1.patch
File kyra_thumbnail_v1.patch, 35.6 KB (added by , 16 years ago) |
---|
-
engines/scumm/thumbnail.cpp
27 27 #include "common/system.h" 28 28 #include "common/savefile.h" 29 29 #include "graphics/scaler.h" 30 #include "graphics/thumbnail.h" 30 31 #include "scumm/scumm.h" 31 32 32 33 namespace Scumm { 33 34 34 #define THMB_VERSION 135 36 struct ThumbnailHeader {37 uint32 type;38 uint32 size;39 byte version;40 uint16 width, height;41 byte bpp;42 };43 44 #define ThumbnailHeaderSize (4+4+1+2+2+1)45 46 inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) {47 r = (((color >> 11) & 0x1F) << 3);48 g = (((color >> 5) & 0x3F) << 2);49 b = ((color&0x1F) << 3);50 }51 52 35 Graphics::Surface *ScummEngine::loadThumbnail(Common::SeekableReadStream *file) { 53 ThumbnailHeader header; 36 // TODO: Until backwards seeking in compressed save files is not supported 37 // We can not use this. 54 38 55 header.type = file->readUint32BE(); 56 // We also accept the bad 'BMHT' header here, for the sake of compatibility 57 // with some older savegames which were written incorrectly due to a bug in 58 // ScummVM which wrote the thumb header type incorrectly on LE systems. 59 if (header.type != MKID_BE('THMB') && header.type != MKID_BE('BMHT')) 60 return 0; 39 //if (!Graphics::checkThumbnailHeader(*file)) 40 // return 0; 61 41 62 header.size = file->readUint32BE(); 63 header.version = file->readByte(); 64 65 if (header.version > THMB_VERSION) { 66 file->skip(header.size - 9); 67 warning("Loading a newer thumbnail version"); 42 Graphics::Surface *thumb = new Graphics::Surface(); 43 assert(thumb); 44 if (!Graphics::loadThumbnail(*file, *thumb)) { 45 delete thumb; 68 46 return 0; 69 47 } 70 48 71 header.width = file->readUint16BE();72 header.height = file->readUint16BE();73 header.bpp = file->readByte();74 75 // TODO: support other bpp values than 276 if (header.bpp != 2) {77 file->skip(header.size - 14);78 return 0;79 }80 81 Graphics::Surface *thumb = new Graphics::Surface();82 thumb->create(header.width, header.height, sizeof(OverlayColor));83 84 OverlayColor* pixels = (OverlayColor *)thumb->pixels;85 86 for (int y = 0; y < thumb->h; ++y) {87 for (int x = 0; x < thumb->w; ++x) {88 uint8 r, g, b;89 colorToRGB(file->readUint16BE(), r, g, b);90 91 // converting to current OSystem Color92 *pixels++ = _system->RGBToColor(r, g, b);93 }94 }95 96 49 return thumb; 97 50 } 98 51 99 52 void ScummEngine::saveThumbnail(Common::OutSaveFile *file) { 53 // Until we support no thumbnails in the SCUMM save formats for NDS 54 // we save a dummy thumbnail. 55 // 56 // TODO: Actually all what has to be done about it, is to update 57 // the code in engines/scumm/saveload.o which skips the saveheader. 58 // Currently impossible because of lacking backward seek support for 59 // compressed save files. 60 // When we change that code to use the new API from graphics/thumbnail.h 61 // it should be all fine to save no header at all for NDS. 62 100 63 Graphics::Surface thumb; 101 64 102 65 #if !defined(__DS__) … … 104 67 #endif 105 68 thumb.create(kThumbnailWidth, kThumbnailHeight2, sizeof(uint16)); 106 69 107 ThumbnailHeader header; 108 header.type = MKID_BE('THMB'); 109 header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel; 110 header.version = THMB_VERSION; 111 header.width = thumb.w; 112 header.height = thumb.h; 113 header.bpp = thumb.bytesPerPixel; 114 115 file->writeUint32BE(header.type); 116 file->writeUint32BE(header.size); 117 file->writeByte(header.version); 118 file->writeUint16BE(header.width); 119 file->writeUint16BE(header.height); 120 file->writeByte(header.bpp); 121 122 // TODO: for later this shouldn't be casted to uint16... 123 uint16* pixels = (uint16 *)thumb.pixels; 124 for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels) 125 file->writeUint16BE(*pixels); 126 70 Graphics::saveThumbnail(*file, thumb); 127 71 thumb.free(); 128 72 } 129 73 -
engines/kyra/kyra_mr.cpp
684 684 assert(_invWsa); 685 685 _invWsa->open("MOODOMTR.WSA", 1, 0); 686 686 _invWsaFrame = 6; 687 saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33) );687 saveGame(getSavegameFilename(0), (const char*)getTableEntry(_optionsFile, 33), 0); 688 688 _soundDigital->beginFadeOut(_musicSoundChannel, 60); 689 689 delayWithTicks(60); 690 690 if (_gameToLoad == -1) -
engines/kyra/kyra_hof.h
907 907 int _dbgPass; 908 908 909 909 // save/load specific 910 void saveGame(const char *fileName, const char *saveName );910 void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); 911 911 void loadGame(const char *fileName); 912 912 }; 913 913 -
engines/kyra/kyra_v1.h
290 290 291 291 bool originalSave; // savegame from original interpreter 292 292 bool oldHeader; // old scummvm save header 293 294 Graphics::Surface *thumbnail; 293 295 }; 294 296 295 297 enum kReadSaveHeaderError { … … 299 301 kRSHEIoError = 3 300 302 }; 301 303 302 static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, SaveHeader &header);304 static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header); 303 305 304 306 Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header); 305 Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName ) const;307 Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const; 306 308 }; 307 309 308 310 } // End of namespace Kyra -
engines/kyra/gui_mr.cpp
33 33 34 34 #include "common/savefile.h" 35 35 36 #include "graphics/scaler.h" 37 36 38 namespace Kyra { 37 39 38 40 void KyraEngine_MR::loadButtonShapes() { … … 1138 1140 GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) { 1139 1141 } 1140 1142 1143 void GUI_MR::createScreenThumbnail(Graphics::Surface &dst) { 1144 ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(0)); 1145 } 1146 1141 1147 void GUI_MR::flagButtonEnable(Button *button) { 1142 1148 if (!button) 1143 1149 return; … … 1450 1456 1451 1457 if (_vm->_lang != lang) { 1452 1458 _reloadTemporarySave = true; 1453 _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame" );1459 _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 3 Savegame", 0); 1454 1460 if (!_vm->loadLanguageFile("ITEMS.", _vm->_itemFile)) 1455 1461 error("Couldn't load ITEMS"); 1456 1462 if (!_vm->loadLanguageFile("SCORE.", _vm->_scoreFile)) -
engines/kyra/screen_lok.cpp
147 147 148 148 void Screen_LoK::loadPageFromDisk(const char *file, int page) { 149 149 debugC(9, kDebugLevelScreen, "Screen_LoK::loadPageFromDisk('%s', %d)", file, page); 150 if (!_saveLoadPage[page/2]) { 151 warning("trying to restore page %d, but no backup found", page); 152 return; 153 } 154 150 155 copyBlockToPage(page, 0, 0, SCREEN_W, SCREEN_H, _saveLoadPage[page/2]); 151 156 delete[] _saveLoadPage[page/2]; 157 _saveLoadPage[page/2] = 0; 152 158 153 159 if (_saveLoadPageOvl[page/2]) { 154 160 uint8 *dstPage = getOverlayPtr(page); … … 160 166 memcpy(dstPage, _saveLoadPageOvl[page/2], SCREEN_OVL_SJIS_SIZE); 161 167 delete[] _saveLoadPageOvl[page/2]; 162 168 _saveLoadPageOvl[page/2] = 0; 163 } _saveLoadPage[page/2] = 0;169 } 164 170 } 165 171 172 void Screen_LoK::queryPageFromDisk(const char *file, int page, uint8 *buffer) { 173 debugC(9, kDebugLevelScreen, "Screen_LoK::queryPageFromDisk('%s', %d, %p)", file, page, (const void *)buffer); 174 if (!_saveLoadPage[page/2]) { 175 warning("trying to query page %d, but no backup found", page); 176 return; 177 } 178 179 memcpy(buffer, _saveLoadPage[page/2], SCREEN_W*SCREEN_H); 180 } 181 166 182 void Screen_LoK::deletePageFromDisk(int page) { 167 183 debugC(9, kDebugLevelScreen, "Screen_LoK::deletePageFromDisk(%d)", page); 168 184 delete[] _saveLoadPage[page/2]; -
engines/kyra/gui_lok.h
103 103 int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel); 104 104 105 105 int buttonMenuCallback(Button *caller); 106 107 void createScreenThumbnail(Graphics::Surface &dst); 106 108 private: 107 109 void initStaticResource(); 108 110 -
engines/kyra/kyra_mr.h
583 583 int albumClose(Button *caller); 584 584 585 585 // save/load 586 void saveGame(const char *fileName, const char *saveName );586 void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); 587 587 void loadGame(const char *fileName); 588 588 589 589 // opcodes -
engines/kyra/gui_hof.cpp
33 33 34 34 #include "common/savefile.h" 35 35 36 #include "graphics/scaler.h" 37 36 38 namespace Kyra { 37 39 38 40 void KyraEngine_HoF::loadButtonShapes() { … … 793 795 794 796 #pragma mark - 795 797 798 void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) { 799 ::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(1)); 800 } 801 796 802 void GUI_HoF::setupPalette() { 797 803 memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); 798 804 … … 996 1002 997 1003 if (_vm->_lang != lang) { 998 1004 _reloadTemporarySave = true; 999 _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame" );1005 _vm->saveGame(_vm->getSavegameFilename(999), "Temporary Kyrandia 2 Savegame", 0); 1000 1006 _vm->loadCCodeBuffer("C_CODE.XXX"); 1001 1007 if (_vm->_flags.isTalkie) 1002 1008 _vm->loadOptionsBuffer("OPTIONS.XXX"); -
engines/kyra/gui_mr.h
47 47 int redrawButtonCallback(Button *button); 48 48 49 49 int optionsButton(Button *button); 50 51 void createScreenThumbnail(Graphics::Surface &dst); 50 52 private: 51 53 void getInput(); 52 54 -
engines/kyra/gui.h
32 32 #include "common/array.h" 33 33 #include "common/func.h" 34 34 35 #include "graphics/surface.h" 36 35 37 namespace Kyra { 36 38 37 39 #define BUTTON_FUNCTOR(type, x, y) Button::Callback(new Common::Functor1Mem<Button*, int, type>(x, y)) … … 153 155 154 156 void processHighlights(Menu &menu, int mouseX, int mouseY); 155 157 158 // utilities for thumbnail creation 159 virtual void createScreenThumbnail(Graphics::Surface &dst) = 0; 156 160 protected: 157 161 KyraEngine_v1 *_vm; 158 162 Screen *_screen; -
engines/kyra/gui_lok.cpp
37 37 #include "common/events.h" 38 38 #include "common/system.h" 39 39 40 #include "graphics/scaler.h" 41 40 42 namespace Kyra { 41 43 42 44 void KyraEngine_LoK::initMainButtonList() { … … 199 201 delete[] _menu; 200 202 } 201 203 204 void GUI_LoK::createScreenThumbnail(Graphics::Surface &dst) { 205 uint8 *screen = new uint8[Screen::SCREEN_W*Screen::SCREEN_H]; 206 if (screen) { 207 _screen->queryPageFromDisk("SEENPAGE.TMP", 0, screen); 208 ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, _screen->getPalette(2)); 209 } 210 delete[] screen; 211 } 212 202 213 int GUI_LoK::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) { 203 214 while (list) { 204 215 if (list->flags & 8) { … … 736 747 } else { 737 748 if (_savegameOffset == 0 && _vm->_gameToLoad == 0) 738 749 _vm->_gameToLoad = getNextSavegameSlot(); 739 if (_vm->_gameToLoad > 0) 740 _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName); 750 if (_vm->_gameToLoad > 0) { 751 Graphics::Surface thumb; 752 createScreenThumbnail(thumb); 753 _vm->saveGame(_vm->getSavegameFilename(_vm->_gameToLoad), _savegameName, &thumb); 754 thumb.free(); 755 } 741 756 } 742 757 743 758 return 0; -
engines/kyra/screen_lok.h
50 50 51 51 void savePageToDisk(const char *file, int page); 52 52 void loadPageFromDisk(const char *file, int page); 53 void queryPageFromDisk(const char *file, int page, uint8 *buffer); 53 54 void deletePageFromDisk(int page); 54 55 55 56 void copyBackgroundBlock(int x, int page, int flag); -
engines/kyra/saveload.cpp
26 26 #include "common/endian.h" 27 27 #include "common/savefile.h" 28 28 #include "common/system.h" 29 #include "graphics/thumbnail.h" 29 30 30 31 #include "kyra/kyra_v1.h" 31 32 32 #define CURRENT_SAVE_VERSION 1 333 #define CURRENT_SAVE_VERSION 14 33 34 34 35 #define GF_FLOPPY (1 << 0) 35 36 #define GF_TALKIE (1 << 1) … … 37 38 38 39 namespace Kyra { 39 40 40 KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header) {41 KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) { 41 42 uint32 type = in->readUint32BE(); 42 43 header.originalSave = false; 43 44 header.oldHeader = false; … … 108 109 if (header.version >= 2) 109 110 header.flags = in->readUint32BE(); 110 111 112 if (header.version >= 14) { 113 if (loadThumbnail) { 114 header.thumbnail = new Graphics::Surface(); 115 assert(header.thumbnail); 116 Graphics::loadThumbnail(*in, *header.thumbnail); 117 } else { 118 Graphics::skipThumbnailHeader(*in); 119 } 120 } 121 111 122 return (in->ioFailed() ? kRSHEIoError : kRSHENoError); 112 123 } 113 124 … … 118 129 if (!(in = _saveFileMan->openForLoading(filename))) 119 130 return 0; 120 131 121 kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header);132 kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header); 122 133 if (errorCode != kRSHENoError) { 123 134 if (errorCode == kRSHEInvalidType) 124 135 warning("No ScummVM Kyra engine savefile header."); … … 162 173 return in; 163 174 } 164 175 165 Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName ) const {166 debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s' )", filename, saveName);176 Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const { 177 debugC(9, kDebugLevelMain, "KyraEngine_v1::openSaveForWriting('%s', '%s', %p)", filename, saveName, (const void *)thumbnail); 167 178 if (_quitFlag) 168 179 return 0; 169 180 … … 191 202 return 0; 192 203 } 193 204 205 if (thumbnail) 206 Graphics::saveThumbnail(*out, *thumbnail); 207 else 208 Graphics::saveThumbnail(*out); 209 194 210 return out; 195 211 } 196 212 -
engines/kyra/timer_mr.cpp
65 65 void KyraEngine_MR::timerFleaDeath(int arg) { 66 66 debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_MR::timerFleaDeath(%d)", arg); 67 67 _timer->setCountdown(4, 5400); 68 saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME" );68 saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); 69 69 _screen->hideMouse(); 70 70 _timer->disable(4); 71 71 runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1); -
engines/kyra/detection.cpp
1065 1065 if (slotNum >= 0 && slotNum <= 999) { 1066 1066 Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); 1067 1067 if (in) { 1068 if (Kyra::KyraEngine_v1::readSaveHeader(in, header) == Kyra::KyraEngine_v1::kRSHENoError)1068 if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) 1069 1069 saveList.push_back(SaveStateDescriptor(slotNum, header.description, *file)); 1070 1070 delete in; 1071 1071 } -
engines/kyra/kyra_lok.h
214 214 protected: 215 215 int32 _speechPlayTime; 216 216 217 void saveGame(const char *fileName, const char *saveName );217 void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail); 218 218 void loadGame(const char *fileName); 219 219 220 220 protected: -
engines/kyra/kyra_v2.h
419 419 int o2_getVocHigh(EMCState *script); 420 420 421 421 // save/load specific 422 virtual void saveGame(const char *fileName, const char *saveName ) = 0;422 virtual void saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumbnail) = 0; 423 423 virtual void loadGame(const char *fileName) = 0; 424 424 }; 425 425 -
engines/kyra/gui_hof.h
41 41 void initStaticData(); 42 42 43 43 int optionsButton(Button *button); 44 45 void createScreenThumbnail(Graphics::Surface &dst); 44 46 private: 45 47 const char *getMenuTitle(const Menu &menu); 46 48 const char *getMenuItemTitle(const MenuItem &menuItem); -
engines/kyra/saveload_hof.cpp
35 35 36 36 namespace Kyra { 37 37 38 void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName ) {39 debugC(9, kDebugLevelMain, "KyraEngine_ HoF::saveGame('%s', '%s')", fileName, saveName);38 void KyraEngine_HoF::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { 39 debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); 40 40 41 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName );41 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); 42 42 if (!out) { 43 43 warning("Can't open file '%s', game not loadable", fileName); 44 44 return; -
engines/kyra/script_mr.cpp
293 293 294 294 int KyraEngine_MR::o3_makeSecondChanceSave(EMCState *script) { 295 295 debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_makeSecondChanceSave(%p) ()", (const void *)script); 296 saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME" );296 saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME", 0); 297 297 return 0; 298 298 } 299 299 -
engines/kyra/kyra_hof.cpp
434 434 if (_gameToLoad == -1) { 435 435 snd_playWanderScoreViaMap(52, 1); 436 436 enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); 437 saveGame(getSavegameFilename(0), "New Game" );437 saveGame(getSavegameFilename(0), "New Game", 0); 438 438 } else { 439 439 loadGame(getSavegameFilename(_gameToLoad)); 440 440 } -
engines/kyra/saveload_lok.cpp
218 218 delete in; 219 219 } 220 220 221 void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName ) {222 debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s' )", fileName, saveName);221 void KyraEngine_LoK::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { 222 debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); 223 223 224 224 if (_quitFlag) 225 225 return; 226 226 227 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName );227 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); 228 228 if (!out) 229 229 return; 230 230 -
engines/kyra/kyra_lok.cpp
388 388 _gui->buttonMenuCallback(0); 389 389 _menuDirectlyToLoad = false; 390 390 } else 391 saveGame(getSavegameFilename(0), "New game" );391 saveGame(getSavegameFilename(0), "New game", 0); 392 392 } else { 393 393 _screen->setFont(Screen::FID_8_FNT); 394 394 loadGame(getSavegameFilename(_gameToLoad)); … … 470 470 else { 471 471 char savegameName[14]; 472 472 sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); 473 saveGame(saveLoadSlot, savegameName );473 saveGame(saveLoadSlot, savegameName, 0); 474 474 } 475 475 } else if (event.kbd.flags == Common::KBD_CTRL) { 476 476 if (event.kbd.keycode == 'd') -
engines/kyra/kyra_v2.cpp
186 186 } else { 187 187 char savegameName[14]; 188 188 sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); 189 saveGame(saveLoadSlot, savegameName );189 saveGame(saveLoadSlot, savegameName, 0); 190 190 } 191 191 } else if (event.kbd.flags == Common::KBD_CTRL) { 192 192 if (event.kbd.keycode == 'd') -
engines/kyra/gui_v2.cpp
618 618 619 619 restorePage1(_vm->_screenBuffer); 620 620 restorePalette(); 621 _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription); 621 622 Graphics::Surface thumb; 623 createScreenThumbnail(thumb); 624 _vm->saveGame(_vm->getSavegameFilename(_saveSlot), _saveDescription, &thumb); 625 thumb.free(); 626 622 627 _displayMenu = false; 623 628 _madeSave = true; 624 629 -
engines/kyra/saveload_mr.cpp
32 32 33 33 namespace Kyra { 34 34 35 void KyraEngine_MR::saveGame(const char *fileName, const char *saveName ) {36 debugC(9, kDebugLevelMain, "KyraEngine_ MR::saveGame('%s', '%s')", fileName, saveName);35 void KyraEngine_MR::saveGame(const char *fileName, const char *saveName, const Graphics::Surface *thumb) { 36 debugC(9, kDebugLevelMain, "KyraEngine_LoK::saveGame('%s', '%s', %p)", fileName, saveName, (const void *)thumb); 37 37 38 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName );38 Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); 39 39 if (!out) { 40 40 warning("Can't open file '%s', game not loadable", fileName); 41 41 return; -
graphics/module.mk
16 16 primitives.o \ 17 17 scaler.o \ 18 18 scaler/thumbnail.o \ 19 surface.o 19 surface.o \ 20 thumbnail.o 20 21 21 22 ifndef DISABLE_SCALERS 22 23 MODULE_OBJS += \ -
graphics/scaler.h
82 82 * @param surf a surface (will always have 16 bpp after this for now) 83 83 * @return false if a error occured 84 84 */ 85 extern bool createThumbnailFromScreen(Graphics::Surface *surf);85 extern bool createThumbnailFromScreen(Graphics::Surface *surf); 86 86 87 /** 88 * creates a surface from a buffer 89 * @param surf destination surface (will always have 16 bpp after this for now) 90 * @param pixels raw pixel data 91 * @param w width 92 * @param h height 93 * @param palette palette in RGB format 94 */ 95 extern bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette); 96 87 97 #endif -
graphics/thumbnail.cpp
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL$ 22 * $Id$ 23 */ 24 25 #include "graphics/thumbnail.h" 26 #include "graphics/scaler.h" 27 #include "common/endian.h" 28 #include "common/system.h" 29 30 namespace Graphics { 31 32 namespace { 33 #define THMB_VERSION 1 34 35 struct ThumbnailHeader { 36 uint32 type; 37 uint32 size; 38 byte version; 39 uint16 width, height; 40 byte bpp; 41 }; 42 43 #define ThumbnailHeaderSize (4+4+1+2+2+1) 44 45 inline void colorToRGB(uint16 color, uint8 &r, uint8 &g, uint8 &b) { 46 r = (((color >> 11) & 0x1F) << 3); 47 g = (((color >> 5) & 0x3F) << 2); 48 b = ((color&0x1F) << 3); 49 } 50 51 bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) { 52 header.type = in.readUint32BE(); 53 // We also accept the bad 'BMHT' header here, for the sake of compatibility 54 // with some older savegames which were written incorrectly due to a bug in 55 // ScummVM which wrote the thumb header type incorrectly on LE systems. 56 if (header.type != MKID_BE('THMB') && header.type != MKID_BE('BMHT')) { 57 if (outputWarnings) 58 warning("couldn't find thumbnail header type"); 59 return false; 60 } 61 62 header.size = in.readUint32BE(); 63 header.version = in.readByte(); 64 65 if (header.version > THMB_VERSION) { 66 if (outputWarnings) 67 warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION); 68 return false; 69 } 70 71 header.width = in.readUint16BE(); 72 header.height = in.readUint16BE(); 73 header.bpp = in.readByte(); 74 75 return true; 76 } 77 } // end of anonymous namespace 78 79 bool checkThumbnailHeader(Common::SeekableReadStream &in) { 80 uint32 position = in.pos(); 81 ThumbnailHeader header; 82 83 bool hasHeader = loadHeader(in, header, false); 84 85 in.seek(position, SEEK_SET); 86 87 return hasHeader; 88 } 89 90 bool skipThumbnailHeader(Common::SeekableReadStream &in) { 91 uint32 position = in.pos(); 92 ThumbnailHeader header; 93 94 if (!loadHeader(in, header, true)) { 95 in.seek(position, SEEK_SET); 96 return false; 97 } 98 99 in.seek(header.size - (in.pos() - position), SEEK_CUR); 100 return true; 101 } 102 103 bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to) { 104 ThumbnailHeader header; 105 106 if (!loadHeader(in, header, true)) 107 return false; 108 109 if (header.bpp != 2) { 110 warning("trying to load thumbnail with unsupported bit depth %d", header.bpp); 111 return false; 112 } 113 114 to.create(header.width, header.height, sizeof(OverlayColor)); 115 116 OverlayColor *pixels = (OverlayColor *)to.pixels; 117 for (int y = 0; y < to.h; ++y) { 118 for (int x = 0; x < to.w; ++x) { 119 uint8 r, g, b; 120 colorToRGB(in.readUint16BE(), r, g, b); 121 122 // converting to current OSystem Color 123 *pixels++ = g_system->RGBToColor(r, g, b); 124 } 125 } 126 127 return true; 128 } 129 130 bool saveThumbnail(Common::WriteStream &out) { 131 Graphics::Surface thumb; 132 133 if (!createThumbnailFromScreen(&thumb)) { 134 warning("Couldn't create thumbnail from screen, aborting thumbnail save"); 135 return false; 136 } 137 138 bool success = saveThumbnail(out, thumb); 139 thumb.free(); 140 141 return success; 142 } 143 144 bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) { 145 if (thumb.bytesPerPixel != 2) { 146 warning("trying to save thumbnail with bpp different than 2"); 147 return false; 148 } 149 150 ThumbnailHeader header; 151 header.type = MKID_BE('THMB'); 152 header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel; 153 header.version = THMB_VERSION; 154 header.width = thumb.w; 155 header.height = thumb.h; 156 header.bpp = thumb.bytesPerPixel; 157 158 out.writeUint32BE(header.type); 159 out.writeUint32BE(header.size); 160 out.writeByte(header.version); 161 out.writeUint16BE(header.width); 162 out.writeUint16BE(header.height); 163 out.writeByte(header.bpp); 164 165 // TODO: for later this shouldn't be casted to uint16... 166 uint16 *pixels = (uint16 *)thumb.pixels; 167 for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels) 168 out.writeUint16BE(*pixels); 169 170 return true; 171 } 172 173 } // end of namespace Graphics 174 -
graphics/scaler/thumbnail.cpp
Property changes on: graphics/thumbnail.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Rev Author URL Id Added: svn:eol-style + native
126 126 return true; 127 127 } 128 128 129 bool createThumbnailFromScreen(Graphics::Surface* surf) { 130 assert(surf); 129 static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { 130 uint16 width = in.w; 131 uint16 inHeight = in.h; 131 132 132 int screenWidth = g_system->getWidth(); 133 int screenHeight = g_system->getHeight(); 134 135 Graphics::Surface screen; 136 137 if (!grabScreen565(&screen)) 138 return false; 139 140 uint16 width = screenWidth; 141 142 if (screenWidth < 320) { 133 if (width < 320) { 143 134 // Special case to handle MM NES (uses a screen width of 256) 144 135 width = 320; 145 136 146 137 // center MM NES screen 147 138 Graphics::Surface newscreen; 148 newscreen.create(width, screen.h, screen.bytesPerPixel);139 newscreen.create(width, in.h, in.bytesPerPixel); 149 140 150 uint8 *dst = (uint8*)newscreen.getBasePtr((320 - screenWidth) / 2, 0);151 uint8 *src = (uint8*)screen.getBasePtr(0, 0);152 uint16 height = screen.h;141 uint8 *dst = (uint8*)newscreen.getBasePtr((320 - in.w) / 2, 0); 142 const uint8 *src = (uint8*)in.getBasePtr(0, 0); 143 uint16 height = in.h; 153 144 154 145 while (height--) { 155 memcpy(dst, src, screen.pitch);146 memcpy(dst, src, in.pitch); 156 147 dst += newscreen.pitch; 157 src += screen.pitch;148 src += in.pitch; 158 149 } 159 150 160 screen.free();161 screen = newscreen;162 } else if ( screenWidth == 720) {151 in.free(); 152 in = newscreen; 153 } else if (width == 720) { 163 154 // Special case to handle Hercules mode 164 155 width = 640; 165 screenHeight = 400;156 inHeight = 400; 166 157 167 158 // cut off menu and so on.. 168 159 Graphics::Surface newscreen; 169 newscreen.create(width, 400, screen.bytesPerPixel);160 newscreen.create(width, 400, in.bytesPerPixel); 170 161 171 uint8 *dst = (uint8*) newscreen.getBasePtr(0, (400 - 240) / 2);172 uint8 *src = (uint8*)screen.getBasePtr(41, 28);162 uint8 *dst = (uint8*)in.getBasePtr(0, (400 - 240) / 2); 163 const uint8 *src = (uint8*)in.getBasePtr(41, 28); 173 164 174 165 for (int y = 0; y < 240; ++y) { 175 memcpy(dst, src, 640 * screen.bytesPerPixel);166 memcpy(dst, src, 640 * in.bytesPerPixel); 176 167 dst += newscreen.pitch; 177 src += screen.pitch;168 src += in.pitch; 178 169 } 179 170 180 screen.free();181 screen = newscreen;171 in.free(); 172 in = newscreen; 182 173 } 183 174 184 uint16 newHeight = !( screenHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1;175 uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1; 185 176 186 177 int gBitFormatBackUp = gBitFormat; 187 178 gBitFormat = 565; 188 surf->create(kThumbnailWidth, newHeight, sizeof(uint16));189 createThumbnail((const uint8 *)screen.pixels, width * sizeof(uint16), (uint8*)surf->pixels, surf->pitch, width, screenHeight);179 out.create(kThumbnailWidth, newHeight, sizeof(uint16)); 180 createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight); 190 181 gBitFormat = gBitFormatBackUp; 191 182 192 screen.free();183 in.free(); 193 184 194 185 return true; 195 186 } 187 188 bool createThumbnailFromScreen(Graphics::Surface* surf) { 189 assert(surf); 190 191 Graphics::Surface screen; 192 193 if (!grabScreen565(&screen)) 194 return false; 195 196 return createThumbnail(*surf, screen); 197 } 198 199 bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette) { 200 assert(surf); 201 202 Graphics::Surface screen; 203 screen.create(w, h, 2); 204 205 for (uint y = 0; y < screen.h; ++y) { 206 for (uint x = 0; x < screen.w; ++x) { 207 byte r, g, b; 208 r = palette[pixels[y * w + x] * 3]; 209 g = palette[pixels[y * w + x] * 3 + 1]; 210 b = palette[pixels[y * w + x] * 3 + 2]; 211 212 ((uint16 *)screen.pixels)[y * screen.w + x] = RGBToColor<ColorMasks<565> >(r, g, b); 213 } 214 } 215 216 return createThumbnail(*surf, screen); 217 } 218 -
graphics/thumbnail.h
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL$ 22 * $Id$ 23 */ 24 25 #ifndef GRAPHICS_THUMBNAIL_H 26 #define GRAPHICS_THUMBNAIL_H 27 28 #include "common/stream.h" 29 #include "graphics/surface.h" 30 31 namespace Graphics { 32 33 /** 34 * Checks for presence of the thumbnail save header. 35 * Seeks automatically back to start position after check. 36 * 37 * @param in stream to check for header 38 */ 39 bool checkThumbnailHeader(Common::SeekableReadStream &in); 40 41 /** 42 * Skips a thumbnail header, if present. 43 * 44 * @param in stream to process 45 */ 46 bool skipThumbnailHeader(Common::SeekableReadStream &in); 47 48 /** 49 * Lodas a thumbnail from the given input stream. 50 * The loaded thumbnail will be automatically converted to the 51 * current overlay pixelformat. 52 */ 53 bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to); 54 55 /** 56 * Saves a thumbnail to the given write stream. 57 * Automatically creates a thumbnail from screen contents. 58 */ 59 bool saveThumbnail(Common::WriteStream &out); 60 61 /** 62 * Saves a (given) thumbnail to the given write stream. 63 */ 64 bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb); 65 66 } // end of namespace Graphics 67 68 #endif 69