Merge remote-tracking branch 'origin/master' into soltys_wip2

This commit is contained in:
Alyssa Milburn 2011-07-07 09:24:10 +02:00
commit 66e81d633f
142 changed files with 3558 additions and 2509 deletions

1
.gitignore vendored
View file

@ -28,6 +28,7 @@ lib*.a
/Icon.* /Icon.*
/build /build
/staging
/backends/platform/dc/gui /backends/platform/dc/gui
/backends/platform/dc/graphics /backends/platform/dc/graphics

12
AUTHORS
View file

@ -19,7 +19,7 @@ ScummVM Team
Jonathan Gray - (retired) Jonathan Gray - (retired)
Vincent Hamm - (retired) Vincent Hamm - (retired)
Max Horn - (retired) Max Horn - (retired)
Travis Howell - (retired) Travis Howell
Pawel Kolodziejski - Codecs, iMUSE, Smush, etc. Pawel Kolodziejski - Codecs, iMUSE, Smush, etc.
Gregory Montoir Gregory Montoir
Eugene Sandulenko - FT INSANE, MM NES, MM C64, game detection, Eugene Sandulenko - FT INSANE, MM NES, MM C64, game detection,
@ -28,7 +28,7 @@ ScummVM Team
HE: HE:
Jonathan Gray - (retired) Jonathan Gray - (retired)
Travis Howell - (retired) Travis Howell
Gregory Montoir Gregory Montoir
Eugene Sandulenko Eugene Sandulenko
@ -37,7 +37,7 @@ ScummVM Team
Matthew Hoops Matthew Hoops
Filippos Karapetis Filippos Karapetis
Pawel Kolodziejski Pawel Kolodziejski
Walter van Niftrik Walter van Niftrik - (retired)
Kari Salminen Kari Salminen
Eugene Sandulenko Eugene Sandulenko
David Symonds - (retired) David Symonds - (retired)
@ -45,7 +45,7 @@ ScummVM Team
AGOS: AGOS:
Torbjorn Andersson Torbjorn Andersson
Paul Gilbert Paul Gilbert
Travis Howell - (retired) Travis Howell
Oliver Kiehl - (retired) Oliver Kiehl - (retired)
Ludvig Strigeus - (retired) Ludvig Strigeus - (retired)
@ -141,7 +141,7 @@ ScummVM Team
Max Horn - (retired) Max Horn - (retired)
Filippos Karapetis Filippos Karapetis
Martin Kiewitz Martin Kiewitz
Walter van Niftrik Walter van Niftrik - (retired)
Willem Jan Palenstijn Willem Jan Palenstijn
Jordi Vilalta Prat Jordi Vilalta Prat
Lars Skovlund Lars Skovlund
@ -361,7 +361,7 @@ Other contributions
Markus Strangl Markus Strangl
Win32: Win32:
Travis Howell - (retired) Travis Howell
Win64: Win64:
Chris Gray - (retired) Chris Gray - (retired)

2
NEWS
View file

@ -5,7 +5,7 @@ For a more comprehensive changelog of the latest experimental code, see:
SDL ports: SDL ports:
- Added support for OpenGL (GSoC Task). - Added support for OpenGL (GSoC Task).
1.3.1 (????-??-??) 1.3.1 (2011-07-12)
General: General:
- Improved audio device detection and fallback. - Improved audio device detection and fallback.
There should be no more silent errors due to invalid audio devices. There should be no more silent errors due to invalid audio devices.

3
README
View file

@ -219,6 +219,7 @@ AGI Games by Sierra:
AGOS Games by Adventuresoft/Horrorsoft: AGOS Games by Adventuresoft/Horrorsoft:
Elvira - Mistress of the Dark [elvira1] Elvira - Mistress of the Dark [elvira1]
Elvira II - The Jaws of Cerberus [elvira2] Elvira II - The Jaws of Cerberus [elvira2]
Personal Nightmare [pn]
Waxworks [waxworks] Waxworks [waxworks]
Simon the Sorcerer 1 [simon1] Simon the Sorcerer 1 [simon1]
Simon the Sorcerer 2 [simon2] Simon the Sorcerer 2 [simon2]
@ -942,6 +943,7 @@ arguments -- see the next section.
-z, --list-games Display list of supported games and exit -z, --list-games Display list of supported games and exit
-t, --list-targets Display list of configured targets and exit -t, --list-targets Display list of configured targets and exit
--list-saves=TARGET Display a list of savegames for the game (TARGET) specified --list-saves=TARGET Display a list of savegames for the game (TARGET) specified
--console Enable the console window (default: enabled) (Windows only)
-c, --config=CONFIG Use alternate configuration file -c, --config=CONFIG Use alternate configuration file
-p, --path=PATH Path to where the game is installed -p, --path=PATH Path to where the game is installed
@ -1974,6 +1976,7 @@ The following keywords are recognized:
confirm_exit bool Ask for confirmation by the user before quitting confirm_exit bool Ask for confirmation by the user before quitting
(SDL backend only). (SDL backend only).
console bool Enable the console window (default: enabled) (Windows only).
cdrom number Number of CD-ROM unit to use for audio. If cdrom number Number of CD-ROM unit to use for audio. If
negative, don't even try to access the CD-ROM. negative, don't even try to access the CD-ROM.
joystick_num number Number of joystick device to use for input joystick_num number Number of joystick device to use for input

View file

