diff --git a/source/common/menu/savegamemanager.cpp b/source/common/menu/savegamemanager.cpp index 45bf519f1..e1f20a9ca 100644 --- a/source/common/menu/savegamemanager.cpp +++ b/source/common/menu/savegamemanager.cpp @@ -403,7 +403,7 @@ unsigned FSavegameManager::ExtractSaveData(int index) PNGHandle *png = M_VerifyPNG(picreader); if (png != nullptr) { - SavePic = nullptr; // not yet implemented: PNGTexture_CreateFromFile(png, node->Filename); + SavePic = PNGTexture_CreateFromFile(png, node->Filename); delete png; if (SavePic && SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1) { diff --git a/source/common/textures/formats/pngtexture.cpp b/source/common/textures/formats/pngtexture.cpp index df0c1a029..04b962871 100644 --- a/source/common/textures/formats/pngtexture.cpp +++ b/source/common/textures/formats/pngtexture.cpp @@ -511,3 +511,129 @@ int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion) } +//========================================================================== +// +// A savegame picture +// This is essentially a stripped down version of the PNG texture +// only supporting the features actually present in a savegame +// that does not use an image source, because image sources are not +// meant to be transient data like the savegame picture. +// +//========================================================================== + +class FPNGFileTexture : public FTexture +{ +public: + FPNGFileTexture (FileReader &lump, int width, int height, uint8_t colortype); + virtual FBitmap GetBgraBitmap(const PalEntry *remap, int *trans) override; + +protected: + + FileReader fr; + uint8_t ColorType; + int PaletteSize; +}; + + +//========================================================================== +// +// +// +//========================================================================== + +FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) +{ + if (M_FindPNGChunk(png, MAKE_ID('I','H','D','R')) == 0) + { + return nullptr; + } + + // Savegame images can only be either 8 bit paletted or 24 bit RGB + auto &data = png->File; + int width = data.ReadInt32BE(); + int height = data.ReadInt32BE(); + uint8_t bitdepth = data.ReadUInt8(); + uint8_t colortype = data.ReadUInt8(); + uint8_t compression = data.ReadUInt8(); + uint8_t filter = data.ReadUInt8(); + uint8_t interlace = data.ReadUInt8(); + + // Reject anything that cannot be put into a savegame picture by GZDoom itself. + if (compression != 0 || filter != 0 || interlace > 0 || bitdepth != 8 || (colortype != 2 && colortype != 3)) return nullptr; + else return new FPNGFileTexture (png->File, width, height, colortype); +} + +//========================================================================== +// +// +// +//========================================================================== + +FPNGFileTexture::FPNGFileTexture (FileReader &lump, int width, int height, uint8_t colortype) +: ColorType(colortype) +{ + Size.x = width; + Size.y = height; + fr = std::move(lump); +} + +//=========================================================================== +// +// FPNGTexture::CopyPixels +// +//=========================================================================== + +FBitmap FPNGFileTexture::GetBgraBitmap(const PalEntry *remap, int *trans) +{ + FBitmap bmp; + // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? + PalEntry pe[256]; + uint32_t len, id; + int pixwidth = Size.x * (ColorType == 2? 3:1); + + FileReader *lump = &fr; + + bmp.Create(Size.x, Size.y); + lump->Seek(33, FileReader::SeekSet); + lump->Read(&len, 4); + lump->Read(&id, 4); + while (id != MAKE_ID('I','D','A','T') && id != MAKE_ID('I','E','N','D')) + { + len = BigLong((unsigned int)len); + if (id != MAKE_ID('P','L','T','E')) + lump->Seek (len, FileReader::SeekCur); + else + { + PaletteSize = std::min (len / 3, 256); + for(int i = 0; i < PaletteSize; i++) + { + pe[i].r = lump->ReadUInt8(); + pe[i].g = lump->ReadUInt8(); + pe[i].b = lump->ReadUInt8(); + pe[i].a = 255; + } + } + lump->Seek(4, FileReader::SeekCur); // Skip CRC + lump->Read(&len, 4); + id = MAKE_ID('I','E','N','D'); + lump->Read(&id, 4); + } + auto StartOfIDAT = (uint32_t)lump->Tell() - 8; + + TArray Pixels(pixwidth * Size.y); + + lump->Seek (StartOfIDAT, FileReader::SeekSet); + lump->Read(&len, 4); + lump->Read(&id, 4); + M_ReadIDAT (*lump, Pixels.Data(), Size.x, Size.y, pixwidth, 8, ColorType, 0, BigLong((unsigned int)len)); + + if (ColorType == 3) + { + bmp.CopyPixelData(0, 0, Pixels.Data(), Size.x, Size.y, 1, Size.x, 0, pe); + } + else + { + bmp.CopyPixelDataRGB(0, 0, Pixels.Data(), Size.x, Size.y, 3, pixwidth, 0, CF_RGB); + } + return bmp; +} \ No newline at end of file diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index a16f62a8f..e4ec15f20 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -164,6 +164,7 @@ void GLInstance::Draw2D(F2DDrawer *drawer) if (cmd.mTexture != nullptr) { auto tex = cmd.mTexture; + if (cmd.mType == F2DDrawer::DrawTypeRotateSprite) { // todo: Set up hictinting. (broken as the feature is...) diff --git a/wadsrc/static/engine/language.csv b/wadsrc/static/engine/language.csv index 724423de4..07f16bb2b 100644 --- a/wadsrc/static/engine/language.csv +++ b/wadsrc/static/engine/language.csv @@ -2090,36 +2090,36 @@ The Morgue/mortuary (dm),TXTS_T_MAP24,,,,,,,,,,,,,,,,,,,,,, Island Caves (dm),TXTS_T_MAP25,,,,,,,,,,,,,,,,,,,,,, Twin Dragon,TXTS_T_TITLE,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP00,Training,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP01,Abu Simbel,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP02,Dendur,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP03,Kalabash,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP04,El Subua,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP05,El Derr,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP06,Abu Churab,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP07,Philae,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP08,El Kab,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP09,Aswan,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP10,10,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP11,Qubbet el Kawa,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP12,Abydos,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP13,Edufu,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP14,West Bank,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP15,Luxor,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP16,Karnak,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP17,Saqqara,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP18,Mitrrahn,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP19,19,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP20,20,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP21,Level 21,No names exist for the MP levels,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP22,Level 22,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP23,Level 23,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP24,Level 24,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP25,Level 25,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP26,Level 26,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP27,Level 27,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP28,Level 28,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP29,Level 29,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP30,Level 30,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP31,Level 31,,,,,,,,,,,,,,,,,,,,,, -TXT_EX_MAP32,Level 32,,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file +Training,TXT_EX_MAP00,,,,,,,,,,,,,,,,,,,,,, +Abu Simbel,TXT_EX_MAP01,,,,,,,,,,,,,,,,,,,,,, +Dendur,TXT_EX_MAP02,,,,,,,,,,,,,,,,,,,,,, +Kalabash,TXT_EX_MAP03,,,,,,,,,,,,,,,,,,,,,, +El Subua,TXT_EX_MAP04,,,,,,,,,,,,,,,,,,,,,, +El Derr,TXT_EX_MAP05,,,,,,,,,,,,,,,,,,,,,, +Abu Churab,TXT_EX_MAP06,,,,,,,,,,,,,,,,,,,,,, +Philae,TXT_EX_MAP07,,,,,,,,,,,,,,,,,,,,,, +El Kab,TXT_EX_MAP08,,,,,,,,,,,,,,,,,,,,,, +Aswan,TXT_EX_MAP09,,,,,,,,,,,,,,,,,,,,,, +10,TXT_EX_MAP10,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, +Qubbet el Kawa,TXT_EX_MAP11,,,,,,,,,,,,,,,,,,,,,, +Abydos,TXT_EX_MAP12,,,,,,,,,,,,,,,,,,,,,, +Edufu,TXT_EX_MAP13,,,,,,,,,,,,,,,,,,,,,, +West Bank,TXT_EX_MAP14,,,,,,,,,,,,,,,,,,,,,, +Luxor,TXT_EX_MAP15,,,,,,,,,,,,,,,,,,,,,, +Karnak,TXT_EX_MAP16,,,,,,,,,,,,,,,,,,,,,, +Saqqara,TXT_EX_MAP17,,,,,,,,,,,,,,,,,,,,,, +Mitrrahn,TXT_EX_MAP18,,,,,,,,,,,,,,,,,,,,,, +19,TXT_EX_MAP19,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, +20,TXT_EX_MAP20,Does not have a readable name.,,,,,,,,,,,,,,,,,,,,, +Level 21,TXT_EX_MAP21,No names exist for the MP levels,,,,,,,,,,,,,,,,,,,,, +Level 22,TXT_EX_MAP22,,,,,,,,,,,,,,,,,,,,,, +Level 23,TXT_EX_MAP23,,,,,,,,,,,,,,,,,,,,,, +Level 24,TXT_EX_MAP24,,,,,,,,,,,,,,,,,,,,,, +Level 25,TXT_EX_MAP25,,,,,,,,,,,,,,,,,,,,,, +Level 26,TXT_EX_MAP26,,,,,,,,,,,,,,,,,,,,,, +Level 27,TXT_EX_MAP27,,,,,,,,,,,,,,,,,,,,,, +Level 28,TXT_EX_MAP28,,,,,,,,,,,,,,,,,,,,,, +Level 29,TXT_EX_MAP29,,,,,,,,,,,,,,,,,,,,,, +Level 30,TXT_EX_MAP30,,,,,,,,,,,,,,,,,,,,,, +Level 31,TXT_EX_MAP31,,,,,,,,,,,,,,,,,,,,,, +Level 32,TXT_EX_MAP32,,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file