[Scummvm-cvs-logs] SF.net SVN: scummvm:[53373] scummvm/trunk/engines/sword25

sev at users.sourceforge.net sev at users.sourceforge.net
Wed Oct 13 01:59:23 CEST 2010


Revision: 53373
          http://scummvm.svn.sourceforge.net/scummvm/?rev=53373&view=rev
Author:   sev
Date:     2010-10-12 23:59:23 +0000 (Tue, 12 Oct 2010)

Log Message:
-----------
SWORD25: Further savegame work, including savegame screenshots

This handles saving (but not yet re-loaded display) of screenshots into savegame files. It also changes the original engine behaviour of temporarily saving the screenshots in a file 'tmp.png' to keeping the raw PNG file data in a memory block.

Modified Paths:
--------------
    scummvm/trunk/engines/sword25/gfx/graphicengine.cpp
    scummvm/trunk/engines/sword25/gfx/graphicengine.h
    scummvm/trunk/engines/sword25/gfx/screenshot.cpp
    scummvm/trunk/engines/sword25/gfx/screenshot.h
    scummvm/trunk/engines/sword25/kernel/filesystemutil.cpp
    scummvm/trunk/engines/sword25/kernel/filesystemutil.h
    scummvm/trunk/engines/sword25/kernel/persistenceservice.cpp

Modified: scummvm/trunk/engines/sword25/gfx/graphicengine.cpp
===================================================================
--- scummvm/trunk/engines/sword25/gfx/graphicengine.cpp	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/gfx/graphicengine.cpp	2010-10-12 23:59:23 UTC (rev 53373)
@@ -88,6 +88,7 @@
 	m_TimerActive(true),
 	m_FrameTimeSampleSlot(0),
 	m_RepaintedPixels(0),