@ -128,7 +128,8 @@ Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType
MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) { MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// Query the selected music device (defaults to MT_AUTO device). // Query the selected music device (defaults to MT_AUTO device).
DeviceHandle hdl = getDeviceHandle(ConfMan.get("music_driver")); Common::String selDevStr = ConfMan.hasKey("music_driver") ? ConfMan.get("music_driver") : Common::String("auto");
DeviceHandle hdl = getDeviceHandle(selDevStr.empty() ? Common::String("auto") : selDevStr);
DeviceHandle reslt = 0; DeviceHandle reslt = 0;
_forceTypeMT32 = false; _forceTypeMT32 = false;
@ -200,7 +201,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
if (getMusicType(hdl) == MT_INVALID) { if (getMusicType(hdl) == MT_INVALID) {
// If the expressly selected driver or device cannot be found (no longer compiled in, turned off, etc.) // If the expressly selected driver or device cannot be found (no longer compiled in, turned off, etc.)
// we display a warning and continue. // we display a warning and continue.
failedDevStr = ConfMan.get("music_driver"); failedDevStr = selDevStr;
Common::String warningMsg = Common::String::format(_("The selected audio device '%s' was not found (e.g. might be turned off or disconnected). Attempting to fall back to the next available device..."), failedDevStr.c_str()); Common::String warningMsg = Common::String::format(_("The selected audio device '%s' was not found (e.g. might be turned off or disconnected). Attempting to fall back to the next available device..."), failedDevStr.c_str());
GUI::MessageDialog dialog(warningMsg); GUI::MessageDialog dialog(warningMsg);
dialog.runModal(); dialog.runModal();
@ -230,13 +231,15 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// If a preferred MT32 or GM device has been selected that device gets returned if available. // If a preferred MT32 or GM device has been selected that device gets returned if available.
Common::String devStr; Common::String devStr;
if (flags & MDT_PREFER_MT32) if (flags & MDT_PREFER_MT32)
devStr = ConfMan.get("mt32_device"); devStr = ConfMan.hasKey("mt32_device") ? ConfMan.get("mt32_device") : Common::String("null");
else if (flags & MDT_PREFER_GM) else if (flags & MDT_PREFER_GM)
devStr = ConfMan.get("gm_device"); devStr = ConfMan.hasKey("gm_device") ? ConfMan.get("gm_device") : Common::String("null");
else else
devStr = "auto"; devStr = "auto";
hdl = getDeviceHandle(devStr); // Default to Null device here, since we also register a default null setting for
// the MT32 or GM device in the config manager.
hdl = getDeviceHandle(devStr.empty() ? Common::String("null") : devStr);
const MusicType type = getMusicType(hdl); const MusicType type = getMusicType(hdl);
// If we have a "Don't use GM/MT-32" setting we skip this part and jump // If we have a "Don't use GM/MT-32" setting we skip this part and jump

View file

@ -27,7 +27,9 @@
#include "backends/fs/ds/ds-fs.h" #include "backends/fs/ds/ds-fs.h"
#include "dsmain.h" //for the isGBAMPAvailable() function #include "dsmain.h" //for the isGBAMPAvailable() function
namespace Common {
DECLARE_SINGLETON(DSFilesystemFactory); DECLARE_SINGLETON(DSFilesystemFactory);
}
AbstractFSNode *DSFilesystemFactory::makeRootFileNode() const { AbstractFSNode *DSFilesystemFactory::makeRootFileNode() const {
if (DS::isGBAMPAvailable()) { if (DS::isGBAMPAvailable()) {

View file

@ -27,7 +27,9 @@
#include "backends/fs/ps2/ps2-fs-factory.h" #include "backends/fs/ps2/ps2-fs-factory.h"
#include "backends/fs/ps2/ps2-fs.h" #include "backends/fs/ps2/ps2-fs.h"
namespace Common {
DECLARE_SINGLETON(Ps2FilesystemFactory); DECLARE_SINGLETON(Ps2FilesystemFactory);
}
AbstractFSNode *Ps2FilesystemFactory::makeRootFileNode() const { AbstractFSNode *Ps2FilesystemFactory::makeRootFileNode() const {
return new Ps2FilesystemNode(); return new Ps2FilesystemNode();

View file

@ -43,7 +43,9 @@
#include <unistd.h> #include <unistd.h>
namespace Common {
DECLARE_SINGLETON(PSPFilesystemFactory); DECLARE_SINGLETON(PSPFilesystemFactory);
}
AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const { AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const {
return new PSPFilesystemNode(); return new PSPFilesystemNode();

View file

@ -40,7 +40,9 @@
#include <smb.h> #include <smb.h>
#endif #endif
namespace Common {
DECLARE_SINGLETON(WiiFilesystemFactory); DECLARE_SINGLETON(WiiFilesystemFactory);
}
WiiFilesystemFactory::WiiFilesystemFactory() : WiiFilesystemFactory::WiiFilesystemFactory() :
_dvdMounted(false), _dvdMounted(false),

View file

@ -752,6 +752,12 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
error("allocating _screen failed"); error("allocating _screen failed");
#endif #endif
// SDL 1.2 palettes default to all black,
// SDL 1.3 palettes default to all white,
// Thus set our own default palette to all black.
// SDL_SetColors does nothing for non indexed surfaces.
SDL_SetColors(_screen, _currentPalette, 0, 256);
// //
// Create the surface that contains the scaled graphics in 16 bit mode // Create the surface that contains the scaled graphics in 16 bit mode
// //

View file

@ -66,7 +66,7 @@
#include "engines/engine.h" #include "engines/engine.h"
#include "graphics/font.h" #include "graphics/fonts/bdf.h"
#include "graphics/surface.h" #include "graphics/surface.h"
#include "icon.h" #include "icon.h"
@ -96,7 +96,7 @@ OSystem_PS2 *g_systemPs2;
#define FOREVER 2147483647 #define FOREVER 2147483647
namespace Graphics { namespace Graphics {
extern const NewFont g_sysfont; extern const BdfFont g_sysfont;
}; };
PS2Device detectBootPath(const char *elfPath, char *bootPath); PS2Device detectBootPath(const char *elfPath, char *bootPath);

View file

@ -62,7 +62,9 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = {
// Class VramAllocator ----------------------------------- // Class VramAllocator -----------------------------------
namespace Common {
DECLARE_SINGLETON(VramAllocator); DECLARE_SINGLETON(VramAllocator);
}
//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ //#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
//#define __PSP_DEBUG_PRINT__ //#define __PSP_DEBUG_PRINT__

View file

@ -30,7 +30,9 @@
//#define __PSP_DEBUG_PRINT__ //#define __PSP_DEBUG_PRINT__
#include "backends/platform/psp/trace.h" #include "backends/platform/psp/trace.h"
namespace Common {
DECLARE_SINGLETON(PowerManager); DECLARE_SINGLETON(PowerManager);
}
// Function to debug the Power Manager (we have no output to screen) // Function to debug the Power Manager (we have no output to screen)
inline void PowerManager::debugPM() { inline void PowerManager::debugPM() {

View file

@ -34,7 +34,9 @@
// Class PspRtc --------------------------------------------------------------- // Class PspRtc ---------------------------------------------------------------
namespace Common {
DECLARE_SINGLETON(PspRtc); DECLARE_SINGLETON(PspRtc);
}
void PspRtc::init() { // init our starting ticks void PspRtc::init() { // init our starting ticks
uint32 ticks[2]; uint32 ticks[2];

View file

@ -24,6 +24,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL #define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h" #include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/error.h" #include "common/error.h"
#include "common/textconsole.h" #include "common/textconsole.h"
@ -44,46 +45,7 @@
#define DEFAULT_CONFIG_FILE "scummvm.ini" #define DEFAULT_CONFIG_FILE "scummvm.ini"
//#define HIDE_CONSOLE
#ifdef HIDE_CONSOLE
struct SdlConsoleHidingWin32 {
DWORD myPid;
DWORD myTid;
HWND consoleHandle;
};
// console hiding for win32
static BOOL CALLBACK initBackendFindConsoleWin32Proc(HWND hWnd, LPARAM lParam) {
DWORD pid, tid;
SdlConsoleHidingWin32 *variables = (SdlConsoleHidingWin32 *)lParam;
tid = GetWindowThreadProcessId(hWnd, &pid);
if ((tid == variables->myTid) && (pid == variables->myPid)) {
variables->consoleHandle = hWnd;
return FALSE;
}
return TRUE;
}
#endif
void OSystem_Win32::init() { void OSystem_Win32::init() {
#ifdef HIDE_CONSOLE
// console hiding for win32
SdlConsoleHidingWin32 consoleHidingWin32;
consoleHidingWin32.consoleHandle = 0;
consoleHidingWin32.myPid = GetCurrentProcessId();
consoleHidingWin32.myTid = GetCurrentThreadId();
EnumWindows (initBackendFindConsoleWin32Proc, (LPARAM)&consoleHidingWin32);
if (!ConfMan.getBool("show_console")) {
if (consoleHidingWin32.consoleHandle) {
// We won't find a window with our TID/PID in case we were started from command-line
ShowWindow(consoleHidingWin32.consoleHandle, SW_HIDE);
}
}
#endif
// Initialize File System Factory // Initialize File System Factory
_fsFactory = new WindowsFilesystemFactory(); _fsFactory = new WindowsFilesystemFactory();
@ -96,6 +58,26 @@ void OSystem_Win32::init() {
OSystem_SDL::init(); OSystem_SDL::init();
} }
void OSystem_Win32::initBackend() {
// Console window is enabled by default on Windows
ConfMan.registerDefault("console", true);
// Enable or disable the window console window
if (ConfMan.getBool("console")) {
if (AllocConsole()) {
freopen("CONIN$","r",stdin);
freopen("CONOUT$","w",stdout);
freopen("CONOUT$","w",stderr);
}
SetConsoleTitle("ScummVM Status Window");
} else {
FreeConsole();
}
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
bool OSystem_Win32::hasFeature(Feature f) { bool OSystem_Win32::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile) if (f == kFeatureDisplayLogFile)

View file

@ -28,6 +28,7 @@
class OSystem_Win32 : public OSystem_SDL { class OSystem_Win32 : public OSystem_SDL {
public: public:
virtual void init(); virtual void init();
virtual void initBackend();
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);

View file

@ -1,10 +1,26 @@
ScummVM Windows CE FAQ ScummVM Windows CE FAQ
Last updated: 2011-05-27 Last updated: 2011-07-01
Release version: 1.3.0 Release version: 1.3.1
------------------------------------------------------------------------ ------------------------------------------------------------------------
New in this version New in this version
------------------- -------------------
1.3.1:
- Fix for Normal2xAspect scaler which was causing screen update issues in some
games.
- Fix for Normal1xAspect scaler which caused problems in the bottom part of the
screen when toolbar was hidden.
- Fix for freelook mode.
- Fix for timer manager, caused timing issues in some games.
- Activated runtime language detection for ScummVM gui.
- Toolbar is now hidden when returning to the game list.
- Double-tap right-click emulation is now turned off for SCI games by default.
- Added a new option "no_doubletap_paneltoggle" for scummvm.ini to disable
toolbar toggling when double-tapping on the top part of the screen.
- SDL library related fixes:
* Fix for screen/mouse-cursor rotation issues (fixes erratic touchscreen
behaviour)
* Fix for hardware keyboard on some devices (HTC Touch Pro, etc.)
1.3.0: 1.3.0:
This is the first official Windows CE release since 1.1.1. This is the first official Windows CE release since 1.1.1.

View file

@ -29,7 +29,9 @@
#include "common/util.h" #include "common/util.h"
#include <malloc.h> #include <malloc.h>
namespace Common {
DECLARE_SINGLETON(ELFMemoryManager); DECLARE_SINGLETON(ELFMemoryManager);
}
ELFMemoryManager::ELFMemoryManager() : ELFMemoryManager::ELFMemoryManager() :
_heap(0), _heapSize(0), _heapAlign(0), _heap(0), _heapSize(0), _heapAlign(0),

View file

@ -33,7 +33,9 @@ extern char __plugin_hole_start; // Indicates start of hole in program file for
extern char __plugin_hole_end; // Indicates end of hole in program file extern char __plugin_hole_end; // Indicates end of hole in program file
extern char _gp[]; // Value of gp register extern char _gp[]; // Value of gp register
namespace Common {
DECLARE_SINGLETON(ShortSegmentManager); // For singleton DECLARE_SINGLETON(ShortSegmentManager); // For singleton
}
ShortSegmentManager::ShortSegmentManager() { ShortSegmentManager::ShortSegmentManager() {
_shortsStart = &__plugin_hole_start ; //shorts segment begins at the plugin hole we made when linking _shortsStart = &__plugin_hole_start ; //shorts segment begins at the plugin hole we made when linking

View file

@ -66,7 +66,7 @@
// System.Title property key, values taken from http://msdn.microsoft.com/en-us/library/bb787584.aspx // System.Title property key, values taken from http://msdn.microsoft.com/en-us/library/bb787584.aspx
const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 }; const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 };
Win32TaskbarManager::Win32TaskbarManager() : _taskbar(NULL) { Win32TaskbarManager::Win32TaskbarManager() : _taskbar(NULL), _count(0), _icon(NULL) {
// Do nothing if not running on Windows 7 or later // Do nothing if not running on Windows 7 or later
if (!isWin7OrLater()) if (!isWin7OrLater())
return; return;
@ -96,6 +96,9 @@ Win32TaskbarManager::~Win32TaskbarManager() {
_taskbar->Release(); _taskbar->Release();
_taskbar = NULL; _taskbar = NULL;
if (_icon)
DestroyIcon(_icon);
CoUninitialize(); CoUninitialize();
} }
@ -144,6 +147,123 @@ void Win32TaskbarManager::setProgressState(TaskbarProgressState state) {
_taskbar->SetProgressState(getHwnd(), (TBPFLAG)state); _taskbar->SetProgressState(getHwnd(), (TBPFLAG)state);
} }
void Win32TaskbarManager::setCount(int count) {
if (_taskbar == NULL)
return;
if (count == 0) {
_taskbar->SetOverlayIcon(getHwnd(), NULL, L"");
return;
}
// FIXME: This isn't really nice and could use a cleanup.
// The only good thing is that it doesn't use GDI+
// and thus does not have a dependancy on it,
// with the downside of being a lot more ugly.
// Maybe replace it by a Graphic::Surface, use
// ScummVM font drawing and extract the contents at
// the end?
if (_count != count || _icon == NULL) {
// Cleanup previous icon
_count = count;
if (_icon)
DestroyIcon(_icon);
Common::String countString = (count < 100 ? Common::String::format("%d", count) : "9+");
// Create transparent background
BITMAPV5HEADER bi;
ZeroMemory(&bi, sizeof(BITMAPV5HEADER));
bi.bV5Size = sizeof(BITMAPV5HEADER);
bi.bV5Width = 16;
bi.bV5Height = 16;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_RGB;
// Set 32 BPP alpha format
bi.bV5RedMask = 0x00FF0000;
bi.bV5GreenMask = 0x0000FF00;
bi.bV5BlueMask = 0x000000FF;
bi.bV5AlphaMask = 0xFF000000;
// Get DC
HDC hdc;
hdc = GetDC(NULL);
HDC hMemDC = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
// Create a bitmap mask
HBITMAP hBitmapMask = CreateBitmap(16, 16, 1, 1, NULL);
// Create the DIB section with an alpha channel
void *lpBits;
HBITMAP hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, 0);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// Load the icon background
HICON hIconBackground = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(1002 /* IDI_COUNT */));
DrawIconEx(hMemDC, 0, 0, hIconBackground, 16, 16, 0, 0, DI_NORMAL);
DeleteObject(hIconBackground);
// Draw the count
LOGFONT lFont;
memset(&lFont, 0, sizeof(LOGFONT));
lFont.lfHeight = 10;
lFont.lfWeight = FW_BOLD;
lFont.lfItalic = 1;
strcpy(lFont.lfFaceName, "Arial");
HFONT hFont = CreateFontIndirect(&lFont);
SelectObject(hMemDC, hFont);
RECT rect;
SetRect(&rect, 4, 4, 12, 12);
SetTextColor(hMemDC, RGB(48, 48, 48));
SetBkMode(hMemDC, TRANSPARENT);
DrawText(hMemDC, countString.c_str(), -1, &rect, DT_NOCLIP|DT_CENTER);
// Set the text alpha to fully opaque (we consider the data inside the text rect)
DWORD *lpdwPixel = (DWORD *)lpBits;
for (int x = 3; x < 12; x++) {
for(int y = 3; y < 12; y++) {
unsigned char *p = (unsigned char *)(lpdwPixel + x * 16 + y);
if (p[0] != 0 && p[1] != 0 && p[2] != 0)
p[3] = 255;
}
}
// Cleanup DC
DeleteObject(hFont);
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
// Prepare our new icon
ICONINFO ii;
ii.fIcon = FALSE;
ii.xHotspot = 0;
ii.yHotspot = 0;
ii.hbmMask = hBitmapMask;
ii.hbmColor = hBitmap;
_icon = CreateIconIndirect(&ii);
DeleteObject(hBitmap);
DeleteObject(hBitmapMask);
if (!_icon) {
warning("[Win32TaskbarManager::setCount] Cannot create icon for count");
return;
}
}
// Sets the overlay icon
LPWSTR desc = ansiToUnicode(Common::String::format("Found games: %d", count).c_str());
_taskbar->SetOverlayIcon(getHwnd(), _icon, desc);
delete[] desc;
}
void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) { void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) {
//warning("[Win32TaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str()); //warning("[Win32TaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str());

View file

@ -41,11 +41,16 @@ public:
virtual void setOverlayIcon(const Common::String &name, const Common::String &description); virtual void setOverlayIcon(const Common::String &name, const Common::String &description);
virtual void setProgressValue(int completed, int total); virtual void setProgressValue(int completed, int total);
virtual void setProgressState(TaskbarProgressState state); virtual void setProgressState(TaskbarProgressState state);
virtual void setCount(int count);
virtual void addRecent(const Common::String &name, const Common::String &description); virtual void addRecent(const Common::String &name, const Common::String &description);
private: private:
ITaskbarList3 *_taskbar; ITaskbarList3 *_taskbar;
// Count handling
HICON _icon;
int _count;
/** /**
* Get the path to an icon for the game * Get the path to an icon for the game
* *

View file

@ -65,6 +65,9 @@ static const char HELP_STRING[] =
" -z, --list-games Display list of supported games and exit\n" " -z, --list-games Display list of supported games and exit\n"
" -t, --list-targets Display list of configured targets and exit\n" " -t, --list-targets Display list of configured targets and exit\n"
" --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n" " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n"
#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
" --console Enable the console window (default:enabled)\n"
#endif
"\n" "\n"
" -c, --config=CONFIG Use alternate configuration file\n" " -c, --config=CONFIG Use alternate configuration file\n"
" -p, --path=PATH Path to where the game is installed\n" " -p, --path=PATH Path to where the game is installed\n"
@ -181,8 +184,8 @@ void registerDefaults() {
ConfMan.registerDefault("native_mt32", false); ConfMan.registerDefault("native_mt32", false);
ConfMan.registerDefault("enable_gs", false); ConfMan.registerDefault("enable_gs", false);
ConfMan.registerDefault("midi_gain", 100); ConfMan.registerDefault("midi_gain", 100);
// ConfMan.registerDefault("music_driver", ???);
ConfMan.registerDefault("music_driver", "auto");
ConfMan.registerDefault("mt32_device", "null"); ConfMan.registerDefault("mt32_device", "null");
ConfMan.registerDefault("gm_device", "null"); ConfMan.registerDefault("gm_device", "null");
@ -231,13 +234,6 @@ void registerDefaults() {
ConfMan.registerDefault("record_temp_file_name", "record.tmp"); ConfMan.registerDefault("record_temp_file_name", "record.tmp");
ConfMan.registerDefault("record_time_file_name", "record.time"); ConfMan.registerDefault("record_time_file_name", "record.time");
#if 0
// NEW CODE TO HIDE CONSOLE FOR WIN32
#ifdef WIN32
// console hiding for win32
ConfMan.registerDefault("show_console", false);
#endif
#endif
} }
// //
@ -554,14 +550,11 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
END_OPTION END_OPTION
#endif #endif
#if 0 #if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
// NEW CODE TO HIDE CONSOLE FOR WIN32 // Optional console window on Windows (default: enabled)
#ifdef WIN32 DO_LONG_OPTION_BOOL("console")
// console hiding for win32
DO_LONG_OPTION_BOOL("show-console")
END_OPTION END_OPTION
#endif #endif
#endif
unknownOption: unknownOption:
// If we get till here, the option is unhandled and hence unknown. // If we get till here, the option is unhandled and hence unknown.
@ -669,7 +662,7 @@ static Common::Error listSaves(const char *target) {
" ---- ------------------------------------------------------\n"); " ---- ------------------------------------------------------\n");
for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) { for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
printf(" %-4s %s\n", x->save_slot().c_str(), x->description().c_str()); printf(" %-4d %s\n", x->getSaveSlot(), x->getDescription().c_str());
// TODO: Could also iterate over the full hashmap, printing all key-value pairs // TODO: Could also iterate over the full hashmap, printing all key-value pairs
} }
} else { } else {

View file

@ -543,7 +543,9 @@ void PluginManager::addToPluginsInMemList(Plugin *plugin) {
#include "engines/metaengine.h" #include "engines/metaengine.h"
namespace Common {
DECLARE_SINGLETON(EngineManager); DECLARE_SINGLETON(EngineManager);
}
/** /**
* This function works for both cached and uncached PluginManagers. * This function works for both cached and uncached PluginManagers.
@ -634,7 +636,9 @@ const EnginePlugin::List &EngineManager::getPlugins() const {
#include "audio/musicplugin.h" #include "audio/musicplugin.h"
namespace Common {
DECLARE_SINGLETON(MusicManager); DECLARE_SINGLETON(MusicManager);
}
const MusicPlugin::List &MusicManager::getPlugins() const { const MusicPlugin::List &MusicManager::getPlugins() const {
return (const MusicPlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC); return (const MusicPlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC);

View file

@ -27,10 +27,10 @@
#include "common/savefile.h" #include "common/savefile.h"
#include "common/textconsole.h" #include "common/textconsole.h"
DECLARE_SINGLETON(Common::EventRecorder);
namespace Common { namespace Common {
DECLARE_SINGLETON(EventRecorder);
#define RECORD_SIGNATURE 0x54455354 #define RECORD_SIGNATURE 0x54455354
#define RECORD_VERSION 1 #define RECORD_VERSION 1

View file

@ -285,7 +285,7 @@ void SearchManager::clear() {
addDirectory(".", ".", -2); addDirectory(".", ".", -2);
} }
DECLARE_SINGLETON(SearchManager);
} // namespace Common } // namespace Common
DECLARE_SINGLETON(Common::SearchManager);

View file

@ -27,8 +27,6 @@
#include "common/system.h" #include "common/system.h"
#include "common/textconsole.h" #include "common/textconsole.h"
DECLARE_SINGLETON(Common::ConfigManager);
static bool isValidDomainName(const Common::String &domName) { static bool isValidDomainName(const Common::String &domName) {
const char *p = domName.c_str(); const char *p = domName.c_str();
while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_')) while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_'))
@ -38,6 +36,8 @@ static bool isValidDomainName(const Common::String &domName) {
namespace Common { namespace Common {
DECLARE_SINGLETON(ConfigManager);
const char *ConfigManager::kApplicationDomain = "scummvm"; const char *ConfigManager::kApplicationDomain = "scummvm";
const char *ConfigManager::kTransientDomain = "__TRANSIENT"; const char *ConfigManager::kTransientDomain = "__TRANSIENT";

View file

@ -23,16 +23,17 @@
#include "common/debug-channels.h" #include "common/debug-channels.h"
#include "common/system.h" #include "common/system.h"
#include "common/textconsole.h" #include "common/textconsole.h"
#include "common/algorithm.h"
#include <stdarg.h> // For va_list etc. #include <stdarg.h> // For va_list etc.
// TODO: Move gDebugLevel into namespace Common. // TODO: Move gDebugLevel into namespace Common.
int gDebugLevel = -1; int gDebugLevel = -1;
DECLARE_SINGLETON(Common::DebugManager);
namespace Common { namespace Common {
DECLARE_SINGLETON(DebugManager);
namespace { namespace {
struct DebugLevelComperator { struct DebugLevelComperator {

View file

@ -106,8 +106,9 @@ private:
HASHMAP_MEMORYPOOL_SIZE = HASHMAP_MIN_CAPACITY * HASHMAP_LOADFACTOR_NUMERATOR / HASHMAP_LOADFACTOR_DENOMINATOR HASHMAP_MEMORYPOOL_SIZE = HASHMAP_MIN_CAPACITY * HASHMAP_LOADFACTOR_NUMERATOR / HASHMAP_LOADFACTOR_DENOMINATOR
}; };
#ifdef USE_HASHMAP_MEMORY_POOL
ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool; ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool;
#endif
Node **_storage; ///< hashtable of size arrsize. Node **_storage; ///< hashtable of size arrsize.
uint _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one uint _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one
@ -128,12 +129,20 @@ private:
#endif #endif
Node *allocNode(const Key &key) { Node *allocNode(const Key &key) {
#ifdef USE_HASHMAP_MEMORY_POOL
return new (_nodePool) Node(key); return new (_nodePool) Node(key);
#else
return new Node(key);
#endif
} }
void freeNode(Node *node) { void freeNode(Node *node) {
if (node && node != HASHMAP_DUMMY_NODE) if (node && node != HASHMAP_DUMMY_NODE)
#ifdef USE_HASHMAP_MEMORY_POOL
_nodePool.deleteChunk(node); _nodePool.deleteChunk(node);
#else
delete node;
#endif
} }
void assign(const HM_t &map); void assign(const HM_t &map);

View file

@ -89,15 +89,13 @@ protected:
}; };
/** /**
* Note that you need to use this macro from the global namespace. * Note that you need to use this macro from the Common namespace.
* *
* This is because C++ requires initial explicit specialization * This is because C++ requires initial explicit specialization
* to be placed in the same namespace as the template. * to be placed in the same namespace as the template.
* It has to be put in the global namespace to assure the correct
* namespace Common is referenced.
*/ */
#define DECLARE_SINGLETON(T) \ #define DECLARE_SINGLETON(T) \
template<> T *Common::Singleton<T>::_singleton = 0 template<> T *Singleton<T>::_singleton = 0
} // End of namespace Common } // End of namespace Common

View file

@ -154,9 +154,9 @@ protected:
#if defined(USE_TASKBAR) #if defined(USE_TASKBAR)
/** /**
* No default value is provided for _savefileManager by OSystem. * No default value is provided for _taskbarManager by OSystem.
* *
* @note _savefileManager is deleted by the OSystem destructor. * @note _taskbarManager is deleted by the OSystem destructor.
*/ */
Common::TaskbarManager *_taskbarManager; Common::TaskbarManager *_taskbarManager;
#endif #endif

View file

@ -37,10 +37,10 @@
#ifdef USE_TRANSLATION #ifdef USE_TRANSLATION
DECLARE_SINGLETON(Common::TranslationManager);
namespace Common { namespace Common {
DECLARE_SINGLETON(TranslationManager);
bool operator<(const TLanguage &l, const TLanguage &r) { bool operator<(const TLanguage &l, const TLanguage &r) {
return strcmp(l.name, r.name) < 0; return strcmp(l.name, r.name) < 0;
} }

View file

@ -31,6 +31,7 @@
#include "common/hashmap.h" #include "common/hashmap.h"
#include "common/hash-str.h" #include "common/hash-str.h"
#include "common/stack.h" #include "common/stack.h"
#include "common/memorypool.h"
namespace Common { namespace Common {

7
configure vendored
View file

@ -175,7 +175,8 @@ _strip=strip
_ar="ar cru" _ar="ar cru"
_as="as" _as="as"
_windres=windres _windres=windres
_win32path="build/x86" _stagingpath="staging"
_win32path="c:/scummvm"
_aos4path="Games:ScummVM" _aos4path="Games:ScummVM"
_staticlibpath=/sw _staticlibpath=/sw
_sdlconfig=sdl-config _sdlconfig=sdl-config
@ -1854,7 +1855,8 @@ case $_host_os in
mingw*) mingw*)
DEFINES="$DEFINES -DWIN32" DEFINES="$DEFINES -DWIN32"
DEFINES="$DEFINES -D__USE_MINGW_ANSI_STDIO=0" DEFINES="$DEFINES -D__USE_MINGW_ANSI_STDIO=0"
LIBS="$LIBS -lmingw32 -lwinmm" LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++"
LIBS="$LIBS -lmingw32 -lwinmm -lgdi32"
OBJS="$OBJS scummvmwinres.o" OBJS="$OBJS scummvmwinres.o"
add_line_to_config_mk 'WIN32 = 1' add_line_to_config_mk 'WIN32 = 1'
;; ;;
@ -3518,6 +3520,7 @@ AS := $_as
ASFLAGS := $ASFLAGS ASFLAGS := $ASFLAGS
WINDRES := $_windres WINDRES := $_windres
WINDRESFLAGS := $WINDRESFLAGS WINDRESFLAGS := $WINDRESFLAGS
STAGINGPATH=$_stagingpath
WIN32PATH=$_win32path WIN32PATH=$_win32path
AOS4PATH=$_aos4path AOS4PATH=$_aos4path
STATICLIBPATH=$_staticlibpath STATICLIBPATH=$_staticlibpath

View file

@ -721,7 +721,7 @@ int gen_c_source(struct font* pf, char *path) {
char bbuf[256]; char bbuf[256];
char hdr1[] = { char hdr1[] = {
"/* Generated by convbdf on %s. */\n" "/* Generated by convbdf on %s. */\n"
"#include \"graphics/font.h\"\n" "#include \"graphics/fonts/bdf.h\"\n"
"\n" "\n"
"/* Font information:\n" "/* Font information:\n"
" name: %s\n" " name: %s\n"
@ -890,7 +890,7 @@ int gen_c_source(struct font* pf, char *path) {
fprintf(ofp, fprintf(ofp,
"/* Exported structure definition. */\n" "/* Exported structure definition. */\n"
"static const FontDesc desc = {\n" "static const BdfFontDesc desc = {\n"
"\t" "\"%s\",\n" "\t" "\"%s\",\n"
"\t" "%d,\n" "\t" "%d,\n"
"\t" "%d,\n" "\t" "%d,\n"
@ -917,7 +917,7 @@ int gen_c_source(struct font* pf, char *path) {
pf->defaultchar); pf->defaultchar);
fprintf(ofp, "\n" "#if !(defined(__GP32__))\n"); fprintf(ofp, "\n" "#if !(defined(__GP32__))\n");
fprintf(ofp, "extern const NewFont g_sysfont(desc);\n"); fprintf(ofp, "extern const BdfFont g_sysfont(desc);\n");
fprintf(ofp, "#else\n"); fprintf(ofp, "#else\n");
fprintf(ofp, "DEFINE_FONT(g_sysfont)\n"); fprintf(ofp, "DEFINE_FONT(g_sysfont)\n");
fprintf(ofp, "#endif\n"); fprintf(ofp, "#endif\n");

View file

@ -72,10 +72,9 @@ Sub CreateInstaller()
' Build command line ' Build command line
Dim commandLine : commandLine = """" & nsisPath & "\makensis.exe"" /V2" & _ Dim commandLine : commandLine = """" & nsisPath & "\makensis.exe"" /V2" & _
" /Dtop_srcdir=""" & rootFolder & """" & _ " /Dtop_srcdir=""" & rootFolder & """" & _
" /Dbuild_dir=""" & targetFolder & """" & _ " /Dstaging_dir=""" & targetFolder & """" & _
" /Dtext_dir=""" & rootFolder & """" & _
" /DARCH=""" & arch & """" & _ " /DARCH=""" & arch & """" & _
" """ & rootFolder & "\dists\nsis\scummvm.nsi""" " """ & rootFolder & "\dists\win32\scummvm.nsi"""
Dim oExec: Set oExec = WshShell.Exec(commandline) Dim oExec: Set oExec = WshShell.Exec(commandline)
If Err.Number <> 0 Then If Err.Number <> 0 Then

View file

@ -23,23 +23,7 @@ if "%~5"=="" goto error_installer
echo Copying data files echo Copying data files
echo. echo.
REM xcopy /F /Y "%~1/AUTHORS" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/COPYING.GPL" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/COPYING" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/COPYING.LGPL" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/COPYRIGHT" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/NEWS" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/README" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/dists/engine-data/*.dat" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/dists/engine-data/*.tbl" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/dists/engine-data/*.cpt" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/gui/themes/*.zip" %~2 1>NUL 2>&1
REM xcopy /F /Y "%~1/gui/themes/translations.dat" %~2 1>NUL 2>&1
xcopy /F /Y "%~4/lib/%~3/SDL.dll" "%~2" 1>NUL 2>&1 xcopy /F /Y "%~4/lib/%~3/SDL.dll" "%~2" 1>NUL 2>&1
xcopy /F /Y "%~4/README-SDL" "%~2" 1>NUL 2>&1
xcopy /F /Y "%~1/backends/vkeybd/packs/vkeybd_default.zip" "%~2" 1>NUL 2>&1 xcopy /F /Y "%~1/backends/vkeybd/packs/vkeybd_default.zip" "%~2" 1>NUL 2>&1
if "%~5"=="0" goto done if "%~5"=="0" goto done

View file

@ -467,7 +467,7 @@ begin_credits("Credits");
add_person("Jonathan Gray", "khalek", "(retired)"); add_person("Jonathan Gray", "khalek", "(retired)");
add_person("Vincent Hamm", "yaz0r", "(retired)"); add_person("Vincent Hamm", "yaz0r", "(retired)");
add_person("Max Horn", "Fingolfin", "(retired)"); add_person("Max Horn", "Fingolfin", "(retired)");
add_person("Travis Howell", "Kirben", "(retired)"); add_person("Travis Howell", "Kirben", "");
add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", "Codecs, iMUSE, Smush, etc."); add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", "Codecs, iMUSE, Smush, etc.");
add_person("Gregory Montoir", "cyx", ""); add_person("Gregory Montoir", "cyx", "");
add_person("Eugene Sandulenko", "sev", "FT INSANE, MM NES, MM C64, game detection, Herc/CGA"); add_person("Eugene Sandulenko", "sev", "FT INSANE, MM NES, MM C64, game detection, Herc/CGA");
@ -476,7 +476,7 @@ begin_credits("Credits");
begin_section("HE"); begin_section("HE");
add_person("Jonathan Gray", "khalek", "(retired)"); add_person("Jonathan Gray", "khalek", "(retired)");
add_person("Travis Howell", "Kirben", "(retired)"); add_person("Travis Howell", "Kirben", "");
add_person("Gregory Montoir", "cyx", ""); add_person("Gregory Montoir", "cyx", "");
add_person("Eugene Sandulenko", "sev", ""); add_person("Eugene Sandulenko", "sev", "");
end_section(); end_section();
@ -486,7 +486,7 @@ begin_credits("Credits");
add_person("Matthew Hoops", "clone2727", ""); add_person("Matthew Hoops", "clone2727", "");
add_person("Filippos Karapetis", "[md5]", ""); add_person("Filippos Karapetis", "[md5]", "");
add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", ""); add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", "");
add_person("Walter van Niftrik", "waltervn", ""); add_person("Walter van Niftrik", "waltervn", "(retired)");
add_person("Kari Salminen", "Buddha^", ""); add_person("Kari Salminen", "Buddha^", "");
add_person("Eugene Sandulenko", "sev", ""); add_person("Eugene Sandulenko", "sev", "");
add_person("David Symonds", "dsymonds", "(retired)"); add_person("David Symonds", "dsymonds", "(retired)");
@ -495,7 +495,7 @@ begin_credits("Credits");
begin_section("AGOS"); begin_section("AGOS");
add_person("Torbj&ouml;rn Andersson", "eriktorbjorn", ""); add_person("Torbj&ouml;rn Andersson", "eriktorbjorn", "");
add_person("Paul Gilbert", "dreammaster", ""); add_person("Paul Gilbert", "dreammaster", "");
add_person("Travis Howell", "Kirben", "(retired)"); add_person("Travis Howell", "Kirben", "");
add_person("Oliver Kiehl", "olki", "(retired)"); add_person("Oliver Kiehl", "olki", "(retired)");
add_person("Ludvig Strigeus", "ludde", "(retired)"); add_person("Ludvig Strigeus", "ludde", "(retired)");
end_section(); end_section();
@ -609,7 +609,7 @@ begin_credits("Credits");
add_person("Max Horn", "Fingolfin", "(retired)"); add_person("Max Horn", "Fingolfin", "(retired)");
add_person("Filippos Karapetis", "[md5]", ""); add_person("Filippos Karapetis", "[md5]", "");
add_person("Martin Kiewitz", "m_kiewitz", ""); add_person("Martin Kiewitz", "m_kiewitz", "");
add_person("Walter van Niftrik", "waltervn", ""); add_person("Walter van Niftrik", "waltervn", "(retired)");
add_person("Willem Jan Palenstijn", "wjp", ""); add_person("Willem Jan Palenstijn", "wjp", "");
add_person("Jordi Vilalta Prat", "jvprat", ""); add_person("Jordi Vilalta Prat", "jvprat", "");
add_person("Lars Skovlund", "lskovlun", ""); add_person("Lars Skovlund", "lskovlun", "");
@ -878,7 +878,7 @@ begin_credits("Credits");
end_section(); end_section();
begin_section("Win32"); begin_section("Win32");
add_person("Travis Howell", "Kirben", "(retired)"); add_person("Travis Howell", "Kirben", "");
end_section(); end_section();
begin_section("Win64"); begin_section("Win64");

View file

@ -39,7 +39,7 @@ my @subs_files = qw(
dists/macosx/Info.plist dists/macosx/Info.plist
dists/iphone/Info.plist dists/iphone/Info.plist
dists/irix/scummvm.spec dists/irix/scummvm.spec
dists/nsis/scummvm.nsi dists/win32/scummvm.nsi
dists/wii/meta.xml dists/wii/meta.xml
dists/android/AndroidManifest.xml dists/android/AndroidManifest.xml
dists/android/plugin-manifest.xml dists/android/plugin-manifest.xml

View file

@ -6,8 +6,13 @@
#define FILE 256 #define FILE 256
#define IDI_ICON 1001 #define IDI_ICON 1001
#define IDI_COUNT 1002
#define ID_GDF_XML __GDF_XML
IDI_ICON ICON DISCARDABLE "icons/scummvm.ico" IDI_ICON ICON DISCARDABLE "icons/scummvm.ico"
IDI_COUNT ICON DISCARDABLE "icons/count.ico"
ID_GDF_XML DATA "dists/win32/scummvm.gdf.xml"
scummmodern.zip FILE "gui/themes/scummmodern.zip" scummmodern.zip FILE "gui/themes/scummmodern.zip"
#ifdef USE_TRANSLATION #ifdef USE_TRANSLATION

View file

@ -6,8 +6,13 @@
#define FILE 256 #define FILE 256
#define IDI_ICON 1001 #define IDI_ICON 1001
#define IDI_COUNT 1002
#define ID_GDF_XML __GDF_XML
IDI_ICON ICON DISCARDABLE "icons/scummvm.ico" IDI_ICON ICON DISCARDABLE "icons/scummvm.ico"
IDI_COUNT ICON DISCARDABLE "icons/count.ico"
ID_GDF_XML DATA "dists/win32/scummvm.gdf.xml"
scummmodern.zip FILE "gui/themes/scummmodern.zip" scummmodern.zip FILE "gui/themes/scummmodern.zip"
#ifdef USE_TRANSLATION #ifdef USE_TRANSLATION

View file

@ -1,8 +1,12 @@
[Setup] [Setup]
DefaultDirName={pf}\ScummVM
AppCopyright=2011 AppCopyright=2011
AppName=ScummVM AppName=ScummVM
AppVerName=ScummVM Git AppVerName=ScummVM Git
AppPublisher=The ScummVM Team
AppPublisherURL=http://www.scummvm.org/
AppSupportURL=http://www.scummvm.org/
AppUpdatesURL=http://www.scummvm.org/
DefaultDirName={pf}\ScummVM
DefaultGroupName=ScummVM DefaultGroupName=ScummVM
AllowNoIcons=true AllowNoIcons=true
AlwaysUsePersonalGroup=false AlwaysUsePersonalGroup=false
@ -14,7 +18,8 @@ DisableStartupPrompt=true
AppendDefaultDirName=false AppendDefaultDirName=false
SolidCompression=true SolidCompression=true
DirExistsWarning=no DirExistsWarning=no
SetupIconFile=scummvm.ico SetupIconFile=graphics\scummvm-install.ico
WizardImageFile=graphics\left.bmp
ShowLanguageDialog=yes ShowLanguageDialog=yes
LanguageDetectionMethod=uilanguage LanguageDetectionMethod=uilanguage
@ -44,6 +49,7 @@ Name: es; MessagesFile: compiler:Languages\Spanish.isl
[Icons] [Icons]
Name: {group}\{cm:UninstallProgram, ScummVM}; Filename: {uninstallexe} Name: {group}\{cm:UninstallProgram, ScummVM}; Filename: {uninstallexe}
Name: {group}\ScummVM; Filename: {app}\scummvm.exe; WorkingDir: {app}; Comment: scummvm; Flags: createonlyiffileexists; IconIndex: 0 Name: {group}\ScummVM; Filename: {app}\scummvm.exe; WorkingDir: {app}; Comment: scummvm; Flags: createonlyiffileexists; IconIndex: 0
Name: {group}\ScummVM (noconsole); Filename: {app}\scummvm.exe; Parameters: "--no-console"; WorkingDir: {app}; Comment: scummvm; Flags: createonlyiffileexists; IconIndex: 0
Name: {group}\Authors; Filename: {app}\AUTHORS.txt; WorkingDir: {app}; Comment: AUTHORS; Flags: createonlyiffileexists Name: {group}\Authors; Filename: {app}\AUTHORS.txt; WorkingDir: {app}; Comment: AUTHORS; Flags: createonlyiffileexists
Name: {group}\Copying; Filename: {app}\COPYING.txt; WorkingDir: {app}; Comment: COPYING; Flags: createonlyiffileexists Name: {group}\Copying; Filename: {app}\COPYING.txt; WorkingDir: {app}; Comment: COPYING; Flags: createonlyiffileexists
Name: {group}\Copying.LGPL; Filename: {app}\COPYING.LGPL.txt; WorkingDir: {app}; Comment: COPYING.LGPL; Flags: createonlyiffileexists Name: {group}\Copying.LGPL; Filename: {app}\COPYING.LGPL.txt; WorkingDir: {app}; Comment: COPYING.LGPL; Flags: createonlyiffileexists

View file

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before After
Before After

Binary file not shown.

View file

@ -0,0 +1,44 @@
<?xml version="1.0"?>
<GameDefinitionFile xmlns:baseTypes="urn:schemas-microsoft-com:GamesExplorerBaseTypes.v1" xmlns="urn:schemas-microsoft-com:GameDescription.v1">
<GameDefinition gameID="{F2475C5C-EA7C-41F0-A56D-1ABF7CFEA389}">
<Name>ScummVM</Name>
<Description>ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed!</Description>
<ReleaseDate>2011-09-30</ReleaseDate>
<Genres>
<Genre>Adventure</Genre>
</Genres>
<Version>
<VersionFile path="scummvm.exe" />
</Version>
<WindowsSystemPerformanceRating minimum="1.0" recommended="2.0" />
<Developers>
<Developer URI="http://www.scummvm.org">The ScummVM Team</Developer>
</Developers>
<Publishers>
<Publisher URI="http://www.scummvm.org">The ScummVM Team</Publisher>
</Publishers>
<GameExecutables>
<GameExecutable path="scummvm.exe" />
</GameExecutables>
<ExtendedProperties>
<GameTasks>
<Play>
<Primary>
<FileTask path="scummvm.exe" arguments="--no-console" />
</Primary>
<Task index="1" name="Play (console)">
<FileTask path="scummvm.exe" arguments="" />
</Task>
</Play>
<Support>
<Task index="0" name="View README">
<FileTask path="README.txt" arguments="" />
</Task>
<Task index="1" name="ScummVM Website">
<URLTask Link="http://www.scummvm.org" />
</Task>
</Support>
</GameTasks>
</ExtendedProperties>
</GameDefinition>
</GameDefinitionFile>

View file

@ -20,19 +20,26 @@
#!define _DEBUG #!define _DEBUG
#!define _INCLUDE_DATA_FILES #!define _INCLUDE_DATA_FILES
!define _ENABLE_GAME_EXPLORER
#!define _LOG_BUILD
!define _CONVERT_TEXT
Name ScummVM Name ScummVM
# Included files # Included files
!include MUI2.nsh !include MUI2.nsh
# Plugins
!ifdef _ENABLE_GAME_EXPLORER
!AddPluginDir "./plugins"
!endif
######################################################################################### #########################################################################################
# Command line options # Command line options
######################################################################################### #########################################################################################
#!define top_srcdir "" #!define top_srcdir ""
#!define build_dir "" #!define staging_dir ""
#!define text_dir ""
#!define ARCH "" ;(optional, defaults to win32) #!define ARCH "" ;(optional, defaults to win32)
# Check parameters # Check parameters
@ -40,17 +47,19 @@ Name ScummVM
!error "Top source folder has not been passed to command line!" !error "Top source folder has not been passed to command line!"
!endif !endif
!ifndef build_dir !ifndef staging_dir
!error "Build folder has not been passed to command line (this folder should contain the executable and linked DLLs)!" !error "Staging folder has not been passed to command line (this folder should contain the executable and linked DLLs)!"
!endif
!ifndef text_dir
!error "Text folder has not been passed to command line (this folder should contain all the text files used by the installer)!"
!endif !endif
!ifndef ARCH !ifndef ARCH
!warning "ARCH has not been defined, defaulting to 'win32'" !warning "ARCH has not been defined, defaulting to 'win32'"
!define ARCH "win32" !define ARCH "win32"
!else
!if "${ARCH}" == ""
!warning "ARCH was empty, defaulting to 'win32'"
!undef ARCH
!define ARCH "win32"
!endif
!endif !endif
######################################################################################### #########################################################################################
@ -72,7 +81,7 @@ Name ScummVM
######################################################################################### #########################################################################################
# Installer configuration # Installer configuration
######################################################################################### #########################################################################################
OutFile ${build_dir}\scummvm-${VERSION}-${ARCH}.exe OutFile ${staging_dir}\scummvm-${VERSION}-${ARCH}.exe
InstallDir $PROGRAMFILES\ScummVM ; Default installation folder InstallDir $PROGRAMFILES\ScummVM ; Default installation folder
InstallDirRegKey HKCU "Software\ScummVM\ScummVM" "InstallPath" ; Get installation folder from registry if available InstallDirRegKey HKCU "Software\ScummVM\ScummVM" "InstallPath" ; Get installation folder from registry if available
; The application name needs to be refered directly instead of through ${REGKEY} ; The application name needs to be refered directly instead of through ${REGKEY}
@ -220,17 +229,35 @@ Var StartMenuGroup
# Installer sections # Installer sections
######################################################################################### #########################################################################################
Section "ScummVM" SecMain Section "ScummVM" SecMain
!ifdef _LOG_BUILD
LogSet on
!endif
SetOutPath $INSTDIR SetOutPath $INSTDIR
SetOverwrite on SetOverwrite on
# Text files # Text files
File /oname=AUTHORS.txt "${text_dir}\AUTHORS" File /oname=AUTHORS.txt "${top_srcdir}\AUTHORS"
File /oname=COPYING.LGPL.txt "${text_dir}\COPYING.LGPL" File /oname=COPYING.LGPL.txt "${top_srcdir}\COPYING.LGPL"
File /oname=COPYING.txt "${text_dir}\COPYING" File /oname=COPYING.txt "${top_srcdir}\COPYING"
File /oname=COPYRIGHT.txt "${text_dir}\COPYRIGHT" File /oname=COPYRIGHT.txt "${top_srcdir}\COPYRIGHT"
File /oname=NEWS.txt "${text_dir}\NEWS" File /oname=NEWS.txt "${top_srcdir}\NEWS"
File /oname=README.txt "${text_dir}\README" File /oname=README.txt "${top_srcdir}\README"
File /oname=README-SDL.txt "${build_dir}\README-SDL"
!ifdef _CONVERT_TEXT
# Convert line endings
Push "$INSTDIR\AUTHORS.txt"
Call unix2dos
Push "$INSTDIR\COPYING.LGPL.txt"
Call unix2dos
Push "$INSTDIR\COPYING.txt"
Call unix2dos
Push "$INSTDIR\COPYRIGHT.txt"
Call unix2dos
Push "$INSTDIR\NEWS.txt"
Call unix2dos
Push "$INSTDIR\README.txt"
Call unix2dos
!endif
!ifdef _INCLUDE_DATA_FILES !ifdef _INCLUDE_DATA_FILES
# Engine data # Engine data
@ -253,10 +280,27 @@ Section "ScummVM" SecMain
!endif !endif
# Main exe and dlls # Main exe and dlls
File "${build_dir}\scummvm.exe" File "${staging_dir}\scummvm.exe"
File "${build_dir}\SDL.dll" File "${staging_dir}\SDL.dll"
WriteRegStr HKCU "${REGKEY}" InstallPath "$INSTDIR" ; Store installation folder WriteRegStr HKCU "${REGKEY}" InstallPath "$INSTDIR" ; Store installation folder
#Register with game explorer
!ifdef _ENABLE_GAME_EXPLORER
Games::registerGame "$INSTDIR\scummvm.exe"
pop $0
# This is for Vista only, for 7 the tasks are defined in the gdf xml
${If} $0 != "0"
${AndIf} $0 != ""
${AndIf} $0 != "$INSTDIR\scummvm.exe"
CreateDirectory "$0\PlayTasks\0"
CreateShortcut "$0\PlayTasks\0\Play.lnk" "$INSTDIR\scummvm.exe" "--no-console"
CreateDirectory "$0\PlayTasks\1"
CreateShortcut "$0\PlayTasks\1\Play (console).lnk" "$INSTDIR\scummvm.exe"
CreateDirectory "$0\SupportTasks\0"
CreateShortcut "$0\SupportTasks\0\Home Page.lnk" "${URL}"
${EndIf}
!endif
SectionEnd SectionEnd
# Write Start menu entries and uninstaller # Write Start menu entries and uninstaller
@ -267,6 +311,7 @@ Section -post SecMainPost
SetShellVarContext all ; Create shortcuts in the all-users folder SetShellVarContext all ; Create shortcuts in the all-users folder
CreateDirectory "$SMPROGRAMS\$StartMenuGroup" CreateDirectory "$SMPROGRAMS\$StartMenuGroup"
CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\$(^Name).exe "" "$INSTDIR\$(^Name).exe" 0 ; Create shortcut with icon CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\$(^Name).exe "" "$INSTDIR\$(^Name).exe" 0 ; Create shortcut with icon
CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name) (No console).lnk" $INSTDIR\$(^Name).exe "--no-console" "$INSTDIR\$(^Name).exe" 0
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Readme.lnk" $INSTDIR\README.txt CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Readme.lnk" $INSTDIR\README.txt
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END !insertmacro MUI_STARTMENU_WRITE_END
@ -320,6 +365,10 @@ Section -un.Main SecUninstall
Delete /REBOOTOK $INSTDIR\translations.dat Delete /REBOOTOK $INSTDIR\translations.dat
!endif !endif
!ifdef _ENABLE_GAME_EXPLORER
Games::unregisterGame "$INSTDIR\scummvm.exe"
!endif
Delete /REBOOTOK $INSTDIR\scummvm.exe Delete /REBOOTOK $INSTDIR\scummvm.exe
Delete /REBOOTOK $INSTDIR\SDL.dll Delete /REBOOTOK $INSTDIR\SDL.dll
SectionEnd SectionEnd
@ -354,3 +403,63 @@ Function un.onInit
ReadRegStr $INSTDIR HKCU "${REGKEY}" InstallPath ReadRegStr $INSTDIR HKCU "${REGKEY}" InstallPath
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
FunctionEnd FunctionEnd
#########################################################################################
# Helper functions
#########################################################################################
!ifdef _CONVERT_TEXT
;-------------------------------------------------------------------------------
; strips all CRs and then converts all LFs into CRLFs
; (this is roughly equivalent to "cat file | dos2unix | unix2dos")
;
; Usage:
; Push "infile"
; Call unix2dos
;
; Note: this function destroys $0 $1 $2
Function unix2dos
ClearErrors
Pop $2
Rename $2 $2.U2D
FileOpen $1 $2 w
FileOpen $0 $2.U2D r
Push $2 ; save name for deleting
IfErrors unix2dos_done
; $0 = file input (opened for reading)
; $1 = file output (opened for writing)
unix2dos_loop:
; read a byte (stored in $2)
FileReadByte $0 $2
IfErrors unix2dos_done ; EOL
; skip CR
StrCmp $2 13 unix2dos_loop
; if LF write an extra CR
StrCmp $2 10 unix2dos_cr unix2dos_write
unix2dos_cr:
FileWriteByte $1 13
unix2dos_write:
; write byte
FileWriteByte $1 $2
; read next byte
Goto unix2dos_loop
unix2dos_done:
; close files
FileClose $0
FileClose $1
; delete original
Pop $0
Delete $0.U2D
FunctionEnd
!endif

View file

@ -20,19 +20,26 @@
#!define _DEBUG #!define _DEBUG
#!define _INCLUDE_DATA_FILES #!define _INCLUDE_DATA_FILES
!define _ENABLE_GAME_EXPLORER
#!define _LOG_BUILD
!define _CONVERT_TEXT
Name ScummVM Name ScummVM
# Included files # Included files
!include MUI2.nsh !include MUI2.nsh
# Plugins
!ifdef _ENABLE_GAME_EXPLORER
!AddPluginDir "./plugins"
!endif
######################################################################################### #########################################################################################
# Command line options # Command line options
######################################################################################### #########################################################################################
#!define top_srcdir "" #!define top_srcdir ""
#!define build_dir "" #!define staging_dir ""
#!define text_dir ""
#!define ARCH "" ;(optional, defaults to win32) #!define ARCH "" ;(optional, defaults to win32)
# Check parameters # Check parameters
@ -40,17 +47,19 @@ Name ScummVM
!error "Top source folder has not been passed to command line!" !error "Top source folder has not been passed to command line!"
!endif !endif
!ifndef build_dir !ifndef staging_dir
!error "Build folder has not been passed to command line (this folder should contain the executable and linked DLLs)!" !error "Staging folder has not been passed to command line (this folder should contain the executable and linked DLLs)!"
!endif
!ifndef text_dir
!error "Text folder has not been passed to command line (this folder should contain all the text files used by the installer)!"
!endif !endif
!ifndef ARCH !ifndef ARCH
!warning "ARCH has not been defined, defaulting to 'win32'" !warning "ARCH has not been defined, defaulting to 'win32'"
!define ARCH "win32" !define ARCH "win32"
!else
!if "${ARCH}" == ""
!warning "ARCH was empty, defaulting to 'win32'"
!undef ARCH
!define ARCH "win32"
!endif
!endif !endif
######################################################################################### #########################################################################################
@ -72,7 +81,7 @@ Name ScummVM
######################################################################################### #########################################################################################
# Installer configuration # Installer configuration
######################################################################################### #########################################################################################
OutFile ${build_dir}\scummvm-${VERSION}-${ARCH}.exe OutFile ${staging_dir}\scummvm-${VERSION}-${ARCH}.exe
InstallDir $PROGRAMFILES\ScummVM ; Default installation folder InstallDir $PROGRAMFILES\ScummVM ; Default installation folder
InstallDirRegKey HKCU "Software\ScummVM\ScummVM" "InstallPath" ; Get installation folder from registry if available InstallDirRegKey HKCU "Software\ScummVM\ScummVM" "InstallPath" ; Get installation folder from registry if available
; The application name needs to be refered directly instead of through ${REGKEY} ; The application name needs to be refered directly instead of through ${REGKEY}
@ -220,17 +229,35 @@ Var StartMenuGroup
# Installer sections # Installer sections
######################################################################################### #########################################################################################
Section "ScummVM" SecMain Section "ScummVM" SecMain
!ifdef _LOG_BUILD
LogSet on
!endif
SetOutPath $INSTDIR SetOutPath $INSTDIR
SetOverwrite on SetOverwrite on
# Text files # Text files
File /oname=AUTHORS.txt "${text_dir}\AUTHORS" File /oname=AUTHORS.txt "${top_srcdir}\AUTHORS"
File /oname=COPYING.LGPL.txt "${text_dir}\COPYING.LGPL" File /oname=COPYING.LGPL.txt "${top_srcdir}\COPYING.LGPL"
File /oname=COPYING.txt "${text_dir}\COPYING" File /oname=COPYING.txt "${top_srcdir}\COPYING"
File /oname=COPYRIGHT.txt "${text_dir}\COPYRIGHT" File /oname=COPYRIGHT.txt "${top_srcdir}\COPYRIGHT"
File /oname=NEWS.txt "${text_dir}\NEWS" File /oname=NEWS.txt "${top_srcdir}\NEWS"
File /oname=README.txt "${text_dir}\README" File /oname=README.txt "${top_srcdir}\README"
File /oname=README-SDL.txt "${build_dir}\README-SDL"
!ifdef _CONVERT_TEXT
# Convert line endings
Push "$INSTDIR\AUTHORS.txt"
Call unix2dos
Push "$INSTDIR\COPYING.LGPL.txt"
Call unix2dos
Push "$INSTDIR\COPYING.txt"
Call unix2dos
Push "$INSTDIR\COPYRIGHT.txt"
Call unix2dos
Push "$INSTDIR\NEWS.txt"
Call unix2dos
Push "$INSTDIR\README.txt"
Call unix2dos
!endif
!ifdef _INCLUDE_DATA_FILES !ifdef _INCLUDE_DATA_FILES
# Engine data # Engine data
@ -253,10 +280,27 @@ Section "ScummVM" SecMain
!endif !endif
# Main exe and dlls # Main exe and dlls
File "${build_dir}\scummvm.exe" File "${staging_dir}\scummvm.exe"
File "${build_dir}\SDL.dll" File "${staging_dir}\SDL.dll"
WriteRegStr HKCU "${REGKEY}" InstallPath "$INSTDIR" ; Store installation folder WriteRegStr HKCU "${REGKEY}" InstallPath "$INSTDIR" ; Store installation folder
#Register with game explorer
!ifdef _ENABLE_GAME_EXPLORER
Games::registerGame "$INSTDIR\scummvm.exe"
pop $0
# This is for Vista only, for 7 the tasks are defined in the gdf xml
${If} $0 != "0"
${AndIf} $0 != ""
${AndIf} $0 != "$INSTDIR\scummvm.exe"
CreateDirectory "$0\PlayTasks\0"
CreateShortcut "$0\PlayTasks\0\Play.lnk" "$INSTDIR\scummvm.exe" "--no-console"
CreateDirectory "$0\PlayTasks\1"
CreateShortcut "$0\PlayTasks\1\Play (console).lnk" "$INSTDIR\scummvm.exe"
CreateDirectory "$0\SupportTasks\0"
CreateShortcut "$0\SupportTasks\0\Home Page.lnk" "${URL}"
${EndIf}
!endif
SectionEnd SectionEnd
# Write Start menu entries and uninstaller # Write Start menu entries and uninstaller
@ -267,6 +311,7 @@ Section -post SecMainPost
SetShellVarContext all ; Create shortcuts in the all-users folder SetShellVarContext all ; Create shortcuts in the all-users folder
CreateDirectory "$SMPROGRAMS\$StartMenuGroup" CreateDirectory "$SMPROGRAMS\$StartMenuGroup"
CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\$(^Name).exe "" "$INSTDIR\$(^Name).exe" 0 ; Create shortcut with icon CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\$(^Name).exe "" "$INSTDIR\$(^Name).exe" 0 ; Create shortcut with icon
CreateShortCut "$SMPROGRAMS\$StartMenuGroup\$(^Name) (No console).lnk" $INSTDIR\$(^Name).exe "--no-console" "$INSTDIR\$(^Name).exe" 0
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Readme.lnk" $INSTDIR\README.txt CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Readme.lnk" $INSTDIR\README.txt
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END !insertmacro MUI_STARTMENU_WRITE_END
@ -320,6 +365,10 @@ Section -un.Main SecUninstall
Delete /REBOOTOK $INSTDIR\translations.dat Delete /REBOOTOK $INSTDIR\translations.dat
!endif !endif
!ifdef _ENABLE_GAME_EXPLORER
Games::unregisterGame "$INSTDIR\scummvm.exe"
!endif
Delete /REBOOTOK $INSTDIR\scummvm.exe Delete /REBOOTOK $INSTDIR\scummvm.exe
Delete /REBOOTOK $INSTDIR\SDL.dll Delete /REBOOTOK $INSTDIR\SDL.dll
SectionEnd SectionEnd
@ -354,3 +403,63 @@ Function un.onInit
ReadRegStr $INSTDIR HKCU "${REGKEY}" InstallPath ReadRegStr $INSTDIR HKCU "${REGKEY}" InstallPath
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
FunctionEnd FunctionEnd
#########################################################################################
# Helper functions
#########################################################################################
!ifdef _CONVERT_TEXT
;-------------------------------------------------------------------------------
; strips all CRs and then converts all LFs into CRLFs
; (this is roughly equivalent to "cat file | dos2unix | unix2dos")
;
; Usage:
; Push "infile"
; Call unix2dos
;
; Note: this function destroys $0 $1 $2
Function unix2dos
ClearErrors
Pop $2
Rename $2 $2.U2D
FileOpen $1 $2 w
FileOpen $0 $2.U2D r
Push $2 ; save name for deleting
IfErrors unix2dos_done
; $0 = file input (opened for reading)
; $1 = file output (opened for writing)
unix2dos_loop:
; read a byte (stored in $2)
FileReadByte $0 $2
IfErrors unix2dos_done ; EOL
; skip CR
StrCmp $2 13 unix2dos_loop
; if LF write an extra CR
StrCmp $2 10 unix2dos_cr unix2dos_write
unix2dos_cr:
FileWriteByte $1 13
unix2dos_write:
; write byte
FileWriteByte $1 $2
; read next byte
Goto unix2dos_loop
unix2dos_done:
; close files
FileClose $0
FileClose $1
; delete original
Pop $0
Delete $0.U2D
FunctionEnd
!endif

View file

@ -86,27 +86,30 @@ void Winnie::parseObjHeader(WTP_OBJ_HDR *objHdr, byte *buffer, int len) {
} }
uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) { uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
char szFile[256] = {0}; Common::String fileName;
if (_vm->getPlatform() == Common::kPlatformPC) if (_vm->getPlatform() == Common::kPlatformPC)
sprintf(szFile, IDS_WTP_ROOM_DOS, iRoom); fileName = Common::String::format(IDS_WTP_ROOM_DOS, iRoom);
else if (_vm->getPlatform() == Common::kPlatformAmiga) else if (_vm->getPlatform() == Common::kPlatformAmiga)
sprintf(szFile, IDS_WTP_ROOM_AMIGA, iRoom); fileName = Common::String::format(IDS_WTP_ROOM_AMIGA, iRoom);
else if (_vm->getPlatform() == Common::kPlatformC64) else if (_vm->getPlatform() == Common::kPlatformC64)
sprintf(szFile, IDS_WTP_ROOM_C64, iRoom); fileName = Common::String::format(IDS_WTP_ROOM_C64, iRoom);
else if (_vm->getPlatform() == Common::kPlatformApple2GS) else if (_vm->getPlatform() == Common::kPlatformApple2GS)
sprintf(szFile, IDS_WTP_ROOM_APPLE, iRoom); fileName = Common::String::format(IDS_WTP_ROOM_APPLE, iRoom);
Common::File file; Common::File file;
if (!file.open(szFile)) { if (!file.open(fileName)) {
warning ("Could not open file \'%s\'", szFile); warning("Could not open file \'%s\'", fileName.c_str());
return 0; return 0;
} }
uint32 filelen = file.size(); uint32 filelen = file.size();
if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address
filelen -= 2; filelen -= 2;
file.seek(2, SEEK_CUR); file.seek(2, SEEK_CUR);
} }
memset(buffer, 0, sizeof(buffer));
memset(buffer, 0, 4096);
file.read(buffer, filelen); file.read(buffer, filelen);
file.close(); file.close();
@ -116,26 +119,30 @@ uint32 Winnie::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
} }
uint32 Winnie::readObj(int iObj, uint8 *buffer) { uint32 Winnie::readObj(int iObj, uint8 *buffer) {
char szFile[256] = {0}; Common::String fileName;
if (_vm->getPlatform() == Common::kPlatformPC) if (_vm->getPlatform() == Common::kPlatformPC)
sprintf(szFile, IDS_WTP_OBJ_DOS, iObj); fileName = Common::String::format(IDS_WTP_OBJ_DOS, iObj);
else if (_vm->getPlatform() == Common::kPlatformAmiga) else if (_vm->getPlatform() == Common::kPlatformAmiga)
sprintf(szFile, IDS_WTP_OBJ_AMIGA, iObj); fileName = Common::String::format(IDS_WTP_OBJ_AMIGA, iObj);
else if (_vm->getPlatform() == Common::kPlatformC64) else if (_vm->getPlatform() == Common::kPlatformC64)
sprintf(szFile, IDS_WTP_OBJ_C64, iObj); fileName = Common::String::format(IDS_WTP_OBJ_C64, iObj);
else if (_vm->getPlatform() == Common::kPlatformApple2GS) else if (_vm->getPlatform() == Common::kPlatformApple2GS)
sprintf(szFile, IDS_WTP_OBJ_APPLE, iObj); fileName = Common::String::format(IDS_WTP_OBJ_APPLE, iObj);
Common::File file; Common::File file;
if (!file.open(szFile)) { if (!file.open(fileName)) {
warning ("Could not open file \'%s\'", szFile); warning ("Could not open file \'%s\'", fileName.c_str());
return 0; return 0;
} }
uint32 filelen = file.size(); uint32 filelen = file.size();
if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address if (_vm->getPlatform() == Common::kPlatformC64) { // Skip the loading address
filelen -= 2; filelen -= 2;
file.seek(2, SEEK_CUR); file.seek(2, SEEK_CUR);
} }
memset(buffer, 0, sizeof(buffer));
memset(buffer, 0, 2048);
file.read(buffer, filelen); file.read(buffer, filelen);
file.close(); file.close();
return filelen; return filelen;
@ -461,8 +468,6 @@ void Winnie::keyHelp() {
} }
void Winnie::inventory() { void Winnie::inventory() {
char szMissing[41] = {0};
if (_game.iObjHave) if (_game.iObjHave)
printObjStr(_game.iObjHave, IDI_WTP_OBJ_TAKE); printObjStr(_game.iObjHave, IDI_WTP_OBJ_TAKE);
else { else {
@ -470,8 +475,9 @@ void Winnie::inventory() {
_vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0); _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0);
} }
sprintf(szMissing, IDS_WTP_INVENTORY_1, _game.nObjMiss); Common::String missing = Common::String::format(IDS_WTP_INVENTORY_1, _game.nObjMiss);
_vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, szMissing);
_vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, missing.c_str());
_vm->_gfx->doUpdate(); _vm->_gfx->doUpdate();
_vm->_system->updateScreen(); //TODO: Move to game's main loop _vm->_system->updateScreen(); //TODO: Move to game's main loop
_vm->getSelection(kSelAnyKey); _vm->getSelection(kSelAnyKey);
@ -1042,16 +1048,15 @@ phase2:
} }
void Winnie::drawPic(const char *szName) { void Winnie::drawPic(const char *szName) {
char szFile[256] = {0}; Common::String fileName = szName;
if (_vm->getPlatform() != Common::kPlatformAmiga)
fileName += ".pic";
Common::File file; Common::File file;
// construct filename if (!file.open(fileName)) {
if (_vm->getPlatform() != Common::kPlatformAmiga) warning ("Could not open file \'%s\'", fileName.c_str());
sprintf(szFile, "%s.pic", szName);
else
strcpy(szFile, szName);
if (!file.open(szFile)) {
warning ("Could not open file \'%s\'", szFile);
return; return;
} }
@ -1142,12 +1147,11 @@ void Winnie::gameOver() {
} }
void Winnie::saveGame() { void Winnie::saveGame() {
Common::OutSaveFile* outfile;
char szFile[256] = {0};
int i = 0; int i = 0;
sprintf(szFile, IDS_WTP_FILE_SAVEGAME); Common::OutSaveFile *outfile = _vm->getSaveFileMan()->openForSaving(IDS_WTP_FILE_SAVEGAME);
if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile)))
if (!outfile)
return; return;
outfile->writeUint32BE(MKTAG('W','I','N','N')); // header outfile->writeUint32BE(MKTAG('W','I','N','N')); // header
@ -1171,19 +1175,18 @@ void Winnie::saveGame() {
outfile->finalize(); outfile->finalize();
if (outfile->err()) if (outfile->err())
warning("Can't write file '%s'. (Disk full?)", szFile); warning("Can't write file '%s'. (Disk full?)", IDS_WTP_FILE_SAVEGAME);
delete outfile; delete outfile;
} }
void Winnie::loadGame() { void Winnie::loadGame() {
Common::InSaveFile* infile;
char szFile[256] = {0};
int saveVersion = 0; int saveVersion = 0;
int i = 0; int i = 0;
sprintf(szFile, IDS_WTP_FILE_SAVEGAME); Common::InSaveFile *infile = _vm->getSaveFileMan()->openForLoading(IDS_WTP_FILE_SAVEGAME);
if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile)))
if (!infile)
return; return;
if (infile->readUint32BE() == MKTAG('W','I','N','N')) { if (infile->readUint32BE() == MKTAG('W','I','N','N')) {

View file

@ -688,8 +688,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
int16 di; int16 di;
uint16 j; uint16 j;
int16 mouseX, mouseY; int16 mouseX, mouseY;
int16 var_16;
int16 var_14;
int16 currentSelection, oldSelection; int16 currentSelection, oldSelection;
int16 var_4; int16 var_4;
SelectionMenu *menu; SelectionMenu *menu;
@ -731,9 +729,6 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
manageEvents(); manageEvents();
getMouseData(mouseUpdateStatus, &button, (uint16 *)&mouseX, (uint16 *)&mouseY); getMouseData(mouseUpdateStatus, &button, (uint16 *)&mouseX, (uint16 *)&mouseY);
var_16 = mouseX;
var_14 = mouseY;
menuVar = 0; menuVar = 0;
do { do {

View file

@ -902,18 +902,8 @@ bool createDialog(int objOvl, int objIdx, int x, int y) {
if (!obj2Ovl) obj2Ovl = j; if (!obj2Ovl) obj2Ovl = j;
char verbe_name[80]; char verbe_name[80];
char obj1_name[80];
char obj2_name[80];
char r_verbe_name[80];
char r_obj1_name[80];
char r_obj2_name[80];
verbe_name[0] = 0; verbe_name[0] = 0;
obj1_name[0] = 0;
obj2_name[0] = 0;
r_verbe_name[0] = 0;
r_obj1_name[0] = 0;
r_obj2_name[0] = 0;
ovlDataStruct *ovl2 = NULL; ovlDataStruct *ovl2 = NULL;
ovlDataStruct *ovl3 = NULL; ovlDataStruct *ovl3 = NULL;

View file

@ -440,7 +440,6 @@ void buildSegment() {
// is segment on screen ? // is segment on screen ?
if (!((tempAX > 199) || (tempDX < 0))) { if (!((tempAX > 199) || (tempDX < 0))) {
int dx = Y1;
int cx = X2 - X1; int cx = X2 - X1;
if (cx == 0) { if (cx == 0) {
// vertical line // vertical line
@ -473,7 +472,6 @@ void buildSegment() {
} else { } else {
if (cx < 0) { if (cx < 0) {
cx = -cx; cx = -cx;
dx = Y2;
SWAP(X1, X2); SWAP(X1, X2);
SWAP(Y1, Y2); SWAP(Y1, Y2);
@ -1490,9 +1488,6 @@ void mainDraw(int16 param) {
if (currentObjPtr->animLoop > 0) if (currentObjPtr->animLoop > 0)
currentObjPtr->animLoop--; currentObjPtr->animLoop--;
} else { } else {
int16 data2;
data2 = currentObjPtr->animStart;
change = false; change = false;
currentObjPtr->animStep = 0; currentObjPtr->animStep = 0;
@ -1512,9 +1507,6 @@ void mainDraw(int16 param) {
if (currentObjPtr->animLoop > 0) if (currentObjPtr->animLoop > 0)
currentObjPtr->animLoop--; currentObjPtr->animLoop--;
} else { } else {
int16 data2;
data2 = currentObjPtr->animStart;
change = false; change = false;
currentObjPtr->animStep = 0; currentObjPtr->animStep = 0;

View file

@ -231,9 +231,7 @@ int32 opcodeType2() {
int type = getByteFromScript(); int type = getByteFromScript();
int overlay = getByteFromScript(); int overlay = getByteFromScript();
int firstOffset; int offset = getShortFromScript();
int offset;
firstOffset = offset = getShortFromScript();
offset += index; offset += index;
int typ7 = type & 7; int typ7 = type & 7;

View file

@ -43,7 +43,7 @@ public:
AdvancedMetaEngine(DreamWeb::gameDescriptions, AdvancedMetaEngine(DreamWeb::gameDescriptions,
sizeof(DreamWeb::DreamWebGameDescription), dreamWebGames) { sizeof(DreamWeb::DreamWebGameDescription), dreamWebGames) {
_singleid = "dreamweb"; _singleid = "dreamweb";
_guioptions = Common::GUIO_NOMIDI; _guioptions = Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD;
} }
virtual const char *getName() const { virtual const char *getName() const {

View file

@ -31,6 +31,7 @@ namespace DreamWeb {
using Common::GUIO_NONE; using Common::GUIO_NONE;
static const DreamWebGameDescription gameDescriptions[] = { static const DreamWebGameDescription gameDescriptions[] = {
// International floppy release
{ {
{ {
"dreamweb", "dreamweb",
@ -81,6 +82,23 @@ static const DreamWebGameDescription gameDescriptions[] = {
}, },
}, },
// French CD release
{
{
"dreamweb",
"CD",
{
{"dreamwfr.r00", 0, "e354582a8564faf5c515df92f207e8d1", 154657},
{"dreamwfr.r02", 0, "57f3f08d5aefd04184eac76927eced80", 200575},
AD_LISTEND
},
Common::FR_FRA,
Common::kPlatformPC,
ADGF_CD | ADGF_UNSTABLE,
GUIO_NONE
},
},
// German floppy release // German floppy release
{ {
{ {
@ -132,6 +150,23 @@ static const DreamWebGameDescription gameDescriptions[] = {
}, },
}, },
// Spanish CD release
{
{
"dreamweb",
"CD",
{
{"dreamwsp.r00", 0, "2df07174321de39c4f17c9ff654b268a", 153608},
{"dreamwsp.r02", 0, "577d435ad5da08fb1bcf6ea3dd6e0b9e", 199499},
AD_LISTEND
},
Common::ES_ESP,
Common::kPlatformPC,
ADGF_CD | ADGF_UNSTABLE,
GUIO_NONE
},
},
// Italian floppy release // Italian floppy release
{ {
{ {

View file

@ -410,7 +410,7 @@ void Engine::openMainMenuDialog() {
// value, which is quite bad since it could // value, which is quite bad since it could
// be a fatal loading error, which renders // be a fatal loading error, which renders
// the engine unusable. // the engine unusable.
if (_saveSlotToLoad > 0) if (_saveSlotToLoad >= 0)
loadGameState(_saveSlotToLoad); loadGameState(_saveSlotToLoad);
syncSoundSettings(); syncSoundSettings();

View file

@ -102,7 +102,7 @@ Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, int s
// Fill the SaveStateDescriptor if it was provided // Fill the SaveStateDescriptor if it was provided
if (descriptor) { if (descriptor) {
// Initialize the SaveStateDescriptor // Initialize the SaveStateDescriptor
descriptor->setVal("save_slot", Common::String('0' + slot)); descriptor->setSaveSlot(slot);
descriptor->setDeletableFlag(true); descriptor->setDeletableFlag(true);
descriptor->setWriteProtectedFlag(false); descriptor->setWriteProtectedFlag(false);
@ -132,7 +132,7 @@ Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, int s
description += c; description += c;
} }
} }
descriptor->setVal("description", description); descriptor->setDescription(description);
} }
// Return a substream, skipping the metadata // Return a substream, skipping the metadata

View file

@ -1350,15 +1350,15 @@ void Script::o_checkvalidsaves() {
uint count = 0; uint count = 0;
SaveStateList::iterator it = list.begin(); SaveStateList::iterator it = list.begin();
while (it != list.end()) { while (it != list.end()) {
int8 slot = it->getVal("save_slot").lastChar() - '0'; int8 slot = it->getSaveSlot();
if (SaveLoad::isSlotValid(slot)) { if (SaveLoad::isSlotValid(slot)) {
debugScript(2, true, " Found valid savegame: %s", it->getVal("description").c_str()); debugScript(2, true, " Found valid savegame: %s", it->getDescription().c_str());
// Mark this slot as used // Mark this slot as used
setVariable(slot, 1); setVariable(slot, 1);
// Cache this slot's description // Cache this slot's description
_saveNames[slot] = it->getVal("description"); _saveNames[slot] = it->getDescription();
count++; count++;
} }
it++; it++;

View file

@ -71,7 +71,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
} }
if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) { if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) {
uint8 *buffer = (uint8 *)malloc(320 * 200 * sizeof(uint8)); uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)];
if (!buffer) { if (!buffer) {
DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n"); DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
return true; return true;
@ -82,7 +82,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
palette.copy(_vm->screen()->getCPagePtr(5), 0, 256); palette.copy(_vm->screen()->getCPagePtr(5), 0, 256);
_vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer); _vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer);
free(buffer); delete[] buffer;
} else if (!_vm->screen()->loadPalette(argv[1], palette)) { } else if (!_vm->screen()->loadPalette(argv[1], palette)) {
DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
return true; return true;

View file

@ -576,6 +576,15 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) {
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
Common::strlcpy(_savegameNames[i], header.description.c_str(), ARRAYSIZE(_savegameNames[0])); Common::strlcpy(_savegameNames[i], header.description.c_str(), ARRAYSIZE(_savegameNames[0]));
// Trim long GMM save descriptions to fit our save slots
_screen->_charWidth = -2;
int fC = _screen->getTextWidth(_savegameNames[i]);
while (_savegameNames[i][0] && (fC > 240 )) {
_savegameNames[i][strlen(_savegameNames[i]) - 1] = 0;
fC = _screen->getTextWidth(_savegameNames[i]);
}
_screen->_charWidth = 0;
Util::convertISOToDOS(_savegameNames[i]); Util::convertISOToDOS(_savegameNames[i]);
menu.item[i].itemString = _savegameNames[i]; menu.item[i].itemString = _savegameNames[i];
@ -693,12 +702,15 @@ void GUI_LoK::updateSavegameString() {
if (_keyPressed.keycode) { if (_keyPressed.keycode) {
length = strlen(_savegameName); length = strlen(_savegameName);
_screen->_charWidth = -2;
int width = _screen->getTextWidth(_savegameName) + 7;
_screen->_charWidth = 0;
char inputKey = _keyPressed.ascii; char inputKey = _keyPressed.ascii;
Util::convertISOToDOS(inputKey); Util::convertISOToDOS(inputKey);
if ((uint8)inputKey > 31 && (uint8)inputKey < (_vm->gameFlags().lang == Common::JA_JPN ? 128 : 226)) { if ((uint8)inputKey > 31 && (uint8)inputKey < (_vm->gameFlags().lang == Common::JA_JPN ? 128 : 226)) {
if (length < ARRAYSIZE(_savegameName)-1) { if ((length < ARRAYSIZE(_savegameName)-1) && (width <= 240)) {
_savegameName[length] = inputKey; _savegameName[length] = inputKey;
_savegameName[length+1] = 0; _savegameName[length+1] = 0;
redrawTextfield(); redrawTextfield();

View file

@ -2572,9 +2572,19 @@ void GUI_LoL::setupSaveMenuSlots(Menu &menu, int num) {
slotOffs = 1; slotOffs = 1;
} }
int saveSlotMaxLen = ((_screen->getScreenDim(8))->w << 3) - _screen->getCharWidth('W');
for (int i = startSlot; i < num && _savegameOffset + i - slotOffs < _savegameListSize; ++i) { for (int i = startSlot; i < num && _savegameOffset + i - slotOffs < _savegameListSize; ++i) {
if (_savegameList[_saveSlots[i + _savegameOffset - slotOffs]]) { if (_savegameList[_saveSlots[i + _savegameOffset - slotOffs]]) {
Common::strlcpy(s, _savegameList[_saveSlots[i + _savegameOffset - slotOffs]], 80); Common::strlcpy(s, _savegameList[_saveSlots[i + _savegameOffset - slotOffs]], 80);
// Trim long GMM save descriptions to fit our save slots
int fC = _screen->getTextWidth(s);
while (s[0] && fC >= saveSlotMaxLen) {
s[strlen(s) - 1] = 0;
fC = _screen->getTextWidth(s);
}
menu.item[i].itemString = s; menu.item[i].itemString = s;
s += (strlen(s) + 1); s += (strlen(s) + 1);
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset - slotOffs]; menu.item[i].saveSlot = _saveSlots[i + _savegameOffset - slotOffs];

View file

@ -457,6 +457,15 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) {
Common::strlcpy(s, header.description.c_str(), 80); Common::strlcpy(s, header.description.c_str(), 80);
Util::convertISOToDOS(s); Util::convertISOToDOS(s);
// Trim long GMM save descriptions to fit our save slots
_screen->_charWidth = -2;
int fC = _screen->getTextWidth(s);
while (s[0] && fC > 240) {
s[strlen(s) - 1] = 0;
fC = _screen->getTextWidth(s);
}
_screen->_charWidth = 0;
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
menu.item[i].enabled = true; menu.item[i].enabled = true;
delete in; delete in;

View file

@ -83,6 +83,8 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
} }
void KyraEngine_v1::pauseEngineIntern(bool pause) { void KyraEngine_v1::pauseEngineIntern(bool pause) {
Engine::pauseEngineIntern(pause);
if (_sound)
_sound->pause(pause); _sound->pause(pause);
_timer->pause(pause); _timer->pause(pause);
} }

View file

@ -3359,7 +3359,7 @@ void SJISFont::drawChar(uint16 c, byte *dst, int pitch) const {
color2 = _colorMap[0]; color2 = _colorMap[0];
} }
_font->drawChar(dst, c, 640, 1, color1, color2); _font->drawChar(dst, c, 640, 1, color1, color2, 640, 400);
} }
#pragma mark - #pragma mark -

View file

@ -43,10 +43,6 @@ Sound::Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer)
Sound::~Sound() { Sound::~Sound() {
} }
void Sound::pause(bool paused) {
_mixer->pauseAll(paused);
}
bool Sound::voiceFileIsPresent(const char *file) { bool Sound::voiceFileIsPresent(const char *file) {
for (int i = 0; _supportedCodecs[i].fileext; ++i) { for (int i = 0; _supportedCodecs[i].fileext; ++i) {
Common::String f = file; Common::String f = file;

View file

@ -156,7 +156,7 @@ public:
/** /**
* Stops all audio playback when paused. Continues after end of pause. * Stops all audio playback when paused. Continues after end of pause.
*/ */
virtual void pause(bool paused); virtual void pause(bool paused) {}
void enableMusic(int enable) { _musicEnabled = enable; } void enableMusic(int enable) { _musicEnabled = enable; }
int musicEnabled() const { return _musicEnabled; } int musicEnabled() const { return _musicEnabled; }

View file

@ -716,9 +716,6 @@ void SoundMidiPC::beginFadeOut() {
} }
void SoundMidiPC::pause(bool paused) { void SoundMidiPC::pause(bool paused) {
// Stop all mixer related sounds
Sound::pause(paused);
Common::StackLock lock(_mutex); Common::StackLock lock(_mutex);
if (paused) { if (paused) {

View file

@ -36,13 +36,329 @@
namespace LastExpress { namespace LastExpress {
#pragma region Sound filters tables
static const int filterData[1424] = {
0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256,
384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0,
192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640,
64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128,
320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576,
704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192,
192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448,
576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832,
320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320,
320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704,
832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448,
448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448,
640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960,
1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576,
576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576,
576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832,
960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088,
1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704,
704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768,
768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960,
1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280,
1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896,
896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896,
896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152,
1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408,
1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600,
1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088,
1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088,
1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152,
1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152,
1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408,
1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536,
1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728,
1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856,
1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344,
1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408,
1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408,
1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472,
1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664,
1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856,
1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984,
2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176,
1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664,
1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664,
1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728,
1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728,
1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984,
2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112,
2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304,
2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432,
1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920,
1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984,
1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984,
1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048,
2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240,
2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432,
2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560,
2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752,
2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240,
2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240,
2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304,
2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304,
2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560,
2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688,
2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880,
3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008,
2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496,
2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560,
2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560,
2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624,
2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816,
2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008,
3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136,
3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328,
2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816,
2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816,
2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880,
2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880,
3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136,
3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264,
3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456,
3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584,
3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072,
3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136,
3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136,
3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200,
3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392,
3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584,
3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712,
3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904,
3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392,
3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392,
3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456,
3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456,
3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712,
3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840,
3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032,
4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160,
3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648,
3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712,
3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712,
3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776,
3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968,
4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160,
4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288,
4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480,
3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968,
3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968,
3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032,
4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032,
4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288,
4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416,
4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608,
4.6, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736,
4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224,
4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288,
4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288,
4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352,
4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544,
4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736,
4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864,
4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056,
4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544,
4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544,
4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608,
4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608,
4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864,
4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992,
5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184,
5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312,
4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800,
4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864,
4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864,
4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928,
5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120,
5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312,
5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440,
5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632,
5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120,
5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120,
5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184,
5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184,
5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440,
5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568,
5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632,
5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632,
5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376,
5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440,
5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440,
5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504,
5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632,
5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632,
5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632,
5632
};
static const int filterData2[1424] = {
0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11,
-13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9,
-11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5,
-7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18,
-1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12,
15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4,
7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19,
-22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14,
-17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5,
-8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26,
30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10,
14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27,
-31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16,
-21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2,
-7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25,
31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3,
9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34,
-40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17,
-24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50,
58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21,
29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55,
-63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32,
-41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5,
-15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50,
61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6,
18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56,
-68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20,
-34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82,
97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8,
24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74,
-90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9,
-27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70,
90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130,
-150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55,
-77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133,
157, 181, -12, -36, -60, -84, -109, -133, -157, -181,
13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93,
-120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191,
221, -14, -44, -73, -103, -132, -162, -191, -221, 16,
48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113,
-146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232,
268, -17, -53, -89, -125, -160, -196, -232, -268, 19,
58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137,
-176, -215, -255, -294, 21, 64, 108, 151, 194, 237,
281, 324, -21, -64, -108, -151, -194, -237, -281, -324,
23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118,
-166, -213, -261, -308, -356, 26, 78, 130, 182, 235,
287, 339, 391, -26, -78, -130, -182, -235, -287, -339,
-391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86,
-143, -201, -258, -316, -373, -431, 31, 94, 158, 221,
284, 347, 411, 474, -31, -94, -158, -221, -284, -347,
-411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34,
-104, -174, -244, -313, -383, -453, -523, 38, 115, 191,
268, 345, 422, 498, 575, -38, -115, -191, -268, -345,
-422, -498, -575, 42, 126, 210, 294, 379, 463, 547,
631, -42, -126, -210, -294, -379, -463, -547, -631,
46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231,
-324, -417, -510, -602, -695, 51, 153, 255, 357, 459,
561, 663, 765, -51, -153, -255, -357, -459, -561, -663,
-765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168,
-280, -392, -505, -617, -729, -841, 61, 185, 308, 432,
555, 679, 802, 926, -61, -185, -308, -432, -555, -679,
-802, -926, 68, 204, 340, 476, 612, 748, 884, 1020,
-68, -204, -340, -476, -612, -748, -884, -1020, 74,
224, 373, 523, 672, 822, 971, 1121, -74, -224, -373,
-523, -672, -822, -971, -1121, 82, 246, 411, 575, 740,
904, 1069, 1233, -82, -246, -411, -575, -740, -904,
-1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357,
-90, -271, -452, -633, -814, -995, -1176, -1357, 99,
298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497,
-696, -895, -1094, -1293, -1492, 109, 328, 547, 766,
985, 1204, 1423, 1642, -109, -328, -547, -766, -985,
-1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324,
1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564,
-1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132,
-397, -662, -927, -1192, -1457, -1722, -1987, 145, 437,
728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728,
-1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121,
1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442,
-1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940,
2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292,
-2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910,
-194, -582, -970, -1358, -1746, -2134, -2522, -2910,
213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213,
-640, -1066, -1493, -1920, -2347, -2773, -3200, 234,
704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704,
-1173, -1643, -2112, -2582, -3051, -3521, 258, 774,
1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291,
-1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988,
2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556,
-3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436,
4060, 4685, -312, -937, -1561, -2186, -2811, -3436,
-4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467,
5154, -343, -1030, -1718, -2405, -3092, -3779, -4467,
-5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670,
-378, -1134, -1890, -2646, -3402, -4158, -4914, -5670,
415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415,
-1247, -2079, -2911, -3742, -4574, -5406, -6238, 457,
1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372,
-2287, -3202, -4117, -5032, -5947, -6862, 503, 1509,
2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516,
-3522, -4529, -5535, -6542, -7548, 553, 1660, 2767,
3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874,
-4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479,
6697, 7915, 9133, -608, -1826, -3044, -4262, -5479,
-6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367,
8706, 10046, -669, -2009, -3348, -4688, -6027, -7367,
-8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577,
11051, -736, -2210, -3683, -5157, -6630, -8104, -9577,
-11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157,
-810, -2431, -4052, -5673, -7294, -8915, -10536, -12157,
891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891,
-2674, -4457, -6240, -8023, -9806, -11589, -13372, 980,
2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941,
-4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236,
5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236,
-5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559,
5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559,
-5933, -8306, -10679, -13052, -15426, -17799, 1305,
3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305,
-3915, -6526, -9136, -11747, -14357, -16968, -19578,
1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538,
-1435, -4307, -7179, -10051, -12922, -15794, -18666,
-21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531,
23690, -1579, -4738, -7896, -11055, -14214, -17373,
-20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111,
22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111,
-22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022,
24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022,
-24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124,
27329, 31533, -2102, -6306, -10511, -14715, -18920,
-23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812,
25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812,
-25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893,
27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893,
-27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183,
30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183,
-30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700,
32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700,
-32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471,
32767, 32767, 32767, -3385, -10157, -16928, -23700,
-30471, -32767, -32767, -32767, 3724, 11172, 18621,
26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621,
-26069, -32767, -32767, -32767, -32767, 4095, 12287,
20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287,
-20479, -28671, -32767, -32767, -32767, -32767
};
static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 };
static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 };
#pragma endregion
// Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles // Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles
// and does not have the 4 byte per channel requirement // and does not have the 4 byte per channel requirement
class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream { class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream {
public: public:
LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize) : LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, int32 filterId) :
Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {} Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {
_currentFilterId = -1;
_nextFilterId = filterId;
}
int readBuffer(int16 *buffer, const int numSamples) { int readBuffer(int16 *buffer, const int numSamples) {
int samples = 0; int samples = 0;
@ -67,6 +383,45 @@ public:
return samples; return samples;
} }
void setFilterId(int32 filterId) { _nextFilterId = filterId; }
private:
int32 _currentFilterId;
int32 _nextFilterId; // the sound filter id, -1 for none
/**
* Sound filter
*
* @param [in] data If non-null, the input data
* @param [in,out] buffer If non-null, the output buffer.
* @param p1 The first filter input.
* @param p2 The second filter input.
*/
static void soundFilter(byte *data, int16 *buffer, int p1, int p2) {
int data1, data2, data1p, data2p;
byte idx;
data2 = data[0];
data1 = data[1] << 6;
data += 2;
for (int count = 0; count < 735; count++) {
idx = data[count] >> 4;
data1p = filterData[idx + data1];
data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767);
buffer[2 * count] = (p2 * data2p) >> p1;
idx = data[count] & 0xF;
data1 = filterData[idx + data1p];
data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767);
buffer[2 * count + 1] = (p2 * data2) >> p1;
}
}
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -92,8 +447,8 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) {
_blockSize = _size / _blocks; _blockSize = _size / _blocks;
} }
Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size) const { Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const {
return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize); return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, filterId);
} }
void SimpleSound::play(Audio::AudioStream *as) { void SimpleSound::play(Audio::AudioStream *as) {
@ -103,10 +458,11 @@ void SimpleSound::play(Audio::AudioStream *as) {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// StreamedSound // StreamedSound
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
StreamedSound::StreamedSound() {} StreamedSound::StreamedSound() : _as(NULL), _loaded(false) {}
StreamedSound::~StreamedSound() {} StreamedSound::~StreamedSound() {}
bool StreamedSound::load(Common::SeekableReadStream *stream) { bool StreamedSound::load(Common::SeekableReadStream *stream, int32 filterId) {
if (!stream) if (!stream)
return false; return false;
@ -115,14 +471,27 @@ bool StreamedSound::load(Common::SeekableReadStream *stream) {
loadHeader(stream); loadHeader(stream);
// Start decoding the input stream // Start decoding the input stream
Audio::AudioStream *as = makeDecoder(stream, _size); _as = makeDecoder(stream, _size, filterId);
// Start playing the decoded audio stream // Start playing the decoded audio stream
play(as); play(_as);
_loaded = true;
return true; return true;
} }
bool StreamedSound::isFinished() {
if (!_loaded)
return false;
return !g_system->getMixer()->isSoundHandleActive(_handle);
}
void StreamedSound::setFilterId(int32 filterId) {
((LastExpress_ADPCMStream *)_as)->setFilterId(filterId);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// StreamedSound // StreamedSound
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -172,4 +541,8 @@ void AppendableSound::finish() {
_finished = true; _finished = true;
} }
bool AppendableSound::isFinished() {
return _as->endOfStream();
}
} // End of namespace LastExpress } // End of namespace LastExpress

View file

@ -55,10 +55,11 @@ public:
virtual ~SimpleSound(); virtual ~SimpleSound();
void stop() const; void stop() const;
virtual bool isFinished() = 0;
protected: protected:
void loadHeader(Common::SeekableReadStream *in); void loadHeader(Common::SeekableReadStream *in);
Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size) const; Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const;
void play(Audio::AudioStream *as); void play(Audio::AudioStream *as);
uint32 _size; ///< data size uint32 _size; ///< data size
@ -75,7 +76,14 @@ public:
StreamedSound(); StreamedSound();
~StreamedSound(); ~StreamedSound();
bool load(Common::SeekableReadStream *stream); bool load(Common::SeekableReadStream *stream, int32 filterId = -1);
virtual bool isFinished();
void setFilterId(int32 filterId);
private:
Audio::AudioStream *_as;
bool _loaded;
}; };
class AppendableSound : public SimpleSound { class AppendableSound : public SimpleSound {
@ -87,6 +95,8 @@ public:
void queueBuffer(Common::SeekableReadStream *bufferIn); void queueBuffer(Common::SeekableReadStream *bufferIn);
void finish(); void finish();
virtual bool isFinished();
private: private:
Audio::QueuingAudioStream *_as; Audio::QueuingAudioStream *_as;
bool _finished; bool _finished;

View file

@ -26,6 +26,8 @@
#include "lastexpress/data/archive.h" #include "lastexpress/data/archive.h"
#include "lastexpress/shared.h" #include "lastexpress/shared.h"
#include "common/array.h"
namespace LastExpress { namespace LastExpress {
class Background; class Background;

View file

@ -89,6 +89,27 @@ enum SoundState {
kSoundState2 = 2 kSoundState2 = 2
}; };
enum SoundStatus {
kSoundStatus_20 = 0x20,
kSoundStatus_40 = 0x40,
kSoundStatus_180 = 0x180,
kSoundStatusClosed = 0x200,
kSoundStatus_400 = 0x400,
kSoundStatus_8000 = 0x8000,
kSoundStatus_20000 = 0x20000,
kSoundStatus_100000 = 0x100000,
kSoundStatus_20000000 = 0x20000000,
kSoundStatus_40000000 = 0x40000000,
kSoundStatusClear0 = 0x10,
kSoundStatusFilter = 0x1F,
kSoundStatusCached = 0x80,
kSoundStatusClear3 = 0x200,
kSoundStatusClear4 = 0x800,
kSoundStatusClearAll = 0xFFFFFFE0
};
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Time values // Time values
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View file

@ -38,15 +38,15 @@
namespace LastExpress { namespace LastExpress {
#define SOUNDCACHE_ENTRY_SIZE 92160
#define FILTER_BUFFER_SIZE 2940
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SoundEntry // SoundEntry
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) {
_type = kSoundTypeNone; _type = kSoundTypeNone;
_currentDataPtr = 0;
_soundData = NULL;
_blockCount = 0; _blockCount = 0;
_time = 0; _time = 0;
@ -55,7 +55,7 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) {
_field_34 = 0; _field_34 = 0;
_field_38 = 0; _field_38 = 0;
_field_3C = 0; _field_3C = 0;
_field_40 = 0; _variant = 0;
_entity = kEntityPlayer; _entity = kEntityPlayer;
_field_48 = 0; _field_48 = 0;
_priority = 0; _priority = 0;
@ -63,13 +63,14 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) {
_subtitle = NULL; _subtitle = NULL;
_soundStream = NULL; _soundStream = NULL;
_queued = false;
} }
SoundEntry::~SoundEntry() { SoundEntry::~SoundEntry() {
// Entries that have been queued would have their streamed disposed automatically // Entries that have been queued will have their streamed disposed automatically
if (!_soundStream) if (!_soundStream)
SAFE_DELETE(_stream); SAFE_DELETE(_stream);
delete _soundStream; delete _soundStream;
// Zero passed pointers // Zero passed pointers
@ -79,18 +80,12 @@ SoundEntry::~SoundEntry() {
void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { void SoundEntry::open(Common::String name, SoundFlag flag, int priority) {
_priority = priority; _priority = priority;
setType(flag); setType(flag);
setStatus(flag); setupStatus(flag);
loadStream(name);
// Add entry to sound list
getSoundQueue()->addToQueue(this);
// Add entry to cache and load sound data
getSoundQueue()->setupCache(this);
loadSoundData(name);
} }
void SoundEntry::close() { void SoundEntry::close() {
_status.status |= kSoundStatusRemoved; _status.status |= kSoundStatusClosed;
// Loop until ready // Loop until ready
while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1))
@ -114,6 +109,43 @@ void SoundEntry::close() {
} }
} }
void SoundEntry::play() {
if (!_stream) {
warning("[SoundEntry::play] stream has been disposed");
return;
}
// Prepare sound stream
if (!_soundStream)
_soundStream = new StreamedSound();
// Compute current filter id
int32 filterId = _status.status & kSoundStatusFilter;
// TODO adjust status (based on stepIndex)
if (_queued) {
_soundStream->setFilterId(filterId);
} else {
_stream->seek(0);
// Load the stream and start playing
_soundStream->load(_stream, filterId);
_queued = true;
}
}
bool SoundEntry::isFinished() {
if (!_stream)
return true;
if (!_soundStream || !_queued)
return false;
// TODO check that all data has been queued
return _soundStream->isFinished();
}
void SoundEntry::setType(SoundFlag flag) { void SoundEntry::setType(SoundFlag flag) {
switch (flag & kFlagType9) { switch (flag & kFlagType9) {
default: default:
@ -186,10 +218,10 @@ void SoundEntry::setType(SoundFlag flag) {
} }
} }
void SoundEntry::setStatus(SoundFlag flag) { void SoundEntry::setupStatus(SoundFlag flag) {
SoundStatus statusFlag = (SoundStatus)flag; SoundStatus statusFlag = (SoundStatus)flag;
if (!((statusFlag & 0xFF) & kSoundStatusClear1)) if (!((statusFlag & 0xFF) & kSoundStatusFilter))
statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); statusFlag = (SoundStatus)(statusFlag | kSoundStatusCached);
if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0) if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0)
_status.status = (uint32)statusFlag; _status.status = (uint32)statusFlag;
@ -197,11 +229,7 @@ void SoundEntry::setStatus(SoundFlag flag) {
_status.status = (statusFlag | kSoundStatusClear4); _status.status = (statusFlag | kSoundStatusClear4);
} }
void SoundEntry::setInCache() { void SoundEntry::loadStream(Common::String name) {
_status.status |= kSoundStatusClear2;
}
void SoundEntry::loadSoundData(Common::String name) {
_name2 = name; _name2 = name;
// Load sound data // Load sound data
@ -210,11 +238,8 @@ void SoundEntry::loadSoundData(Common::String name) {
if (!_stream) if (!_stream)
_stream = getArchive("DEFAULT.SND"); _stream = getArchive("DEFAULT.SND");
if (_stream) { if (!_stream)
warning("[Sound::loadSoundData] Not implemented"); _status.status = kSoundStatusClosed;
} else {
_status.status = kSoundStatusRemoved;
}
} }
void SoundEntry::update(uint val) { void SoundEntry::update(uint val) {
@ -225,7 +250,7 @@ void SoundEntry::update(uint val) {
if (val) { if (val) {
if (getSoundQueue()->getFlag() & 32) { if (getSoundQueue()->getFlag() & 32) {
_field_40 = val; _variant = val;
value2 = val * 2 + 1; value2 = val * 2 + 1;
} }
@ -237,15 +262,65 @@ void SoundEntry::update(uint val) {
} }
} }
bool SoundEntry::updateSound() {
bool result;
char sub[16];
if (_status.status2 & 4) {
result = false;
} else {
if (_status.status2 & 0x80) {
if (_field_48 <= getSound()->getData2()) {
_status.status |= 0x20;
_status.status &= ~0x8000;
strcpy(sub, _name2.c_str());
int l = strlen(sub) + 1;
if (l - 1 > 4)
sub[l - 1 - 4] = 0;
showSubtitle(sub);
}
} else {
if (!(getSoundQueue()->getFlag() & 0x20)) {
if (!(_status.status3 & 8)) {
if (_entity) {
if (_entity < 0x80) {
updateEntryFlag(getSound()->getSoundFlag(_entity));
}
}
}
}
//if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer)
// Sound_FillSoundBuffer(v1);
}
result = true;
}
return result;
}
void SoundEntry::updateEntryFlag(SoundFlag flag) {
if (flag) {
if (getSoundQueue()->getFlag() & 0x20 && _type != kSoundType9 && _type != kSoundType7)
update(flag);
else
_status.status = flag + (_status.status & ~0x1F);
} else {
_variant = 0;
_status.status |= 0x80u;
_status.status &= ~0x10001F;
}
}
void SoundEntry::updateState() { void SoundEntry::updateState() {
if (getSoundQueue()->getFlag() & 32) { if (getSoundQueue()->getFlag() & 32) {
if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) {
uint32 newStatus = _status.status & kSoundStatusClear1; uint32 variant = _status.status & kSoundStatusFilter;
_status.status &= kSoundStatusClearAll; _status.status &= kSoundStatusClearAll;
_field_40 = newStatus; _variant = variant;
_status.status |= newStatus * 2 + 1; _status.status |= variant * 2 + 1;
} }
} }
@ -253,13 +328,14 @@ void SoundEntry::updateState() {
} }
void SoundEntry::reset() { void SoundEntry::reset() {
_status.status |= kSoundStatusRemoved; _status.status |= kSoundStatusClosed;
_entity = kEntityPlayer; _entity = kEntityPlayer;
if (_stream) { if (_stream) {
if (!_soundStream) { if (!_soundStream) {
SAFE_DELETE(_stream); SAFE_DELETE(_stream);
} else { } else {
// the original stream will be disposed
_soundStream->stop(); _soundStream->stop();
SAFE_DELETE(_soundStream); SAFE_DELETE(_soundStream);
} }
@ -307,13 +383,6 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) {
} }
} }
void SoundEntry::loadStream() {
if (!_soundStream)
_soundStream = new StreamedSound();
_soundStream->load(_stream);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// SubtitleEntry // SubtitleEntry
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -335,7 +404,7 @@ void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) {
_sound = soundEntry; _sound = soundEntry;
// Load subtitle data // Load subtitle data
if (_engine->getResourceManager()->hasFile(filename)) { if (_engine->getResourceManager()->hasFile(_filename)) {
if (getSoundQueue()->getSubtitleFlag() & 2) if (getSoundQueue()->getSubtitleFlag() & 2)
return; return;
@ -369,6 +438,8 @@ void SubtitleEntry::setupAndDraw() {
} }
getSoundQueue()->setCurrentSubtitle(this); getSoundQueue()->setCurrentSubtitle(this);
// TODO Missing code
} }
void SubtitleEntry::draw() { void SubtitleEntry::draw() {
@ -384,12 +455,10 @@ void SubtitleEntry::draw() {
} }
void SubtitleEntry::drawOnScreen() { void SubtitleEntry::drawOnScreen() {
getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() & -1);
if (_data == NULL) if (_data == NULL)
return; return;
if (getSoundQueue()->getSubtitleFlag() & 1) getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() & -2);
_engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay); _engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay);
} }

View file

@ -76,27 +76,6 @@ namespace LastExpress {
class LastExpressEngine; class LastExpressEngine;
class SubtitleEntry; class SubtitleEntry;
enum SoundStatus {
kSoundStatus_20 = 0x20,
kSoundStatus_40 = 0x40,
kSoundStatus_180 = 0x180,
kSoundStatusRemoved = 0x200,
kSoundStatus_400 = 0x400,
kSoundStatus_8000 = 0x8000,
kSoundStatus_20000 = 0x20000,
kSoundStatus_100000 = 0x100000,
kSoundStatus_20000000 = 0x20000000,
kSoundStatus_40000000 = 0x40000000,
kSoundStatusClear0 = 0x10,
kSoundStatusClear1 = 0x1F,
kSoundStatusClear2 = 0x80,
kSoundStatusClear3 = 0x200,
kSoundStatusClear4 = 0x800,
kSoundStatusClearAll = 0xFFFFFFE0
};
union SoundStatusUnion { union SoundStatusUnion {
uint32 status; uint32 status;
byte status1; byte status1;
@ -119,16 +98,13 @@ public:
void open(Common::String name, SoundFlag flag, int priority); void open(Common::String name, SoundFlag flag, int priority);
void close(); void close();
void play();
void setStatus(SoundFlag flag);
void setType(SoundFlag flag);
void setInCache();
void loadSoundData(Common::String name);
void update(uint val);
void updateState();
void reset(); void reset();
bool isFinished();
void loadStream(); void update(uint val);
bool updateSound();
void updateState();
void updateEntryFlag(SoundFlag flag);
// Subtitles // Subtitles
void showSubtitle(Common::String filename); void showSubtitle(Common::String filename);
@ -150,12 +126,7 @@ public:
Common::String getName2() { return _name2; } Common::String getName2() { return _name2; }
// Streams // Streams
Common::SeekableReadStream *getStream() { return _stream; } SimpleSound *getSoundStream() { return _soundStream; }
StreamedSound *getStreamedSound() { return _soundStream; }
public:
// TODO replace by on-the-fly allocated buffer
void *_soundData;
private: private:
LastExpressEngine *_engine; LastExpressEngine *_engine;
@ -164,18 +135,18 @@ private:
SoundType _type; // int SoundType _type; // int
//int _data; //int _data;
//int _endOffset; //int _endOffset;
int _currentDataPtr; byte * _currentDataPtr;
//int _currentBufferPtr; //int _currentBufferPtr;
int _blockCount; int _blockCount;
uint32 _time; uint32 _time;
//int _size; //int _size;
//int _field_28; //int _field_28;
Common::SeekableReadStream *_stream; // int Common::SeekableReadStream *_stream; // The file stream
//int _field_30; //int _archive;
int _field_34; int _field_34;
int _field_38; int _field_38;
int _field_3C; int _field_3C;
int _field_40; int _variant;
EntityIndex _entity; EntityIndex _entity;
int _field_48; int _field_48;
uint32 _priority; uint32 _priority;
@ -184,8 +155,13 @@ private:
// original has pointer to the next structure in the list (not used) // original has pointer to the next structure in the list (not used)
SubtitleEntry *_subtitle; SubtitleEntry *_subtitle;
// Sound stream // Sound buffer & stream
StreamedSound *_soundStream; bool _queued;
StreamedSound *_soundStream; // the filtered sound stream
void setType(SoundFlag flag);
void setupStatus(SoundFlag flag);
void loadStream(Common::String name);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View file

@ -32,18 +32,11 @@
namespace LastExpress { namespace LastExpress {
#define SOUNDCACHE_ENTRY_SIZE 92160
#define SOUNDCACHE_MAX_SIZE 6
SoundQueue::SoundQueue(LastExpressEngine *engine) : _engine(engine) { SoundQueue::SoundQueue(LastExpressEngine *engine) : _engine(engine) {
_state = 0; _state = 0;
_currentType = kSoundType16; _currentType = kSoundType16;
_flag = 0; _flag = 0;
// Cache and filter buffers
memset(&_buffer, 0, sizeof(_buffer));
_soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE);
_subtitlesFlag = 0; _subtitlesFlag = 0;
_currentSubtitle = NULL; _currentSubtitle = NULL;
} }
@ -53,17 +46,12 @@ SoundQueue::~SoundQueue() {
SAFE_DELETE(*i); SAFE_DELETE(*i);
_soundList.clear(); _soundList.clear();
// Entries in the cache are just pointers to sound list entries
_soundCache.clear();
for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i)
SAFE_DELETE(*i); SAFE_DELETE(*i);
_subtitles.clear(); _subtitles.clear();
_currentSubtitle = NULL; _currentSubtitle = NULL;
free(_soundCacheData);
// Zero passed pointers // Zero passed pointers
_engine = NULL; _engine = NULL;
} }
@ -76,14 +64,17 @@ void SoundQueue::handleTimer() {
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
SoundEntry *entry = (*i); SoundEntry *entry = (*i);
if (entry->getStream() == NULL) {
SAFE_DELETE(*i); // When the entry has stopped playing, we remove his buffer
if (entry->isFinished()) {
entry->close();
SAFE_DELETE(entry);
i = _soundList.reverse_erase(i); i = _soundList.reverse_erase(i);
continue; continue;
} else if (!entry->getStreamedSound()) {
// TODO: stream any sound in the queue after filtering
entry->loadStream();
} }
// Queue the entry data, applying filtering
entry->play();
} }
} }
@ -111,9 +102,80 @@ void SoundQueue::removeFromQueue(Common::String filename) {
} }
void SoundQueue::updateQueue() { void SoundQueue::updateQueue() {
Common::StackLock locker(_mutex); //Common::StackLock locker(_mutex);
warning("[Sound::updateQueue] Not implemented"); //warning("[Sound::updateQueue] Not implemented");
int maxPriority = 0;
Common::List<SoundEntry *>::iterator lsnd;
SoundEntry *msnd;
bool loopedPlaying;
loopedPlaying = 0;
//++g_sound_flag;
for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) {
if ((*lsnd)->getType() == kSoundType1)
break;
}
if (getSoundState() & 1) {
if (!(*lsnd) || getFlags()->flag_3 || (*lsnd && (*lsnd)->getTime() > getSound()->getLoopingSoundDuration())) {
getSound()->playLoopingSound(0x45);
} else {
if (getSound()->getData1() && getSound()->getData2() >= getSound()->getData1()) {
(*lsnd)->update(getSound()->getData0());
getSound()->setData1(0);
}
}
}
msnd = NULL;
for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) {
if ((*lsnd)->getStatus().status2 & 0x1) { // Sound is stopped
// original code
//if ((*lsnd)->soundBuffer)
// Sound_RemoveSoundDataFromCache(*lsnd);
//if ((*lsnd)->archive) {
// Archive_SetStatusNotLoaded((*lsnd)->archive);
// (*lsnd)->archive = 0;
// (*lsnd)->field_28 = 3;
//}
if (_soundList.size() < 6) {
if ((*lsnd)->getStatus().status1 & 0x1F) {
int pri = (*lsnd)->getPriority() + ((*lsnd)->getStatus().status1 & 0x1F);
if (pri > maxPriority) {
msnd = *lsnd;
maxPriority = pri;
}
}
}
}
if (!(*lsnd)->updateSound() && !((*lsnd)->getStatus().status3 & 0x8)) {
if (msnd == *lsnd) {
maxPriority = 0;
msnd = 0;
}
if (*lsnd) {
(*lsnd)->close();
SAFE_DELETE(*lsnd);
lsnd = _soundList.reverse_erase(lsnd);
}
}
}
// We don't need this
//if (msnd)
// msnd->updateEntryInternal();
getFlags()->flag_3 = 0;
//--g_sound_flag;
} }
void SoundQueue::resetQueue() { void SoundQueue::resetQueue() {
@ -301,11 +363,11 @@ void SoundQueue::updateSubtitles() {
if (!(status & kSoundStatus_40) if (!(status & kSoundStatus_40)
|| status & kSoundStatus_180 || status & kSoundStatus_180
|| soundEntry->getTime() == 0 || soundEntry->getTime() == 0
|| (status & kSoundStatusClear1) < 6 || (status & kSoundStatusFilter) < 6
|| ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) { || ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) {
current_index = 0; current_index = 0;
} else { } else {
current_index = soundEntry->getPriority() + (status & kSoundStatusClear1); current_index = soundEntry->getPriority() + (status & kSoundStatusFilter);
if (_currentSubtitle == (*i)) if (_currentSubtitle == (*i))
current_index += 4; current_index += 4;
@ -333,66 +395,6 @@ void SoundQueue::updateSubtitles() {
} }
} }
//////////////////////////////////////////////////////////////////////////
// Cache
//////////////////////////////////////////////////////////////////////////
bool SoundQueue::setupCache(SoundEntry *entry) {
if (entry->_soundData)
return true;
if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) {
SoundEntry *cacheEntry = NULL;
uint32 size = 1000;
for (Common::List<SoundEntry *>::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) {
if (!((*i)->getStatus().status & kSoundStatus_180)) {
uint32 newSize = (*i)->getPriority() + ((*i)->getStatus().status & kSoundStatusClear1);
if (newSize < size) {
cacheEntry = (*i);
size = newSize;
}
}
}
if (entry->getPriority() <= size)
return false;
if (!cacheEntry)
error("[SoundManager::setupCache] Cannot find a valid entry");
cacheEntry->setInCache();
// TODO: Wait until the cache entry is ready to be removed
while (!(cacheEntry->getStatus().status1 & 1))
;
if (cacheEntry->_soundData)
removeFromCache(cacheEntry);
_soundCache.push_back(entry);
entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1);
} else {
_soundCache.push_back(entry);
entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1);
}
return true;
}
void SoundQueue::removeFromCache(SoundEntry *entry) {
for (Common::List<SoundEntry *>::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) {
if ((*i) == entry) {
// Remove sound buffer
entry->_soundData = NULL;
// Remove entry from sound cache
i = _soundCache.reverse_erase(i);
}
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Savegame // Savegame
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -431,355 +433,6 @@ uint32 SoundQueue::count() {
return numEntries; return numEntries;
} }
//////////////////////////////////////////////////////////////////////////
// Sound filters
//////////////////////////////////////////////////////////////////////////
static const int filterData[1424] = {
0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256,
384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0,
192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640,
64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128,
320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576,
704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192,
192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448,
576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832,
320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320,
320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704,
832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448,
448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448,
640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960,
1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576,
576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576,
576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832,
960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088,
1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704,
704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768,
768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960,
1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280,
1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896,
896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896,
896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152,
1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408,
1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600,
1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088,
1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088,
1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152,
1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152,
1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408,
1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536,
1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728,
1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856,
1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344,
1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408,
1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408,
1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472,
1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664,
1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856,
1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984,
2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176,
1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664,
1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664,
1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728,
1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728,
1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984,
2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112,
2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304,
2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432,
1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920,
1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984,
1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984,
1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048,
2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240,
2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432,
2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560,
2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752,
2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240,
2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240,
2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304,
2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304,
2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560,
2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688,
2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880,
3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008,
2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496,
2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560,
2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560,
2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624,
2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816,
2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008,
3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136,
3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328,
2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816,
2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816,
2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880,
2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880,
3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136,
3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264,
3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456,
3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584,
3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072,
3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136,
3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136,
3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200,
3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392,
3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584,
3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712,
3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904,
3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392,
3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392,
3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456,
3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456,
3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712,
3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840,
3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032,
4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160,
3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648,
3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712,
3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712,
3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776,
3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968,
4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160,
4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288,
4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480,
3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968,
3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968,
3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032,
4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032,
4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288,
4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416,
4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608,
4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736,
4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224,
4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288,
4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288,
4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352,
4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544,
4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736,
4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864,
4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056,
4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544,
4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544,
4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608,
4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608,
4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864,
4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992,
5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184,
5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312,
4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800,
4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864,
4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864,
4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928,
5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120,
5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312,
5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440,
5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632,
5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120,
5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120,
5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184,
5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184,
5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440,
5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568,
5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632,
5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632,
5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376,
5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440,
5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440,
5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504,
5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632,
5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632,
5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632,
5632
};
static const int filterData2[1424] = {
0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11,
-13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9,
-11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5,
-7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18,
-1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12,
15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4,
7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19,
-22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14,
-17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5,
-8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26,
30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10,
14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27,
-31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16,
-21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2,
-7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25,
31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3,
9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34,
-40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17,
-24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50,
58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21,
29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55,
-63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32,
-41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5,
-15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50,
61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6,
18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56,
-68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20,
-34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82,
97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8,
24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74,
-90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9,
-27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70,
90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130,
-150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55,
-77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133,
157, 181, -12, -36, -60, -84, -109, -133, -157, -181,
13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93,
-120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191,
221, -14, -44, -73, -103, -132, -162, -191, -221, 16,
48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113,
-146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232,
268, -17, -53, -89, -125, -160, -196, -232, -268, 19,
58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137,
-176, -215, -255, -294, 21, 64, 108, 151, 194, 237,
281, 324, -21, -64, -108, -151, -194, -237, -281, -324,
23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118,
-166, -213, -261, -308, -356, 26, 78, 130, 182, 235,
287, 339, 391, -26, -78, -130, -182, -235, -287, -339,
-391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86,
-143, -201, -258, -316, -373, -431, 31, 94, 158, 221,
284, 347, 411, 474, -31, -94, -158, -221, -284, -347,
-411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34,
-104, -174, -244, -313, -383, -453, -523, 38, 115, 191,
268, 345, 422, 498, 575, -38, -115, -191, -268, -345,
-422, -498, -575, 42, 126, 210, 294, 379, 463, 547,
631, -42, -126, -210, -294, -379, -463, -547, -631,
46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231,
-324, -417, -510, -602, -695, 51, 153, 255, 357, 459,
561, 663, 765, -51, -153, -255, -357, -459, -561, -663,
-765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168,
-280, -392, -505, -617, -729, -841, 61, 185, 308, 432,
555, 679, 802, 926, -61, -185, -308, -432, -555, -679,
-802, -926, 68, 204, 340, 476, 612, 748, 884, 1020,
-68, -204, -340, -476, -612, -748, -884, -1020, 74,
224, 373, 523, 672, 822, 971, 1121, -74, -224, -373,
-523, -672, -822, -971, -1121, 82, 246, 411, 575, 740,
904, 1069, 1233, -82, -246, -411, -575, -740, -904,
-1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357,
-90, -271, -452, -633, -814, -995, -1176, -1357, 99,
298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497,
-696, -895, -1094, -1293, -1492, 109, 328, 547, 766,
985, 1204, 1423, 1642, -109, -328, -547, -766, -985,
-1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324,
1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564,
-1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132,
-397, -662, -927, -1192, -1457, -1722, -1987, 145, 437,
728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728,
-1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121,
1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442,
-1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940,
2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292,
-2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910,
-194, -582, -970, -1358, -1746, -2134, -2522, -2910,
213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213,
-640, -1066, -1493, -1920, -2347, -2773, -3200, 234,
704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704,
-1173, -1643, -2112, -2582, -3051, -3521, 258, 774,
1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291,
-1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988,
2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556,
-3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436,
4060, 4685, -312, -937, -1561, -2186, -2811, -3436,
-4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467,
5154, -343, -1030, -1718, -2405, -3092, -3779, -4467,
-5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670,
-378, -1134, -1890, -2646, -3402, -4158, -4914, -5670,
415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415,
-1247, -2079, -2911, -3742, -4574, -5406, -6238, 457,
1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372,
-2287, -3202, -4117, -5032, -5947, -6862, 503, 1509,
2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516,
-3522, -4529, -5535, -6542, -7548, 553, 1660, 2767,
3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874,
-4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479,
6697, 7915, 9133, -608, -1826, -3044, -4262, -5479,
-6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367,
8706, 10046, -669, -2009, -3348, -4688, -6027, -7367,
-8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577,
11051, -736, -2210, -3683, -5157, -6630, -8104, -9577,
-11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157,
-810, -2431, -4052, -5673, -7294, -8915, -10536, -12157,
891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891,
-2674, -4457, -6240, -8023, -9806, -11589, -13372, 980,
2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941,
-4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236,
5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236,
-5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559,
5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559,
-5933, -8306, -10679, -13052, -15426, -17799, 1305,
3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305,
-3915, -6526, -9136, -11747, -14357, -16968, -19578,
1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538,
-1435, -4307, -7179, -10051, -12922, -15794, -18666,
-21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531,
23690, -1579, -4738, -7896, -11055, -14214, -17373,
-20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111,
22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111,
-22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022,
24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022,
-24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124,
27329, 31533, -2102, -6306, -10511, -14715, -18920,
-23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812,
25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812,
-25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893,
27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893,
-27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183,
30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183,
-30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700,
32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700,
-32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471,
32767, 32767, 32767, -3385, -10157, -16928, -23700,
-30471, -32767, -32767, -32767, 3724, 11172, 18621,
26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621,
-26069, -32767, -32767, -32767, -32767, 4095, 12287,
20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287,
-20479, -28671, -32767, -32767, -32767, -32767
};
static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 };
static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 };
static void soundFilter(byte *data, int16 *buffer, int p1, int p2);
void SoundQueue::applyFilter(SoundEntry *entry, int16 *buffer) {
if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) {
entry->setStatus(entry->getStatus().status | kSoundStatus_20000000);
} else {
int variant = entry->getStatus().status & 0x1f;
soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]);
}
}
static void soundFilter(byte *data, int16 *buffer, int p1, int p2) {
int data1, data2, data1p, data2p;
byte idx;
data2 = data[0];
data1 = data[1] << 6;
data += 2;
for (int count = 0; count < 735; count++) {
idx = data[count] >> 4;
data1p = filterData[idx + data1];
data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767);
buffer[2 * count] = (p2 * data2p) >> p1;
idx = data[count] & 0xF;
data1 = filterData[idx + data1p];
data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767);
buffer[2 * count + 1] = (p2 * data2) >> p1;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Debug // Debug
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -787,7 +440,7 @@ void SoundQueue::stopAllSound() {
Common::StackLock locker(_mutex); Common::StackLock locker(_mutex);
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
(*i)->getStreamedSound()->stop(); (*i)->getSoundStream()->stop();
} }
} // End of namespace LastExpress } // End of namespace LastExpress

View file

@ -78,9 +78,6 @@ public:
void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; }
SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; }
// Cache
bool setupCache(SoundEntry *entry);
// Serializable // Serializable
void saveLoadWithSerializer(Common::Serializer &ser); void saveLoadWithSerializer(Common::Serializer &ser);
uint32 count(); uint32 count();
@ -109,7 +106,6 @@ private:
// Entries // Entries
Common::List<SoundEntry *> _soundList; ///< List of all sound entries Common::List<SoundEntry *> _soundList; ///< List of all sound entries
Common::List<SoundEntry *> _soundCache; ///< List of entries with a data buffer
void *_soundCacheData; void *_soundCacheData;
// Subtitles // Subtitles
@ -117,12 +113,6 @@ private:
Common::List<SubtitleEntry *> _subtitles; Common::List<SubtitleEntry *> _subtitles;
SubtitleEntry *_currentSubtitle; SubtitleEntry *_currentSubtitle;
// Filters
int32 _buffer[2940]; ///< Static sound buffer
void removeFromCache(SoundEntry *entry);
void applyFilter(SoundEntry *entry, int16 *buffer);
friend class Debugger; friend class Debugger;
}; };

View file

@ -162,13 +162,17 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla
entry->setStatus(entry->getStatus().status | kSoundStatus_8000); entry->setStatus(entry->getStatus().status | kSoundStatus_8000);
} else { } else {
// Get subtitles name // Get subtitles name
while (filename.size() > 4) uint32 size = filename.size();
while (filename.size() > size - 4)
filename.deleteLastChar(); filename.deleteLastChar();
entry->showSubtitle(filename); entry->showSubtitle(filename);
entry->updateState(); entry->updateState();
} }
// Add entry to sound list
_queue->addToQueue(entry);
return (entry->getType() != kSoundTypeNone); return (entry->getType() != kSoundTypeNone);
} }

