diff options
Diffstat (limited to 'engines/sword25')
47 files changed, 828 insertions, 1384 deletions
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp index caa1cf51ac..edb8c30545 100644 --- a/engines/sword25/detection.cpp +++ b/engines/sword25/detection.cpp @@ -24,6 +24,7 @@ #include "engines/advancedDetector.h" #include "sword25/sword25.h" +#include "sword25/detection_tables.h" #include "sword25/kernel/persistenceservice.h" namespace Sword25 { @@ -35,38 +36,6 @@ static const PlainGameDescriptor Sword25Game[] = { {0, 0} }; -namespace Sword25 { - -// TODO: Need to decide whether we're going to implement code to detect all the various languages allowed, -// both by the core data package, as well as the extra languages added by the patch file; also, I don't -// think that all the languages supported by the game currently have constants in ScummVM -static const ADGameDescription gameDescriptions[] = { - { - "sword25", - "", - AD_ENTRY1s("data.b25c", "f8b6e03ada2d2f6cf27fbc11ad1572e9", 654310588), - Common::EN_ANY, - Common::kPlatformUnknown, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - { - "sword25", - "Extracted", - {{"_includes.lua", 0, 0, -1}, - {"boot.lua", 0, 0, -1}, - {"kernel.lua", 0, 0, -1}, - AD_LISTEND}, - Common::EN_ANY, - Common::kPlatformUnknown, - GF_EXTRACTED, - Common::GUIO_NONE - }, - AD_TABLE_END_MARKER -}; - -} // End of namespace Sword25 - static const char *directoryGlobs[] = { "system", // Used by extracted dats 0 @@ -102,7 +71,7 @@ public: Sword25MetaEngine() : AdvancedMetaEngine(detectionParams) {} virtual const char *getName() const { - return "Broken Sword 2.5"; + return "Sword25"; } virtual const char *getOriginalCopyright() const { diff --git a/engines/sword25/detection_tables.h b/engines/sword25/detection_tables.h new file mode 100644 index 0000000000..ca586b4f01 --- /dev/null +++ b/engines/sword25/detection_tables.h @@ -0,0 +1,129 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +namespace Sword25 { + +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSFX; +using Common::GUIO_NOMUSIC; + +static const ADGameDescription gameDescriptions[] = { + { + "sword25", + "", + AD_ENTRY1s("data.b25c", "f8b6e03ada2d2f6cf27fbc11ad1572e9", 654310588), + Common::EN_ANY, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_fr.b25c", "690caf157387e06d2c3d1ca53c43f428", 1006043), + Common::FR_FRA, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("data.b25c", "f8b6e03ada2d2f6cf27fbc11ad1572e9", 654310588), + Common::DE_DEU, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_hr.b25c", "e881054d1f8ec1e527422fc521c25405", 1273217), + Common::HU_HUN, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_it.b25c", "f3325666da0515cc2b42062e953c0889", 996197), + Common::IT_ITA, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_pl.b25c", "49dc1a20f95391a808e475c49be2bac0", 1281799), + Common::PL_POL, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_pt.b25c", "1df701432f9e13dcefe1adeb890b9c69", 993812), + Common::PT_BRA, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_ru.b25c", "deb33dd2f90a71ff60181918a8ce5063", 1235378), + Common::RU_RUS, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + { + "sword25", + "", + AD_ENTRY1s("lang_es.b25c", "384c19072d83725f351bb9ecb4d3f02b", 987965), + Common::ES_ESP, + Common::kPlatformUnknown, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + + // Extracted version + { + "sword25", + "Extracted", + {{"_includes.lua", 0, 0, -1}, + {"boot.lua", 0, 0, -1}, + {"kernel.lua", 0, 0, -1}, + AD_LISTEND}, + Common::EN_ANY, + Common::kPlatformUnknown, + GF_EXTRACTED, + Common::GUIO_NONE + }, + AD_TABLE_END_MARKER +}; + +} // End of namespace Sword25 diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp index d267506ae2..d0ad41de22 100644 --- a/engines/sword25/fmv/movieplayer.cpp +++ b/engines/sword25/fmv/movieplayer.cpp @@ -145,7 +145,7 @@ bool MoviePlayer::isMovieLoaded() { } bool MoviePlayer::isPaused() { - return _decoder.isPaused(); + return _decoder.isPaused() || _decoder.endOfVideo(); } float MoviePlayer::getScaleFactor() { diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp index 07cb56356d..be6d940d23 100644 --- a/engines/sword25/fmv/theora_decoder.cpp +++ b/engines/sword25/fmv/theora_decoder.cpp @@ -54,7 +54,6 @@ static double rint(double v) { TheoraDecoder::TheoraDecoder(Audio::Mixer::SoundType soundType) { _fileStream = 0; - _surface = 0; _theoraPacket = 0; _vorbisPacket = 0; @@ -298,8 +297,14 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) { _endOfAudio = true; } - _surface = new Graphics::Surface(); - _surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, g_system->getScreenFormat()); + _surface.create(_theoraInfo.frame_width, _theoraInfo.frame_height, g_system->getScreenFormat()); + + // Set up a display surface + _displaySurface.pixels = _surface.getBasePtr(_theoraInfo.pic_x, _theoraInfo.pic_y); + _displaySurface.w = _theoraInfo.pic_width; + _displaySurface.h = _theoraInfo.pic_height; + _displaySurface.format = _surface.format; + _displaySurface.pitch = _surface.pitch; // Set the frame rate _frameRate = Common::Rational(_theoraInfo.fps_numerator, _theoraInfo.fps_denominator); @@ -337,9 +342,9 @@ void TheoraDecoder::close() { delete _fileStream; _fileStream = 0; - _surface->free(); - delete _surface; - _surface = 0; + _surface.free(); + _displaySurface.pixels = 0; + _displaySurface.free(); reset(); } @@ -412,7 +417,7 @@ const Graphics::Surface *TheoraDecoder::decodeNextFrame() { } } - return _surface; + return &_displaySurface; } bool TheoraDecoder::queueAudio() { @@ -440,7 +445,11 @@ bool TheoraDecoder::queueAudio() { _audiobufFill += (i * _vorbisInfo.channels) << 1; if (_audiobufFill == AUDIOFD_FRAGSIZE) { - _audStream->queueBuffer((byte *)_audiobuf, AUDIOFD_FRAGSIZE, DisposeAfterUse::NO, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO); + byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO; +#ifdef SCUMM_LITTLE_ENDIAN + flags |= Audio::FLAG_LITTLE_ENDIAN; +#endif + _audStream->queueBuffer((byte *)_audiobuf, AUDIOFD_FRAGSIZE, DisposeAfterUse::NO, flags); // The audio mixer is now responsible for the old audio buffer. // We need to create a new one. @@ -533,7 +542,7 @@ void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer) { assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1); assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1); - Graphics::convertYUV420ToRGB(_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride); + Graphics::convertYUV420ToRGB(&_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride); } } // End of namespace Sword25 diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h index 10a05647c3..e8cc5ab8b9 100644 --- a/engines/sword25/fmv/theora_decoder.h +++ b/engines/sword25/fmv/theora_decoder.h @@ -70,8 +70,8 @@ public: const Graphics::Surface *decodeNextFrame(); bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { return _surface->w; } - uint16 getHeight() const { return _surface->h; } + uint16 getWidth() const { return _displaySurface.w; } + uint16 getHeight() const { return _displaySurface.h; } uint32 getFrameCount() const { // It is not possible to get frame count easily @@ -80,7 +80,7 @@ public: return 0; } - Graphics::PixelFormat getPixelFormat() const { return _surface->format; } + Graphics::PixelFormat getPixelFormat() const { return _displaySurface.format; } uint32 getElapsedTime() const; uint32 getTimeToNextFrame() const; @@ -96,7 +96,8 @@ private: void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer); Common::SeekableReadStream *_fileStream; - Graphics::Surface *_surface; + Graphics::Surface _surface; + Graphics::Surface _displaySurface; Common::Rational _frameRate; double _nextFrameStartTime; bool _endOfVideo; diff --git a/engines/sword25/gfx/graphicengine.h b/engines/sword25/gfx/graphicengine.h index 04826c2e5a..3309763966 100644 --- a/engines/sword25/gfx/graphicengine.h +++ b/engines/sword25/gfx/graphicengine.h @@ -106,7 +106,7 @@ public: // --------- /** - * Initialises the graphics engine and sets the screen mode. Returns + * Initializes the graphics engine and sets the screen mode. Returns * true if initialisation failed. * @note This method should be called immediately after the * initialisation of all services. diff --git a/engines/sword25/gfx/image/imgloader.cpp b/engines/sword25/gfx/image/imgloader.cpp new file mode 100644 index 0000000000..1df0fba70c --- /dev/null +++ b/engines/sword25/gfx/image/imgloader.cpp @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +#include "common/memstream.h" +#include "sword25/gfx/image/image.h" +#include "sword25/gfx/image/imgloader.h" +#include "graphics/pixelformat.h" +#include "graphics/png.h" + +namespace Sword25 { + +bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) { + Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO); + Graphics::PNG *png = new Graphics::PNG(); + if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done + error("Error while reading PNG image"); + + Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + Graphics::Surface *pngSurface = png->getSurface(format); + + width = pngSurface->w; + height = pngSurface->h; + uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h]; + memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h); + pngSurface->free(); + + delete pngSurface; + delete png; + + // Signal success + return true; +} + +bool ImgLoader::decodeThumbnailImage(const byte *pFileData, uint fileSize, byte *&pUncompressedData, int &width, int &height, int &pitch) { + const byte *src = pFileData + 4; // skip header + width = READ_LE_UINT16(src); src += 2; + height = READ_LE_UINT16(src); src += 2; + src++; // version, ignored for now + pitch = width * 4; + + uint32 totalSize = pitch * height; + pUncompressedData = new byte[totalSize]; + uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output + const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + byte r, g, b; + + for (uint32 i = 0; i < totalSize / 4; i++) { + r = *src++; + g = *src++; + b = *src++; + *dst++ = format.RGBToColor(r, g, b); + } + + return true; +} + +} // End of namespace Sword25 diff --git a/engines/sword25/gfx/image/pngloader.h b/engines/sword25/gfx/image/imgloader.h index 6b5f65ff57..735ab9203c 100644 --- a/engines/sword25/gfx/image/pngloader.h +++ b/engines/sword25/gfx/image/imgloader.h @@ -29,30 +29,22 @@ * */ -#ifndef SWORD25_PNGLOADER2_H -#define SWORD25_PNGLOADER2_H +#ifndef SWORD25_IMGLOADER_H +#define SWORD25_IMGLOADER_H #include "sword25/kernel/common.h" #include "sword25/gfx/graphicengine.h" namespace Sword25 { -// Define to use ScummVM's PNG decoder, instead of libpng -#define USE_INTERNAL_PNG_DECODER - /** * Class for loading PNG files, and PNG data embedded into savegames. * * Originally written by Malte Thiesen. */ -class PNGLoader { +class ImgLoader { protected: - PNGLoader() {} // Protected constructor to prevent instances - - static bool doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch); -#ifndef USE_INTERNAL_PNG_DECODER - static bool doImageProperties(const byte *fileDataPtr, uint fileSize, int &width, int &height); -#endif + ImgLoader() {} // Protected constructor to prevent instances public: @@ -70,28 +62,15 @@ public: * @remark This function does not free the image buffer passed to it, * it is the callers responsibility to do so. */ - static bool decodeImage(const byte *pFileData, uint fileSize, + static bool decodePNGImage(const byte *pFileData, uint fileSize, byte *&pUncompressedData, int &width, int &height, int &pitch); -#ifndef USE_INTERNAL_PNG_DECODER - /** - * Extract the properties of an image. - * @param[in] fileDatePtr pointer to the image data - * @param[in] fileSize size of the image data in bytes - * @param[out] width if successful, this is set to the width of the image - * @param[out] height if successful, this is set to the height of the image - * @return returns true if extraction of the properties was successful, false in case of an error - * - * @remark This function does not free the image buffer passed to it, - * it is the callers responsibility to do so. - */ - static bool imageProperties(const byte *fileDatePtr, uint fileSize, - int &width, - int &height); -#endif - + static bool decodeThumbnailImage(const byte *pFileData, uint fileSize, + byte *&pUncompressedData, + int &width, int &height, + int &pitch); }; } // End of namespace Sword25 diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp deleted file mode 100644 index 6f370d8861..0000000000 --- a/engines/sword25/gfx/image/pngloader.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -#ifndef USE_INTERNAL_PNG_DECODER -// Disable symbol overrides so that we can use png.h -#define FORBIDDEN_SYMBOL_ALLOW_ALL -#endif - -#include "common/memstream.h" -#include "sword25/gfx/image/image.h" -#include "sword25/gfx/image/pngloader.h" -#ifndef USE_INTERNAL_PNG_DECODER -#include <png.h> -#else -#include "graphics/pixelformat.h" -#include "graphics/png.h" -#endif - -namespace Sword25 { - -#ifndef USE_INTERNAL_PNG_DECODER -static void png_user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { - const byte **ref = (const byte **)png_get_io_ptr(png_ptr); - memcpy(data, *ref, length); - *ref += length; -} - -static bool doIsCorrectImageFormat(const byte *fileDataPtr, uint fileSize) { - return (fileSize > 8) && png_check_sig(const_cast<byte *>(fileDataPtr), 8); -} -#endif - -bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) { -#ifndef USE_INTERNAL_PNG_DECODER - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - - int bitDepth; - int colorType; - int interlaceType; - int i; - - // Check for valid PNG signature - if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) { - error("png_check_sig failed"); - } - - // Create both PNG structures - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - error("Could not create libpng read struct."); - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - error("Could not create libpng info struct."); - } - - // Use alternative reading function - const byte **ref = &fileDataPtr; - png_set_read_fn(png_ptr, (void *)ref, png_user_read_data); - - // Read PNG header - png_read_info(png_ptr, info_ptr); - - // Read out PNG informations - - png_uint_32 w, h; - png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL); - width = w; - height = h; - - // Calculate pitch of output image - pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width); - - // Allocate memory for the final image data. - // To keep memory framentation low this happens before allocating memory for temporary image data. - uncompressedDataPtr = new byte[pitch * height]; - if (!uncompressedDataPtr) { - error("Could not allocate memory for output image."); - } - - // Images of all color formates will be transformed into ARGB images - if (bitDepth == 16) - png_set_strip_16(png_ptr); - if (colorType == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); - if (bitDepth < 8) - png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - if (colorType == PNG_COLOR_TYPE_GRAY || - colorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - - png_set_bgr(png_ptr); - - if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - - // After the transformations have been registered, the image data is read again. - png_read_update_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); - width = w; - height = h; - - if (interlaceType == PNG_INTERLACE_NONE) { - // PNGs without interlacing can simply be read row by row. - for (i = 0; i < height; i++) { - png_read_row(png_ptr, uncompressedDataPtr + i * pitch, NULL); - } - } else { - // PNGs with interlacing require us to allocate an auxillary - // buffer with pointers to all row starts. - - // Allocate row pointer buffer - png_bytep *pRowPtr = new png_bytep[height]; - if (!pRowPtr) { - error("Could not allocate memory for row pointers."); - } - - // Initialize row pointers - for (i = 0; i < height; i++) - pRowPtr[i] = uncompressedDataPtr + i * pitch; - - // Read image data - png_read_image(png_ptr, pRowPtr); - - // Free row pointer buffer - delete[] pRowPtr; - } - - // Read additional data at the end. - png_read_end(png_ptr, NULL); - - // Destroy libpng structures - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); -#else - Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO); - Graphics::PNG *png = new Graphics::PNG(); - if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done - error("Error while reading PNG image"); - - Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); - Graphics::Surface *pngSurface = png->getSurface(format); - - width = pngSurface->w; - height = pngSurface->h; - uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h]; - memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h); - pngSurface->free(); - - delete pngSurface; - delete png; - -#endif - // Signal success - return true; -} - -bool PNGLoader::decodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) { - return doDecodeImage(fileDataPtr, fileSize, uncompressedDataPtr, width, height, pitch); -} - -#ifndef USE_INTERNAL_PNG_DECODER -bool PNGLoader::doImageProperties(const byte *fileDataPtr, uint fileSize, int &width, int &height) { - // Check for valid PNG signature - if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) - return false; - - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - - // Create both PNG structures - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - error("Could not create libpng read struct."); - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - error("Could not create libpng info struct."); - } - - // Use alternative reading function - const byte **ref = &fileDataPtr; - png_set_read_fn(png_ptr, (void *)ref, png_user_read_data); - - // Read PNG Header - png_read_info(png_ptr, info_ptr); - - // Read out PNG informations - int bitDepth; - int colorType; - png_uint_32 w, h; - png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); - - width = w; - height = h; - - // Destroy libpng structures - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - return true; - -} - -bool PNGLoader::imageProperties(const byte *fileDataPtr, uint fileSize, int &width, int &height) { - return doImageProperties(fileDataPtr, fileSize, width, height); -} - -#else - // We don't need to read the image properties here... -#endif - - -} // End of namespace Sword25 diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index 23bf2623ad..a9c9de4f0c 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -35,21 +35,13 @@ #include "common/savefile.h" #include "sword25/package/packagemanager.h" -#include "sword25/gfx/image/pngloader.h" +#include "sword25/gfx/image/imgloader.h" #include "sword25/gfx/image/renderedimage.h" #include "common/system.h" namespace Sword25 { -// Duplicated from kernel/persistenceservice.cpp -static Common::String generateSavegameFilename(uint slotID) { - char buffer[100]; - // NOTE: This is hardcoded to sword25 - snprintf(buffer, 100, "%s.%.3d", "sword25", slotID); - return Common::String(buffer); -} - // ----------------------------------------------------------------------------- // CONSTRUCTION / DESTRUCTION // ----------------------------------------------------------------------------- @@ -74,8 +66,9 @@ static Common::String loadString(Common::SeekableReadStream &in, uint maxSize = static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSize, bool &isPNG) { byte *pFileData; Common::SaveFileManager *sfm = g_system->getSavefileManager(); - int slotNum = atoi(filename.c_str() + filename.size() - 3); - Common::InSaveFile *file = sfm->openForLoading(generateSavegameFilename(slotNum)); + Common::InSaveFile *file = sfm->openForLoading(lastPathComponent(filename, '/')); + if (!file) + error("Save file \"%s\" could not be loaded.", filename.c_str()); // Seek to the actual PNG image loadString(*file); // Marker (BS25SAVEGAME) @@ -100,30 +93,6 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz return pFileData; } -// TODO: Move this method into a more generic image loading class, together with the PNG reading code -static bool decodeThumbnail(const byte *pFileData, uint fileSize, byte *&pUncompressedData, int &width, int &height, int &pitch) { - const byte *src = pFileData + 4; // skip header - width = READ_LE_UINT16(src); src += 2; - height = READ_LE_UINT16(src); src += 2; - src++; // version, ignored for now - pitch = width * 4; - - uint32 totalSize = pitch * height; - pUncompressedData = new byte[totalSize]; - uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output - const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); - byte r, g, b; - - for (uint32 i = 0; i < totalSize / 4; i++) { - r = *src++; - g = *src++; - b = *src++; - *dst++ = format.RGBToColor(r, g, b); - } - - return true; -} - RenderedImage::RenderedImage(const Common::String &filename, bool &result) : _data(0), _width(0), @@ -152,21 +121,12 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : return; } -#ifndef USE_INTERNAL_PNG_DECODER - // Determine image properties - if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) { - error("Could not read image properties."); - delete[] pFileData; - return; - } -#endif - // Uncompress the image int pitch; if (isPNG) - result = PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch); + result = ImgLoader::decodePNGImage(pFileData, fileSize, _data, _width, _height, pitch); else - result = decodeThumbnail(pFileData, fileSize, _data, _width, _height, pitch); + result = ImgLoader::decodeThumbnailImage(pFileData, fileSize, _data, _width, _height, pitch); if (!result) { error("Could not decode image."); diff --git a/engines/sword25/gfx/image/swimage.cpp b/engines/sword25/gfx/image/swimage.cpp index 92d47368b2..0b9cc11df2 100644 --- a/engines/sword25/gfx/image/swimage.cpp +++ b/engines/sword25/gfx/image/swimage.cpp @@ -30,7 +30,7 @@ */ #include "sword25/package/packagemanager.h" -#include "sword25/gfx/image/pngloader.h" +#include "sword25/gfx/image/imgloader.h" #include "sword25/gfx/image/swimage.h" namespace Sword25 { @@ -53,18 +53,10 @@ SWImage::SWImage(const Common::String &filename, bool &result) : return; } -#ifndef USE_INTERNAL_PNG_DECODER - // Determine image properties - if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) { - error("Could not read image properties."); - return; - } -#endif - // Uncompress the image int pitch; byte *pUncompressedData; - if (!PNGLoader::decodeImage(pFileData, fileSize, pUncompressedData, _width, _height, pitch)) { + if (!ImgLoader::decodePNGImage(pFileData, fileSize, pUncompressedData, _width, _height, pitch)) { error("Could not decode image."); return; } diff --git a/engines/sword25/gfx/panel.cpp b/engines/sword25/gfx/panel.cpp index 34ab4876ea..6d5b2a623d 100644 --- a/engines/sword25/gfx/panel.cpp +++ b/engines/sword25/gfx/panel.cpp @@ -47,12 +47,12 @@ Panel::Panel(RenderObjectPtr<RenderObject> parentPtr, int width, int height, uin _height = height; if (_width < 0) { - error("Tried to initialise a panel with an invalid width (%d).", _width); + error("Tried to initialize a panel with an invalid width (%d).", _width); return; } if (_height < 0) { - error("Tried to initialise a panel with an invalid height (%d).", _height); + error("Tried to initialize a panel with an invalid height (%d).", _height); return; } diff --git a/engines/sword25/gfx/screenshot.cpp b/engines/sword25/gfx/screenshot.cpp index 8306d9ce6f..4f9ba1d3c5 100644 --- a/engines/sword25/gfx/screenshot.cpp +++ b/engines/sword25/gfx/screenshot.cpp @@ -29,9 +29,6 @@ * */ -// Disable symbol overrides so that we can use png.h -#define FORBIDDEN_SYMBOL_ALLOW_ALL - #include "common/memstream.h" #include "common/textconsole.h" #include "sword25/gfx/screenshot.h" @@ -53,6 +50,8 @@ bool Screenshot::saveToFile(Graphics::Surface *data, Common::WriteStream *stream for (uint y = 0; y < data->h; y++) { for (uint x = 0; x < data->w; x++) { + // This is only called by createThumbnail below, which + // provides a fake 'surface' with LE data in it. uint32 srcPixel = READ_LE_UINT32(pSrc); pSrc += sizeof(uint32); stream->writeByte((srcPixel >> 16) & 0xff); // R @@ -93,7 +92,7 @@ Common::SeekableReadStream *Screenshot::createThumbnail(Graphics::Surface *data) 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); + uint32 pixel = READ_UINT32(srcP + i); alpha += (pixel >> 24); red += (pixel >> 16) & 0xff; green += (pixel >> 8) & 0xff; diff --git a/engines/sword25/input/inputengine.h b/engines/sword25/input/inputengine.h index a84c215076..f79890a9fd 100644 --- a/engines/sword25/input/inputengine.h +++ b/engines/sword25/input/inputengine.h @@ -172,7 +172,7 @@ public: /// -------------------------------------------------------------- /** - * Initialises the input engine + * Initializes the input engine * @return Returns a true on success, otherwise false. */ bool init(); diff --git a/engines/sword25/kernel/kernel.cpp b/engines/sword25/kernel/kernel.cpp index f45137ce02..d6388eee2b 100644 --- a/engines/sword25/kernel/kernel.cpp +++ b/engines/sword25/kernel/kernel.cpp @@ -63,7 +63,7 @@ Kernel::Kernel() : // Create the resource manager _resourceManager = new ResourceManager(this); - // Initialise the script engine + // Initialize the script engine _script = new LuaScriptEngine(this); if (!_script || !_script->init()) { _initSuccess = false; diff --git a/engines/sword25/kernel/kernel.h b/engines/sword25/kernel/kernel.h index a0c2927fdc..adf69f92d6 100644 --- a/engines/sword25/kernel/kernel.h +++ b/engines/sword25/kernel/kernel.h @@ -79,7 +79,7 @@ public: uint getMilliTicks(); /** - * Specifies whether the kernel was successfully initialised + * Specifies whether the kernel was successfully initialized */ bool getInitSuccess() const { return _initSuccess; diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp index a6c71433a7..17e9199b5c 100644 --- a/engines/sword25/kernel/persistenceservice.cpp +++ b/engines/sword25/kernel/persistenceservice.cpp @@ -29,9 +29,6 @@ * */ -// Disable symbol overrides so that we can use zlib.h -#define FORBIDDEN_SYMBOL_ALLOW_ALL - #include "common/fs.h" #include "common/savefile.h" #include "common/zlib.h" @@ -304,6 +301,7 @@ bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotF if (thumbnail) { byte *buffer = new byte[FILE_COPY_BUFFER_SIZE]; + thumbnail->seek(0, SEEK_SET); while (!thumbnail->eos()) { int bytesRead = thumbnail->read(&buffer[0], FILE_COPY_BUFFER_SIZE); file->write(&buffer[0], bytesRead); diff --git a/engines/sword25/math/polygon.cpp b/engines/sword25/math/polygon.cpp index fe2fc84cad..2e7836ff77 100644 --- a/engines/sword25/math/polygon.cpp +++ b/engines/sword25/math/polygon.cpp @@ -59,7 +59,7 @@ Polygon::~Polygon() { } bool Polygon::init(int vertexCount_, const Vertex *vertices_) { - // Rember the old obstate to restore it if an error occurs whilst initialising it with the new data + // Rember the old obstate to restore it if an error occurs whilst initializing it with the new data int oldvertexCount = this->vertexCount; Vertex *oldvertices = this->vertices; diff --git a/engines/sword25/math/polygon.h b/engines/sword25/math/polygon.h index eac19d7900..ffdbf14f6b 100644 --- a/engines/sword25/math/polygon.h +++ b/engines/sword25/math/polygon.h @@ -78,15 +78,15 @@ public: virtual ~Polygon(); /** - * Initialises the BS_Polygon with a list of Vertecies. + * Initializes the BS_Polygon with a list of Vertecies. * * The Vertices need to define a polygon must not have self-intersections. - * If a polygon already has verticies, this will re-initialise it with the new list. + * If a polygon already has verticies, this will re-initialize it with the new list. * * @param VertexCount The number of vertices being passed * @param Vertecies An array of BS_Vertex objects representing the vertices in the polygon. * @return Returns false if the Vertecies have self-intersections. In this case, - * the object is not initialised. + * the object is not initialized. */ bool init(int vertexCount_, const Vertex *vertices_); diff --git a/engines/sword25/math/region.cpp b/engines/sword25/math/region.cpp index 8790860a55..7681ef6d9f 100644 --- a/engines/sword25/math/region.cpp +++ b/engines/sword25/math/region.cpp @@ -115,7 +115,7 @@ bool Region::init(const Polygon &contour, const Common::Array<Polygon> *pHoles) } - // Initialise bounding box + // Initialize bounding box updateBoundingBox(); _valid = true; diff --git a/engines/sword25/math/region.h b/engines/sword25/math/region.h index f9a3f50b3f..0fd7223631 100644 --- a/engines/sword25/math/region.h +++ b/engines/sword25/math/region.h @@ -73,12 +73,12 @@ public: virtual ~Region(); /** - * Initialises a BS_Region object + * Initializes a BS_Region object * @param Contour A polygon indicating the outline of the region * @param pHoles A pointer to an array of polygons representing the hole state in the region. * If the region has no holes, it must be passed as NULL. The default value is NULL. * @return Returns true if the initialisation was successful, otherwise false. - * @remark If the region was already initialised, the old state will be deleted. + * @remark If the region was already initialized, the old state will be deleted. */ virtual bool init(const Polygon &contour, const Common::Array<Polygon> *pHoles = NULL); diff --git a/engines/sword25/math/vertex.h b/engines/sword25/math/vertex.h index 817f48e760..4cb0eaca30 100644 --- a/engines/sword25/math/vertex.h +++ b/engines/sword25/math/vertex.h @@ -43,7 +43,8 @@ #include <math.h> #include "common/rect.h" #include "sword25/kernel/common.h" -#include "sword25/util/lua/lua.h" + +struct lua_State; #if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__) #define sqrtf(x) ((float)sqrt(x)) diff --git a/engines/sword25/math/walkregion.cpp b/engines/sword25/math/walkregion.cpp index 3eea689877..bace4d54bc 100644 --- a/engines/sword25/math/walkregion.cpp +++ b/engines/sword25/math/walkregion.cpp @@ -101,7 +101,7 @@ static void initDijkstraNodes(DijkstraNode::Container &dijkstraNodes, const Regi // Allocate sufficient space in the array dijkstraNodes.resize(nodes.size()); - // Initialise all the nodes which are visible from the starting node + // Initialize all the nodes which are visible from the starting node DijkstraNode::Iter dijkstraIter = dijkstraNodes.begin(); for (Common::Array<Vertex>::const_iterator nodesIter = nodes.begin(); nodesIter != nodes.end(); nodesIter++, dijkstraIter++) { @@ -173,7 +173,7 @@ void reverseArray(Common::Array<T> &arr) { bool WalkRegion::findPath(const Vertex &start, const Vertex &end, BS_Path &path) const { // This is an implementation of Dijkstra's algorithm - // Initialise edge node list + // Initialize edge node list DijkstraNode::Container dijkstraNodes; initDijkstraNodes(dijkstraNodes, *this, start, _nodes); @@ -247,7 +247,7 @@ void WalkRegion::initNodeVector() { } void WalkRegion::computeVisibilityMatrix() { - // Initialise visibility matrix + // Initialize visibility matrix _visibilityMatrix = Common::Array< Common::Array <int> >(); for (uint idx = 0; idx < _nodes.size(); ++idx) { Common::Array<int> arr; diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk index da91c848b5..302120c500 100644 --- a/engines/sword25/module.mk +++ b/engines/sword25/module.mk @@ -24,7 +24,7 @@ MODULE_OBJS := \ gfx/text.o \ gfx/timedrenderobject.o \ gfx/image/art.o \ - gfx/image/pngloader.o \ + gfx/image/imgloader.o \ gfx/image/renderedimage.o \ gfx/image/swimage.o \ gfx/image/vectorimage.o \ @@ -60,7 +60,6 @@ MODULE_OBJS := \ util/lua/ldblib.o \ util/lua/ldebug.o \ util/lua/ldo.o \ - util/lua/ldump.o \ util/lua/lfunc.o \ util/lua/lgc.o \ util/lua/linit.o \ @@ -79,10 +78,9 @@ MODULE_OBJS := \ util/lua/ltable.o \ util/lua/ltablib.o \ util/lua/ltm.o \ - util/lua/lundump.o \ util/lua/lvm.o \ util/lua/lzio.o \ - util/lua/print.o \ + util/lua/scummvm_file.o \ util/pluto/pdep.o \ util/pluto/pluto.o \ util/pluto/plzio.o diff --git a/engines/sword25/script/luascript.cpp b/engines/sword25/script/luascript.cpp index 7fd3d1b658..9d394309e6 100644 --- a/engines/sword25/script/luascript.cpp +++ b/engines/sword25/script/luascript.cpp @@ -112,7 +112,7 @@ bool LuaScriptEngine::init() { // Place the error handler function in the Lua registry, and remember the index _pcallErrorhandlerRegistryIndex = luaL_ref(_state, LUA_REGISTRYINDEX); - // Initialise the Pluto-Persistence library + // Initialize the Pluto-Persistence library luaopen_pluto(_state); lua_pop(_state, 1); @@ -177,7 +177,7 @@ bool LuaScriptEngine::executeFile(const Common::String &fileName) { } bool LuaScriptEngine::executeString(const Common::String &code) { - return executeBuffer((byte *)code.c_str(), code.size(), "???"); + return executeBuffer((const byte *)code.c_str(), code.size(), "???"); } namespace { diff --git a/engines/sword25/script/luascript.h b/engines/sword25/script/luascript.h index f3530d68ed..1a4a38c3be 100644 --- a/engines/sword25/script/luascript.h +++ b/engines/sword25/script/luascript.h @@ -36,7 +36,8 @@ #include "common/str-array.h" #include "sword25/kernel/common.h" #include "sword25/script/script.h" -#include "sword25/util/lua/lua.h" + +struct lua_State; namespace Sword25 { @@ -48,7 +49,7 @@ public: virtual ~LuaScriptEngine(); /** - * Initialises the scripting engine + * Initializes the scripting engine * @return Returns true if successful, otherwise false. */ virtual bool init(); diff --git a/engines/sword25/script/script.h b/engines/sword25/script/script.h index e4ce846b66..04f248fe7e 100644 --- a/engines/sword25/script/script.h +++ b/engines/sword25/script/script.h @@ -54,7 +54,7 @@ public: // ----------------------------------------------------------------------------- /** - * Initialises the scrip tengine. Returns true if successful, false otherwise. + * Initializes the scrip tengine. Returns true if successful, false otherwise. */ virtual bool init() = 0; diff --git a/engines/sword25/sfx/soundengine.h b/engines/sword25/sfx/soundengine.h index c087392570..4dbd475846 100644 --- a/engines/sword25/sfx/soundengine.h +++ b/engines/sword25/sfx/soundengine.h @@ -88,7 +88,7 @@ public: ~SoundEngine() {} /** - * Initialises the sound engine + * Initializes the sound engine * @param SampleRate Specifies the sample rate to use. * @param Channels The maximum number of channels. The default is 32. * @return Returns true on success, otherwise false. diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp index 93666fed39..b111746c32 100644 --- a/engines/sword25/sword25.cpp +++ b/engines/sword25/sword25.cpp @@ -94,7 +94,7 @@ Common::Error Sword25Engine::run() { } Common::Error Sword25Engine::appStart() { - // Initialise the graphics mode to ARGB8888 + // Initialize the graphics mode to ARGB8888 Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); initGraphics(800, 600, true, &format); if (format != g_system->getScreenFormat()) @@ -142,7 +142,7 @@ bool Sword25Engine::appMain() { } bool Sword25Engine::appEnd() { - // The kernel is shutdown, and un-initialises all subsystems + // The kernel is shutdown, and un-initializes all subsystems Kernel::deleteInstance(); AnimationTemplateRegistry::destroy(); diff --git a/engines/sword25/sword25.h b/engines/sword25/sword25.h index 5d11aa69e5..1254ea177b 100644 --- a/engines/sword25/sword25.h +++ b/engines/sword25/sword25.h @@ -82,7 +82,7 @@ protected: // void pauseEngineIntern(bool pause); // TODO: Implement this!!! // void syncSoundSettings(); // TODO: Implement this!!! // Common::Error loadGameState(int slot); // TODO: Implement this? -// Common::Error saveGameState(int slot, const char *desc); // TODO: Implement this? +// Common::Error saveGameState(int slot, const Common::String &desc); // TODO: Implement this? // bool canLoadGameStateCurrently(); // TODO: Implement this? // bool canSaveGameStateCurrently(); // TODO: Implement this? diff --git a/engines/sword25/util/lua/lapi.cpp b/engines/sword25/util/lua/lapi.cpp index b1118db368..16f8460e39 100644 --- a/engines/sword25/util/lua/lapi.cpp +++ b/engines/sword25/util/lua/lapi.cpp @@ -26,9 +26,8 @@ #include "lstring.h" #include "ltable.h" #include "ltm.h" -#include "lundump.h" #include "lvm.h" - +#include "common/textconsole.h" const char lua_ident[] = @@ -876,17 +875,8 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); - else - status = 1; - lua_unlock(L); - return status; + error("lua_dump not supported: Handling of precompiled LUA scripts has been removed in ScummVM"); + return 1; // error } diff --git a/engines/sword25/util/lua/lauxlib.cpp b/engines/sword25/util/lua/lauxlib.cpp index 526b1c84ab..8978cd5613 100644 --- a/engines/sword25/util/lua/lauxlib.cpp +++ b/engines/sword25/util/lua/lauxlib.cpp @@ -22,7 +22,8 @@ #include "lua.h" #include "lauxlib.h" - +#include "scummvm_file.h" +#include "common/textconsole.h" #define FREELIST_REF 0 /* free list of references */ @@ -520,7 +521,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { typedef struct LoadF { int extraline; - FILE *f; + Sword25::Sword25FileProxy *f; char buff[LUAL_BUFFERSIZE]; } LoadF; @@ -533,23 +534,31 @@ static const char *getF (lua_State *L, void *ud, size_t *size) { *size = 1; return "\n"; } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + if (lf->f->eof()) return NULL; + *size = lf->f->read(lf->buff, 1, sizeof(lf->buff)); return (*size > 0) ? lf->buff : NULL; } static int errfile (lua_State *L, const char *what, int fnameindex) { - return luaL_error(L, "LUA function errfile has been removed in ScummVM"); + const char *serr = "General error"; + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; } LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { LoadF lf; int status, readstatus; - int c; +// int c; int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ lf.extraline = 0; + + lua_pushfstring(L, "@%s", filename); + lf.f = new Sword25::Sword25FileProxy(filename, "r"); +/* if (filename == NULL) { lua_pushliteral(L, "=stdin"); lf.f = stdin; @@ -559,23 +568,25 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } - c = getc(lf.f); - if (c == '#') { /* Unix exec. file? */ + + c = lf.f->getc(); + if (c == '#') { // Unix exec. file? lf.extraline = 1; - while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ - if (c == '\n') c = getc(lf.f); + while ((c = lf.f->getc()) != EOF && c != '\n') ; // skip first line + if (c == '\n') c = lf.f->getc(); } - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (c == LUA_SIGNATURE[0] && filename) { // binary file? + lf.f = freopen(filename, "rb", lf.f); // reopen in binary mode if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + // skip eventual `#!...' + while ((c = lf.f->getc()) != EOF && c != LUA_SIGNATURE[0]) ; lf.extraline = 0; } ungetc(c, lf.f); +*/ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ + readstatus = 0; //ferror(lf.f); + if (filename) delete lf.f; // close file (even in case of errors) if (readstatus) { lua_settop(L, fnameindex); /* ignore results from `lua_load' */ return errfile(L, "read", fnameindex); @@ -633,7 +644,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { static int panic (lua_State *L) { (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + warning("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); return 0; } diff --git a/engines/sword25/util/lua/ldo.cpp b/engines/sword25/util/lua/ldo.cpp index 07508fbb14..bbcdf98b3d 100644 --- a/engines/sword25/util/lua/ldo.cpp +++ b/engines/sword25/util/lua/ldo.cpp @@ -5,6 +5,16 @@ */ +// FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. +// Neither of these is supported in ScummVM. So we need to come up +// with a replacement. The most simple, direct and crude approach: +// Replace "throw" with an "error()" call. Of course we only +// would want to do that if this actually never happens... +#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp +#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp + +#include "common/textconsole.h" + #include <setjmp.h> #include <stdlib.h> #include <string.h> @@ -26,10 +36,9 @@ #include "lstring.h" #include "ltable.h" #include "ltm.h" -#include "lundump.h" #include "lvm.h" #include "lzio.h" - +#include "common/textconsole.h" @@ -94,6 +103,11 @@ static void resetstack (lua_State *L, int status) { void luaD_throw (lua_State *L, int errcode) { if (L->errorJmp) { L->errorJmp->status = errcode; + // FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. + // Neither of these is supported in ScummVM. So we need to come up + // with a replacement. The most simple, direct and crude approach: + // Replace "throw" with an "error()" call. Of course we only + // would want to do that if this actually never happens... LUAI_THROW(L, L->errorJmp); } else { @@ -103,7 +117,7 @@ void luaD_throw (lua_State *L, int errcode) { lua_unlock(L); G(L)->panic(L); } - exit(EXIT_FAILURE); + error("luaD_throw failure"); } } @@ -113,6 +127,11 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { lj.status = 0; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; + // FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. + // Neither of these is supported in ScummVM. So we need to come up + // with a replacement. The most simple, direct and crude approach: + // Replace "throw" with an "error()" call. Of course we only + // would want to do that if this actually never happens... LUAI_TRY(L, &lj, (*f)(L, ud); ); @@ -494,8 +513,9 @@ static void f_parser (lua_State *L, void *ud) { struct SParser *p = cast(struct SParser *, ud); int c = luaZ_lookahead(p->z); luaC_checkGC(L); - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, - &p->buff, p->name); + if (c == LUA_SIGNATURE[0]) + error("Handling of precompiled LUA scripts has been removed in ScummVM"); + tf = luaY_parser(L, p->z, &p->buff, p->name); cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); cl->l.p = tf; for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ diff --git a/engines/sword25/util/lua/ldump.cpp b/engines/sword25/util/lua/ldump.cpp deleted file mode 100644 index 3ce16542d6..0000000000 --- a/engines/sword25/util/lua/ldump.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* -** $Id$ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include <stddef.h> - -#define ldump_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; -} DumpState; - -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } -} - -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); -} - -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); -} - -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL || getstr(s)==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size,D); - } -} - -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; i<n; i++) - { - const TValue* o=&f->k[i]; - DumpChar(ttype(o),D); - switch (ttype(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: - lua_assert(0); /* cannot happen */ - break; - } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); -} - -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; i<n; i++) - { - DumpString(f->locvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; i<n; i++) DumpString(f->upvalues[i],D); -} - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -{ - DumpString((f->source==p || D->strip) ? NULL : f->source,D); - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->nups,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpDebug(f,D); -} - -static void DumpHeader(DumpState* D) -{ - char h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); -} - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,NULL,&D); - return D.status; -} diff --git a/engines/sword25/util/lua/liolib.cpp b/engines/sword25/util/lua/liolib.cpp index f9bad30aed..b505d1e4df 100644 --- a/engines/sword25/util/lua/liolib.cpp +++ b/engines/sword25/util/lua/liolib.cpp @@ -16,7 +16,8 @@ #include "lauxlib.h" #include "lualib.h" - +#include "common/textconsole.h" +#include "scummvm_file.h" #define IO_INPUT 1 @@ -27,50 +28,64 @@ static const char *const fnames[] = {"input", "output"}; static int pushresult (lua_State *L, int i, const char *filename) { - return luaL_error(L, "LUA file I/O functions have been removed in ScummVM"); + int en = 0; /*errno;*/ // Currently hardcoded for ScumMVM, this may need to be changed + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, "General error" /*strerror(en)*/); + else + lua_pushfstring(L, "%s", "General error" /*strerror(en)*/); + lua_pushinteger(L, en); + return 3; + } } - +/* static void fileerror (lua_State *L, int arg, const char *filename) { lua_pushfstring(L, "%s: %s", filename, "LUA I/O error descriptions have been removed in ScummVM"); luaL_argerror(L, arg, lua_tostring(L, -1)); } - +*/ #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - +#define tofileProxy(L) ((Sword25::Sword25FileProxy **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int io_type (lua_State *L) { + return luaL_error(L, "%s", "LUA I/O has been removed in ScummVM"); +/* void *ud; luaL_checkany(L, 1); ud = lua_touserdata(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) - lua_pushnil(L); /* not a file */ + lua_pushnil(L); // not a file else if (*((FILE **)ud) == NULL) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); return 1; +*/ } - -static FILE *tofile (lua_State *L) { - FILE **f = tofilep(L); +static Sword25::Sword25FileProxy *tofile (lua_State *L) { + Sword25::Sword25FileProxy **f = tofileProxy(L); if (*f == NULL) luaL_error(L, "attempt to use a closed file"); return *f; } - /* ** When creating file handles, always creates a `closed' file handle ** before opening the actual file; so, if there is a memory error, the ** file is not left opened. */ -static FILE **newfile (lua_State *L) { - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); +static Sword25::Sword25FileProxy **newfile (lua_State *L) { + Sword25::Sword25FileProxy **pf = (Sword25::Sword25FileProxy **)lua_newuserdata(L, sizeof(Sword25::Sword25FileProxy *)); *pf = NULL; /* file handle is currently `closed' */ luaL_getmetatable(L, LUA_FILEHANDLE); lua_setmetatable(L, -2); @@ -92,10 +107,13 @@ static int io_noclose (lua_State *L) { ** function to close 'popen' files */ static int io_pclose (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); +/* FILE **p = tofilep(L); int ok = lua_pclose(L, *p); *p = NULL; return pushresult(L, ok, NULL); + */ } @@ -103,52 +121,63 @@ static int io_pclose (lua_State *L) { ** function to close regular files */ static int io_fclose (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); + /* FILE **p = tofilep(L); int ok = (fclose(*p) == 0); *p = NULL; return pushresult(L, ok, NULL); + */ } - +/* static int aux_close (lua_State *L) { lua_getfenv(L, 1); lua_getfield(L, -1, "__close"); return (lua_tocfunction(L, -1))(L); } - +*/ static int io_close (lua_State *L) { if (lua_isnone(L, 1)) lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); - tofile(L); /* make sure argument is a file */ - return aux_close(L); + + Sword25::Sword25FileProxy **f = tofileProxy(L); + delete *f; + *f = NULL; + + return 0; } static int io_gc (lua_State *L) { - FILE *f = *tofilep(L); - /* ignore closed files */ - if (f != NULL) - aux_close(L); + Sword25::Sword25FileProxy **f = tofileProxy(L); + // ignore closed files + if (*f != NULL) + delete *f; + return 0; } static int io_tostring (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); + /* FILE *f = *tofilep(L); if (f == NULL) lua_pushliteral(L, "file (closed)"); else lua_pushfstring(L, "file (%p)", f); return 1; + */ } static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); + Sword25::Sword25FileProxy **pf = newfile(L); + *pf = new Sword25::Sword25FileProxy(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } @@ -158,21 +187,22 @@ static int io_open (lua_State *L) { ** correct __close for 'popen' files */ static int io_popen (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); +/* const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = lua_popen(L, filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; + */ } static int io_tmpfile (lua_State *L) { - FILE **pf = newfile(L); - *pf = tmpfile(); - return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; + return luaL_error(L, "%s", "LUA I/O error descriptions have been removed in ScummVM"); } - +/* static FILE *getiofile (lua_State *L, int findex) { FILE *f; lua_rawgeti(L, LUA_ENVIRONINDEX, findex); @@ -181,8 +211,8 @@ static FILE *getiofile (lua_State *L, int findex) { luaL_error(L, "standard %s file is closed", fnames[findex - 1]); return f; } - - +*/ +/* static int g_iofile (lua_State *L, int f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); @@ -193,24 +223,26 @@ static int g_iofile (lua_State *L, int f, const char *mode) { fileerror(L, 1, filename); } else { - tofile(L); /* check that it's a valid file handle */ + tofile(L); // check that it's a valid file handle lua_pushvalue(L, 1); } lua_rawseti(L, LUA_ENVIRONINDEX, f); } - /* return current value */ + // return current value lua_rawgeti(L, LUA_ENVIRONINDEX, f); return 1; } - +*/ static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); + error("LUA I/O has been removed in ScummVM"); +// return g_iofile(L, IO_INPUT, "r"); } static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); + error("LUA I/O has been removed in ScummVM"); +// return g_iofile(L, IO_OUTPUT, "w"); } @@ -232,8 +264,10 @@ static int f_lines (lua_State *L) { static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - /* will iterate over default input */ + error("LUA I/O has been removed in ScummVM"); +/* + if (lua_isnoneornil(L, 1)) { // no arguments? + // will iterate over default input lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); return f_lines(L); } @@ -246,6 +280,7 @@ static int io_lines (lua_State *L) { aux_lines(L, lua_gettop(L), 1); return 1; } + */ } @@ -255,18 +290,18 @@ static int io_lines (lua_State *L) { ** ======================================================= */ - -static int read_number (lua_State *L, FILE *f) { +/* +static int read_number (lua_State *L, Sword25::Sword25FileProxy *f) { lua_Number d; if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { lua_pushnumber(L, d); return 1; } - else return 0; /* read fails */ + else return 0; // read fails } -static int test_eof (lua_State *L, FILE *f) { +static int test_eof (lua_State *L, Sword25::Sword25FileProxy *f) { int c = getc(f); ungetc(c, f); lua_pushlstring(L, NULL, 0); @@ -274,56 +309,56 @@ static int test_eof (lua_State *L, FILE *f) { } -static int read_line (lua_State *L, FILE *f) { +static int read_line (lua_State *L, Sword25::Sword25FileProxy *f) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t l; char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { // eof? + luaL_pushresult(&b); // close buffer + return (lua_objlen(L, -1) > 0); // check whether read something } l = strlen(p); if (l == 0 || p[l-1] != '\n') luaL_addsize(&b, l); else { - luaL_addsize(&b, l - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ + luaL_addsize(&b, l - 1); // do not include `eol' + luaL_pushresult(&b); // close buffer + return 1; // read at least an `eol' } } } -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ +static int read_chars (lua_State *L, Sword25::Sword25FileProxy *f, size_t n) { + size_t rlen; // how much to read + size_t nr; // number of chars actually read luaL_Buffer b; luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + rlen = LUAL_BUFFERSIZE; // try to read that much each time do { char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ + if (rlen > n) rlen = n; // cannot read more than asked nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ + n -= nr; // still have to read `n' chars + } while (n > 0 && nr == rlen); // until end of count or eof + luaL_pushresult(&b); // close buffer return (n == 0 || lua_objlen(L, -1) > 0); } -static int g_read (lua_State *L, FILE *f, int first) { +static int g_read (lua_State *L, Sword25::Sword25FileProxy *f, int first) { int nargs = lua_gettop(L) - 1; int success; int n; clearerr(f); - if (nargs == 0) { /* no arguments? */ + if (nargs == 0) { // no arguments? success = read_line(L, f); - n = first+1; /* to return 1 result */ + n = first+1; // to return 1 result } - else { /* ensure stack space for all results and for auxlib's buffer */ + else { // ensure stack space for all results and for auxlib's buffer luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); success = 1; for (n = first; nargs-- && success; n++) { @@ -335,15 +370,15 @@ static int g_read (lua_State *L, FILE *f, int first) { const char *p = lua_tostring(L, n); luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); switch (p[1]) { - case 'n': /* number */ + case 'n': // number success = read_number(L, f); break; - case 'l': /* line */ + case 'l': // line success = read_line(L, f); break; - case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ - success = 1; /* always success */ + case 'a': // file + read_chars(L, f, ~((size_t)0)); // read MAX_SIZE_T chars + success = 1; // always success break; default: return luaL_argerror(L, n, "invalid format"); @@ -354,58 +389,66 @@ static int g_read (lua_State *L, FILE *f, int first) { if (ferror(f)) return pushresult(L, 0, NULL); if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ + lua_pop(L, 1); // remove last result + lua_pushnil(L); // push nil instead } return n - first; } - +*/ static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); + error("LUA I/O has been removed in ScummVM"); +// return g_read(L, getiofile(L, IO_INPUT), 1); } static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); + error("LUA I/O has been removed in ScummVM"); +// return g_read(L, tofile(L), 2); } static int io_readline (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); +/* FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); int sucess; - if (f == NULL) /* file is already closed? */ + if (f == NULL) // file is already closed? luaL_error(L, "file is already closed"); sucess = read_line(L, f); if (ferror(f)) return luaL_error(L, "%s", "LUA I/O error descriptions have been removed in ScummVM"); if (sucess) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + else { // EOF + if (lua_toboolean(L, lua_upvalueindex(2))) { // generator created file? lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ + aux_close(L); // close it } return 0; } +*/ } /* }====================================================== */ -static int g_write (lua_State *L, FILE *f, int arg) { +static int g_write (lua_State *L, Sword25::Sword25FileProxy *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } + // optimization: could be done exactly as for strings + if (status) { + char buffer[20]; + sprintf(buffer, LUA_NUMBER_FMT, lua_tonumber(L, arg)); + status = f->write(buffer, strlen(buffer)) == strlen(buffer); + } + } else { size_t l; const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); + status = status && (f->write(s, l) == l); } } return pushresult(L, status, NULL); @@ -413,7 +456,8 @@ static int g_write (lua_State *L, FILE *f, int arg) { static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); + error("LUA I/O has been removed in ScummVM"); +// return g_write(L, getiofile(L, IO_OUTPUT), 1); } @@ -423,6 +467,8 @@ static int f_write (lua_State *L) { static int f_seek (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); + /* static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); @@ -430,15 +476,18 @@ static int f_seek (lua_State *L) { long offset = luaL_optlong(L, 3, 0); op = fseek(f, offset, mode[op]); if (op) - return pushresult(L, 0, NULL); /* error */ + return pushresult(L, 0, NULL); // error else { lua_pushinteger(L, ftell(f)); return 1; } +*/ } static int f_setvbuf (lua_State *L) { + error("LUA I/O has been removed in ScummVM"); + /* static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; static const char *const modenames[] = {"no", "full", "line", NULL}; FILE *f = tofile(L); @@ -446,17 +495,20 @@ static int f_setvbuf (lua_State *L) { lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); int res = setvbuf(f, NULL, mode[op], sz); return pushresult(L, res == 0, NULL); + */ } static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); + error("LUA I/O has been removed in ScummVM"); +// return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L)) == 0, NULL); + error("LUA I/O has been removed in ScummVM"); +// return pushresult(L, fflush(tofile(L)) == 0, NULL); } @@ -497,18 +549,18 @@ static void createmeta (lua_State *L) { luaL_register(L, NULL, flib); /* file methods */ } - +/* static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { *newfile(L) = f; if (k > 0) { lua_pushvalue(L, -1); lua_rawseti(L, LUA_ENVIRONINDEX, k); } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ + lua_pushvalue(L, -2); // copy environment + lua_setfenv(L, -2); // set it lua_setfield(L, -3, fname); } - +*/ static void newfenv (lua_State *L, lua_CFunction cls) { lua_createtable(L, 0, 1); @@ -526,9 +578,11 @@ LUALIB_API int luaopen_io (lua_State *L) { luaL_register(L, LUA_IOLIBNAME, iolib); /* create (and set) default files */ newfenv(L, io_noclose); /* close function for default files */ +/* createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stderr, 0, "stderr"); +*/ lua_pop(L, 1); /* pop environment for default files */ lua_getfield(L, -1, "popen"); newfenv(L, io_pclose); /* create environment for 'popen' */ diff --git a/engines/sword25/util/lua/llex.cpp b/engines/sword25/util/lua/llex.cpp index 87eafea45a..4d73a6a600 100644 --- a/engines/sword25/util/lua/llex.cpp +++ b/engines/sword25/util/lua/llex.cpp @@ -6,6 +6,7 @@ #include <ctype.h> +#include <stdio.h> #include <string.h> #define llex_c @@ -175,11 +176,23 @@ static void buffreplace (LexState *ls, char from, char to) { static void trydecpoint (LexState *ls, SemInfo *seminfo) { /* format error: try to update decimal point separator */ - // Non-portable call to update the decimal point separator. - // It has been simplified in ScummVM to not use any system locale - // information, as it's not used in sword25. + // Normally we'd use localeconv() to get the decimal point separator, but + // annoyingly that is not available on some platforms, e.g. Android. Figure + // it out by formatting a known value and extract the separator from that + // instead. The result could be cached, but considering the game I doubt + // this will ever be a bottleneck. Note that the separator is assumed to fit + // in a char, but that was a limitation in the original code as well. char old = ls->decpoint; + char buf[5]; + int i; + sprintf(buf, "%.1f", 1.0); ls->decpoint = '.'; + for (i = 0; buf[i]; i++) { + if (!isspace(buf[i]) && !isdigit(buf[i])) { + ls->decpoint = buf[i]; + break; + } + } buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { /* format error with correct decimal point: no more options */ diff --git a/engines/sword25/util/lua/lmathlib.cpp b/engines/sword25/util/lua/lmathlib.cpp index 7e64d75789..6c36bbcf4e 100644 --- a/engines/sword25/util/lua/lmathlib.cpp +++ b/engines/sword25/util/lua/lmathlib.cpp @@ -5,6 +5,10 @@ */ +// FIXME: rand and srand should be replaced by a RandomSource +#define FORBIDDEN_SYMBOL_EXCEPTION_rand +#define FORBIDDEN_SYMBOL_EXCEPTION_srand + #include <stdlib.h> // MSVC does not define M_PI, M_SQRT2 and other math defines by default. // _USE_MATH_DEFINES must be defined in order to have these defined, thus diff --git a/engines/sword25/util/lua/loadlib.cpp b/engines/sword25/util/lua/loadlib.cpp index 2549e2bdb1..9795a575f5 100644 --- a/engines/sword25/util/lua/loadlib.cpp +++ b/engines/sword25/util/lua/loadlib.cpp @@ -9,10 +9,6 @@ */ -#include <stdlib.h> -#include <string.h> - - #define loadlib_c #define LUA_LIB @@ -35,18 +31,6 @@ #define LIB_FAIL "open" -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - -#define setprogdir(L) ((void)0) - - -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); - - /* ** {====================================================== ** Fallback for other systems @@ -60,24 +44,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); #define DLMSG "dynamic libraries not enabled; check your Lua installation" -static void ll_unloadlib (void *lib) { - (void)lib; /* to avoid warnings */ -} - - -static void *ll_load (lua_State *L, const char *path) { - (void)path; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)lib; (void)sym; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - /* }====================================================== */ @@ -108,39 +74,33 @@ static void **ll_register (lua_State *L, const char *path) { */ static int gctm (lua_State *L) { void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); - if (*lib) ll_unloadlib(*lib); *lib = NULL; /* mark library as closed */ return 0; } -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void **reg = ll_register(L, path); - if (*reg == NULL) *reg = ll_load(L, path); - if (*reg == NULL) - return ERRLIB; /* unable to load library */ - else { - lua_CFunction f = ll_sym(L, *reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); - return 0; /* return function */ - } -} +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 static int ll_loadlib (lua_State *L) { const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ +// const char *init = luaL_checkstring(L, 2); + int stat; + void **reg = ll_register(L, path); + if (*reg == NULL) { + stat = ERRLIB; /* unable to load library */ + } else { + stat = ERRFUNC; /* unable to find function */ } + lua_pushliteral(L, DLMSG); + + /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ } @@ -152,109 +112,6 @@ static int ll_loadlib (lua_State *L) { */ -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATHSEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATHSEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname) { - const char *path; - name = luaL_gsub(L, name, ".", LUA_DIRSEP); - lua_getfield(L, LUA_ENVIRONINDEX, pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - lua_pushliteral(L, ""); /* error accumulator */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename; - filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); - lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ - } - return NULL; /* not found */ -} - - -static void loaderror (lua_State *L, const char *filename) { - luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int loader_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); - if (filename == NULL) return 1; /* library not found in this path */ - if (luaL_loadfile(L, filename) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static const char *mkfuncname (lua_State *L, const char *modname) { - const char *funcname; - const char *mark = strchr(modname, *LUA_IGMARK); - if (mark) modname = mark + 1; - funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); - funcname = lua_pushfstring(L, POF"%s", funcname); - lua_remove(L, -2); /* remove 'gsub' result */ - return funcname; -} - - -static int loader_C (lua_State *L) { - const char *funcname; - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); - if (filename == NULL) return 1; /* library not found in this path */ - funcname = mkfuncname(L, name); - if (ll_loadfunc(L, filename, funcname) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static int loader_Croot (lua_State *L) { - const char *funcname; - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); - if (filename == NULL) return 1; /* root not found */ - funcname = mkfuncname(L, name); - if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { - if (stat != ERRFUNC) loaderror(L, filename); /* real error */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; /* function not found */ - } - return 1; -} - - static int loader_preload (lua_State *L) { const char *name = luaL_checkstring(L, 1); lua_getfield(L, LUA_ENVIRONINDEX, "preload"); @@ -407,23 +264,11 @@ static int ll_seeall (lua_State *L) { -/* auxiliary mark (for internal use) */ -#define AUXMARK "\1" - static void setpath (lua_State *L, const char *fieldname, const char *envname, const char *def) { - const char *path = getenv(envname); - if (path == NULL) /* no environment variable? */ - lua_pushstring(L, def); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, - LUA_PATHSEP AUXMARK LUA_PATHSEP); - luaL_gsub(L, path, AUXMARK, def); - lua_remove(L, -2); - } - setprogdir(L); - lua_setfield(L, -2, fieldname); + // no environment variable -> use default + lua_pushstring(L, def); + lua_setfield(L, -2, fieldname); } @@ -442,7 +287,7 @@ static const luaL_Reg ll_funcs[] = { static const lua_CFunction loaders[] = - {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; + {loader_preload, NULL}; LUALIB_API int luaopen_package (lua_State *L) { diff --git a/engines/sword25/util/lua/loslib.cpp b/engines/sword25/util/lua/loslib.cpp index 578a7cb09a..b61f8c65e1 100644 --- a/engines/sword25/util/lua/loslib.cpp +++ b/engines/sword25/util/lua/loslib.cpp @@ -4,9 +4,9 @@ ** See Copyright Notice in lua.h */ +// FIXME: Get rid of all time.h stuff +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h -#include <stdlib.h> -#include <string.h> #include <time.h> #define loslib_c @@ -17,9 +17,14 @@ #include "lauxlib.h" #include "lualib.h" +#include "common/system.h" +#include "common/textconsole.h" + static int os_execute (lua_State *L) { - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + // Non-portable call, removed in ScummVM. + // FIXME: Is this ever invoked? If so, investigate that code further. + lua_pushinteger(L, -1); // signal that an error occurred return 1; } @@ -35,24 +40,30 @@ static int os_remove (lua_State *L) { static int os_rename (lua_State *L) { - // Removed in ScummVM, does nothing. + // Non-portable call, removed in ScummVM. return 1; } static int os_tmpname (lua_State *L) { + // Non-portable call, removed in ScummVM. + // FIXME: Why do we return an error in tmpname, but for other + // removed methods we just do nothing? return luaL_error(L, "unable to generate a unique filename"); } static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + // Non-portable call, removed in ScummVM. + // FIXME: Is this ever invoked? If so, investigate that code further. + lua_pushstring(L, NULL); return 1; } static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + // Non-portable call to clock() replaced by invocation of OSystem::getMillis. + lua_pushnumber(L, ((lua_Number)g_system->getMillis())/(lua_Number)1000); return 1; } @@ -103,6 +114,12 @@ static int getfield (lua_State *L, const char *key, int d) { static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); + // FIXME: Rewrite the code below to use OSystem::getTimeAndDate + // Alternatively, remove it, if sword25 does not use it. + // + // The former would mean sacrificing the ability to choose the timezone, *or* + // we would have to drive an effort to add time zone support to OSystem (is it + // worth that, though???) time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); struct tm *stm; if (*s == '!') { /* UTC? */ @@ -148,6 +165,8 @@ static int os_date (lua_State *L) { static int os_time (lua_State *L) { + // FIXME: Rewrite the code below to use OSystem::getTimeAndDate. + // Alternatively, remove it, if sword25 does not use it. time_t t; if (lua_isnoneornil(L, 1)) /* called without args? */ t = time(NULL); /* get current time */ @@ -173,6 +192,9 @@ static int os_time (lua_State *L) { static int os_difftime (lua_State *L) { + // FIXME: difftime is not portable, unfortunately. + // So we either have to replace this code, or just remove it, + // depending on whether sword25 actually uses it. lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), (time_t)(luaL_optnumber(L, 2, 0)))); return 1; @@ -189,7 +211,13 @@ static int os_setlocale (lua_State *L) { static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); + // FIXME: Using exit is not portable! + // Using OSystem::quit() isn't really a great idea, either. + // We really would prefer to let the main run loop exit, so that + // our main() can perform cleanup. + if (0 == luaL_optint(L, 1, EXIT_SUCCESS)) + g_system->quit(); + error("LUA os_exit invokes with non-zero exit value"); } static const luaL_Reg syslib[] = { diff --git a/engines/sword25/util/lua/lua.h b/engines/sword25/util/lua/lua.h index 088a511cf9..417cdadf8b 100644 --- a/engines/sword25/util/lua/lua.h +++ b/engines/sword25/util/lua/lua.h @@ -9,6 +9,8 @@ #ifndef lua_h #define lua_h +#include "common/scummsys.h" + #include <stdarg.h> #include <stddef.h> diff --git a/engines/sword25/util/lua/luaconf.h b/engines/sword25/util/lua/luaconf.h index 29411d5af1..f3509e969b 100644 --- a/engines/sword25/util/lua/luaconf.h +++ b/engines/sword25/util/lua/luaconf.h @@ -18,14 +18,6 @@ ** =================================================================== */ -#if defined(__ANDROID__) -/* Android is missing strcoll(). -** For more information, refer to: -** http://www.damonkohler.com/2008/12/lua-on-android.html -*/ -#define strcoll strcmp -#endif - /* @@ LUA_ANSI controls the use of non-ansi features. @@ -357,7 +349,7 @@ /* @@ LUA_COMPAT_LSTR controls compatibility with old long string nesting @* facility. -** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** CHANGE it to 2 if you want the old behavior, or undefine it to turn ** off the advisory error when nesting [[...]]. */ #define LUA_COMPAT_LSTR 1 diff --git a/engines/sword25/util/lua/lundump.cpp b/engines/sword25/util/lua/lundump.cpp deleted file mode 100644 index 4ffc623575..0000000000 --- a/engines/sword25/util/lua/lundump.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* -** $Id$ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include <string.h> - -#define lundump_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - -typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; -} LoadState; - -#ifdef LUAC_TRUST_BINARIES -#define IF(c,s) -#define error(S,s) -#else -#define IF(c,s) if (c) error(S,s) - -static void error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); -} -#endif - -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - size_t r=luaZ_read(S->Z,b,size); - UNUSED(r); - IF (r!=0, "unexpected end"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - IF (x<0, "bad integer"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static Proto* LoadFunction(LoadState* S, TString* p); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; i<n; i++) setnilvalue(&f->k[i]); - for (i=0; i<n; i++) - { - TValue* o=&f->k[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: - error(S,"bad constant"); - break; - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; i<n; i++) f->p[i]=NULL; - for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; i<n; i++) f->locvars[i].varname=NULL; - for (i=0; i<n; i++) - { - f->locvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,TString*); - f->sizeupvalues=n; - for (i=0; i<n; i++) f->upvalues[i]=NULL; - for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); -} - -static Proto* LoadFunction(LoadState* S, TString* p) -{ - Proto* f=luaF_newproto(S->L); - setptvalue2s(S->L,S->L->top,f); incr_top(S->L); - f->source=LoadString(S); if (f->source==NULL) f->source=p; - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->nups=LoadByte(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; - return f; -} - -static void LoadHeader(LoadState* S) -{ - char h[LUAC_HEADERSIZE]; - char s[LUAC_HEADERSIZE]; - luaU_header(h); - LoadBlock(S,s,LUAC_HEADERSIZE); - IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -} - -/* -** load precompiled chunk -*/ -Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - return LoadFunction(&S,luaS_newliteral(L,"=?")); -} - -/* -* make header -*/ -void luaU_header (char* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); - h+=sizeof(LUA_SIGNATURE)-1; - *h++=(char)LUAC_VERSION; - *h++=(char)LUAC_FORMAT; - *h++=(char)*(char*)&x; /* endianness */ - *h++=(char)sizeof(int); - *h++=(char)sizeof(size_t); - *h++=(char)sizeof(Instruction); - *h++=(char)sizeof(lua_Number); - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ -} diff --git a/engines/sword25/util/lua/lundump.h b/engines/sword25/util/lua/lundump.h deleted file mode 100644 index f791a4f173..0000000000 --- a/engines/sword25/util/lua/lundump.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id$ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "lobject.h" -#include "lzio.h" - -/* load one chunk; from lundump.c */ -LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (char* h); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); - -#ifdef luac_c -/* print one chunk; from print.c */ -LUAI_FUNC void luaU_print (const Proto* f, int full); -#endif - -/* for header of binary files -- this is Lua 5.1 */ -#define LUAC_VERSION 0x51 - -/* for header of binary files -- this is the official format */ -#define LUAC_FORMAT 0 - -/* size of header of binary files */ -#define LUAC_HEADERSIZE 12 - -#endif diff --git a/engines/sword25/util/lua/lvm.cpp b/engines/sword25/util/lua/lvm.cpp index ae70fe2645..fb700c20a2 100644 --- a/engines/sword25/util/lua/lvm.cpp +++ b/engines/sword25/util/lua/lvm.cpp @@ -202,7 +202,7 @@ static int l_strcmp (const TString *ls, const TString *rs) { const char *r = getstr(rs); size_t lr = rs->tsv.len; for (;;) { - int temp = strcoll(l, r); + int temp = strcmp(l, r); if (temp != 0) return temp; else { /* strings are equal up to a `\0' */ size_t len = strlen(l); /* index of first `\0' in both strings */ diff --git a/engines/sword25/util/lua/print.cpp b/engines/sword25/util/lua/print.cpp deleted file mode 100644 index 22039c9861..0000000000 --- a/engines/sword25/util/lua/print.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* -** $Id$ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include <ctype.h> -#include <stdio.h> - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lundump.h" - -#define PrintFunction luaU_print - -#define Sizeof(x) ((int)sizeof(x)) -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=ts->tsv.len; - putchar('"'); - for (i=0; i<n; i++) - { - int c=s[i]; - switch (c) - { - case '"': printf("\\\""); break; - case '\\': printf("\\\\"); break; - case '\a': printf("\\a"); break; - case '\b': printf("\\b"); break; - case '\f': printf("\\f"); break; - case '\n': printf("\\n"); break; - case '\r': printf("\\r"); break; - case '\t': printf("\\t"); break; - case '\v': printf("\\v"); break; - default: if (isprint((unsigned char)c)) - putchar(c); - else - printf("\\%03u",(unsigned char)c); - } - } - putchar('"'); -} - -static void PrintConstant(const Proto* f, int i) -{ - const TValue* o=&f->k[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; - case LUA_TSTRING: - PrintString(rawtsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc<n; pc++) - { - Instruction i=code[pc]; - OpCode o=GET_OPCODE(i); - int a=GETARG_A(i); - int b=GETARG_B(i); - int c=GETARG_C(i); - int bx=GETARG_Bx(i); - int sbx=GETARG_sBx(i); - int line=getline(f,pc); - printf("\t%d\t",pc+1); - if (line>0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); - break; - case iABx: - if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); - break; - case iAsBx: - if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); - break; - case OP_GETGLOBAL: - case OP_SETGLOBAL: - printf("\t; %s",svalue(&f->k[bx])); - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_POW: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); - else printf("\t; %d",c); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) (x==1)?"":"s" -#define S(x) x,SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=getstr(f->source); - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - f->numparams,f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->nups)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintConstants(const Proto* f) -{ - int i,n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; i<n; i++) - { - printf("\t%d\t",i+1); - PrintConstant(f,i); - printf("\n"); - } -} - -static void PrintLocals(const Proto* f) -{ - int i,n=f->sizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; i<n; i++) - { - printf("\t%d\t%s\t%d\t%d\n", - i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } -} - -static void PrintUpvalues(const Proto* f) -{ - int i,n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - if (f->upvalues==NULL) return; - for (i=0; i<n; i++) - { - printf("\t%d\t%s\n",i,getstr(f->upvalues[i])); - } -} - -void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) - { - PrintConstants(f); - PrintLocals(f); - PrintUpvalues(f); - } - for (i=0; i<n; i++) PrintFunction(f->p[i],full); -} diff --git a/engines/sword25/util/lua/scummvm_file.cpp b/engines/sword25/util/lua/scummvm_file.cpp new file mode 100644 index 0000000000..3c0377d0ee --- /dev/null +++ b/engines/sword25/util/lua/scummvm_file.cpp @@ -0,0 +1,205 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "sword25/util/lua/scummvm_file.h" +#include "common/config-manager.h" +#include "common/util.h" + +namespace Sword25 { + +Sword25FileProxy::Sword25FileProxy(const Common::String &filename, const Common::String &mode) { + assert(filename.contains("config.lua")); + if (mode == "r") + setupConfigFile(); +} + +void Sword25FileProxy::setupConfigFile() { + double sfxVolume = ConfMan.hasKey("sfx_volume") ? 1.0 : 1.0 * ConfMan.getInt("sfx_volume") / 255.0; + double musicVolume = ConfMan.hasKey("music_volume") ? 0.5 : 1.0 * ConfMan.getInt("music_volume") / 255.0; + double speechVolume = ConfMan.hasKey("speech_volume") ? 1.0 : 1.0 * ConfMan.getInt("speech_volume") / 255.0; + bool subtitles = ConfMan.hasKey("subtitles") ? true : ConfMan.getBool("subtitles"); + + _readData = Common::String::format( +"GAME_LANGUAGE = \"%s\"\r\n\ +GAME_SUBTITLES = %s\r\n\ +MAX_MEMORY_USAGE = 256000000\r\n\ +GFX_VSYNC_ACTIVE = true\r\n\ +SFX_SAMPLING_RATE = 44100\r\n\ +SFX_CHANNEL_COUNT = 32\r\n\ +SFX_SOUND_VOLUME = %f\r\n\ +SFX_MUSIC_VOLUME = %f\r\n\ +SFX_SPEECH_VOLUME = %f\r\n", + getLanguage().c_str(), subtitles ? "true" : "false", sfxVolume, musicVolume, speechVolume); + + _readPos = 0; +} + +Sword25FileProxy::~Sword25FileProxy() { + if (!_settings.empty()) + writeSettings(); +} + +size_t Sword25FileProxy::read(void *ptr, size_t size, size_t count) { + size_t bytesRead = MIN<size_t>(_readData.size() - _readPos, size * count); + memmove(ptr, &_readData.c_str()[_readPos], bytesRead); + _readPos += bytesRead; + return bytesRead / size; +} + +size_t Sword25FileProxy::write(const char *ptr, size_t count) { + // Loop through the provided line(s) + while (*ptr) { + if ((*ptr == '-') && (*(ptr + 1) == '-')) { + // Comment line to skip over + while ((*ptr != '\r') && (*ptr != '\n')) + ++ptr; + } else { + // Legitimate data + const char *p = strchr(ptr, '\n'); + if (!p) p = ptr + strlen(ptr); + while ((*p == '\r') || (*p == '\n')) + ++p; + + _settings += Common::String(ptr, p - ptr); + ptr = p; + } + + while ((*ptr == '\r') || (*ptr == '\n')) + ++ptr; + } + + return count; +} + +void Sword25FileProxy::writeSettings() { + // Loop through the setting lines + const char *pSrc = _settings.c_str(); + while (*pSrc) { + if ((*pSrc != '\r') && (*pSrc != '\n')) { + const char *p = strchr(pSrc, '='); + assert(p); + + // Get the setting name + const char *pEnd = p - 1; + while (*pEnd == ' ') + --pEnd; + Common::String settingName(pSrc, pEnd - pSrc + 1); + + // Get the setting value + const char *pStart = p + 1; + while (*pStart == ' ') + ++pStart; + + pEnd = pStart + 1; + while ((*pEnd != '\r') && (*pEnd != '\n') && (*pEnd != '\0')) + ++pEnd; + Common::String value(pStart + (*pStart == '"' ? 1 : 0), pEnd - pStart - (*pStart == '"' ? 2 : 0)); + + // Update the setting + updateSetting(settingName, value); + pSrc = pEnd; + } + + // Move to next line + while ((*pSrc == '\r') || (*pSrc == '\n')) + ++pSrc; + } + + ConfMan.flushToDisk(); +} + +void Sword25FileProxy::updateSetting(const Common::String &setting, const Common::String &value) { + if (setting == "GAME_LANGUAGE") + setLanguage(value); + else if (setting == "GAME_SUBTITLES") + ConfMan.setBool("subtitles", value == "true"); + else if (setting == "SFX_SOUND_VOLUME") { + double v = strtod(value.c_str(), NULL); + ConfMan.setInt("sfx_volume", (int)(v * 255)); + } else if (setting == "SFX_MUSIC_VOLUME") { + double v = strtod(value.c_str(), NULL); + ConfMan.setInt("music_volume", (int)(v * 255)); + } else if (setting == "SFX_SPEECH_VOLUME") { + double v = strtod(value.c_str(), NULL); + ConfMan.setInt("speech_volume", (int)(v * 255)); + } else { + // All other settings are ignored + } +} + +/** + * Get the language code used by the game for each language it supports + */ +Common::String Sword25FileProxy::getLanguage() { + Common::Language lang = Common::parseLanguage(ConfMan.get("language")); + switch (lang) { + case Common::EN_ANY: + return "en"; + case Common::DE_DEU: + return "de"; + case Common::ES_ESP: + return "es"; + case Common::FR_FRA: + return "fr"; + case Common::HU_HUN: + return "hr"; + case Common::IT_ITA: + return "it"; + case Common::PL_POL: + return "pl"; + case Common::PT_BRA: + return "pt"; + case Common::RU_RUS: + return "ru"; + default: + error("Unknown language '%s' encountered", ConfMan.get("language").c_str()); + break; + } +} + +/** + * Set the language code fro the game + */ +void Sword25FileProxy::setLanguage(const Common::String &lang) { + if (lang == "en") + ConfMan.set("language", Common::getLanguageCode(Common::EN_ANY)); + else if (lang == "de") + ConfMan.set("language", Common::getLanguageCode(Common::DE_DEU)); + else if (lang == "es") + ConfMan.set("language", Common::getLanguageCode(Common::ES_ESP)); + else if (lang == "fr") + ConfMan.set("language", Common::getLanguageCode(Common::FR_FRA)); + else if (lang == "hr") + ConfMan.set("language", Common::getLanguageCode(Common::HU_HUN)); + else if (lang == "it") + ConfMan.set("language", Common::getLanguageCode(Common::IT_ITA)); + else if (lang == "pl") + ConfMan.set("language", Common::getLanguageCode(Common::PL_POL)); + else if (lang == "pt") + ConfMan.set("language", Common::getLanguageCode(Common::PT_BRA)); + else if (lang == "ru") + ConfMan.set("language", Common::getLanguageCode(Common::RU_RUS)); + else + error("Unknown language encountered"); +} + +} // End of namespace Sword25 diff --git a/engines/sword25/util/lua/scummvm_file.h b/engines/sword25/util/lua/scummvm_file.h new file mode 100644 index 0000000000..a4cbd2a6cf --- /dev/null +++ b/engines/sword25/util/lua/scummvm_file.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SWORD25_SCUMMVM_FILE_H +#define SWORD25_SCUMMVM_FILE_H + +#include "common/str.h" + +namespace Sword25 { + +/** + * The following class acts as a proxy interface to the I/O code, pretending that the ScummVM + * settings are a properly formatted 'config.lua' file + */ +class Sword25FileProxy { +private: + Common::String _readData; + uint _readPos; + Common::String _settings; + + void setupConfigFile(); + Common::String getLanguage(); + void setLanguage(const Common::String &lang); + void writeSettings(); + void updateSetting(const Common::String &setting, const Common::String &value); +public: + Sword25FileProxy(const Common::String &filename, const Common::String &mode); + ~Sword25FileProxy(); + + bool eof() const { return _readPos >= _readData.size(); } + size_t read(void *ptr, size_t size, size_t count); + size_t write(const char *ptr, size_t count); +}; + +} // End of namespace Sword25 + +#endif |