+	_thumbnail(NULL),
 	ResourceService(pKernel) {
 	m_FrameTimeSamples.resize(FRAMETIME_SAMPLE_COUNT);
 
@@ -99,6 +100,8 @@
 
 GraphicEngine::~GraphicEngine() {
 	_backSurface.free();
+	_frameBuffer.free();
+	delete _thumbnail;
 }
 
 Service *GraphicEngine_CreateObject(Kernel *pKernel) {
@@ -129,6 +132,7 @@
 	m_ScreenRect.bottom = m_Height;
 
 	_backSurface.create(Width, Height, 4);
+	_frameBuffer.create(Width, Height, 4);
 
 	// Standardm\xE4\xDFig ist Vsync an.
 	SetVsync(true);
@@ -163,6 +167,15 @@
 	// Scene zeichnen
 	_renderObjectManagerPtr->render();
 
+	// FIXME: The frame buffer surface is only used as the base for creating thumbnails when saving the
+	// game, since the _backSurface is blanked. Currently I'm doing a slightly hacky check and only
+	// copying the back surface if line 50 (the first line after the interface area) is non-blank
+	if (READ_LE_UINT32((byte *)_backSurface.pixels + (_backSurface.pitch * 50)) & 0xffffff) {
+		// Make a copy of the current frame into the frame buffer
+		Common::copy((byte *)_backSurface.pixels, (byte *)_backSurface.pixels + 
+			(_backSurface.pitch * _backSurface.h), (byte *)_frameBuffer.pixels); 
+	}
+
 	g_system->updateScreen();
 
 	// Debug-Lines zeichnen
@@ -236,58 +249,11 @@
 
 // -----------------------------------------------------------------------------
 
-bool GraphicEngine::GetScreenshot(uint &Width, uint &Height, byte **Data) {
-	if (!ReadFramebufferContents(m_Width, m_Height, Data))
-		return false;
-
-	// Die Gr\xF6\xDFe des Framebuffers zur\xFCckgeben.
-	Width = m_Width;
-	Height = m_Height;
-
-	// Bilddaten vom OpenGL-Format in unser eigenes Format umwandeln.
-	ReverseRGBAComponentOrder(*Data, Width * Height);
-	FlipImagedataVertical(Width, Height, *Data);
-
-	return true;
+Graphics::Surface *GraphicEngine::GetScreenshot() {
+	return &_frameBuffer;
 }
 
 // -----------------------------------------------------------------------------
-
-bool GraphicEngine::ReadFramebufferContents(uint Width, uint Height, byte **Data) {
-    *Data = (byte *)malloc(Width * Height * 4);
-	
-	return true;
-}
-
-// -----------------------------------------------------------------------------
-
-void GraphicEngine::ReverseRGBAComponentOrder(byte *Data, uint size) {
-	uint32 *ptr = (uint32 *)Data;
-
-	for (uint i = 0; i < size; i++) {
-		uint Pixel = *ptr;
-		*ptr = (Pixel & 0xff00ff00) | ((Pixel >> 16) & 0xff) | ((Pixel & 0xff) << 16);
-		++ptr;
-	}
-}
-
-// -----------------------------------------------------------------------------
-
-void GraphicEngine::FlipImagedataVertical(uint Width, uint Height, byte *Data) {
-#if 0 // TODO
-	vector<uint> LineBuffer(Width);
-
-	for (uint Y = 0; Y < Height / 2; ++Y) {
-		vector<uint>::iterator Line1It = Data.begin() + Y * Width;
-		vector<uint>::iterator Line2It = Data.begin() + (Height - 1 - Y) * Width;
-		copy(Line1It, Line1It + Width, LineBuffer.begin());
-		copy(Line2It, Line2It + Width, Line1It);
-		copy(LineBuffer.begin(), LineBuffer.end(), Line2It);
-	}
-#endif
-}
-
-// -----------------------------------------------------------------------------
 // RESOURCE MANAGING
 // -----------------------------------------------------------------------------
 
@@ -432,28 +398,37 @@
 }
 
 namespace {
-bool DoSaveScreenshot(GraphicEngine &GraphicEngine, const Common::String &Filename, bool Thumbnail) {
-	uint Width;
-	uint Height;
-	byte *Data;
-	if (!GraphicEngine.GetScreenshot(Width, Height, &Data)) {
+bool DoSaveScreenshot(GraphicEngine &GraphicEngine, const Common::String &Filename) {
+	Graphics::Surface *data = GraphicEngine.GetScreenshot();
+	if (!data) {
 		BS_LOG_ERRORLN("Call to GetScreenshot() failed. Cannot save screenshot.");
 		return false;
 	}
 
-	if (Thumbnail)
-		return Screenshot::SaveThumbnailToFile(Width, Height, Data, Filename);
-	else
-		return Screenshot::SaveToFile(Width, Height, Data, Filename);
+	Common::FSNode f(Filename);
+	Common::WriteStream *stream = f.createWriteStream();
+	if (!stream) {
+		BS_LOG_ERRORLN("Call to GetScreenshot() failed. Cannot save screenshot.");
+		return false;
+	}
+
+	bool result = Screenshot::SaveToFile(data, stream);
+	delete stream;
+
+	return result;
 }
 }
 
 bool GraphicEngine::SaveScreenshot(const Common::String &Filename) {
-	return DoSaveScreenshot(*this, Filename, false);
+	return DoSaveScreenshot(*this, Filename);
 }
 
 bool GraphicEngine::SaveThumbnailScreenshot(const Common::String &Filename) {
-	return DoSaveScreenshot(*this, Filename, true);
+	// Note: In ScumMVM, rather than saivng the thumbnail to a file, we store it in memory 
+	// until needed when creating savegame files
+	delete _thumbnail;
+	_thumbnail = Screenshot::createThumbnail(&_frameBuffer);
+	return true;
 }
 
 void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint Color) {

Modified: scummvm/trunk/engines/sword25/gfx/graphicengine.h
===================================================================
--- scummvm/trunk/engines/sword25/gfx/graphicengine.h	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/gfx/graphicengine.h	2010-10-12 23:59:23 UTC (rev 53373)
@@ -181,7 +181,7 @@
 	 * @param Height    Returns the height of the frame buffer
 	 * @param Data      Returns the raw data of the frame buffer as an array of 32-bit colour values.
 	*/
-	bool GetScreenshot(uint &Width, uint &Height, byte **Data);
+	Graphics::Surface *GetScreenshot();
 
 
 	RenderObjectPtr<Panel> GetMainPanel();
@@ -285,6 +285,12 @@
 	Graphics::Surface _backSurface;
 	Graphics::Surface *getSurface() { return &_backSurface; }
 
+	Graphics::Surface _frameBuffer;
+	Graphics::Surface *getFrameBuffer() { return &_frameBuffer; }
+
+	Common::MemoryReadStream *_thumbnail;
+	Common::MemoryReadStream *getThumbnail() { return _thumbnail; }
+
 	// Access methods
 
 	/**
@@ -385,10 +391,6 @@
 	};
 
 	Common::Array<DebugLine> m_DebugLines;
-
-	static bool ReadFramebufferContents(uint Width, uint Height, byte **Data);
-	static void ReverseRGBAComponentOrder(byte *Data, uint size);
-	static void FlipImagedataVertical(uint Width, uint Height, byte *Data);
 };
 
 } // End of namespace Sword25

Modified: scummvm/trunk/engines/sword25/gfx/screenshot.cpp
===================================================================
--- scummvm/trunk/engines/sword25/gfx/screenshot.cpp	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/gfx/screenshot.cpp	2010-10-12 23:59:23 UTC (rev 53373)
@@ -38,175 +38,152 @@
 // Includes
 // -----------------------------------------------------------------------------
 
+#include "common/system.h"
+#include "common/savefile.h"
 #include "sword25/gfx/screenshot.h"
+#include "sword25/kernel/filesystemutil.h"
 #include <png.h>
 
 namespace Sword25 {
 
 // -----------------------------------------------------------------------------
 
+#include "common/pack-start.h"
 struct RGB_PIXEL {
-	RGB_PIXEL(byte _Red, byte _Green, byte _Blue) :
-		Red(_Red),
-		Green(_Green),
-		Blue(_Blue)
-	{};
-
 	byte Red;
 	byte Green;
 	byte Blue;
-};
+} PACKED_STRUCT;
+#include "common/pack-end.h"
 
-bool Screenshot::SaveToFile(uint Width, uint Height, const byte *Data, const Common::String &Filename) {
-#if 0
-	BS_ASSERT(Data.size() == Width * Height);
+void userWriteFn(png_structp png_ptr, png_bytep data, png_size_t length) {
+	static_cast<Common::WriteStream *>(png_ptr->io_ptr)->write(data, length);
+}
 
-	// Buffer f\xFCr Bildschirminhalt in RGB reservieren
-	vector<RGB_PIXEL> PixelBuffer;
-	PixelBuffer.reserve(Width * Height);
+void userFlushFn(png_structp png_ptr) {
+}
 
-	// Framebufferdaten pixelweise von RGBA nach RGB konvertieren
-	vector<uint>::const_iterator it = Data.begin();
-	for (uint y = 0; y < Height; y++) {
-		for (uint x = 0; x < Width; x++) {
-			uint SrcPixel = *it++;
-			PixelBuffer.push_back(RGB_PIXEL((SrcPixel >> 16) & 0xff, (SrcPixel >> 8) & 0xff, SrcPixel & 0xff));
-		}
-	}
-	BS_ASSERT(it == Data.end());
-	BS_ASSERT(Data.size() == PixelBuffer.size());
 
-	// Variablen f\xFCr die PNG-Erstellung
-	FILE *OutFile = 0;
-	png_structp png_ptr = 0;
-	png_infop info_ptr = 0;
+bool Screenshot::SaveToFile(Graphics::Surface *Data, Common::WriteStream *Stream) {
+	// Reserve buffer space
+	RGB_PIXEL *pixelBuffer = new RGB_PIXEL[Data->w * Data->h];
 
-	try {
-		OutFile = fopen(Filename.c_str(), "wb");
-		if (!OutFile) {
-			BS_LOG_ERRORLN("Could not create screenshot-file \"%s\".", Filename.c_str());
-			throw(0);
-		}
+	// Convert the RGBA data to RGB
+	const byte *pSrc = (const byte *)Data->getBasePtr(0, 0);
+	RGB_PIXEL *pDest = pixelBuffer;
 
-		png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-		if (!png_ptr) {
-			BS_LOG_ERRORLN("Could not create PNG write-struct.");
-			throw(0);
+	for (uint y = 0; y < Data->h; y++) {
+		for (uint x = 0; x < Data->w; x++) {
+			uint32 srcPixel = READ_LE_UINT32(pSrc);
+			pSrc += sizeof(uint32);
+			pDest->Red = (srcPixel >> 16) & 0xff;
+			pDest->Green = (srcPixel >> 8) & 0xff;
+			pDest->Blue = srcPixel & 0xff;
+			++pDest;
 		}
+	}
 
-		png_infop info_ptr = png_create_info_struct(png_ptr);
-		if (!info_ptr) {
-			BS_LOG_ERRORLN("Could not create PNG info-struct.");
-			throw(0);
-		}
+	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if (!png_ptr)
+		error("Could not create PNG write-struct.");
 
-		// Der Kompressionsbuffer muss gro\xDF genug sein um das gesamte Bild zu beinhalten.
-		// Dieses stellt sicher, dass nur ein IDAT Chunk erstellt wird.
-		// Als Buffergr\xF6\xDFe wird 110% der Rohdatengr\xF6\xDFe verwandt, um sicher zu gehen.
-		png_set_compression_buffer_size(png_ptr, (Width * Height * 3 * 110) / 100);
+	png_infop info_ptr = png_create_info_struct(png_ptr);
+	if (!info_ptr)
+		error("Could not create PNG info-struct.");
 
-		// PNG-Info Struktur initialisieren
-		png_set_IHDR(png_ptr, info_ptr,
-		             Width,                          // Breite
-		             Height,                         // H\xF6he
-		             8,                              // Bittiefe pro Kanal
-		             PNG_COLOR_TYPE_RGB,             // Farbformat
-		             PNG_INTERLACE_NONE,             // Interlacing-Typ
-		             PNG_COMPRESSION_TYPE_DEFAULT,   // Kompressions-Typ
-		             PNG_FILTER_TYPE_DEFAULT);       // Filter-Typ
+	//  The compression buffer must be large enough to the entire image.
+	// This ensures that only an IDAT chunk is created.
+	// When buffer size is used 110% of the raw data size to be sure.
+	png_set_compression_buffer_size(png_ptr, (Data->w * Data->h * 3 * 110) / 100);
 
-		// Rowpointer erstellen
-		vector<png_bytep> RowPointers;
-		RowPointers.reserve(Height);
-		for (uint i = 0; i < Height; i++) {
-			RowPointers.push_back((png_bytep)(&PixelBuffer[Width * i]));
-		}
-		png_set_rows(png_ptr, info_ptr, &RowPointers[0]);
+	// Initialise PNG-Info structure
+	png_set_IHDR(png_ptr, info_ptr,
+	             Data->w,                        // Width
+	             Data->h,                        // Height
+	             8,                             // Bits depth
+	             PNG_COLOR_TYPE_RGB,             // Colour type
+	             PNG_INTERLACE_NONE,             // No interlacing
+	             PNG_COMPRESSION_TYPE_DEFAULT,   // Compression type
+	             PNG_FILTER_TYPE_DEFAULT);       // Filter Type
 
-		png_init_io(png_ptr, OutFile);
-
-		// Bild schreiben
-		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
-
-		png_destroy_write_struct(&png_ptr, &info_ptr);
-		fclose(OutFile);
+	// Rowpointer erstellen
+	png_bytep *rowPointers = new png_bytep[Data->h];
+	for (uint i = 0; i < Data->h; i++) {
+		rowPointers[i] = (png_bytep)&pixelBuffer[Data->w * i];
 	}
+	png_set_rows(png_ptr, info_ptr, &rowPointers[0]);
 
-	catch (int) {
-		// Wenn die Datei bereits erstellt wurde, Datei schlie\xDFen und l\xF6schen.
-		if (OutFile) {
-			fclose(OutFile);
-			remove(Filename.c_str());
-		}
+	// Write out the png data to the file
+	png_set_write_fn(png_ptr, (void *)Stream, userWriteFn, userFlushFn);
+	png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
 
-		if (info_ptr) png_destroy_write_struct(0, &info_ptr);
-		if (png_ptr) png_destroy_write_struct(&png_ptr, (png_infopp) 0);
+	png_destroy_write_struct(&png_ptr, &info_ptr);
 
-		BS_LOG_ERRORLN("Could not create screenshot (\"%s\").", Filename.c_str());
-		return false;
-	}
-#else
-	warning("STUB: BS_Screenshot::SaveToFile(%d, %d, .., %s)", Width, Height, Filename.c_str());
-#endif
+	delete[] pixelBuffer;
+	delete[] rowPointers;
 
 	return true;
 }
 
 // -----------------------------------------------------------------------------
 
-bool Screenshot::SaveThumbnailToFile(uint Width, uint Height, const byte *Data, const Common::String &Filename) {
-#if 0
-	//
-	// Diese Methode nimmt ein Screenshot mit den Ma\xDFen von 800x600 und erzeugt einen Screenshot mit den Ma\xDFen von 200x125.
-	// Dabei werden je 50 Pixel oben und unten abgeschnitten (die Interface-Leisten im Spiel). Das verbleibende Bild von 800x500 wird auf
-	// ein 16tel seiner Gr\xF6\xDFe reduziert, indem es in 4x4 Pixelbl\xF6cke ausgeteilt wird und der Durchschnitt jedes Blockes einen Pixel des Zielbildes generiert.
-	// Abschlie\xDFend wird das Ergebnis als PNG-Datei unter dem \xFCbergebenen Dateinamen gespeichert.
-	//
+Common::MemoryReadStream *Screenshot::createThumbnail(Graphics::Surface *Data) {
+	// This method takes a screen image with a dimension of 800x600, and creates a screenshot with a dimension of 200x125.
+	// First 50 pixels are cut off the top and bottom (the interface boards in the game). The remaining image of 800x500 
+	// will be on a 16th of its size, reduced by being handed out in 4x4 pixel blocks and the average of each block 
+	// generates a pixel of the target image. Finally, the result as a PNG file is stored as a file.
 
-	// Die Ausgangsgr\xF6\xDFe muss 800x600 sein.
-	if (Width != 800 || Height != 600) {
+	// The source image must be 800x600.
+	if (Data->w != 800 || Data->h != 600 || Data->bytesPerPixel != 4) {
 		BS_LOG_ERRORLN("The sreenshot dimensions have to be 800x600 in order to be saved as a thumbnail.");
 		return false;
 	}
 
-	// Buffer f\xFCr die Zieldaten erstellen (RGBA Bild mit den Ma\xDFen 200x125).
-	vector<uint> ThumbnailData(200 * 125);
+	// Buffer for the output thumbnail
+	Graphics::Surface thumbnail;
+	thumbnail.create(200, 125, 4);
 
 	// \xDCber das Zielbild iterieren und einen Pixel zur Zeit berechnen.
 	uint x, y;
 	x = y = 0;
-	for (vector<uint>::iterator Iter = ThumbnailData.begin(); Iter != ThumbnailData.end(); ++Iter) {
-		// Durchschnitt \xFCber 4x4 Pixelblock im Quellbild bilden.
-		uint Alpha, Red, Green, Blue;
-		Alpha = Red = Green = Blue = 0;
-		for (uint j = 0; j < 4; ++j) {
-			for (uint i = 0; i < 4; ++i) {
-				uint Pixel = Data[((y * 4) + j + 50) * 800 + ((x * 4) + i)];
-				Alpha += (Pixel >> 24);
-				Red += (Pixel >> 16) & 0xff;
-				Green += (Pixel >> 8) & 0xff;
-				Blue += Pixel & 0xff;
+	
+	for (byte *pDest = (byte *)thumbnail.pixels; pDest < ((byte *)thumbnail.pixels + thumbnail.pitch * thumbnail.h); ) {
+		// Get an average over a 4x4 pixel block in the source image
+		int alpha, red, green, blue;
+		alpha = red = green = blue = 0;
+		for (int j = 0; j < 4; ++j) {
+			const uint32 *srcP = (const uint32 *)Data->getBasePtr(x * 4, y * 4 + j + 50);
+			for (int i = 0; i < 4; ++i) {
+				uint32 pixel = READ_LE_UINT32(srcP + i);
+				alpha += (pixel >> 24);
+				red += (pixel >> 16) & 0xff;
+				green += (pixel >> 8) & 0xff;
+				blue += pixel & 0xff;
 			}
 		}
 
-		// Zielpixel schreiben.
-		*Iter = ((Alpha / 16) << 24) | ((Red / 16) << 16) | ((Green / 16) << 8) | (Blue / 16);
+		// Write target pixel
+		*pDest++ = blue / 16;
+		*pDest++ = green / 16;
+		*pDest++ = red / 16;
+		*pDest++ = alpha / 16;
 
-		// Mitz\xE4hlen an welcher Stelle im Zielbild wir uns befinden.
+		// Move to next block
 		++x;
-		if (x == 200) {
+		if (x == thumbnail.w) {
 			x = 0;
 			++y;
 		}
 	}
 
-	// Bild als PNG Speichern.
-	return SaveToFile(200, 125, ThumbnailData, Filename);
-#else
-	warning("STUB: BS_Screenshot::SaveThumbnailToFile(%d, %d, .., %s)", Width, Height, Filename.c_str());
+	// Create a PNG representation of the thumbnail data
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	SaveToFile(&thumbnail, stream);
 
-	return true;
-#endif
+	// Output a MemoryReadStream that encompasses the written data
+	Common::MemoryReadStream *result = new Common::MemoryReadStream(stream->getData(), stream->size(),
+		DisposeAfterUse::YES);
+	return result;
 }
 
 } // End of namespace Sword25

Modified: scummvm/trunk/engines/sword25/gfx/screenshot.h
===================================================================
--- scummvm/trunk/engines/sword25/gfx/screenshot.h	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/gfx/screenshot.h	2010-10-12 23:59:23 UTC (rev 53373)
@@ -39,6 +39,7 @@
 // Includes
 // -----------------------------------------------------------------------------
 
+#include "graphics/surface.h"
 #include "sword25/kernel/common.h"
 
 namespace Sword25 {
@@ -49,8 +50,8 @@
 
 class Screenshot {
 public:
-	static bool SaveToFile(uint Width, uint Height, const byte *Data, const Common::String &Filename);
-	static bool SaveThumbnailToFile(uint Width, uint Height, const byte *Data, const Common::String &Filename);
+	static bool SaveToFile(Graphics::Surface *Data, Common::WriteStream *Stream);
+	static Common::MemoryReadStream *createThumbnail(Graphics::Surface *Data);
 };
 
 } // End of namespace Sword25

Modified: scummvm/trunk/engines/sword25/kernel/filesystemutil.cpp
===================================================================
--- scummvm/trunk/engines/sword25/kernel/filesystemutil.cpp	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/kernel/filesystemutil.cpp	2010-10-12 23:59:23 UTC (rev 53373)
@@ -41,6 +41,7 @@
 #include "common/savefile.h"
 #include "common/system.h"
 #include "sword25/kernel/filesystemutil.h"
+#include "sword25/kernel/persistenceservice.h"
 
 namespace Sword25 {
 
@@ -113,7 +114,13 @@
 
 	virtual bool FileExists(const Common::String &Filename) {
 		Common::File f;
-		return f.exists(Filename);
+		if (f.exists(Filename))
+			return true;
+
+		// Check if the file exists in the save folder
+		Common::FSNode folder(PersistenceService::GetSavegameDirectory());
+		Common::FSNode fileNode = folder.getChild(FileSystemUtil::GetInstance().GetPathFilename(Filename));
+		return fileNode.exists();
 	}
 
 	virtual bool CreateDirectory(const Common::String &DirectoryName) {
@@ -128,6 +135,16 @@
 		sort(filenames.begin(), filenames.end());
 		return filenames;
 	}
+
+	virtual Common::String GetPathFilename(const Common::String &Path) {
+		for (int i = Path.size() - 1; i >= 0; --i) {
+			if ((Path[i] == '/') || (Path[i] == '\\')) {
+				return Common::String(&Path.c_str()[i + 1]);
+			}
+		}
+
+		return Path;
+	}
 };
 
 // -----------------------------------------------------------------------------

Modified: scummvm/trunk/engines/sword25/kernel/filesystemutil.h
===================================================================
--- scummvm/trunk/engines/sword25/kernel/filesystemutil.h	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/kernel/filesystemutil.h	2010-10-12 23:59:23 UTC (rev 53373)
@@ -107,6 +107,12 @@
 	 * @return              Returns a vector containing all of the found filenames
 	 */
 	virtual Common::StringArray GetFilesInDirectory(const Common::String &Path) = 0;
+	/**
+	 * Gets the filename from a path and filename
+	 * @param Filename		The full path and filename
+	 * @return				Returns just the filename
+	 */
+	virtual Common::String GetPathFilename(const Common::String &Path) = 0;
 };
 
 } // End of namespace Sword25

Modified: scummvm/trunk/engines/sword25/kernel/persistenceservice.cpp
===================================================================
--- scummvm/trunk/engines/sword25/kernel/persistenceservice.cpp	2010-10-12 23:58:51 UTC (rev 53372)
+++ scummvm/trunk/engines/sword25/kernel/persistenceservice.cpp	2010-10-12 23:59:23 UTC (rev 53373)
@@ -62,7 +62,7 @@
 const char         *FILE_MARKER = "BS25SAVEGAME";
 const uint  SLOT_COUNT = 18;
 const uint  FILE_COPY_BUFFER_SIZE = 1024 * 10;
-const char *VERSIONID = "5";
+const char *VERSIONID = "SCUMMVM1";
 
 // -------------------------------------------------------------------------
 
@@ -194,8 +194,8 @@
 				// Die Beschreibung des Spielstandes besteht aus einer textuellen Darstellung des \xC4nderungsdatums der Spielstanddatei.
 				CurSavegameInfo.Description = FormatTimestamp(FileSystemUtil::GetInstance().GetFileTime(Filename));
 				// Den Offset zu den gespeicherten Spieldaten innerhalb der Datei speichern.
-				// Dieses entspricht der aktuellen Position + 1, da nach der letzten Headerinformation noch ein Leerzeichen als trenner folgt.
-				CurSavegameInfo.GamedataOffset = static_cast<uint>(File->pos()) + 1;
+				// Dieses entspricht der aktuellen Position, da nach der letzten Headerinformation noch ein Leerzeichen als trenner folgt.
+				CurSavegameInfo.GamedataOffset = static_cast<uint>(File->pos());
 			}
 
 			delete File;
@@ -357,17 +357,18 @@
 		error("Unable to write game data to savegame file \"%s\".", Filename.c_str());
 	}
 