View file

@ -64,7 +64,13 @@ public:
// Accessors // Accessors
SoundQueue *getQueue() { return _queue; } SoundQueue *getQueue() { return _queue; }
uint32 getData2() { return _data2; } uint32 getData0() { return _data0; }
int32 getData1() { return _data1; }
int32 getData2() { return _data2; }
uint32 getLoopingSoundDuration() { return _loopingSoundDuration; }
// Setters
void setData1(int32 data) { _data1 = data; }
private: private:
LastExpressEngine *_engine; LastExpressEngine *_engine;
@ -78,8 +84,8 @@ private:
// Unknown data // Unknown data
uint32 _data0; uint32 _data0;
uint32 _data1; int32 _data1;
uint32 _data2; int32 _data2;
}; };
} // End of namespace LastExpress } // End of namespace LastExpress

View file

@ -98,7 +98,6 @@ void Disk::openFile(uint8 fileNum) {
error("Could not open %s", sFilename); error("Could not open %s", sFilename);
char buffer[7]; char buffer[7];
uint32 bytesRead;
// If it's the support file, then move to the correct language area // If it's the support file, then move to the correct language area
@ -130,7 +129,7 @@ void Disk::openFile(uint8 fileNum) {
// Validate the header // Validate the header
bytesRead = _fileHandle->read(buffer, 6); _fileHandle->read(buffer, 6);
buffer[6] = '\0'; buffer[6] = '\0';
if (strcmp(buffer, HEADER_IDENT_STRING) != 0) if (strcmp(buffer, HEADER_IDENT_STRING) != 0)
error("The file %s was not a valid VGA file", sFilename); error("The file %s was not a valid VGA file", sFilename);

View file

@ -763,7 +763,7 @@ void Hotspot::showMessage(uint16 messageId, uint16 destCharacterId) {
MemoryBlock *data = res.messagesData(); MemoryBlock *data = res.messagesData();
Hotspot *hotspot; Hotspot *hotspot;
uint8 *msgData = (uint8 *) data->data(); uint8 *msgData = (uint8 *) data->data();
uint16 v2, idVal; uint16 idVal;
messageId &= 0x7fff; messageId &= 0x7fff;
// Skip through header to find table for given character // Skip through header to find table for given character
@ -781,7 +781,6 @@ void Hotspot::showMessage(uint16 messageId, uint16 destCharacterId) {
// Scan through secondary list // Scan through secondary list
uint16 *v = (uint16 *) (msgData + READ_LE_UINT16(msgData + idx + sizeof(uint16))); uint16 *v = (uint16 *) (msgData + READ_LE_UINT16(msgData + idx + sizeof(uint16)));
v2 = 0;
while ((idVal = READ_LE_UINT16(v)) != 0xffff) { while ((idVal = READ_LE_UINT16(v)) != 0xffff) {
++v; ++v;
if (READ_LE_UINT16(v) == messageId) break; if (READ_LE_UINT16(v) == messageId) break;

View file

@ -31,7 +31,9 @@
#include "common/endian.h" #include "common/endian.h"
#include "audio/midiparser.h" #include "audio/midiparser.h"
namespace Common {
DECLARE_SINGLETON(Lure::SoundManager); DECLARE_SINGLETON(Lure::SoundManager);
}
namespace Lure { namespace Lure {

View file

@ -542,7 +542,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const; virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
const ADGameDescription *fallbackDetect(const Common::FSList &fslist, const FileMap &allFiles) const; const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
}; };
@ -564,7 +564,7 @@ bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
return gd != 0; return gd != 0;
} }
const ADGameDescription *MadeMetaEngine::fallbackDetect(const Common::FSList &fslist, const FileMap &allFiles) const { const ADGameDescription *MadeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
// Set the default values for the fallback descriptor's ADGameDescription part. // Set the default values for the fallback descriptor's ADGameDescription part.
Made::g_fallbackDesc.desc.language = Common::UNK_LANG; Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
Made::g_fallbackDesc.desc.platform = Common::kPlatformPC; Made::g_fallbackDesc.desc.platform = Common::kPlatformPC;

View file

@ -700,14 +700,25 @@ bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) {
} }
bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) { bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) {
if (argc == 1) { if (argc < 2 || argc > 3) {
DebugPrintf("Usage: changePage <page> [<mode>]\n"); DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
return true; return true;
} }
if (_vm->tryLoadPageStart(argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]), atoi(argv[1]))) int page, subpage = 0;
if (sscanf(argv[1], "%d.%d", &page, &subpage) == 0) {
DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n");
return true;
}
LBMode mode = argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]);
if (subpage == 0) {
if (_vm->tryLoadPageStart(mode, page))
return false; return false;
DebugPrintf("no such page %d\n", atoi(argv[1])); } else {
if (_vm->loadPage(mode, page, subpage))
return false;
}
DebugPrintf("no such page %d.%d\n", page, subpage);
return true; return true;
} }