-	// Screenshotdatei an die Datei anf\xFCgen.
-	if (FileSystemUtil::GetInstance().FileExists(ScreenshotFilename)) {
-		Common::File ScreenshotFile;
-		if (!ScreenshotFile.open(ScreenshotFilename.c_str()))
-			error("Unable to load screenshot file");
+	// Get the screenshot
+	Common::MemoryReadStream *thumbnail = (static_cast<GraphicEngine *>(
+		Kernel::GetInstance()->GetService("gfx")))->getThumbnail();
 
+	if (thumbnail) {
 		byte *Buffer = new Byte[FILE_COPY_BUFFER_SIZE];
-		while (!ScreenshotFile.eos()) {
-			int bytesRead = ScreenshotFile.read(&Buffer[0], FILE_COPY_BUFFER_SIZE);
+		while (!thumbnail->eos()) {
+			int bytesRead = thumbnail->read(&Buffer[0], FILE_COPY_BUFFER_SIZE);
 			File->write(&Buffer[0], bytesRead);
 		}
+
+		delete[] Buffer;
 	} else {
 		BS_LOG_WARNINGLN("The screenshot file \"%s\" does not exist. Savegame is written without a screenshot.", Filename.c_str());
 	}
@@ -416,7 +417,7 @@
 	byte *CompressedDataBuffer = new byte[CurSavegameInfo.GamedataLength];
 	byte *UncompressedDataBuffer = new Bytef[CurSavegameInfo.GamedataUncompressedLength];
 
-	File = sfm->openForLoading(GenerateSavegamePath(SlotID));
+	File = sfm->openForLoading(GenerateSavegameFilename(SlotID));
 
 	File->seek(CurSavegameInfo.GamedataOffset);
 	File->read(reinterpret_cast<char *>(&CompressedDataBuffer[0]), CurSavegameInfo.GamedataLength);


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list