View file

@ -252,6 +252,17 @@ void LivingBooksCursorManager_v2::setCursor(uint16 id) {
} }
} }
void LivingBooksCursorManager_v2::setCursor(const Common::String &name) {
if (!_sysArchive)
return;
uint16 id = _sysArchive->findResourceID(ID_TCUR, name);
if (id == 0xffff)
error("Could not find cursor '%s'", name.c_str());
else
setCursor(id);
}
PECursorManager::PECursorManager(const Common::String &appName) { PECursorManager::PECursorManager(const Common::String &appName) {
_exe = new Common::PEResources(); _exe = new Common::PEResources();

View file

@ -56,6 +56,7 @@ public:
virtual void showCursor(); virtual void showCursor();
virtual void hideCursor(); virtual void hideCursor();
virtual void setCursor(uint16 id); virtual void setCursor(uint16 id);
virtual void setCursor(const Common::String &name) {}
virtual void setDefaultCursor(); virtual void setDefaultCursor();
virtual bool hasSource() const { return false; } virtual bool hasSource() const { return false; }
@ -157,6 +158,7 @@ public:
~LivingBooksCursorManager_v2(); ~LivingBooksCursorManager_v2();
void setCursor(uint16 id); void setCursor(uint16 id);
void setCursor(const Common::String &name);
bool hasSource() const { return _sysArchive != 0; } bool hasSource() const { return _sysArchive != 0; }
private: private:

View file

@ -1474,6 +1474,21 @@ static const MohawkGameDescription gameDescriptions[] = {
0 0
}, },
{
{
"arthurrace",
"",
AD_ENTRY1("BookOutline", "f0a9251824a648fce1b49cb7c1a0ba67"),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_UNSTABLE,
Common::GUIO_NONE
},
GType_LIVINGBOOKSV3,
0,
0
},
// From zerep in bug #3287894 // From zerep in bug #3287894
{ {
{ {

View file

@ -87,8 +87,14 @@ void LBPage::open(Archive *mhk, uint16 baseId) {
_baseId = baseId; _baseId = baseId;
_vm->addArchive(_mhk); _vm->addArchive(_mhk);
if (_vm->hasResource(ID_BCOD, baseId)) if (!_vm->hasResource(ID_BCOD, baseId)) {
// assume that BCOD is mandatory for v4/v5
if (_vm->getGameType() == GType_LIVINGBOOKSV4 || _vm->getGameType() == GType_LIVINGBOOKSV5)
error("missing BCOD resource (id %d)", baseId);
_code = new LBCode(_vm, 0);
} else {
_code = new LBCode(_vm, baseId); _code = new LBCode(_vm, baseId);
}
loadBITL(baseId); loadBITL(baseId);
for (uint i = 0; i < _items.size(); i++) for (uint i = 0; i < _items.size(); i++)
@ -2300,8 +2306,6 @@ void LBItem::readData(uint16 type, uint16 size, Common::MemoryReadStreamEndian *
{ {
assert(size == 4); assert(size == 4);
uint offset = stream->readUint32(); uint offset = stream->readUint32();
if (!_page->_code)
error("no BCOD?");
_page->_code->runCode(this, offset); _page->_code->runCode(this, offset);
} }
break; break;
@ -2823,8 +2827,6 @@ int LBItem::runScriptEntry(LBScriptEntry *entry) {
break; break;
case kLBOpSendExpression: case kLBOpSendExpression:
if (!_page->_code)
error("no BCOD?");
_page->_code->runCode(this, entry->offset); _page->_code->runCode(this, entry->offset);
break; break;
@ -2858,8 +2860,6 @@ int LBItem::runScriptEntry(LBScriptEntry *entry) {
case kLBOpJumpUnlessExpression: case kLBOpJumpUnlessExpression:
case kLBOpBreakExpression: case kLBOpBreakExpression:
case kLBOpJumpToExpression: case kLBOpJumpToExpression:
if (!_page->_code)
error("no BCOD?");
{ {
LBValue r = _page->_code->runCode(this, entry->offset); LBValue r = _page->_code->runCode(this, entry->offset);
// FIXME // FIXME
@ -2884,257 +2884,24 @@ void LBItem::setNextTime(uint16 min, uint16 max, uint32 start) {
debug(9, "nextTime is now %d frames away", _nextTime - (uint)(_vm->_system->getMillis() / 16)); debug(9, "nextTime is now %d frames away", _nextTime - (uint)(_vm->_system->getMillis() / 16));
} }
enum LBTokenType {
kLBNoToken,
kLBNameToken,
kLBStringToken,
kLBOperatorToken,
kLBIntegerToken,
kLBEndToken
};
static Common::String readToken(const Common::String &source, uint &pos, LBTokenType &type) {
Common::String token;
type = kLBNoToken;
bool done = false;
while (pos < source.size() && !done) {
if (type == kLBStringToken) {
if (source[pos] == '"') {
pos++;
return token;
}
token += source[pos];
pos++;
continue;
}
switch (source[pos]) {
case ' ':
pos++;
done = true;
break;
case ')':
if (type == kLBNoToken) {
type = kLBEndToken;
return Common::String();
}
done = true;
break;
case ';':
if (type == kLBNoToken) {
pos++;
type = kLBEndToken;
return Common::String();
}
done = true;
break;
case '@':
// FIXME
error("found @ in string '%s', not supported yet", source.c_str());
case '+':
case '-':
case '!':
case '=':
case '>':
case '<':
if (type == kLBNoToken)
type = kLBOperatorToken;
if (type == kLBOperatorToken)
token += source[pos];
else
done = true;
break;
case '"':
if (type == kLBNoToken)
type = kLBStringToken;
else
done = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (type == kLBNoToken)
type = kLBIntegerToken;
if (type == kLBNameToken || type == kLBIntegerToken)
token += source[pos];
else
done = true;
break;
default:
if (type == kLBNoToken)
type = kLBNameToken;
if (type == kLBNameToken)
token += source[pos];
else
done = true;
break;
}
if (!done)
pos++;
}
if (type == kLBStringToken)
error("readToken: ran out of input while parsing string from '%s'", source.c_str());
if (!token.size()) {
assert(type == kLBNoToken);
type = kLBEndToken;
}
return token;
}
LBValue LBItem::parseValue(const Common::String &source, uint &pos) {
LBTokenType type, postOpType;
Common::String preOp, postOp;
Common::String str = readToken(source, pos, type);
if (type == kLBOperatorToken) {
preOp = str;
str = readToken(source, pos, type);
}
LBValue value;
if (type == kLBStringToken) {
value.type = kLBValueString;
value.string = str;
} else if (type == kLBIntegerToken) {
value.type = kLBValueInteger;
value.integer = atoi(str.c_str());
} else if (type == kLBNameToken) {
value = _vm->_variables[str];
} else {
error("expected string/integer as value in '%s', got '%s'", source.c_str(), str.c_str());
}
uint readAheadPos = pos;
postOp = readToken(source, readAheadPos, postOpType);
if (postOpType != kLBEndToken) {
if (postOpType != kLBOperatorToken)
error("expected operator after '%s' in '%s', got '%s'", str.c_str(), source.c_str(), postOp.c_str());
// might be a comparison operator, caller will handle other cases if valid
if (postOp == "-" || postOp == "+") {
pos = readAheadPos;
LBValue nextValue = parseValue(source, pos);
if (value.type != kLBValueInteger || nextValue.type != kLBValueInteger)
error("expected integer for arthmetic operator in '%s'", source.c_str());
if (postOp == "+")
value.integer += nextValue.integer;
else if (postOp == "-")
value.integer -= nextValue.integer;
}
}
if (preOp.size()) {
if (preOp == "!") {
if (value.type == kLBValueInteger)
value.integer = !value.integer;
else
error("expected integer after ! operator in '%s'", source.c_str());
} else {
error("expected valid operator before '%s' in '%s', got '%s'", str.c_str(), source.c_str(), preOp.c_str());
}
}
return value;
}
void LBItem::runCommand(const Common::String &command) { void LBItem::runCommand(const Common::String &command) {
uint pos = 0; LBCode tempCode(_vm, 0);
LBTokenType type;
debug(2, "running command '%s'", command.c_str()); debug(2, "running command '%s'", command.c_str());
while (pos < command.size()) { uint offset = tempCode.parseCode(command);
Common::String varname = readToken(command, pos, type); tempCode.runCode(this, offset);
if (type != kLBNameToken)
error("expected name as lvalue of command '%s', got '%s'", command.c_str(), varname.c_str());
Common::String op = readToken(command, pos, type);
if (type != kLBOperatorToken || (op != "=" && op != "++" && op != "--"))
error("expected assignment/postincrement/postdecrement operator for command '%s', got '%s'", command.c_str(), op.c_str());
if (op == "=") {
LBValue value = parseValue(command, pos);
_vm->_variables[varname] = value;
} else {
if (_vm->_variables[varname].type != kLBValueInteger)
error("expected integer after postincrement/postdecrement operator in '%s'", command.c_str());
if (op == "++")
_vm->_variables[varname].integer++;
else if (op == "--")
_vm->_variables[varname].integer--;
}
if (pos < command.size() && command[pos] == ';')
pos++;
}
} }
bool LBItem::checkCondition(const Common::String &condition) { bool LBItem::checkCondition(const Common::String &condition) {
uint pos = 0; LBCode tempCode(_vm, 0);
LBTokenType type;
debug(3, "checking condition '%s'", condition.c_str()); debug(3, "checking condition '%s'", condition.c_str());
if (condition.size() <= pos || condition[pos] != '(') uint offset = tempCode.parseCode(condition);
error("bad condition '%s' (started wrong)", condition.c_str()); LBValue result = tempCode.runCode(this, offset);
pos++;
LBValue value1 = parseValue(condition, pos); return result.toInt();
Common::String op = readToken(condition, pos, type);
if (type == kLBEndToken) {
if (condition.size() != pos + 1 || condition[pos] != ')')
error("bad condition '%s' (ended wrong)", condition.c_str());
if (value1.type == kLBValueInteger)
return value1.integer;
else
error("expected comparison operator for condition '%s'", condition.c_str());
}
if (type != kLBOperatorToken || (op != "!=" && op != "==" && op != ">" && op != "<" && op != ">=" && op != "<="))
error("expected comparison operator for condition '%s', got '%s'", condition.c_str(), op.c_str());
LBValue value2 = parseValue(condition, pos);
if (condition.size() != pos + 1 || condition[pos] != ')')
error("bad condition '%s' (ended wrong)", condition.c_str());
if (op == "!=")
return (value1 != value2);
else if (op == "==")
return (value1 == value2);
if (value1.type != kLBValueInteger || value2.type != kLBValueInteger)
error("evaluation operator %s in condition '%s' expected two integer operands!", op.c_str(), condition.c_str());
if (op == ">")
return (value1.integer > value2.integer);
else if (op == ">=")
return (value1.integer >= value2.integer);
else if (op == "<")
return (value1.integer < value2.integer);
else if (op == "<=")
return (value1.integer <= value2.integer);
return false; // unreachable
} }
LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) {

View file

@ -434,7 +434,6 @@ protected:
void runScript(uint event, uint16 data = 0, uint16 from = 0); void runScript(uint event, uint16 data = 0, uint16 from = 0);
int runScriptEntry(LBScriptEntry *entry); int runScriptEntry(LBScriptEntry *entry);
LBValue parseValue(const Common::String &command, uint &pos);
void runCommand(const Common::String &command); void runCommand(const Common::String &command);
bool checkCondition(const Common::String &condition); bool checkCondition(const Common::String &condition);
@ -689,6 +688,7 @@ public:
LBMode getCurMode() { return _curMode; } LBMode getCurMode() { return _curMode; }
bool tryLoadPageStart(LBMode mode, uint page); bool tryLoadPageStart(LBMode mode, uint page);
bool loadPage(LBMode mode, uint page, uint subpage);
void prevPage(); void prevPage();
void nextPage(); void nextPage();
@ -717,7 +717,6 @@ private:
Common::Queue<DelayedEvent> _eventQueue; Common::Queue<DelayedEvent> _eventQueue;
LBItem *_focus; LBItem *_focus;
void destroyPage(); void destroyPage();
bool loadPage(LBMode mode, uint page, uint subpage);
void updatePage(); void updatePage();
uint16 _lastSoundOwner, _lastSoundId; uint16 _lastSoundOwner, _lastSoundId;

View file

@ -127,6 +127,12 @@ Common::Rect LBValue::toRect() const {
} }
LBCode::LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId) : _vm(vm) { LBCode::LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId) : _vm(vm) {
if (!baseId) {
_data = NULL;
_size = 0;
return;
}
Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, baseId); Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, baseId);
uint32 totalSize = bcodStream->readUint32(); uint32 totalSize = bcodStream->readUint32();
@ -172,12 +178,8 @@ LBValue LBCode::runCode(LBItem *src, uint32 offset) {
} }
void LBCode::nextToken() { void LBCode::nextToken() {
if (_currOffset + 1 >= _size) { if (_currOffset >= _size) {
// TODO error("went off the end of code");
warning("went off the end of code");
_currToken = kTokenEndOfFile;
_currValue = LBValue();
return;
} }
_currToken = _data[_currOffset++]; _currToken = _data[_currOffset++];
@ -186,6 +188,8 @@ void LBCode::nextToken() {
switch (_currToken) { switch (_currToken) {
case kTokenIdentifier: case kTokenIdentifier:
{ {
if (_currOffset + 2 > _size)
error("went off the end of code reading identifier");
uint16 offset = READ_BE_UINT16(_data + _currOffset); uint16 offset = READ_BE_UINT16(_data + _currOffset);
// TODO: check string exists // TODO: check string exists
_currValue = _strings[offset]; _currValue = _strings[offset];
@ -195,9 +199,13 @@ void LBCode::nextToken() {
case kTokenLiteral: case kTokenLiteral:
{ {
if (_currOffset + 1 > _size)
error("went off the end of code reading literal");
byte literalType = _data[_currOffset++]; byte literalType = _data[_currOffset++];
switch (literalType) { switch (literalType) {
case kLBCodeLiteralInteger: case kLBCodeLiteralInteger:
if (_currOffset + 2 > _size)
error("went off the end of code reading literal integer");
_currValue = READ_BE_UINT16(_data + _currOffset); _currValue = READ_BE_UINT16(_data + _currOffset);
_currOffset += 2; _currOffset += 2;
break; break;
@ -211,6 +219,8 @@ void LBCode::nextToken() {
case kTokenConstEventId: case kTokenConstEventId:
case 0x5e: // TODO: ?? case 0x5e: // TODO: ??
case kTokenKeycode: case kTokenKeycode:
if (_currOffset + 2 > _size)
error("went off the end of code reading immediate");
_currValue = READ_BE_UINT16(_data + _currOffset); _currValue = READ_BE_UINT16(_data + _currOffset);
_currOffset += 2; _currOffset += 2;
break; break;
@ -227,6 +237,8 @@ void LBCode::nextToken() {
case kTokenString: case kTokenString:
{ {
if (_currOffset + 2 > _size)
error("went off the end of code reading string");
uint16 offset = READ_BE_UINT16(_data + _currOffset); uint16 offset = READ_BE_UINT16(_data + _currOffset);
// TODO: check string exists // TODO: check string exists
_currValue = _strings[offset]; _currValue = _strings[offset];
@ -265,8 +277,7 @@ LBValue LBCode::runCode(byte terminator) {
void LBCode::parseStatement() { void LBCode::parseStatement() {
parseComparisons(); parseComparisons();
if (_currToken != kTokenAnd && _currToken != kTokenOr) while (_currToken == kTokenAnd || _currToken == kTokenOr) {
return;
byte op = _currToken; byte op = _currToken;
if (op == kTokenAnd) if (op == kTokenAnd)
debugN(" && "); debugN(" && ");
@ -287,6 +298,7 @@ void LBCode::parseStatement() {
debugN(" [--> %s]", result ? "true" : "false"); debugN(" [--> %s]", result ? "true" : "false");
_stack.push(result); _stack.push(result);
} }
}
void LBCode::parseComparisons() { void LBCode::parseComparisons() {
parseConcat(); parseConcat();
@ -353,9 +365,7 @@ void LBCode::parseComparisons() {
void LBCode::parseConcat() { void LBCode::parseConcat() {
parseArithmetic1(); parseArithmetic1();
if (_currToken != kTokenConcat) while (_currToken == kTokenConcat) {
return;
debugN(" & "); debugN(" & ");
nextToken(); nextToken();
parseArithmetic1(); parseArithmetic1();
@ -366,13 +376,12 @@ void LBCode::parseConcat() {
debugN(" [--> \"%s\"]", result.c_str()); debugN(" [--> \"%s\"]", result.c_str());
_stack.push(result); _stack.push(result);
} }
}
void LBCode::parseArithmetic1() { void LBCode::parseArithmetic1() {
parseArithmetic2(); parseArithmetic2();
if (_currToken != kTokenMinus && _currToken != kTokenPlus) while (_currToken == kTokenMinus || _currToken == kTokenPlus) {
return;
byte op = _currToken; byte op = _currToken;
if (op == kTokenMinus) if (op == kTokenMinus)
debugN(" - "); debugN(" - ");
@ -390,12 +399,61 @@ void LBCode::parseArithmetic1() {
result = val1.toInt() - val2.toInt(); result = val1.toInt() - val2.toInt();
else else
result = val1.toInt() + val2.toInt(); result = val1.toInt() + val2.toInt();
debugN(" [--> %d]", result.toInt());
_stack.push(result); _stack.push(result);
} }
}
void LBCode::parseArithmetic2() { void LBCode::parseArithmetic2() {
// FIXME: other math operators
parseMain(); parseMain();
while (true) {
byte op = _currToken;
switch (op) {
case kTokenMultiply:
debugN(" * ");
break;
case kTokenDivide:
debugN(" / ");
break;
case kTokenIntDivide:
debugN(" div ");
break;
case kTokenModulo:
debugN(" %% ");
break;
default:
return;
}
nextToken();
parseMain();
LBValue val2 = _stack.pop();
LBValue val1 = _stack.pop();
LBValue result;
// TODO: cope with non-integers
if (op == kTokenMultiply) {
result = val1.toInt() * val2.toInt();
} else if (val2.toInt() == 0) {
result = 1;
} else {
switch (op) {
case kTokenDivide:
// TODO: fp divide
result = val1.toInt() / val2.toInt();
break;
case kTokenIntDivide:
result = val1.toInt() / val2.toInt();
break;
case kTokenModulo:
result = val1.toInt() % val2.toInt();
break;
}
}
_stack.push(result);
}
} }
void LBCode::parseMain() { void LBCode::parseMain() {
@ -549,6 +607,16 @@ void LBCode::parseMain() {
} }
} }
LBItem *LBCode::resolveItem(const LBValue &value) {
if (value.type == kLBValueItemPtr)
return value.item;
if (value.type == kLBValueString)
return _vm->getItemByName(value.string);
if (value.type == kLBValueInteger)
return _vm->getItemById(value.integer);
return NULL;
}
Common::Array<LBValue> LBCode::readParams() { Common::Array<LBValue> LBCode::readParams() {
Common::Array<LBValue> params; Common::Array<LBValue> params;
@ -616,8 +684,8 @@ struct CodeCommandInfo {
#define NUM_GENERAL_COMMANDS 129 #define NUM_GENERAL_COMMANDS 129
CodeCommandInfo generalCommandInfo[NUM_GENERAL_COMMANDS] = { CodeCommandInfo generalCommandInfo[NUM_GENERAL_COMMANDS] = {
{ "eval", 0 }, { "eval", &LBCode::cmdEval },
{ "random", 0 }, { "random", &LBCode::cmdRandom },
{ "stringLen", 0 }, { "stringLen", 0 },
{ "substring", 0 }, { "substring", 0 },
{ "max", 0 }, { "max", 0 },
@ -773,6 +841,26 @@ void LBCode::cmdUnimplemented(const Common::Array<LBValue> &params) {
warning("unimplemented command called"); warning("unimplemented command called");
} }
void LBCode::cmdEval(const Common::Array<LBValue> &params) {
// FIXME: v4 eval is different?
if (params.size() != 1)
error("incorrect number of parameters (%d) to eval", params.size());
LBCode tempCode(_vm, 0);
uint offset = tempCode.parseCode(params[0].toString());
_stack.push(tempCode.runCode(_currSource, offset));
}
void LBCode::cmdRandom(const Common::Array<LBValue> &params) {
if (params.size() != 2)
error("incorrect number of parameters (%d) to random", params.size());
int min = params[0].toInt();
int max = params[1].toInt();
_stack.push(_vm->_rnd->getRandomNumberRng(min, max));
}
void LBCode::cmdGetRect(const Common::Array<LBValue> &params) { void LBCode::cmdGetRect(const Common::Array<LBValue> &params) {
if (params.size() < 2) { if (params.size() < 2) {
_stack.push(getRectFromParams(params)); _stack.push(getRectFromParams(params));
@ -915,7 +1003,7 @@ CodeCommandInfo itemCommandInfo[NUM_ITEM_COMMANDS] = {
{ "moveTo", &LBCode::itemMoveTo }, { "moveTo", &LBCode::itemMoveTo },
{ "mute", 0 }, { "mute", 0 },
{ "play", 0 }, { "play", 0 },
{ "seek", 0 }, { "seek", &LBCode::itemSeek },
{ "seekToFrame", 0 }, { "seekToFrame", 0 },
{ "setParent", &LBCode::itemSetParent }, { "setParent", &LBCode::itemSetParent },
{ "setZOrder", 0 }, { "setZOrder", 0 },
@ -951,6 +1039,17 @@ void LBCode::itemMoveTo(const Common::Array<LBValue> &params) {
warning("ignoring moveTo"); warning("ignoring moveTo");
} }
void LBCode::itemSeek(const Common::Array<LBValue> &params) {
if (params.size() != 2)
error("incorrect number of parameters (%d) to seek", params.size());
LBItem *item = resolveItem(params[0]);
if (!item)
error("attempted seek on invalid item (%s)", params[0].toString().c_str());
uint seekTo = params[1].toInt();
item->seek(seekTo);
}
void LBCode::itemSetParent(const Common::Array<LBValue> &params) { void LBCode::itemSetParent(const Common::Array<LBValue> &params) {
if (params.size() > 2) if (params.size() > 2)
error("incorrect number of parameters (%d) to setParent", params.size()); error("incorrect number of parameters (%d) to setParent", params.size());
@ -1035,4 +1134,278 @@ void LBCode::runNotifyCommand() {
} }
} }
/*
* Helper function for parseCode/parseCodeSymbol:
* Returns an unused string id.
*/
uint LBCode::nextFreeString() {
for (uint i = 0; i <= 0xffff; i++) {
if (!_strings.contains(i))
return i;
}
error("nextFreeString couldn't find a space");
}
/*
* Helper function for parseCode:
* Given a name, appends the appropriate data to the provided code array and
* returns true if it's a function, or false otherwise.
*/
bool LBCode::parseCodeSymbol(const Common::String &name, uint &pos, Common::Array<byte> &code) {
// first, check whether the name matches a known function
for (uint i = 0; i < 2; i++) {
byte cmdToken;
CodeCommandInfo *cmdInfo;
uint cmdCount;
switch (i) {
case 0:
cmdInfo = generalCommandInfo;
cmdToken = kTokenGeneralCommand;
cmdCount = NUM_GENERAL_COMMANDS;
break;
case 1:
cmdInfo = itemCommandInfo;
cmdToken = kTokenItemCommand;
cmdCount = NUM_ITEM_COMMANDS;
break;
}
for (uint n = 0; n < cmdCount; n++) {
const char *cmdName = cmdInfo[n].name;
if (!cmdName)
continue;
if (!name.equalsIgnoreCase(cmdName))
continue;
// found a matching function
code.push_back(cmdToken);
code.push_back(n + 1);
return true;
}
}
// not a function, so must be an identifier
code.push_back(kTokenIdentifier);
uint stringId = nextFreeString();
_strings[stringId] = name;
char tmp[2];
WRITE_BE_UINT16(tmp, (int16)stringId);
code.push_back(tmp[0]);
code.push_back(tmp[1]);
return false;
}
/*
* Parse a string for later execution, and return the offset where it was
* stored.
*/
uint LBCode::parseCode(const Common::String &source) {
struct LBCodeOperator {
byte token;
byte op;
byte lookahead1;
byte lookahead1Op;
byte lookahead2;
byte lookahead2Op;
};
#define NUM_LB_OPERATORS 11
static const LBCodeOperator operators[NUM_LB_OPERATORS] = {
{ '+', kTokenPlus, '+', kTokenPlusPlus, '=', kTokenPlusEquals },
{ '-', kTokenMinus, '-', kTokenMinusMinus, '=', kTokenMinusEquals },
{ '/', kTokenDivide, '=', kTokenDivideEquals, 0, 0 },
{ '*', kTokenMultiply, '=', kTokenMultiplyEquals, 0, 0 },
{ '=', kTokenAssign, '=', kTokenEquals, 0, 0 },
{ '>', kTokenGreaterThan, '=', kTokenGreaterThanEq, 0, 0 },
{ '<', kTokenLessThan, '=', kTokenLessThanEq, 0, 0 },
{ '!', kTokenNot, '=', kTokenNotEq, 0, 0 },
{ '&', kTokenConcat, '&', kTokenAnd, '=', kTokenAndEquals },
{ '|', 0, '|', kTokenOr, 0, 0 },
{ ';', kTokenEndOfStatement, 0, 0, 0, 0 }
};
uint pos = 0;
Common::Array<byte> code;
Common::Array<uint> counterPositions;
bool wasFunction = false;
while (pos < source.size()) {
byte token = source[pos];
byte lookahead = 0;
if (pos + 1 < source.size())
lookahead = source[pos + 1];
pos++;
if (token != ' ' && token != '(' && wasFunction)
error("while parsing script '%s', encountered incomplete function call", source.c_str());
// First, we check for simple operators.
for (uint i = 0; i < NUM_LB_OPERATORS; i++) {
if (token != operators[i].token)
continue;
if (lookahead) {
if (lookahead == operators[i].lookahead1) {
code.push_back(operators[i].lookahead1Op);
token = 0;
} else if (lookahead == operators[i].lookahead2) {
code.push_back(operators[i].lookahead2Op);
token = 0;
}
if (!token) {
pos++;
break;
}
}
if (operators[i].op) {
code.push_back(operators[i].op);
token = 0;
}
break;
}
if (!token)
continue;
// Then, we check for more complex tokens.
switch (token) {
// whitespace
case ' ':
// ignore
break;
// literal string
case '"':
case '\'':
{
Common::String tempString;
while (pos < source.size()) {
if (source[pos] == token)
break;
tempString += source[pos++];
}
if (pos++ == source.size())
error("while parsing script '%s', string had no end", source.c_str());
code.push_back(kTokenString);
uint stringId = nextFreeString();
_strings[stringId] = tempString;
char tmp[2];
WRITE_BE_UINT16(tmp, (int16)stringId);
code.push_back(tmp[0]);
code.push_back(tmp[1]);
}
break;
// open bracket
case '(':
if (wasFunction) {
// function call parameters
wasFunction = false;
// we will need to back-patch the parameter count,
// if parameters are encountered
counterPositions.push_back(code.size());
code.push_back(1);
// if the next token is a ) then there are no
// parameters, otherwise start with 1 and increment
// if/when we encounter commas
for (uint i = pos; i < source.size(); i++) {
if (source[i] == ' ')
continue;
if (source[i] != ')')
break;
code[code.size() - 1] = 0;
break;
}
} else {
// brackets around expression
counterPositions.push_back(0);
}
code.push_back(kTokenOpenBracket);
break;
// close bracket
case ')':
if (counterPositions.empty())
error("while parsing script '%s', encountered unmatched )", source.c_str());
counterPositions.pop_back();
code.push_back(kTokenCloseBracket);
break;
// comma (seperating function params)
case ',':
{
if (counterPositions.empty())
error("while parsing script '%s', encountered unexpected ,", source.c_str());
code.push_back(kTokenComma);
uint counterPos = counterPositions.back();
if (!counterPos)
error("while parsing script '%s', encountered , outside parameter list", source.c_str());
code[counterPos]++;
}
break;
// old-style explicit function call
case '@':
{
Common::String tempString;
while (pos < source.size()) {
if (!isalpha(source[pos]) && !isdigit(source[pos]))
break;
tempString += source[pos++];
}
wasFunction = parseCodeSymbol(tempString, pos, code);
if (!wasFunction)
error("while parsing script '%s', encountered explicit function call to unknown function '%s'",
source.c_str(), tempString.c_str());
}
break;
default:
if (isdigit(token)) {
const char *in = source.c_str() + pos - 1;
// FIXME: handle floats?
char *endptr;
long int intValue = strtol(in, &endptr, 0);
assert(endptr > in);
pos += (endptr - in) - 1;
// FIXME: handle storing longs if needed
code.push_back(kTokenLiteral);
code.push_back(kLBCodeLiteralInteger);
char tmp[2];
WRITE_BE_UINT16(tmp, (int16)intValue);
code.push_back(tmp[0]);
code.push_back(tmp[1]);
} else if (isalpha(token)) {
Common::String tempString;
tempString += token;
while (pos < source.size()) {
if (!isalpha(source[pos]) && !isdigit(source[pos]))
break;
tempString += source[pos++];
}
wasFunction = parseCodeSymbol(tempString, pos, code);
} else {
error("while parsing script '%s', couldn't parse '%c'", source.c_str(), token);
}
}
}
if (wasFunction)
error("while parsing script '%s', encountered incomplete function call", source.c_str());
if (counterPositions.size())
error("while parsing script '%s', unmatched (", source.c_str());
code.push_back(kTokenEndOfFile);
uint codeOffset = _size;
byte *newData = new byte[_size + code.size()];
memcpy(newData, _data, _size);
memcpy(newData, &code[0], code.size());
delete[] _data;
_data = newData;
_size += code.size();
return codeOffset;
}
} // End of namespace Mohawk } // End of namespace Mohawk

View file

@ -181,6 +181,7 @@ public:
~LBCode(); ~LBCode();
LBValue runCode(LBItem *src, uint32 offset); LBValue runCode(LBItem *src, uint32 offset);
uint parseCode(const Common::String &source);
protected: protected:
MohawkEngine_LivingBooks *_vm; MohawkEngine_LivingBooks *_vm;
@ -206,6 +207,7 @@ protected:
void parseArithmetic2(); void parseArithmetic2();
void parseMain(); void parseMain();
LBItem *resolveItem(const LBValue &value);
Common::Array<LBValue> readParams(); Common::Array<LBValue> readParams();
Common::Rect getRectFromParams(const Common::Array<LBValue> &params); Common::Rect getRectFromParams(const Common::Array<LBValue> &params);
@ -213,8 +215,13 @@ protected:
void runItemCommand(); void runItemCommand();
void runNotifyCommand(); void runNotifyCommand();
uint nextFreeString();
bool parseCodeSymbol(const Common::String &name, uint &pos, Common::Array<byte> &code);
public: public:
void cmdUnimplemented(const Common::Array<LBValue> &params); void cmdUnimplemented(const Common::Array<LBValue> &params);
void cmdEval(const Common::Array<LBValue> &params);
void cmdRandom(const Common::Array<LBValue> &params);
void cmdGetRect(const Common::Array<LBValue> &params); void cmdGetRect(const Common::Array<LBValue> &params);
void cmdTopLeft(const Common::Array<LBValue> &params); void cmdTopLeft(const Common::Array<LBValue> &params);
void cmdBottomRight(const Common::Array<LBValue> &params); void cmdBottomRight(const Common::Array<LBValue> &params);
@ -228,9 +235,10 @@ public:
void cmdSetHitTest(const Common::Array<LBValue> &params); void cmdSetHitTest(const Common::Array<LBValue> &params);
void cmdKey(const Common::Array<LBValue> &params); void cmdKey(const Common::Array<LBValue> &params);
void itemSetParent(const Common::Array<LBValue> &params);
void itemMoveTo(const Common::Array<LBValue> &params);
void itemIsPlaying(const Common::Array<LBValue> &params); void itemIsPlaying(const Common::Array<LBValue> &params);
void itemMoveTo(const Common::Array<LBValue> &params);
void itemSeek(const Common::Array<LBValue> &params);
void itemSetParent(const Common::Array<LBValue> &params);
}; };
} // End of namespace Mohawk } // End of namespace Mohawk

View file

@ -560,6 +560,7 @@ void MystScriptParser::o_playSoundBlocking(uint16 op, uint16 var, uint16 argc, u
debugC(kDebugScript, "Opcode %d: playSoundBlocking", op); debugC(kDebugScript, "Opcode %d: playSoundBlocking", op);
debugC(kDebugScript, "\tsoundId: %d", soundId); debugC(kDebugScript, "\tsoundId: %d", soundId);
_vm->_sound->stopSound();
_vm->_sound->playSoundBlocking(soundId); _vm->_sound->playSoundBlocking(soundId);
} }

View file

@ -102,6 +102,7 @@ void Mechanical::setupOpcodes() {
void Mechanical::disablePersistentScripts() { void Mechanical::disablePersistentScripts() {
_fortressSimulationRunning = false; _fortressSimulationRunning = false;
_elevatorRotationLeverMoving = false;
_elevatorGoingMiddle = false; _elevatorGoingMiddle = false;
_birdSinging = false; _birdSinging = false;
_fortressRotationRunning = false; _fortressRotationRunning = false;
@ -126,10 +127,10 @@ void Mechanical::runPersistentScripts() {
uint16 Mechanical::getVar(uint16 var) { uint16 Mechanical::getVar(uint16 var) {
switch(var) { switch(var) {
case 0: // Sirrus's Secret Panel State case 0: // Achenar's Secret Panel State
return _state.sirrusPanelState;
case 1: // Achenar's Secret Panel State
return _state.achenarPanelState; return _state.achenarPanelState;
case 1: // Sirrus's Secret Panel State
return _state.sirrusPanelState;
case 2: // Achenar's Secret Room Crate Lid Open and Blue Page Present case 2: // Achenar's Secret Room Crate Lid Open and Blue Page Present
if (_state.achenarCrateOpened) { if (_state.achenarCrateOpened) {
if (_globals.bluePagesInBook & 4 || _globals.heldPage == 3) if (_globals.bluePagesInBook & 4 || _globals.heldPage == 3)
@ -195,16 +196,21 @@ uint16 Mechanical::getVar(uint16 var) {
void Mechanical::toggleVar(uint16 var) { void Mechanical::toggleVar(uint16 var) {
switch(var) { switch(var) {
case 0: // Sirrus's Secret Panel State case 0: // Achenar's Secret Panel State
_state.sirrusPanelState ^= 1;
case 1: // Achenar's Secret Panel State
_state.achenarPanelState ^= 1; _state.achenarPanelState ^= 1;
break;
case 1: // Sirrus's Secret Panel State
_state.sirrusPanelState ^= 1;
break;
case 3: // Achenar's Secret Room Crate State case 3: // Achenar's Secret Room Crate State
_state.achenarCrateOpened ^= 1; _state.achenarCrateOpened ^= 1;
break;
case 4: // Myst Book Room Staircase State case 4: // Myst Book Room Staircase State
_mystStaircaseState ^= 1; _mystStaircaseState ^= 1;
break;
case 10: // Fortress Staircase State case 10: // Fortress Staircase State
_state.staircaseState ^= 1; _state.staircaseState ^= 1;
break;
case 16: // Code Lock Shape #1 - Left case 16: // Code Lock Shape #1 - Left
case 17: // Code Lock Shape #2 case 17: // Code Lock Shape #2
case 18: // Code Lock Shape #3 case 18: // Code Lock Shape #3
@ -242,6 +248,7 @@ bool Mechanical::setVarValue(uint16 var, uint16 value) {
switch (var) { switch (var) {
case 13: case 13:
_elevatorPosition = value; _elevatorPosition = value;
break;
case 14: // Elevator going down when at top case 14: // Elevator going down when at top
_elevatorGoingDown = value; _elevatorGoingDown = value;
break; break;
@ -724,6 +731,7 @@ void Mechanical::birdSing_run() {
uint32 time = _vm->_system->getMillis(); uint32 time = _vm->_system->getMillis();
if (_birdSingEndTime < time) { if (_birdSingEndTime < time) {
_bird->pauseMovie(true); _bird->pauseMovie(true);
_vm->_sound->stopSound();
_birdSinging = false; _birdSinging = false;
} }
} }

View file

@ -294,7 +294,7 @@ bool MohawkArchive::openStream(Common::SeekableReadStream *stream) {
// We need to do this because of the way Mohawk is set up (this is much more "proper" // We need to do this because of the way Mohawk is set up (this is much more "proper"
// than passing _stream at the right offset). We may want to do that in the future, though. // than passing _stream at the right offset). We may want to do that in the future, though.
if (tag == ID_TMOV) { if (tag == ID_TMOV) {
if (index == fileTable.size() - 1) if (index == fileTable.size())
res.size = stream->size() - fileTable[index - 1].offset; res.size = stream->size() - fileTable[index - 1].offset;
else else
res.size = fileTable[index].offset - fileTable[index - 1].offset; res.size = fileTable[index].offset - fileTable[index - 1].offset;
@ -304,7 +304,6 @@ bool MohawkArchive::openStream(Common::SeekableReadStream *stream) {
debug(4, "Entry[%02x]: ID = %04x (%d) Index = %04x", j, id, id, index); debug(4, "Entry[%02x]: ID = %04x (%d) Index = %04x", j, id, id, index);
} }
// Return to next TypeTable entry // Return to next TypeTable entry
stream->seek(absOffset + (i + 1) * 8 + 4); stream->seek(absOffset + (i + 1) * 8 + 4);

View file

@ -141,6 +141,19 @@ Audio::SoundHandle *Sound::replaceSoundMyst(uint16 id, byte volume, bool loop) {
&& name.equals(_vm->getResourceName(ID_MSND, convertMystID(_handles[i].id)))) && name.equals(_vm->getResourceName(ID_MSND, convertMystID(_handles[i].id))))
return &_handles[i].handle; return &_handles[i].handle;
// The original engine also forces looping for those sounds
switch (id) {
case 2205:
case 2207:
case 5378:
case 7220:
case 9119: // Elevator engine sound in mechanical age is looping.
case 9120:
case 9327:
loop = true;
break;
}
stopSound(); stopSound();
return playSound(id, volume, loop); return playSound(id, volume, loop);
} }

View file

@ -28,6 +28,7 @@
#include "common/hashmap.h" #include "common/hashmap.h"
#include "common/hash-str.h" #include "common/hash-str.h"
#include "common/stream.h" #include "common/stream.h"
#include "common/array.h"
#include "graphics/surface.h" #include "graphics/surface.h"

View file

@ -24,6 +24,17 @@
#include "graphics/surface.h" #include "graphics/surface.h"
#include "common/textconsole.h" #include "common/textconsole.h"
SaveStateDescriptor::SaveStateDescriptor()
// FIXME: default to 0 (first slot) or to -1 (invalid slot) ?
: _slot(-1), _description(), _isDeletable(true), _isWriteProtected(false),
_saveDate(), _saveTime(), _playTime(), _thumbnail() {
}
SaveStateDescriptor::SaveStateDescriptor(int s, const Common::String &d)
: _slot(s), _description(d), _isDeletable(true), _isWriteProtected(false),
_saveDate(), _saveTime(), _playTime(), _thumbnail() {
}
void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) { void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
if (_thumbnail.get() == t) if (_thumbnail.get() == t)
return; return;
@ -31,42 +42,16 @@ void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
_thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter()); _thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter());
} }
bool SaveStateDescriptor::getBool(const Common::String &key) const {
if (contains(key)) {
const Common::String value = getVal(key);
bool valueAsBool;
if (Common::parseBool(value, valueAsBool))
return valueAsBool;
error("SaveStateDescriptor: %s '%s' has unknown value '%s' for boolean '%s'",
save_slot().c_str(), description().c_str(), value.c_str(), key.c_str());
}
return false;
}
void SaveStateDescriptor::setDeletableFlag(bool state) {
setVal("is_deletable", state ? "true" : "false");
}
void SaveStateDescriptor::setWriteProtectedFlag(bool state) {
setVal("is_write_protected", state ? "true" : "false");
}
void SaveStateDescriptor::setSaveDate(int year, int month, int day) { void SaveStateDescriptor::setSaveDate(int year, int month, int day) {
Common::String buffer; _saveDate = Common::String::format("%.2d.%.2d.%.4d", day, month, year);
buffer = Common::String::format("%.2d.%.2d.%.4d", day, month, year);
setVal("save_date", buffer);
} }
void SaveStateDescriptor::setSaveTime(int hour, int min) { void SaveStateDescriptor::setSaveTime(int hour, int min) {
Common::String buffer; _saveTime = Common::String::format("%.2d:%.2d", hour, min);
buffer = Common::String::format("%.2d:%.2d", hour, min);
setVal("save_time", buffer);
} }
void SaveStateDescriptor::setPlayTime(int hours, int minutes) { void SaveStateDescriptor::setPlayTime(int hours, int minutes) {
Common::String buffer; _playTime = Common::String::format("%.2d:%.2d", hours, minutes);
buffer = Common::String::format("%.2d:%.2d", hours, minutes);
setVal("play_time", buffer);
} }
void SaveStateDescriptor::setPlayTime(uint32 msecs) { void SaveStateDescriptor::setPlayTime(uint32 msecs) {

View file

@ -24,7 +24,7 @@
#define ENGINES_SAVESTATE_H #define ENGINES_SAVESTATE_H
#include "common/array.h" #include "common/array.h"
#include "common/hash-str.h" #include "common/str.h"
#include "common/ptr.h" #include "common/ptr.h"
@ -33,65 +33,60 @@ struct Surface;
} }
/** /**
* A hashmap describing details about a given save state. * Object describing a save state.
* TODO *
* Guaranteed to contain save_slot and description values. * This at least includes the save slot number and a human readable
* Additional ideas: Playtime, creation date, thumbnail, ... * description of the save state.
*
* Further possibilites are a thumbnail, play time, creation date,
* creation time, delete protected, write protection.
*/ */
class SaveStateDescriptor : public Common::StringMap { class SaveStateDescriptor {
protected:
Common::SharedPtr<Graphics::Surface> _thumbnail; // can be 0
public: public:
SaveStateDescriptor() : _thumbnail() { SaveStateDescriptor();
setVal("save_slot", "-1"); // FIXME: default to 0 (first slot) or to -1 (invalid slot) ? SaveStateDescriptor(int s, const Common::String &d);
setVal("description", "");
}
SaveStateDescriptor(int s, const Common::String &d) : _thumbnail() { /**
setVal("save_slot", Common::String::format("%d", s)); * @param slot The saveslot id, as it would be passed to the "-x" command line switch.
setVal("description", d); */
} void setSaveSlot(int slot) { _slot = slot; }
SaveStateDescriptor(const Common::String &s, const Common::String &d) : _thumbnail() { /**
setVal("save_slot", s); * @return The saveslot id, as it would be passed to the "-x" command line switch.
setVal("description", d); */
} int getSaveSlot() const { return _slot; }
/** The saveslot id, as it would be passed to the "-x" command line switch. */ /**
Common::String &save_slot() { return getVal("save_slot"); } * @param desc A human readable description of the save state.
*/
void setDescription(const Common::String &desc) { _description = desc; }
/** The saveslot id, as it would be passed to the "-x" command line switch (read-only variant). */ /**
const Common::String &save_slot() const { return getVal("save_slot"); } * @return A human readable description of the save state.
*/
/** A human readable description of the save state. */ const Common::String &getDescription() const { return _description; }
Common::String &description() { return getVal("description"); }
/** A human readable description of the save state (read-only variant). */
const Common::String &description() const { return getVal("description"); }
/** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */ /** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */
/** /**
* Returns the value of a given key as boolean. * Defines whether the save state is allowed to be deleted.
* It accepts 'true', 'yes' and '1' for true and
* 'false', 'no' and '0' for false.
* (FIXME:) On unknown value it errors out ScummVM.
* On unknown key it returns false as default.
*/ */
bool getBool(const Common::String &key) const; void setDeletableFlag(bool state) { _isDeletable = state; }
/** /**
* Sets the 'is_deletable' key, which indicates if the * Queries whether the save state is allowed to be deleted.
* given savestate is safe for deletion.
*/ */
void setDeletableFlag(bool state); bool getDeletableFlag() const { return _isDeletable; }
/** /**
* Sets the 'is_write_protected' key, which indicates if the * Defines whether the save state is write protected.
* given savestate can be overwritten or not
*/ */
void setWriteProtectedFlag(bool state); void setWriteProtectedFlag(bool state) { _isWriteProtected = state; }
/**
* Queries whether the save state is write protected.
*/
bool getWriteProtectedFlag() const { return _isWriteProtected; }
/** /**
* Return a thumbnail graphics surface representing the savestate visually. * Return a thumbnail graphics surface representing the savestate visually.
@ -109,24 +104,100 @@ public:
void setThumbnail(Graphics::Surface *t); void setThumbnail(Graphics::Surface *t);
/** /**
* Sets the 'save_date' key properly, based on the given values. * Sets the date the save state was created.
*
* @param year Year of creation.
* @param month Month of creation.
* @param day Day of creation.
*/ */
void setSaveDate(int year, int month, int day); void setSaveDate(int year, int month, int day);
/** /**
* Sets the 'save_time' key properly, based on the given values. * Queries a human readable description of the date the save state was created.
*
* This will return an empty string in case the value is not set.
*/
const Common::String &getSaveDate() const { return _saveDate; }
/**
* Sets the time the save state was created.
*
* @param hour Hour of creation.
* @param min Minute of creation.
*/ */
void setSaveTime(int hour, int min); void setSaveTime(int hour, int min);
/** /**
* Sets the 'play_time' key properly, based on the given values. * Queries a human readable description of the time the save state was created.
*
* This will return an empty string in case the value is not set.
*/
const Common::String &getSaveTime() const { return _saveTime; }
/**
* Sets the time the game was played before the save state was created.
*
* @param hours How many hours the user played the game so far.
* @param min How many minutes the user played the game so far.
*/ */
void setPlayTime(int hours, int minutes); void setPlayTime(int hours, int minutes);
/** /**
* Sets the 'play_time' key properly, based on the given value. * Sets the time the game was played before the save state was created.
*
* @param msecs How many milliseconds the user played the game so far.
*/ */
void setPlayTime(uint32 msecs); void setPlayTime(uint32 msecs);
/**
* Queries a human readable description of the time the game was played
* before the save state was created.
*
* This will return an empty string in case the value is not set.
*/
const Common::String &getPlayTime() const { return _playTime; }
private:
/**
* The saveslot id, as it would be passed to the "-x" command line switch.
*/
int _slot;
/**
* A human readable description of the save state.
*/
Common::String _description;
/**
* Whether the save state can be deleted.
*/
bool _isDeletable;
/**
* Whether the save state is write protected.
*/
bool _isWriteProtected;
/**
* Human readable description of the date the save state was created.
*/
Common::String _saveDate;
/**
* Human readable description of the time the save state was created.
*/
Common::String _saveTime;
/**
* Human readable description of the time the game was played till the
* save state was created.
*/
Common::String _playTime;
/**
* The thumbnail of the save state.
*/
Common::SharedPtr<Graphics::Surface> _thumbnail;
}; };
/** List of savestates. */ /** List of savestates. */

View file

@ -730,6 +730,10 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) {
case 8: { // Dup case 8: { // Dup
const char *rawString = 0; const char *rawString = 0;
uint32 size = 0; uint32 size = 0;
reg_t stringHandle;
// We allocate the new string first because if the StringTable needs to
// grow, our rawString pointer will be invalidated
SciString *dupString = s->_segMan->allocateString(&stringHandle);
if (argv[1].segment == s->_segMan->getStringSegmentId()) { if (argv[1].segment == s->_segMan->getStringSegmentId()) {
SciString *string = s->_segMan->lookupString(argv[1]); SciString *string = s->_segMan->lookupString(argv[1]);
@ -741,8 +745,6 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) {
size = string.size() + 1; size = string.size() + 1;
} }
reg_t stringHandle;
SciString *dupString = s->_segMan->allocateString(&stringHandle);
dupString->setSize(size); dupString->setSize(size);
for (uint32 i = 0; i < size; i++) for (uint32 i = 0; i < size; i++)

View file

@ -338,7 +338,7 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte
void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) { void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) {
byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2; byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2;
// we don't use outline, so color 0 is actually not used // we don't use outline, so color 0 is actually not used
commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0); commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0, -1, -1);
} }
byte GfxScreen::getVisual(int x, int y) { byte GfxScreen::getVisual(int x, int y) {

View file

@ -779,7 +779,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->format.bytesPerPixel); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->format.bytesPerPixel);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
else if (_vm->_cjkFont) else if (_vm->_cjkFont)
_vm->_cjkFont->drawChar(vs, chr, _left, drawTop, _color, _shadowColor); _vm->_cjkFont->drawChar(*vs, chr, _left, drawTop, _color, _shadowColor);
#endif #endif
} else { } else {
dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier); dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);

View file

@ -39,7 +39,6 @@ public:
virtual void send(MidiChannel *mc) = 0; virtual void send(MidiChannel *mc) = 0;
virtual void copy_to(Instrument *dest) = 0; virtual void copy_to(Instrument *dest) = 0;
virtual bool is_valid() = 0; virtual bool is_valid() = 0;
virtual operator int() { return 255; }
}; };
class Instrument { class Instrument {

View file

@ -105,7 +105,9 @@ static const byte imxOtherTable[6][64] = {
void releaseImcTables() { void releaseImcTables() {
free(_destImcTable); free(_destImcTable);
_destImcTable = NULL;
free(_destImcTable2); free(_destImcTable2);
_destImcTable2 = NULL;
} }
void initializeImcTables() { void initializeImcTables() {

Some files were not shown because too many files have changed in this diff Show more