aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--COPYRIGHT5
-rw-r--r--NEWS18
-rw-r--r--README9
-rw-r--r--backends/events/default/default-events.cpp14
-rw-r--r--backends/platform/PalmOS/Src/be_base.h4
-rw-r--r--backends/platform/PalmOS/Src/launcher/launch.cpp2
-rw-r--r--backends/platform/dc/dc.h4
-rw-r--r--backends/platform/dc/display.cpp22
-rw-r--r--backends/platform/dc/input.cpp12
-rw-r--r--backends/platform/dc/selector.cpp2
-rw-r--r--backends/platform/dc/softkbd.cpp2
-rw-r--r--backends/platform/ds/arm9/data/icons.rawbin15360 -> 24576 bytes
-rw-r--r--backends/platform/ds/arm9/makefile121
-rw-r--r--backends/platform/ds/arm9/source/blitters.cpp8
-rw-r--r--backends/platform/ds/arm9/source/blitters.h18
-rw-r--r--backends/platform/ds/arm9/source/blitters.s339
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp363
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h25
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.cpp54
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.h3
-rw-r--r--backends/platform/ds/arm9/source/fat/disc_io.c2
-rw-r--r--backends/platform/ds/arm9/source/fat/disc_io.h4
-rw-r--r--backends/platform/ds/arm9/source/fat/gba_nds_fat.c13
-rw-r--r--backends/platform/ds/arm9/source/fat/io_dldi.h2
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.cpp15
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.h2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp61
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h22
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.cpp180
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.h7
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.cpp67
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.h8
-rw-r--r--backends/platform/ds/arm9/source/zipreader.cpp6
-rw-r--r--backends/platform/gp2x/build/build.sh1
-rw-r--r--backends/platform/gp2x/build/bundle.sh17
-rw-r--r--backends/platform/gp2x/build/config.sh2
-rw-r--r--backends/platform/gp2x/build/mmuhack.obin0 -> 1720 bytes
-rw-r--r--backends/platform/gp2x/events.cpp60
-rw-r--r--backends/platform/gp2x/gp2x-common.h15
-rw-r--r--backends/platform/gp2x/gp2x-hw.cpp49
-rw-r--r--backends/platform/gp2x/gp2x-hw.h1
-rw-r--r--backends/platform/gp2x/gp2x-mem.c124
-rw-r--r--backends/platform/gp2x/gp2x-mem.h17
-rw-r--r--backends/platform/gp2x/gp2x.cpp30
-rw-r--r--backends/platform/gp2x/graphics.cpp55
-rw-r--r--backends/platform/ps2/systemps2.cpp10
-rw-r--r--backends/platform/ps2/systemps2.h7
-rw-r--r--backends/platform/psp/osys_psp.h9
-rw-r--r--backends/platform/sdl/events.cpp4
-rw-r--r--backends/platform/wince/Makefile2
-rw-r--r--backends/saves/default/default-saves.cpp7
-rw-r--r--base/main.cpp6
-rw-r--r--common/frac.h55
-rw-r--r--common/savefile.h2
-rw-r--r--common/scummsys.h2
-rw-r--r--common/system.h17
-rwxr-xr-xconfigure230
-rw-r--r--dists/msvc8/scummvm.vcproj4
-rw-r--r--engines/agi/agi.cpp2
-rw-r--r--engines/agi/agi.h12
-rw-r--r--engines/agi/cycle.cpp21
-rw-r--r--engines/agi/graphics.cpp161
-rw-r--r--engines/agi/graphics.h3
-rw-r--r--engines/agi/keyboard.cpp14
-rw-r--r--engines/agi/op_cmd.cpp12
-rw-r--r--engines/agi/picture.cpp4
-rw-r--r--engines/agi/saveload.cpp63
-rw-r--r--engines/agi/sprite.cpp13
-rw-r--r--engines/agi/words.cpp2
-rw-r--r--engines/agos/agos.cpp18
-rw-r--r--engines/agos/agos.h10
-rw-r--r--engines/agos/animation.cpp7
-rw-r--r--engines/agos/contain.cpp16
-rw-r--r--engines/agos/debugger.cpp2
-rw-r--r--engines/agos/detection_tables.h2
-rw-r--r--engines/agos/event.cpp5
-rw-r--r--engines/agos/input.cpp62
-rw-r--r--engines/agos/intern.h14
-rw-r--r--engines/agos/items.cpp28
-rw-r--r--engines/agos/menus.cpp4
-rw-r--r--engines/agos/oracle.cpp18
-rw-r--r--engines/agos/res.cpp54
-rw-r--r--engines/agos/rooms.cpp22
-rw-r--r--engines/agos/saveload.cpp54
-rw-r--r--engines/agos/script.cpp16
-rw-r--r--engines/agos/script_e1.cpp24
-rw-r--r--engines/agos/script_e2.cpp38
-rw-r--r--engines/agos/script_ff.cpp2
-rw-r--r--engines/agos/script_s1.cpp26
-rw-r--r--engines/agos/script_s2.cpp2
-rw-r--r--engines/agos/script_ww.cpp9
-rw-r--r--engines/agos/string.cpp10
-rw-r--r--engines/agos/vga.cpp53
-rw-r--r--engines/agos/vga.h16
-rw-r--r--engines/cine/various.cpp5
-rw-r--r--engines/cruise/saveload.cpp4
-rw-r--r--engines/engine.cpp23
-rw-r--r--engines/engine.h48
-rw-r--r--engines/gob/detection.cpp20
-rw-r--r--engines/gob/game.h16
-rw-r--r--engines/gob/goblin.h6
-rw-r--r--engines/gob/imd.h4
-rw-r--r--engines/gob/inter_v1.cpp7
-rw-r--r--engines/gob/map.h4
-rw-r--r--engines/gob/mult.h22
-rw-r--r--engines/gob/music.cpp6
-rw-r--r--engines/gob/saveload_v3.cpp5
-rw-r--r--engines/gob/scenery.h10
-rw-r--r--engines/gob/sound.cpp30
-rw-r--r--engines/gob/sound.h6
-rw-r--r--engines/gob/video.cpp2
-rw-r--r--engines/gob/video.h2
-rw-r--r--engines/kyra/gui.cpp6
-rw-r--r--engines/kyra/kyra.cpp24
-rw-r--r--engines/kyra/resource.cpp29
-rw-r--r--engines/kyra/scene.cpp10
-rw-r--r--engines/kyra/screen.cpp7
-rw-r--r--engines/kyra/script.cpp12
-rw-r--r--engines/kyra/script.h10
-rw-r--r--engines/kyra/script_v1.cpp4
-rw-r--r--engines/kyra/sound_digital.cpp2
-rw-r--r--engines/lure/res_struct.h40
-rw-r--r--engines/parallaction/animation.cpp10
-rw-r--r--engines/parallaction/archive.cpp8
-rw-r--r--engines/parallaction/callables.cpp2
-rw-r--r--engines/parallaction/defs.h1
-rw-r--r--engines/parallaction/dialogue.cpp343
-rw-r--r--engines/parallaction/disk.cpp123
-rw-r--r--engines/parallaction/disk.h11
-rw-r--r--engines/parallaction/graphics.cpp47
-rw-r--r--engines/parallaction/graphics.h9
-rw-r--r--engines/parallaction/location.cpp25
-rw-r--r--engines/parallaction/menu.cpp10
-rw-r--r--engines/parallaction/parallaction.cpp14
-rw-r--r--engines/parallaction/parallaction.h47
-rw-r--r--engines/parallaction/parser.cpp81
-rw-r--r--engines/parallaction/parser.h2
-rw-r--r--engines/parallaction/saveload.cpp32
-rw-r--r--engines/parallaction/zone.cpp31
-rw-r--r--engines/parallaction/zone.h7
-rw-r--r--engines/saga/actor.cpp13
-rw-r--r--engines/saga/actor.h3
-rw-r--r--engines/saga/animation.cpp12
-rw-r--r--engines/saga/detection_tables.h399
-rw-r--r--engines/saga/events.cpp1
-rw-r--r--engines/saga/gfx.h2
-rw-r--r--engines/saga/interface.cpp1
-rw-r--r--engines/saga/music.cpp58
-rw-r--r--engines/saga/music.h3
-rw-r--r--engines/saga/render.cpp6
-rw-r--r--engines/saga/render.h2
-rw-r--r--engines/saga/saga.h20
-rw-r--r--engines/saga/scene.cpp2
-rw-r--r--engines/saga/script.h2
-rw-r--r--engines/saga/sfuncs.cpp96
-rw-r--r--engines/saga/sndres.cpp42
-rw-r--r--engines/saga/sound.cpp35
-rw-r--r--engines/saga/sound.h8
-rw-r--r--engines/scumm/akos.cpp4
-rw-r--r--engines/scumm/base-costume.h2
-rw-r--r--engines/scumm/boxes.cpp2
-rw-r--r--engines/scumm/detection.cpp21
-rw-r--r--engines/scumm/dialogs.cpp32
-rw-r--r--engines/scumm/dialogs.h14
-rw-r--r--engines/scumm/file.cpp3
-rw-r--r--engines/scumm/he/intern_he.h2
-rw-r--r--engines/scumm/he/resource_he.h40
-rw-r--r--engines/scumm/imuse/instrument.cpp8
-rw-r--r--engines/scumm/input.cpp150
-rw-r--r--engines/scumm/intern.h4
-rw-r--r--engines/scumm/module.mk6
-rw-r--r--engines/scumm/object.h6
-rw-r--r--engines/scumm/player_v2.h2
-rw-r--r--engines/scumm/saveload.cpp7
-rw-r--r--engines/scumm/script.cpp32
-rw-r--r--engines/scumm/scumm-md5.h5
-rw-r--r--engines/scumm/scumm.cpp48
-rw-r--r--engines/scumm/scumm.h20
-rw-r--r--engines/scumm/smush/codec47.cpp19
-rw-r--r--engines/scumm/smush/codec47ARM.s372
-rw-r--r--engines/scumm/verbs.cpp14
-rw-r--r--engines/scumm/verbs.h12
-rw-r--r--engines/sky/music/mt32music.cpp4
-rw-r--r--engines/sky/sound.cpp4
-rw-r--r--engines/sky/struc.h8
-rw-r--r--engines/sword1/control.cpp9
-rw-r--r--engines/sword1/mouse.h2
-rw-r--r--engines/sword1/object.h10
-rw-r--r--engines/sword1/router.h4
-rw-r--r--engines/sword1/sound.cpp30
-rw-r--r--engines/sword1/sound.h3
-rw-r--r--engines/sword1/staticres.cpp2
-rw-r--r--engines/sword1/sword1.cpp20
-rw-r--r--engines/sword1/sworddefs.h10
-rw-r--r--engines/touche/ui.cpp10
-rw-r--r--graphics/cursorman.h3
-rw-r--r--graphics/dxa_player.cpp2
-rw-r--r--gui/KeysDialog.cpp16
-rw-r--r--gui/KeysDialog.h4
-rw-r--r--gui/ListWidget.cpp18
-rw-r--r--gui/ListWidget.h4
-rw-r--r--gui/PopUpWidget.cpp10
-rw-r--r--gui/TabWidget.cpp4
-rw-r--r--gui/TabWidget.h2
-rw-r--r--gui/about.cpp8
-rw-r--r--gui/about.h4
-rw-r--r--gui/console.cpp22
-rw-r--r--gui/console.h2
-rw-r--r--gui/credits.h4
-rw-r--r--gui/dialog.cpp16
-rw-r--r--gui/dialog.h4
-rw-r--r--gui/editable.cpp6
-rw-r--r--gui/editable.h2
-rw-r--r--gui/launcher.cpp33
-rw-r--r--gui/launcher.h4
-rw-r--r--gui/newgui.cpp4
-rw-r--r--gui/options.cpp12
-rw-r--r--gui/theme-config.cpp42
-rw-r--r--gui/themes/classic080.ini19
-rw-r--r--gui/themes/modern.ini245
-rw-r--r--gui/widget.h5
-rw-r--r--sound/audiostream.cpp32
-rw-r--r--sound/mididrv.cpp2
-rw-r--r--sound/mixer.cpp13
-rw-r--r--sound/mods/infogrames.cpp25
-rw-r--r--sound/mods/infogrames.h19
-rw-r--r--sound/mods/module.h2
-rw-r--r--sound/mods/paula.cpp161
-rw-r--r--sound/mods/paula.h93
-rw-r--r--sound/mods/protracker.cpp85
-rw-r--r--sound/mods/rjp1.cpp24
-rw-r--r--sound/mods/soundfx.cpp38
-rw-r--r--sound/rate.cpp98
-rw-r--r--sound/rate_arm.cpp28
-rw-r--r--sound/rate_arm_asm.s100
-rw-r--r--sound/softsynth/ym2612.cpp4
-rw-r--r--sound/voc.h4
-rw-r--r--test/common/pack.h2
-rwxr-xr-xtools/credits.pl2
-rw-r--r--tools/scumm-md5.txt39
-rw-r--r--tools/skycpt/AsciiCptCompile.cpp2
-rw-r--r--tools/skycpt/stdafx.cpp7
243 files changed, 4785 insertions, 2265 deletions
diff --git a/AUTHORS b/AUTHORS
index 9c33b881bf..c400b02164 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -138,6 +138,8 @@ ScummVM Team
Miscellaneous:
Jerome Fisher - MT-32 emulator
Jochen Hoenicke - Speaker & PCjr sound support, Adlib work
+ Robin Watts - ARM assembly routines for nice speedups on
+ several ports; improvements to the sound mixer
Website (content)
-----------------
@@ -246,7 +248,6 @@ Other contributions
Daniel Schepler - Final MI1 CD music support, initial Ogg Vorbis
support
Andre Souza - SDL-based OpenGL renderer
- Robin Watts - ARM assembly routines for the Windows CE port
And to all the contributors, users, and beta testers we've missed. Thanks!
diff --git a/COPYRIGHT b/COPYRIGHT
index 11eb153752..cf585143dc 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -13,7 +13,7 @@ Jurgen Braam
Ralph Brorsen
James Brown
Stuart Caie
-Filippos Carapetis
+Filippos Karapetis
Jamieson Christian
Marcus Comstedt
Paolo Costabel
@@ -83,7 +83,7 @@ Andreas Bierfert "awjb"
Elio Blanca "eblanca76"
David Breakey "dbreakey"
Robert Buchholz "prendi"
-Filippos Carapetis "thebluegr"
+Filippos Karapetis "thebluegr"
Mathieu Carot "yokna"
Stefano Ceccherini "jackburton"
Travis S Coady "theealien"
@@ -108,6 +108,7 @@ Matti Hamalainen "ccrtnsp"
Matt Hargett "matt_hargett"
Stefan Haubenthal "polluks"
Alexander Holler "holler"
+Matthew Hoops "clone2727"
Falk Hueffner "mellum"
Casey Hutchinson "nnooiissee"
Gregor Jasny "gjasny"
diff --git a/NEWS b/NEWS
index f208b21824..b3d3820b74 100644
--- a/NEWS
+++ b/NEWS
@@ -2,9 +2,27 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
http://scummvm.sourceforge.net/daily/ChangeLog
0.11.0 (????-??-??)
+ General:
+ - Added ARM assembly routines for code in the sound mixer and SCUMM
+ video playback, resulting in some nice speedups on several ports.
+ - Improved the way keyboard input is handled internally, resolving
+ some odd quirks in some game / port combinations.
+ - Added optional 'confirm exit' dialog to the SDL backend.
+
+ AGOS:
+ - Fixed crashes related to OmniTV playback in The Feeble Files.
+
Broken Sword 1:
- Added support for FLAC encoded music.
+ SCUMM:
+ - Added subtitle skipping (via '.' key) in older games which didn't have
+ this feature so far (e.g. Zak, MM, Indy3, Loom).
+
+ SAGA:
+ - Added support for compressed sound effects, voices and music
+
+
0.10.0 (2007-06-20)
New Games:
- Added Cinematique evo 1 engine. Currently only Future Wars is supported.
diff --git a/README b/README
index 20d6f7be33..7aa58fe2f7 100644
--- a/README
+++ b/README
@@ -1422,6 +1422,9 @@ files.
Running "compress_sword1 --vorbis" will compress the files using Ogg Vorbis
instead of MP3.
+Running "compress_sword1 --flac" will compress the files using Flac
+instead of MP3.
+
Use "compress_sword1 --help" to get a full list of the options.
@@ -1572,6 +1575,8 @@ The following keywords are recognized:
super2xsai, supereagle, advmame2x, advmame3x,
hq2x, hq3x, tv2x, dotmatrix)
+ confirm_exit bool Ask for confirmation by the user before quitting
+ (SDL backend only).
cdrom number Number of CD-ROM unit to use for audio. If
negative, don't even try to access the CD-ROM.
joystick_num number Number of joystick device to use for input
@@ -1597,8 +1602,8 @@ The following keywords are recognized:
midi_gain number The MIDI gain (0-1000) (default: 100) (Only
supported by some MIDI drivers.)
- copy_protection bool Enable copy protection in SCUMM games, when
- ScummVM disables it by default.
+ copy_protection bool Enable copy protection in certain games, in those
+ cases where ScummVM disables it by default.
demo_mode bool Start demo in Maniac Mansion
alt_intro bool Use alternative intro for CD versions of
Beneath a Steel Sky and Flight of the Amazon
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index ad21b09070..6bd97c7f71 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -26,9 +26,13 @@
#if !defined(DISABLE_DEFAULT_EVENTMANAGER)
#include "common/stdafx.h"
+#include "common/config-manager.h"
#include "common/system.h"
#include "backends/events/default/default-events.h"
+#include "engines/engine.h"
+#include "gui/message.h"
+
DefaultEventManager::DefaultEventManager(OSystem *boss) :
_boss(boss),
_buttonState(0),
@@ -93,7 +97,15 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
break;
case Common::EVENT_QUIT:
- _shouldQuit = true;
+ if (ConfMan.getBool("confirm_exit")) {
+ if (g_engine)
+ g_engine->pauseEngine(true);
+ GUI::MessageDialog alert("Do you really want to quit?", "Yes", "No");
+ result = _shouldQuit = (alert.runModal() == GUI::kMessageOK);
+ if (g_engine)
+ g_engine->pauseEngine(false);
+ } else
+ _shouldQuit = true;
break;
default:
diff --git a/backends/platform/PalmOS/Src/be_base.h b/backends/platform/PalmOS/Src/be_base.h
index a5891b99c8..7881275358 100644
--- a/backends/platform/PalmOS/Src/be_base.h
+++ b/backends/platform/PalmOS/Src/be_base.h
@@ -196,10 +196,6 @@ public:
virtual int16 getOverlayHeight();
virtual int16 getOverlayWidth();
- virtual int screenToOverlayX(int x);
- virtual int screenToOverlayY(int y);
- virtual int overlayToScreenX(int x);
- virtual int overlayToScreenY(int y);
virtual OverlayColor ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b);
virtual void colorToARGB(OverlayColor color, uint8 &a, uint8 &r, uint8 &g, uint8 &b);
diff --git a/backends/platform/PalmOS/Src/launcher/launch.cpp b/backends/platform/PalmOS/Src/launcher/launch.cpp
index 7bc07c4fdf..9613abf1cc 100644
--- a/backends/platform/PalmOS/Src/launcher/launch.cpp
+++ b/backends/platform/PalmOS/Src/launcher/launch.cpp
@@ -424,7 +424,7 @@ Boolean StartScummVM(Int16 engine) {
toLauncher= (gPrefs->exitLauncher);
// gVars values
- // (gVars->HRrefNum defined in checkHRmode on Clié)
+ // (gVars->HRrefNum defined in checkHRmode on Clie)
#ifndef _DEBUG_ENGINE
gVars->VFS.volRefNum = (gPrefs->card.autoDetect ? vfsInvalidVolRef : gPrefs->card.volRefNum);
#else
diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h
index fa47ed21f5..aa2f7b2f92 100644
--- a/backends/platform/dc/dc.h
+++ b/backends/platform/dc/dc.h
@@ -144,10 +144,6 @@ class OSystem_Dreamcast : public OSystem {
// Overlay
int16 getOverlayHeight();
int16 getOverlayWidth();
- int screenToOverlayX(int x);
- int screenToOverlayY(int y);
- int overlayToScreenX(int x);
- int overlayToScreenY(int y);
void showOverlay();
void hideOverlay();
void clearOverlay();
diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp
index da9f6e83ff..1790785b67 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -585,7 +585,7 @@ void OSystem_Dreamcast::copyRectToOverlay(const int16 *buf, int pitch,
static const OSystem::GraphicsMode gfxmodes[] = {
- { "default", "640×480 16bpp", 0 },
+ { "default", "640x480 16bpp", 0 },
{ NULL, NULL, 0 }
};
@@ -645,23 +645,3 @@ int16 OSystem_Dreamcast::getOverlayWidth()
return OVL_W;
}
-int OSystem_Dreamcast::screenToOverlayX(int x)
-{
- return x - _overlay_x;
-}
-
-int OSystem_Dreamcast::screenToOverlayY(int y)
-{
- return y - _overlay_y;
-}
-
-int OSystem_Dreamcast::overlayToScreenX(int x)
-{
- return x + _overlay_x;
-}
-
-int OSystem_Dreamcast::overlayToScreenY(int y)
-{
- return y + _overlay_y;
-}
-
diff --git a/backends/platform/dc/input.cpp b/backends/platform/dc/input.cpp
index f3638a28db..aa0d9efa21 100644
--- a/backends/platform/dc/input.cpp
+++ b/backends/platform/dc/input.cpp
@@ -48,7 +48,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y,
if(!(buttons & 4)) lmb++;
if(!(buttons & 2)) rmb++;
- if(!(buttons & 8)) newkey = Common::ASCII_F5;
+ if(!(buttons & 8)) newkey = Common::KEYCODE_F5;
else if(!(buttons & 512)) newkey = ' ';
else if(!(buttons & 1024)) newkey = numpadmap[(buttons>>4)&15];
@@ -69,7 +69,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y,
if(!(buttons & 4)) lmb++;
if(!(buttons & 2)) rmb++;
- if(!(buttons & 8)) newkey = Common::ASCII_F5;
+ if(!(buttons & 8)) newkey = Common::KEYCODE_F5;
mouse_x += pad->cond.mouse.axis1;
mouse_y += pad->cond.mouse.axis2;
@@ -98,10 +98,10 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y,
newkey = key+('1'-0x59);
else if(key >= 0x2d && key <= 0x38 && key != 0x31)
newkey = ((shift & 0x22)?
- "=¯`{ }+*½<>?" :
- "-^@[ ];:§,./")[key - 0x2d];
+ "=?`{ }+*?<>?" :
+ "-^@[ ];:?,./")[key - 0x2d];
else if(key >= 0x3a && key <= 0x43)
- newkey = key+(Common::ASCII_F1-0x3a);
+ newkey = key+(Common::KEYCODE_F1-0x3a);
else if(key >= 0x54 && key <= 0x57)
newkey = "/*-+"[key-0x54];
else switch(key) {
@@ -134,7 +134,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y,
case 0x64: case 0x87:
newkey = ((shift & 0x22)? '_' : '\\'); break;
case 0x89:
- newkey = ((shift & 0x22)? '|' : '¥'); break;
+ newkey = ((shift & 0x22)? '|' : '?'); break;
}
}
}
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 8262a39614..b082afabf5 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -364,7 +364,7 @@ int gameMenu(Game *games, int num_games)
event = handleInput(locked_get_pads(), mousex, mousey, shiftFlags);
setimask(mask);
- if(event==-Common::EVENT_LBUTTONDOWN || event==13 || event==Common::ASCII_F5) {
+ if(event==-Common::EVENT_LBUTTONDOWN || event==Common::KEYCODE_ENTER || event==Common::KEYCODE_F5) {
int selected_game = top_game + selector_pos;
for(int fade=0; fade<=256; fade+=4) {
diff --git a/backends/platform/dc/softkbd.cpp b/backends/platform/dc/softkbd.cpp
index 58b492f6db..79363713a5 100644
--- a/backends/platform/dc/softkbd.cpp
+++ b/backends/platform/dc/softkbd.cpp
@@ -52,7 +52,7 @@ static const char key_names[] =
static const short key_codes[] =
{
- Common::KEYCODE_ESCAPE, Common::ASCII_F1, Common::ASCII_F2, Common::ASCII_F3, Common::ASCII_F4, Common::ASCII_F5, Common::ASCII_F6, Common::ASCII_F7, Common::ASCII_F8, Common::ASCII_F9, Common::ASCII_F10,
+ Common::KEYCODE_ESCAPE, Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3, Common::KEYCODE_F4, Common::KEYCODE_F5, Common::KEYCODE_F6, Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9, Common::KEYCODE_F10,
K('1','!'), K('2','"'), K('3','#'), K('4','$'), K('5','%'),
K('6','&'), K('7','\''), K('8','('), K('9',')'), K('0','~'), K('-','='),
K('q','Q'), K('w','W'), K('e','E'), K('r','R'), K('t','T'),
diff --git a/backends/platform/ds/arm9/data/icons.raw b/backends/platform/ds/arm9/data/icons.raw
index c2915b2914..c8fbfd6e9a 100644
--- a/backends/platform/ds/arm9/data/icons.raw
+++ b/backends/platform/ds/arm9/data/icons.raw
Binary files differ
diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile
index cb41774064..c9ca5467f3 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -4,18 +4,32 @@ libndsdir = /home/neil/devkitpro/libnds
# Select the build you want by uncommenting one of the following lines:
-DS_BUILD_A = 1
+
+#DS_BUILD_A = 1
#DS_BUILD_B = 1
#DS_BUILD_C = 1
-#DS_BUILD_D = 1
+DS_BUILD_D = 1
+#DS_BUILD_E = 1
+#DS_BUILD_F = 1
# Uncomment the following line to build in support for MP3 audio
# using libmad:
-USE_MAD = 1
+
+ifdef DS_BUILD_F
+ # TODO: Fix this. When libmad is compiled in, the Kyrandia resource loading
+ # searches through it's entire index to find an mp3 each time a voice sample is requested
+ # this causes a nasty pause.
+else
+ USE_MAD = 1
+endif
# Uncomment the following line to enable support for the
# ace DS Debugger (remembering to make the same change in the arm7 makefile):
#USE_DEBUGGER = 1
+
+# Uncomment the following line to enable the profiler
+#USE_PROFILER = 1
+
# NOTE: The header and libs for the debugger is assumed to be in the libnds
# folder.
@@ -24,6 +38,7 @@ VPATH = $(srcdir)
# Command to build libmad is:
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork'
+ARM = 1
ifdef DS_BUILD_A
DEFINES = -DDS_SCUMM_BUILD -DDS_BUILD_A
@@ -44,6 +59,7 @@ ifdef DS_BUILD_A
DISABLE_AGI = 1
DISABLE_TOUCHE = 1
DISABLE_PARALLACTION = 1
+ DISABLE_CRUISE = 1
BUILD=scummvm-A
endif
@@ -66,6 +82,7 @@ ifdef DS_BUILD_B
DISABLE_AGI = 1
DISABLE_TOUCHE = 1
DISABLE_PARALLACTION = 1
+ DISABLE_CRUISE = 1
BUILD=scummvm-B
endif
@@ -81,13 +98,14 @@ ifdef DS_BUILD_C
DISABLE_SWORD2 = 1
DISABLE_QUEEN = 1
DISABLE_SAGA = 1
- #DISABLE_KYRA = 1
- #DISABLE_GOB = 1
+ DISABLE_KYRA = 1
+ DISABLE_GOB = 1
DISABLE_LURE = 1
DISABLE_CINE = 1
DISABLE_AGI = 1
DISABLE_TOUCHE = 1
DISABLE_PARALLACTION = 1
+ DISABLE_CRUISE = 1
BUILD=scummvm-C
endif
@@ -104,15 +122,62 @@ ifdef DS_BUILD_D
DISABLE_QUEEN = 1
DISABLE_SAGA = 1
DISABLE_KYRA = 1
- DISABLE_GOB = 1
+ #DISABLE_GOB = 1
DISABLE_LURE = 1
#DISABLE_CINE = 1
#DISABLE_AGI = 1
DISABLE_TOUCHE = 1
DISABLE_PARALLACTION = 1
- BUILD=scummvm-A
+ DISABLE_CRUISE = 1
+ BUILD=scummvm-D
endif
+ifdef DS_BUILD_E
+ DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_E
+ LOGO = logoc.bmp
+ DISABLE_HE = 1
+ DISABLE_SCUMM = 1
+ DISABLE_SCUMM_7_8 = 1
+ DISABLE_AGOS = 1
+ DISABLE_SKY = 1
+ DISABLE_SWORD1 = 1
+ DISABLE_SWORD2 = 1
+ DISABLE_QUEEN = 1
+ #DISABLE_SAGA = 1
+ DISABLE_KYRA = 1
+ DISABLE_GOB = 1
+ DISABLE_LURE = 1
+ DISABLE_CINE = 1
+ DISABLE_AGI = 1
+ DISABLE_TOUCHE = 1
+ DISABLE_PARALLACTION = 1
+ DISABLE_CRUISE = 1
+ BUILD=scummvm-E
+endif
+
+ifdef DS_BUILD_F
+ DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_F
+ LOGO = logoc.bmp
+ DISABLE_HE = 1
+ DISABLE_SCUMM = 1
+ DISABLE_SCUMM_7_8 = 1
+ DISABLE_AGOS = 1
+ DISABLE_SKY = 1
+ DISABLE_SWORD1 = 1
+ DISABLE_SWORD2 = 1
+ DISABLE_QUEEN = 1
+ DISABLE_SAGA = 1
+ #DISABLE_KYRA = 1
+ DISABLE_GOB = 1
+ DISABLE_LURE = 1
+ DISABLE_CINE = 1
+ DISABLE_AGI = 1
+ DISABLE_TOUCHE = 1
+ DISABLE_PARALLACTION = 1
+ DISABLE_CRUISE = 1
+ BUILD=scummvm-F
+
+endif
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
@@ -120,7 +185,7 @@ ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
CC = arm-eabi-gcc
CXX = arm-eabi-g++
-CFLAGS = -Wno-multichar -Wall -Os\
+CFLAGS = -Wno-multichar -Wall\
-Wno-multichar -mcpu=arm9tdmi -mtune=arm9tdmi \
-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
-ffast-math -mthumb-interwork
@@ -129,12 +194,17 @@ ifdef USE_DEBUGGER
DEFINES += -DUSE_DEBUGGER
CFLAGS += -g
endif
+
+ifdef USE_PROFILER
+ CFLAGS += -mpoke-function-name -finstrument-functions -g
+ DEFINES += -DUSE_PROFILER
+endif
CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-non-virtual-dtor \
-fno-exceptions -fno-rtti
ASFLAGS = -mcpu=arm9tdmi -mthumb-interwork
-DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER
+DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DARM
ifdef USE_MAD
DEFINES += -DUSE_MAD
endif
@@ -182,9 +252,14 @@ PORT_OBJS := $(portdir)/source/blitters.o $(portdir)/source/cdaudio.o $(portdir)
$(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\
$(portdir)/source/osystem_ds.o $(portdir)/source/portdefs.o $(portdir)/source/ramsave.o\
$(portdir)/source/scummconsole.o $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\
- $(portdir)/source/dsoptions.o $(portdir)/source/keys.o
+ $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o
-DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o
+ifdef USE_PROFILER
+ PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o
+endif
+
+
+DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o
COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o
@@ -209,7 +284,9 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o
LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o
-
+# Files in this list will be compiled with -O2, otherwise they will be compiled with -Os
+OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp
+#OPTLIST :=
OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS)
@@ -269,6 +346,7 @@ endef
# rm $(*).tmp
#endef
+
##############
# Replacement rule for the one in makefile.common
##############
@@ -276,6 +354,7 @@ ifndef HAVE_GCC3
# If you use GCC, disable the above and enable this for intelligent
# dependency tracking.
.cpp.o:
+
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
# $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
@@ -287,9 +366,19 @@ else
# Also, with this GCC inserts additional dummy rules for the involved headers,
# which ensures a smooth compilation even if said headers become obsolete.
.cpp.o:
+# echo !!!!!!!!!!!! $(notdir $<)
+# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) )
+# OPTFLAG=-O3
+# else
+# OPTFLAG=-Os
+# endif
+
+# export OPTFLAG = ;
+# echo !!!!!!!! $(OPTFLAG)
+
$(MKDIR) $(*D)/$(DEPDIR)
-# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
- $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
+ $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
+ $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o $(if $(findstring $(notdir $<), $(OPTLIST)), -O2, -Os)
endif
@@ -333,8 +422,8 @@ endif
#---------------------------------------------------------------------------------
%.nds: %.bin
- @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port"
- ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port"
+ @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port"
+ ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port"
dsbuild $@ -l ../ndsloader.bin
padbin 16 $(basename $@).ds.gba
diff --git a/backends/platform/ds/arm9/source/blitters.cpp b/backends/platform/ds/arm9/source/blitters.cpp
index 9af3c5d611..ec33a5aab4 100644
--- a/backends/platform/ds/arm9/source/blitters.cpp
+++ b/backends/platform/ds/arm9/source/blitters.cpp
@@ -1,8 +1,6 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 Neil Millstone
+ * Copyright (C) 2006 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/backends/platform/ds/arm9/source/blitters.h b/backends/platform/ds/arm9/source/blitters.h
index 9fb50cdf0d..fe6966fdae 100644
--- a/backends/platform/ds/arm9/source/blitters.h
+++ b/backends/platform/ds/arm9/source/blitters.h
@@ -23,6 +23,10 @@
#ifndef _BLITTERS_H_
#define _BLITTERS_H_
+#define USING_ARM_BLITTERS
+
+#ifndef USING_ARM_BLITTERS
+
namespace DS {
void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst,
@@ -33,4 +37,18 @@ void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStr
}
+#else
+
+extern "C" {
+
+void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst,
+ int vsPitch, int vmScreenWidth, int textSurfacePitch);
+void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height);
+void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, const u16* palette, int destStride, int srcStride);
+void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride);
+
+}
+
+#endif
+
#endif
diff --git a/backends/platform/ds/arm9/source/blitters.s b/backends/platform/ds/arm9/source/blitters.s
new file mode 100644
index 0000000000..2f14c5a140
--- /dev/null
+++ b/backends/platform/ds/arm9/source/blitters.s
@@ -0,0 +1,339 @@
+@ ScummVM Scumm Interpreter
+@ Copyright (C) 2007 The ScummVM project
+@
+@ This program is free software@ you can redistribute it and/or
+@ modify it under the terms of the GNU General Public License
+@ as published by the Free Software Foundation@ either version 2
+@ of the License, or (at your option) any later version.
+@
+@ This program is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@ GNU General Public License for more details.
+@
+@ You should have received a copy of the GNU General Public License
+@ along with this program@ if not, write to the Free Software
+@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+@
+@ $URL: $
+@ $Id: $
+@
+@ @author Robin Watts (robin@wss.co.uk)
+
+ .text
+
+ .global asmDrawStripToScreen
+ .global asmCopy8Col
+ .global Rescale_320x256xPAL8_To_256x256x1555
+ .global Rescale_320x256x1555_To_256x256x1555
+
+ @ ARM implementation of asmDrawStripToScreen.
+ @
+ @ C prototype would be:
+ @
+ @ extern "C" void asmDrawStripToScreen(int height,
+ @ int width,
+ @ byte const *text,
+ @ byte const *src,
+ @ byte *dst,
+ @ int vsPitch,
+ @ int vsScreenWidth,
+ @ int textSurfacePitch);
+ @
+ @ In addition, we assume that text, src and dst are all word (4 byte)
+ @ aligned. This is the same assumption that the old 'inline' version
+ @ made.
+asmDrawStripToScreen:
+ @ r0 = height
+ @ r1 = width
+ @ r2 = text
+ @ r3 = src
+ MOV r12,r13
+ STMFD r13!,{r4-r7,r9-r11,R14}
+ LDMIA r12,{r4,r5,r6,r7}
+ @ r4 = dst
+ @ r5 = vsPitch
+ @ r6 = vmScreenWidth
+ @ r7 = textSurfacePitch
+
+ CMP r0,#0 @ If height<=0
+ MOVLE r0,#1 @ height=1
+ CMP r1,#4 @ If width<4
+ BLT end @ return
+
+ @ Width &= ~4 ? What's that about then? Width &= ~3 I could have
+ @ understood...
+ BIC r1,r1,#4
+
+ SUB r5,r5,r1 @ vsPitch -= width
+ SUB r6,r6,r1 @ vmScreenWidth -= width
+ SUB r7,r7,r1 @ textSurfacePitch -= width
+ MOV r10,#253
+ ORR r10,r10,r10,LSL #8
+ ORR r10,r10,r10,LSL #16 @ r10 = mask
+yLoop:
+ MOV r14,r1 @ r14 = width
+xLoop:
+ LDR r12,[r2],#4 @ r12 = [text]
+ LDR r11,[r3],#4 @ r11 = [src]
+ CMP r12,r10
+ BNE singleByteCompare
+ SUBS r14,r14,#4
+ STR r11,[r4], #4 @ r4 = [dst]
+ BGT xLoop
+
+ ADD r2,r2,r7 @ text += textSurfacePitch
+ ADD r3,r3,r5 @ src += vsPitch
+ ADD r4,r4,r6 @ dst += vmScreenWidth
+ SUBS r0,r0,#1
+ BGT yLoop
+ LDMFD r13!,{r4-r7,r9-r11,PC}
+
+singleByteCompare:
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ STR r12,[r4],#4
+ SUBS r14,r14,#4
+ BGT xLoop
+
+ ADD r2,r2,r7 @ text += textSurfacePitch
+ ADD r3,r3,r5 @ src += vsPitch
+ ADD r4,r4,r6 @ dst += vmScreenWidth
+ SUBS r0,r0,#1
+ BGT yLoop
+end:
+ LDMFD r13!,{r4-r7,r9-r11,PC}
+
+
+ @ ARM implementation of asmCopy8Col
+ @
+ @ C prototype would be:
+ @
+ @ extern "C" void asmCopy8Col(byte *dst,
+ @ int dstPitch,
+ @ const byte *src,
+ @ int height);
+ @
+ @ In addition, we assume that src and dst are both word (4 byte)
+ @ aligned. This is the same assumption that the old 'inline' version
+ @ made.
+asmCopy8Col:
+ @ r0 = dst
+ @ r1 = dstPitch
+ @ r2 = src
+ @ r3 = height
+ STMFD r13!,{r14}
+ SUB r1,r1,#4
+
+ TST r3,#1
+ ADDNE r3,r3,#1
+ BNE roll2
+yLoop2:
+ LDR r12,[r2],#4
+ LDR r14,[r2],r1
+ STR r12,[r0],#4
+ STR r14,[r0],r1
+roll2:
+ LDR r12,[r2],#4
+ LDR r14,[r2],r1
+ SUBS r3,r3,#2
+ STR r12,[r0],#4
+ STR r14,[r0],r1
+ BNE yLoop2
+
+ LDMFD r13!,{PC}
+
+
+ @ ARM implementation of Rescale_320x256x1555_To_256x256x1555
+ @
+ @ C prototype would be:
+ @
+ @ extern "C" void Rescale_320x256x1555_To_256x256x1555(
+ @ u16 *dst,
+ @ const u16 *src,
+ @ int dstStride,
+ @ int srcStride);
+Rescale_320x256x1555_To_256x256x1555:
+ @ r0 = dst
+ @ r1 = src
+ @ r2 = dstStride
+ @ r3 = srcStride
+ STMFD r13!,{r4-r5,r8-r11,r14}
+
+ SUB r2,r2,#64*5 @ srcStride -= line length
+ SUB r3,r3,#64*4 @ dstStride -= line length
+
+ MOV r8, #0x0000001F
+ ORR r8, r8,#0x00007C00
+ ORR r8, r8,#0x03E00000 @ r8 = mask
+ MOV r5, #200 @ r5 = y
+yLoop3:
+ MOV r4, #64 @ r4 = x
+xLoop3:
+ LDRH r9, [r0],#2 @ r9 = src0
+ LDRH r10,[r0],#2 @ r10= src1
+ LDRH r11,[r0],#2 @ r11= src2
+ LDRH r12,[r0],#2 @ r12= src3
+ LDRH r14,[r0],#2 @ r14= src4
+
+ ORR r9, r9, r9, LSL #16 @ r9 = src0 | src0
+ ORR r10,r10,r10,LSL #16 @ r10= src1 | src1
+ ORR r11,r11,r11,LSL #16 @ r11= src2 | src2
+ ORR r12,r12,r12,LSL #16 @ r12= src3 | src3
+ ORR r14,r14,r14,LSL #16 @ r13= src4 | src4
+
+ AND r9, r9, r8 @ r9 = 0 | G0 | 0 | B0 | 0 | R0
+ AND r10,r10,r8 @ r10= 0 | G1 | 0 | B1 | 0 | R1
+ AND r11,r11,r8 @ r11= 0 | G2 | 0 | B2 | 0 | R2
+ AND r12,r12,r8 @ r12= 0 | G3 | 0 | B3 | 0 | R3
+ AND r14,r14,r8 @ r14= 0 | G4 | 0 | B4 | 0 | R4
+
+ ADD r9, r9, r9, LSL #1 @ r9 = 3*src0
+ ADD r9, r9, r10 @ r9 = dst0<<2
+ ADD r10,r10,r11 @ r10= dst1
+ ADD r11,r11,r12 @ r11= dst2
+ ADD r12,r12,r14 @ r12= src3 + src4
+ ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2
+
+ AND r9, r8, r9, LSR #2 @ r9 = dst0 (split)
+ AND r10,r8, r10,LSR #1 @ r10= dst1 (split)
+ AND r11,r8, r11,LSR #1 @ r11= dst2 (split)
+ AND r12,r8, r12,LSR #2 @ r12= dst3 (split)
+
+ ORR r9, r9, r9, LSR #16 @ r9 = dst0
+ ORR r10,r10,r10,LSR #16 @ r10= dst1
+ ORR r11,r11,r11,LSR #16 @ r11= dst2
+ ORR r12,r12,r12,LSR #16 @ r12= dst3
+
+ ORR r9, r9, #0x8000
+ ORR r10,r10,#0x8000
+ ORR r11,r11,#0x8000
+ ORR r12,r12,#0x8000
+
+ STRH r9, [r1],#2
+ STRH r10,[r1],#2
+ STRH r11,[r1],#2
+ STRH r12,[r1],#2
+
+ SUBS r4,r4,#1
+ BGT xLoop3
+
+ ADD r0,r0,r2,LSL #1
+ ADD r1,r2,r3,LSL #1
+ SUBS r5,r5,#1
+ BGT yLoop3
+
+ LDMFD r13!,{r4-r5,r8-r11,PC}
+
+ @ ARM implementation of Rescale_320x256xPAL8_To_256x256x1555
+ @
+ @ C prototype would be:
+ @
+ @ extern "C" void Rescale_320x256xPAL8_To_256x256x1555(
+ @ u16 *dst,
+ @ const u8 *src,
+ @ int dstStride,
+ @ int srcStride,
+ @ const u16 *pal);
+ @
+ @ This is a slight reordering of the params from the existing C one.
+ @ Sorry, but it makes the code easier.
+Rescale_320x256xPAL8_To_256x256x1555:
+ @ r0 = dst
+ @ r1 = src
+ @ r2 = dstStride
+ @ r3 = srcStride
+ STMFD r13!,{r4-r5,r8-r11,r14}
+ MOV r8, #0x0000001F
+ ORR r8, r8,#0x00007C00
+ ORR r8, r8,#0x03E00000 @ r8 = mask
+ LDR r9, [r13,#7*4] @ r9 = palette
+
+ SUB r13,r13,#256*4 @ r13 = 1K of space on the stack.
+ MOV r5, r13 @ r5 points to this space
+ MOV r14,#256
+palLoop:
+ LDRH r10,[r9],#2 @ r10 = palette entry
+ SUBS r14,r14,#1
+ ORR r10,r10,r10,LSL #16
+ AND r10,r10,r8 @ r10 = separated palette entry
+ STR r10,[r5], #4
+ BGT palLoop
+
+ SUB r2,r2,#64*5 @ srcStride -= line length
+ SUB r3,r3,#64*4 @ dstStride -= line length
+
+ MOV r5,#200 @ r5 = y
+yLoop4:
+ MOV r4,#64 @ r4 = x
+xLoop4:
+ LDRB r9, [r0],#1 @ r9 = src0
+ LDRB r10,[r0],#1 @ r10= src1
+ LDRB r11,[r0],#1 @ r11= src2
+ LDRB r12,[r0],#1 @ r12= src3
+ LDRB r14,[r0],#1 @ r14= src4
+
+ LDR r9, [r13,r9, LSL #2] @ r9 = pal[src0]
+ LDR r10,[r13,r10,LSL #2] @ r10= pal[src1]
+ LDR r11,[r13,r11,LSL #2] @ r11= pal[src2]
+ LDR r12,[r13,r12,LSL #2] @ r12= pal[src3]
+ LDR r14,[r13,r14,LSL #2] @ r13= pal[src4]
+
+ ADD r9, r9, r9, LSL #1 @ r9 = 3*src0
+ ADD r9, r9, r10 @ r9 = dst0<<2
+ ADD r10,r10,r11 @ r10= dst1
+ ADD r11,r11,r12 @ r11= dst2
+ ADD r12,r12,r14 @ r12= src3 + src4
+ ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2
+
+ AND r9, r8, r9, LSR #2 @ r9 = dst0 (split)
+ AND r10,r8, r10,LSR #1 @ r10= dst1 (split)
+ AND r11,r8, r11,LSR #1 @ r11= dst2 (split)
+ AND r12,r8, r12,LSR #2 @ r12= dst3 (split)
+
+ ORR r9, r9, r9, LSR #16 @ r9 = dst0
+ ORR r10,r10,r10,LSR #16 @ r10= dst1
+ ORR r11,r11,r11,LSR #16 @ r11= dst2
+ ORR r12,r12,r12,LSR #16 @ r12= dst3
+
+ ORR r9, r9, #0x8000
+ ORR r10,r10,#0x8000
+ ORR r11,r11,#0x8000
+ ORR r12,r12,#0x8000
+
+ STRH r9, [r1],#2
+ STRH r10,[r1],#2
+ STRH r11,[r1],#2
+ STRH r12,[r1],#2
+
+ SUBS r4,r4,#1
+ BGT xLoop4
+
+ ADD r0,r0,r2
+ ADD r1,r2,r3,LSL #1
+ SUBS r5,r5,#1
+ BGT yLoop4
+
+ ADD r13,r13,#256*4
+
+ LDMFD r13!,{r4-r5,r8-r11,PC}
+
+
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index af5addac66..aafa54e347 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -44,9 +44,32 @@
// - Delete saves?
// - Software scaler?
// - 100% scale
+
+// - Arrow keys cause key events when keyboard enabled - Done
+// - Mouse cursor display - Done
+// - Disable scaler on options menu - Done
+// - Fix scale icons on top screen - Done
+// - Fseek optimisation? - No need
+// - Fix agi hack to be cleaner - done
+// - Fix not typing looong words - Done
+// - Show keyboard by default in AGI games
+// - Fix mouse moving when cursor on keyboard screen - Done
+// - Fix 'fit' thingy always appearing - Done
+// - check cine backbuffer code - Done
+// - Add long filename support - Done
+// - New icons
+// - Add key config for gob engine: Start:F1, Shift-numbers: F keys - Done
+// - Fix [ds] appearing in game menu
+
// - Find out what's going wrong when you turn the console off
+// - enable console when asserting
+
+// - AGI: Adding keyboard hack
+// - CINE: Framebuffer modification should check if it works without, fix for overwrite crash
+// - KYRA: GetFileSize modification
+
-#define USE_LIBCARTRESET
+//#define USE_LIBCARTRESET
//#define USE_BUILT_IN_DRIVER_SELECTION
#include <nds.h>
@@ -78,6 +101,8 @@
#include "blitters.h"
#include "cartreset_nolibfat.h"
#include "keys.h"
+#include "profiler/cyg-profile.h"
+//test
namespace DS {
@@ -151,13 +176,16 @@ bool displayModeIs8Bit = false;
// Game id
u8 gameID;
-bool consoleEnable = true;
+bool consoleEnable = false;
bool gameScreenSwap = false;
bool isCpuScalerEnabled();
//#define HEAVY_LOGGING
MouseMode mouseMode;
+int storedMouseX = 0;
+int storedMouseY = 0;
+
// Sprites
SpriteEntry sprites[128];
SpriteEntry spritesMain[128];
@@ -173,6 +201,9 @@ bool keyboardIcon = false;
// Touch
int touchScX, touchScY, touchX, touchY;
+int mouseHotspotX, mouseHotspotY;
+bool cursorEnable = false;
+bool mouseCursorVisible = true;
// Dragging
int dragStartX, dragStartY;
@@ -188,20 +219,12 @@ int gameHeight = 200;
// Scale
bool twoHundredPercentFixedScale = false;
+#define NUM_SUPPORTED_GAMES 17
-enum controlType {
- CONT_SCUMM_ORIGINAL,
- CONT_SCUMM_SAMNMAX,
- CONT_SKY,
- CONT_SIMON,
-};
-
-struct gameListType {
- char gameId[16];
- controlType control;
-};
+#ifdef USE_PROFILER
+int hBlankCount = 0;
+#endif
-#define NUM_SUPPORTED_GAMES 15
gameListType gameList[NUM_SUPPORTED_GAMES] = {
// Unknown game - use normal SCUMM controls
@@ -222,8 +245,10 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = {
{"sky", CONT_SKY},
{"simon1", CONT_SIMON},
{"simon2", CONT_SIMON},
- {"gob1", CONT_SCUMM_ORIGINAL},
- {"queen", CONT_SCUMM_ORIGINAL}
+ {"gob", CONT_GOBLINS},
+ {"queen", CONT_SCUMM_ORIGINAL},
+ {"cine", CONT_FUTURE_WARS},
+ {"agi", CONT_AGI}
};
gameListType* currentGame = NULL;
@@ -259,9 +284,11 @@ int getKeysChanged();
void updateStatus();
void triggerIcon(int imageNum);
void setIcon(int num, int x, int y, int imageNum, int flags, bool enable);
+void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable);
TransferSound soundControl;
+
bool isCpuScalerEnabled()
{
return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds"));
@@ -332,20 +359,21 @@ void initSprites() {
void saveGameBackBuffer() {
#ifdef DISABLE_SCUMM
- if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight];
+ if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight];
for (int r = 0; r < gameHeight; r++) {
memcpy(savedBuffer + (r * gameWidth), ((u8 *) (get8BitBackBuffer())) + (r * 512), gameWidth);
+ }
#endif
}
void restoreGameBackBuffer() {
#ifdef DISABLE_SCUMM
if (savedBuffer) {
- for (int r = 0; r < gameHeight; r++) {
- memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth);
- memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth);
- }
-
+ for (int r = 0; r < gameHeight; r++) {
+ memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth);
+ memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth);
+ }
+
delete savedBuffer;
savedBuffer = NULL;
}
@@ -413,7 +441,7 @@ void initGame() {
//strcpy(gameName, ConfMan.getActiveDomain().c_str());
strcpy(gameName, ConfMan.get("gameid").c_str());
-// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
+ //consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
currentGame = &gameList[0]; // Default game
@@ -590,7 +618,51 @@ void checkSleepMode() {
}
}
-void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) {
+void setShowCursor(bool enable)
+{
+ if (currentGame->control == CONT_SCUMM_SAMNMAX)
+ {
+ if (cursorEnable) {
+ sprites[1].attribute[0] = ATTR0_BMP | 150;
+ } else {
+ sprites[1].attribute[0] = ATTR0_DISABLED;
+ }
+
+ }
+
+ cursorEnable = enable;
+}
+
+void setMouseCursorVisible(bool enable)
+{
+ mouseCursorVisible = enable;
+}
+
+void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY) {
+
+ mouseHotspotX = hotspotX;
+ mouseHotspotY = hotspotY;
+
+ {
+ int off = 128*64;
+
+
+ memset(SPRITE_GFX + off, 0, 32 * 32 * 2);
+
+ for (uint y=0; y<h; y++) {
+ for (uint x=0; x<w; x++) {
+ int color = icon[y*w+x];
+
+ if (color == keycolor) {
+ SPRITE_GFX[off+(y)*32+x] = 0x0000; // black background
+ } else {
+ SPRITE_GFX[off+(y)*32+x] = BG_PALETTE[color] | 0x8000;
+ }
+ }
+ }
+
+ }
+
if (currentGame->control != CONT_SCUMM_SAMNMAX)
return;
@@ -619,6 +691,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) {
for (uint y=0; y<h; y++) {
for (uint x=0; x<w; x++) {
int color = icon[y*w+x];
+
if (color == keycolor) {
SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = 0x8000; // black background
} else {
@@ -626,10 +699,18 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) {
}
}
}
-
- sprites[1].attribute[0] = ATTR0_BMP | 150;
- sprites[1].attribute[1] = ATTR1_SIZE_64 | pos;
- sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48;
+
+
+ if ((cursorEnable))
+ {
+ sprites[1].attribute[0] = ATTR0_BMP | 150;
+ sprites[1].attribute[1] = ATTR1_SIZE_64 | pos;
+ sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48;
+ } else {
+ sprites[1].attribute[0] = ATTR0_DISABLED | 150;
+ sprites[1].attribute[1] = ATTR1_SIZE_64 | pos;
+ sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48;
+ }
}
@@ -734,7 +815,7 @@ void displayMode16BitFlipBuffer() {
#endif
const u8* back = (const u8*)get8BitBackBuffer();
u16* base = BG_GFX + 0x10000;
- DS::Rescale_320x256xPAL8_To_256x256x1555( base,
+ Rescale_320x256xPAL8_To_256x256x1555( base,
back,
BG_PALETTE,
256,
@@ -867,7 +948,7 @@ void addIndyFightingKeys() {
event.type = Common::EVENT_KEYDOWN;
event.kbd.flags = 0;
- consolePrintf("Fight keys\n");
+// consolePrintf("Fight keys\n");
if ((getKeysDown() & KEY_L)) {
indyFightRight = false;
@@ -877,7 +958,7 @@ void addIndyFightingKeys() {
indyFightRight = true;
}
- consolePrintf("ifr:%d\n", indyFightRight);
+// consolePrintf("ifr:%d\n", indyFightRight);
if ((getKeysChanged() & KEY_UP)) {
event.type = getKeyEvent(KEY_UP);
@@ -966,10 +1047,10 @@ void setKeyboardEnable(bool en) {
if (keyboardEnable) {
- DS::drawKeyboard(1, 12, backupBank);
+ DS::drawKeyboard(1, 14, backupBank);
- SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12);
+ SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(14);
if (displayModeIs8Bit) {
SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer
@@ -1025,6 +1106,16 @@ void addEventsToQueue() {
Common::Event event;
+#ifdef USE_PROFILER
+ if (keysDown() & KEY_R) {
+ cygprofile_begin();
+ cygprofile_enable();
+ }
+ if (keysDown() & KEY_L) {
+ cygprofile_disable();
+ cygprofile_end();
+ }
+#endif
if (system->isEventQueueEmpty()) {
@@ -1051,7 +1142,7 @@ void addEventsToQueue() {
if (!indyFightState) {
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysChanged() & KEY_B)) {
event.kbd.keycode = 27;
event.kbd.ascii = 27;
event.kbd.flags = 0;
@@ -1073,8 +1164,37 @@ void addEventsToQueue() {
}
}
+ if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeyboardEnable())) {
+ event.kbd.flags = 0;
+
+ if (getKeysChanged() & KEY_LEFT) {
+ event.kbd.keycode = SDLK_LEFT;
+ event.kbd.ascii = SDLK_LEFT;
+ event.type = getKeyEvent(KEY_LEFT);
+ }
+
+ if (getKeysChanged() & KEY_RIGHT) {
+ event.kbd.keycode = SDLK_RIGHT;
+ event.kbd.ascii = SDLK_RIGHT;
+ event.type = getKeyEvent(KEY_RIGHT);
+ }
+
+ if (getKeysChanged() & KEY_UP) {
+ event.kbd.keycode = SDLK_UP;
+ event.kbd.ascii = SDLK_UP;
+ event.type = getKeyEvent(KEY_UP);
+ }
+
+ if (getKeysChanged() & KEY_DOWN) {
+ event.kbd.keycode = SDLK_DOWN;
+ event.kbd.ascii = SDLK_DOWN;
+ event.type = getKeyEvent(KEY_DOWN);
+ }
+
+ system->addEvent(event);
+ }
- if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState())) {
+ if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
if ((getKeysDown() & KEY_A) && (!indyFightState)) {
gameScreenSwap = !gameScreenSwap;
@@ -1084,16 +1204,25 @@ void addEventsToQueue() {
if (getKeysDown() & KEY_LEFT) {
mouseMode = MOUSE_LEFT;
}
+
if (getKeysDown() & KEY_RIGHT) {
- if (currentGame->control != CONT_SCUMM_SAMNMAX) {
+ if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS)) {
mouseMode = MOUSE_RIGHT;
} else {
// If we're playing sam and max, click and release the right mouse
// button to change verb
Common::Event event;
+
+ if (currentGame->control == CONT_FUTURE_WARS) {
+ event.mouse = Common::Point(320 - 128, 200 - 128);
+ event.type = Common::EVENT_MOUSEMOVE;
+ system->addEvent(event);
+ } else {
+ event.mouse = Common::Point(getPenX(), getPenY());
+ }
+
event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
system->addEvent(event);
event.type = Common::EVENT_RBUTTONUP;
@@ -1126,14 +1255,16 @@ void addEventsToQueue() {
Common::Event event;
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
- }
if (!keyboardEnable) {
+
+ if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
+ }
+
if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN;
@@ -1179,7 +1310,7 @@ void addEventsToQueue() {
if (currentGame->control == CONT_SKY) {
- // Extra controls for Benieth a Steel Sky
+ // Extra controls for Beneath a Steel Sky
if ((getKeysDown() & KEY_DOWN)) {
penY = 0;
penX = 160; // Show inventory by moving mouse onto top line
@@ -1253,8 +1384,18 @@ void addEventsToQueue() {
if ((getKeysChanged() & KEY_START)) {
event.type = getKeyEvent(KEY_START);
- event.kbd.keycode = Common::KEYCODE_F5;
- event.kbd.ascii = Common::ASCII_F5;
+ if (currentGame->control == CONT_FUTURE_WARS) {
+ event.kbd.keycode = Common::KEYCODE_F10;
+ event.kbd.ascii = Common::ASCII_F10;
+ } else if (currentGame->control == CONT_GOBLINS) {
+ event.kbd.keycode = Common::KEYCODE_F1;
+ event.kbd.ascii = Common::ASCII_F1;
+// consolePrintf("!!!!!F1!!!!!");
+ } else {
+ event.kbd.keycode = Common::KEYCODE_F5;
+ event.kbd.ascii = Common::ASCII_F5;
+// consolePrintf("!!!!!F5!!!!!");
+ }
event.kbd.flags = 0;
system->addEvent(event);
}
@@ -1280,11 +1421,17 @@ void triggerIcon(int imageNum) {
void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) {
- sprites[num].attribute[0] = ATTR0_BMP | y | (!enable? ATTR0_DISABLED: 0);
+ sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0);
sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags;
sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
}
+void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable) {
+ spritesMain[num].attribute[0] = ATTR0_BMP | (y & 0x1FF) | (!enable? ATTR0_DISABLED: 0);
+ spritesMain[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags;
+ spritesMain[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
+}
+
void updateStatus() {
int offs;
@@ -1313,7 +1460,7 @@ void updateStatus() {
if (indyFightState) {
setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true);
- consolePrintf("%d\n", indyFightRight);
+// consolePrintf("%d\n", indyFightRight);
} else {
// setIcon(1, 0, 0, 0, 0, false);
}
@@ -1324,7 +1471,7 @@ void updateStatus() {
} else {
setIcon(4, 0, 0, 0, 0, false);
}
-
+
} else {
setIcon(0, 0, 0, 0, 0, false);
setIcon(1, 0, 0, 0, 0, false);
@@ -1334,14 +1481,16 @@ void updateStatus() {
}
if ((keyboardIcon) && (!keyboardEnable) && (!displayModeIs8Bit)) {
- spritesMain[0].attribute[0] = ATTR0_BMP | 160;
- spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0;
- spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64;
+// spritesMain[0].attribute[0] = ATTR0_BMP | 160;
+// spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0;
+// spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64;
+ setIconMain(0, 0, 160, 4, 0, true);
} else {
- spritesMain[0].attribute[0] = ATTR0_DISABLED;
- spritesMain[0].attribute[1] = 0;
- spritesMain[0].attribute[2] = 0;
- spritesMain[0].attribute[3] = 0;
+// spritesMain[0].attribute[0] = ATTR0_DISABLED;
+// spritesMain[0].attribute[1] = 0;
+// spritesMain[0].attribute[2] = 0;
+// spritesMain[0].attribute[3] = 0;
+ setIconMain(0, 0, 0, 0, 0, false);
}
}
@@ -1428,6 +1577,10 @@ void setZoomedScreenScale(int x, int y) {
}
}
+#ifdef USE_PROFILER
+void VBlankHandler(void) __attribute__ ((no_instrument_function));
+#endif
+
void VBlankHandler(void) {
// BG_PALETTE[0] = RGB15(31, 31, 31);
// if (*((int *) (0x023FFF00)) != 0xBEEFCAFE) {
@@ -1473,6 +1626,19 @@ void VBlankHandler(void) {
frameCount++;
+ if ((cursorEnable) && (mouseCursorVisible))
+ {
+ if (!keyboardEnable) {
+ storedMouseX = penX;
+ storedMouseY = penY;
+ }
+
+ setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
+ }
+ else
+ {
+ setIconMain(3, 0, 0, 0, 0, false);
+ }
if (callback) {
@@ -1563,7 +1729,7 @@ void VBlankHandler(void) {
if (zooming) {
subScX = subScTargetX;
subScY = subScTargetY;
- triggerIcon(0);
+ triggerIcon(5);
}
} else if ( ((subScreenWidth) > 128 - 8) && ((subScreenWidth) < 128 + 8) ) {
subScreenWidth = 128;
@@ -1571,7 +1737,7 @@ void VBlankHandler(void) {
if (zooming) {
subScX = subScTargetX;
subScY = subScTargetY;
- triggerIcon(1);
+ triggerIcon(6);
}
} else if (subScreenWidth > 256) {
subScreenWidth = 320;
@@ -1579,10 +1745,10 @@ void VBlankHandler(void) {
if (zooming) {
subScX = subScTargetX;
subScY = subScTargetY;
- triggerIcon(2);
+ triggerIcon(7);
}
} else {
- triggerIcon(-1);
+ //triggerIcon(-1);
}
}
@@ -1745,6 +1911,14 @@ void setTopScreenTarget(int x, int y) {
subScTargetY <<=8;
}
+#ifdef USE_PROFILER
+void hBlankHanlder() __attribute__ ((no_instrument_function));
+
+void hBlankHandler() {
+ hBlankCount++;
+}
+#endif
+
void initHardware() {
// Guard band
//((int *) (0x023FFF00)) = 0xBEEFCAFE;
@@ -1757,7 +1931,7 @@ void initHardware() {
vramSetBankB(VRAM_B_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG); */
vramSetBankI(VRAM_I_SUB_SPRITE);
- vramSetBankG(VRAM_G_MAIN_SPRITE);
+ vramSetBankE(VRAM_E_MAIN_SPRITE);
currentTimeMillis = 0;
@@ -1825,6 +1999,11 @@ void initHardware() {
irqEnable(IRQ_VBLANK);
irqEnable(IRQ_TIMER0);
irqEnable(IRQ_TIMER2);
+
+#ifdef USE_PROFILER
+ irqSet(IRQ_HBLANK, hBlankHandler);
+ irqEnable(IRQ_HBLANK);
+#endif
// Set up a millisecond timer
@@ -1847,14 +2026,22 @@ void initHardware() {
// Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit!
u8* srcTex = (u8 *) icons_raw;
- for (int r = 32 * 160 ; r >= 0; r--) {
+ for (int r = 32 * 256 ; r >= 0; r--) {
SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10);
SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10);
}
+
+
+
+
WAIT_CR &= ~(0x0080);
// REG_WRAM_CNT = 0;
+ // This is a bodge to get around the fact that the cursor is turned on before it's image is set
+ // during startup in Sam & Max. This bodge moves the cursor offscreen so it is not seen.
+ sprites[1].attribute[1] = ATTR1_SIZE_64 | 192;
+
}
@@ -2067,23 +2254,28 @@ bool getIndyFightState() {
return indyFightState;
}
+gameListType* getCurrentGame() {
+ return currentGame;
+}
+
///////////////////
// Fast Ram
///////////////////
-#define FAST_RAM_SIZE (30000)
+#define FAST_RAM_SIZE (24000)
u8* fastRamPointer;
u8 fastRamData[FAST_RAM_SIZE] ITCM_DATA;
void* fastRamAlloc(int size) {
+// return malloc(size);
void* result = (void *) fastRamPointer;
fastRamPointer += size;
return (void *) (result);
}
void fastRamReset() {
- fastRamPointer = fastRamData;
+ fastRamPointer = &fastRamData[0];
}
@@ -2308,24 +2500,34 @@ int main(void)
// }
-
+ //2372
consolePrintf("-------------------------------\n");
consolePrintf("ScummVM DS\n");
consolePrintf("Ported by Neil Millstone\n");
- FIXME: Change this code to make use of base/internal_version.h
- resp. uses gScummVMVersion from base/version.h
- consolePrintf("Version 0.10.0SVN ");
+ consolePrintf("Version 0.10.0 beta1 ");
#if defined(DS_BUILD_A)
consolePrintf("build A\n");
- consolePrintf("Supports: Lucasarts SCUMM\n");
+ consolePrintf("Lucasarts SCUMM games (SCUMM)\n");
consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_B)
consolePrintf("build B\n");
- consolePrintf("Supports: BASS, QUEEN\n");
+ consolePrintf("BASS, QUEEN\n");
consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_C)
consolePrintf("build C\n");
- consolePrintf("Supports: SIMON, KYRA, GOB\n");
+ consolePrintf("Simon the Sorcerer 1/2 (SIMON)\n");
+ consolePrintf("-------------------------------\n");
+#elif defined(DS_BUILD_D)
+ consolePrintf("build D\n");
+ consolePrintf("AGI, CINE, GOB\n");
+ consolePrintf("-------------------------------\n");
+#elif defined(DS_BUILD_E)
+ consolePrintf("build E\n");
+ consolePrintf("Inherit the earth (SAGA)\n");
+ consolePrintf("-------------------------------\n");
+#elif defined(DS_BUILD_F)
+ consolePrintf("build F\n");
+ consolePrintf("The Legend of Kyrandia (KYRA)\n");
consolePrintf("-------------------------------\n");
#endif
consolePrintf("L/R + D-pad/pen: Scroll view\n");
@@ -2333,7 +2535,7 @@ int main(void)
consolePrintf("D-pad right: Right mouse button\n");
consolePrintf("D-pad up: Hover mouse\n");
consolePrintf("B button: Skip cutscenes\n");
- consolePrintf("Select: DS Options menu\n");
+ consolePrintf("Select: DS Options menu\n");
consolePrintf("Start: Game menu (some games)\n");
consolePrintf("Y (in game): Toggle console\n");
consolePrintf("X: Toggle keyboard\n");
@@ -2457,10 +2659,13 @@ int main(void)
#elif defined(DS_BUILD_C)
char* argv[2] = {"/scummvmds", "--config=scummvmc.ini"};
#elif defined(DS_BUILD_D)
- char* argv[2] = {"/scummvmds", "--config=scummvmd.ini"};
+ char* argv[3] = {"/scummvmds", "--config=scummvmd.ini"};
+#elif defined(DS_BUILD_E)
+ char* argv[3] = {"/scummvmds", "--config=scummvme.ini"};
+#elif defined(DS_BUILD_F)
+ char* argv[3] = {"/scummvmds", "--config=scummvmf.ini"};
#endif
-
#ifdef DS_NON_SCUMM_BUILD
while (1) {
@@ -2482,3 +2687,13 @@ int main(void)
int main() {
DS::main();
}
+
+
+#ifdef USE_PROFILER
+int cygprofile_getHBlanks() __attribute__ ((no_instrument_function));
+
+
+int cygprofile_getHBlanks() {
+ return DS::hBlankCount;
+}
+#endif
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index 58a5be9240..94f02145a2 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -31,6 +31,22 @@
namespace DS {
+
+enum controlType {
+ CONT_SCUMM_ORIGINAL,
+ CONT_SCUMM_SAMNMAX,
+ CONT_SKY,
+ CONT_SIMON,
+ CONT_FUTURE_WARS,
+ CONT_AGI,
+ CONT_GOBLINS
+};
+
+struct gameListType {
+ char gameId[16];
+ controlType control;
+};
+
// Pen reading functions
void penInit();
void penUpdate();
@@ -83,7 +99,9 @@ void VBlankHandler();
// Sam and Max Stuff
void setGameID(int id);
-void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor);
+void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY);
+void setShowCursor(bool enable);
+void setMouseCursorVisible(bool visible);
// Shake
void setShakePos(int shakePos);
@@ -123,7 +141,12 @@ void fastRamReset();
void* fastRamAlloc(int size);
+gameListType* getCurrentGame();
+
+
}
+int cygprofile_getHBlanks();
+
#endif
diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp
index 171d1e044c..b29b1d9fa7 100644
--- a/backends/platform/ds/arm9/source/dsoptions.cpp
+++ b/backends/platform/ds/arm9/source/dsoptions.cpp
@@ -55,7 +55,8 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) {
_twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 20, 70, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T');
_highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 20, 85, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
_disablePowerOff = new GUI::CheckboxWidget(this, 20, 100, 250, 20, "Disable power off on quit", 0, 'T');
- _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T');
+// _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T');
+ _showCursorCheckbox = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "Show mouse cursor", 0, 'T');
new GUI::StaticTextWidget(this, 20, 130, 110, 15, "Touch X Offset", GUI::kTextAlignLeft);
_touchX = new GUI::SliderWidget(this, 130, 130, 130, 12, 1);
@@ -79,6 +80,12 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) {
_delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm);
#endif
+ if (ConfMan.hasKey("showcursor", "ds")) {
+ _showCursorCheckbox->setState(ConfMan.getBool("showcursor", "ds"));
+ } else {
+ _showCursorCheckbox->setState(false);
+ }
+
if (ConfMan.hasKey("lefthanded", "ds")) {
_leftHandedCheckbox->setState(ConfMan.getBool("lefthanded", "ds"));
} else {
@@ -108,13 +115,13 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) {
} else {
_disablePowerOff->setState(false);
}
-
+/*
if (ConfMan.hasKey("cpu_scaler", "ds")) {
_cpuScaler->setState(ConfMan.getBool("cpu_scaler", "ds"));
} else {
_cpuScaler->setState(false);
}
-
+*/
_indyFightCheckbox->setState(DS::getIndyFightState());
if (ConfMan.hasKey("xoffset", "ds")) {
@@ -137,9 +144,10 @@ DSOptionsDialog::~DSOptionsDialog() {
ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds");
ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
- ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds");
+// ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds");
ConfMan.setInt("xoffset", _touchX->getValue(), "ds");
ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
+ ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds");
DS::setOptions();
DS::setIndyFightState(_indyFightCheckbox->getState());
ConfMan.flushToDisk();
@@ -181,15 +189,27 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint
}
+void togglePause() {
+ // Toggle pause mode by simulating pressing 'p'. Not a good way of doing things!
+
+ if (getCurrentGame()->control == CONT_SCUMM_ORIGINAL) {
+ Common::Event event;
+ OSystem_DS* system = OSystem_DS::instance();
+
+ event.type = Common::EVENT_KEYDOWN;
+ event.kbd.keycode = 'p';
+ event.kbd.ascii = 'p';
+ event.kbd.flags = 0;
+ system->addEvent(event);
+
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+ }
+}
+
void showOptionsDialog() {
- OSystem_DS* system = OSystem_DS::instance();
- Common::Event event;
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = 'P'; // F5
- event.kbd.ascii = 'P';
- event.kbd.flags = 0;
- system->addEvent(event);
+ togglePause();
DS::displayMode16Bit();
@@ -201,11 +221,7 @@ void showOptionsDialog() {
DS::displayMode8Bit();
- event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = 'P'; // F5
- event.kbd.ascii = 'P';
- event.kbd.flags = 0;
- system->addEvent(event);
+ togglePause();
}
void setOptions() {
@@ -217,6 +233,12 @@ void setOptions() {
DS::setLeftHanded(false);
}
+ if (ConfMan.hasKey("showcursor", "ds")) {
+ DS::setMouseCursorVisible(ConfMan.getBool("showcursor", "ds"));
+ } else {
+ DS::setMouseCursorVisible(true);
+ }
+
if (ConfMan.hasKey("unscaled", "ds")) {
DS::setUnscaledMode(ConfMan.getBool("unscaled", "ds"));
} else {
diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h
index 8dde086f57..6976fb1a59 100644
--- a/backends/platform/ds/arm9/source/dsoptions.h
+++ b/backends/platform/ds/arm9/source/dsoptions.h
@@ -43,7 +43,7 @@ public:
protected:
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
-
+ void togglePause();
GUI::SliderWidget* _touchX;
GUI::SliderWidget* _touchY;
@@ -54,6 +54,7 @@ protected:
GUI::CheckboxWidget* _highQualityAudioCheckbox;
GUI::CheckboxWidget* _disablePowerOff;
GUI::CheckboxWidget* _cpuScaler;
+ GUI::CheckboxWidget* _showCursorCheckbox;
#ifdef DS_SCUMM_BUILD
Scumm::SaveLoadChooser* _delDialog;
diff --git a/backends/platform/ds/arm9/source/fat/disc_io.c b/backends/platform/ds/arm9/source/fat/disc_io.c
index c706cf8b3e..3cb70f510b 100644
--- a/backends/platform/ds/arm9/source/fat/disc_io.c
+++ b/backends/platform/ds/arm9/source/fat/disc_io.c
@@ -358,7 +358,7 @@ void disc_getDldiId(char* id) {
bool disc_setDsSlotInterface (void)
{
#ifdef ARM9
- REG_EXMEMCNT &= ~(1<<11);
+ REG_EXEMEMCNT &= ~(1<<11);
#endif
#ifdef ARM7
REG_EXEMEMCNT |= (1<<11);
diff --git a/backends/platform/ds/arm9/source/fat/disc_io.h b/backends/platform/ds/arm9/source/fat/disc_io.h
index 1fbcc78c19..06804afec7 100644
--- a/backends/platform/ds/arm9/source/fat/disc_io.h
+++ b/backends/platform/ds/arm9/source/fat/disc_io.h
@@ -33,7 +33,11 @@
// Disk caching is disabled on GBA to conserve memory
#define DISC_CACHE // uncomment this line to enable disc caching
+#ifdef DS_BUILD_F
+#define DISC_CACHE_COUNT 128 // maximum number of sectors to cache (512 bytes per sector)
+#else
#define DISC_CACHE_COUNT 32 // maximum number of sectors to cache (512 bytes per sector)
+#endif
//#define DISK_CACHE_DMA // use DMA for cache copies. If this is enabled, the data buffers must be word aligned
diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
index f343c4b997..b5fdd665df 100644
--- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
+++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c
@@ -1362,9 +1362,18 @@ DIR_ENT FAT_DirEntFromPath (const char* path)
DIR_ENT dirEntry;
u32 dirCluster;
bool flagLFN, dotSeen;
-
// Start at beginning of path
pathPos = 0;
+
+#ifdef DS_BUILD_F
+ // Problems with Kyrandia doing a load of path lookups are reduced by this hack.
+ if (strstr(path, ".voc") || strstr(path, ".voc"))
+ {
+ dirEntry.name[0] = FILE_FREE;
+ dirEntry.attrib = 0x00;
+ return;
+ }
+#endif
if (path[pathPos] == '/')
{
@@ -2499,6 +2508,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin)
u32 position;
u32 curPos;
+
if ((file == NULL) || (file->inUse == false)) // invalid file
{
return -1;
@@ -2613,6 +2623,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin)
}
return 0;
+
}
/*-----------------------------------------------------------------
diff --git a/backends/platform/ds/arm9/source/fat/io_dldi.h b/backends/platform/ds/arm9/source/fat/io_dldi.h
index 86c3407374..053de3a94c 100644
--- a/backends/platform/ds/arm9/source/fat/io_dldi.h
+++ b/backends/platform/ds/arm9/source/fat/io_dldi.h
@@ -30,7 +30,7 @@ extern u8 _dldi_driver_name;
static inline LPIO_INTERFACE DLDI_GetInterface(void) {
#ifdef NDS
// NDM: I'm really not sure about this change ARM9 - ARM7
- REG_EXMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD);
+ REG_EXEMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD);
#endif // defined NDS
return &_io_dldi;
}
diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp
index 7f7bf958df..0131040e1d 100644
--- a/backends/platform/ds/arm9/source/gbampsave.cpp
+++ b/backends/platform/ds/arm9/source/gbampsave.cpp
@@ -29,7 +29,7 @@
GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) {
handle = DS::std_fopen(name, saveOrLoad? "w": "r");
-// consolePrintf("%s handle is %d\n", name, handle);
+ consolePrintf("%s handle is %d\n", name, handle);
// consolePrintf("Created %s\n", name);
bufferPos = 0;
saveSize = 0;
@@ -39,6 +39,7 @@ GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) {
GBAMPSaveFile::~GBAMPSaveFile() {
flushSaveBuffer();
if (handle) DS::std_fclose(handle);
+ consolePrintf("Closed file\n");
}
uint32 GBAMPSaveFile::read(void *buf, uint32 size) {
@@ -57,7 +58,7 @@ void GBAMPSaveFile::skip(uint32 bytes) {
void GBAMPSaveFile::flushSaveBuffer() {
if (bufferPos != 0) {
- consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer);
+// consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer);
flushed += bufferPos;
DS::std_fwrite(buffer, 1, bufferPos, handle);
bufferPos = 0;
@@ -174,8 +175,10 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu
char path[128];
DS::std_cwd((char *) getSavePath());
+
+ consolePrintf("Save path: %s\n", getSavePath());
- int fileType = FAT_FindFirstFile(name);
+ int fileType = FAT_FindFirstFileLFN(name);
for (int r = 0; r < num; r++) {
marks[r] = false;
@@ -192,17 +195,17 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu
sprintf(str, "%s%02d", prefix, r);
-// consolePrintf("%s != %s", str, name);
+ consolePrintf("%s != %s", str, name);
if (!stricmp(str, name)) {
marks[r] = true;
-// consolePrintf("Matched %d", r);
+ consolePrintf("Matched %d", r);
}
}
}
- } while ((fileType = FAT_FindNextFile(name)));
+ } while ((fileType = FAT_FindNextFileLFN(name)));
FAT_chdir("/");
}
diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h
index 1580533f66..c7d9732d4c 100644
--- a/backends/platform/ds/arm9/source/gbampsave.h
+++ b/backends/platform/ds/arm9/source/gbampsave.h
@@ -37,7 +37,7 @@ class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
public:
GBAMPSaveFile(char* name, bool saveOrLoad);
- ~GBAMPSaveFile();
+ virtual ~GBAMPSaveFile();
virtual uint32 read(void *buf, uint32 size);
virtual uint32 write(const void *buf, uint32 size);
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index cad6ad6b78..32eafe1af7 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -37,6 +37,7 @@
#include "common/str.h"
#include "cdaudio.h"
#include "graphics/surface.h"
+#include "touchkeyboard.h"
OSystem_DS* OSystem_DS::_instance = NULL;
@@ -138,9 +139,12 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
green >>= 3;
blue >>= 3;
- BG_PALETTE[r] = red | (green << 5) | (blue << 10);
- if (!DS::getKeyboardEnable()) {
- BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10);
+// if (r != 255)
+ {
+ BG_PALETTE[r] = red | (green << 5) | (blue << 10);
+ if (!DS::getKeyboardEnable()) {
+ BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10);
+ }
}
// if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
@@ -173,8 +177,8 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
u16* src = (u16 *) buf;
if (DS::getKeyboardEnable()) {
- for (int dy = y; dy < y + h; dy++)
- {
+
+ for (int dy = y; dy < y + h; dy++) {
u16* dest = bg + (dy << 8) + (x >> 1);
DC_FlushRange(src, w << 1);
@@ -185,8 +189,7 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
}
} else {
- for (int dy = y; dy < y + h; dy++)
- {
+ for (int dy = y; dy < y + h; dy++) {
u16* dest1 = bg + (dy << 8) + (x >> 1);
u16* dest2 = bgSub + (dy << 8) + (x >> 1);
@@ -294,6 +297,7 @@ int16 OSystem_DS::getOverlayWidth()
bool OSystem_DS::showMouse(bool visible)
{
+ DS::setShowCursor(visible);
return true;
}
@@ -302,7 +306,7 @@ void OSystem_DS::warpMouse(int x, int y)
}
void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) {
- DS::setCursorIcon(buf, w, h, keycolor);
+ DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY);
}
void OSystem_DS::addEvent(Common::Event& e) {
@@ -323,11 +327,11 @@ bool OSystem_DS::pollEvent(Common::Event &event)
event.kbd.ascii = 0;
event.kbd.keycode = 0;
event.kbd.flags = 0;
- consolePrintf("type: %d\n", event.type);
+// consolePrintf("type: %d\n", event.type);
return false;
} else {
event = eventQueue[eventNum++];
- consolePrintf("type: %d\n", event.type);
+// consolePrintf("type: %d\n", event.type);
return true;
}
}
@@ -474,36 +478,25 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager()
}
}
-Graphics::Surface *OSystem_DS::lockScreen() {
- // For now, we create a full temporary screen surface, to which we copy the
- // the screen content. Later unlockScreen will copy everything back.
- // Not very nice nor efficient, but at least works, and is not worse
- // than in the bad old times where we used grabRawScreen + copyRectToScreen.
-
- _framebuffer.create(DS::getGameWidth(), DS::getGameHeight(), 1);
+bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
+ surf->create(DS::getGameWidth(), DS::getGameHeight(), 1);
// Ensure we copy using 16 bit quantities due to limitation of VRAM addressing
+ size_t imageStrideInBytes = DS::isCpuScalerEnabled()? DS::getGameWidth() : 512;
+ size_t imageStrideInWords = imageStrideInBytes / 2;
u16* image = (u16 *) DS::get8BitBackBuffer();
for (int y = 0; y < DS::getGameHeight(); y++)
{
- DC_FlushRange(image + (y << 8), DS::getGameWidth());
+ DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++)
{
- *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x];
+ *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x];
}
}
- return &_framebuffer;
-}
-
-void OSystem_DS::unlockScreen() {
- // Copy temp framebuffer back to screen
- copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h);
-
- // Free memory
- _framebuffer.free();
+ return true;
}
void OSystem_DS::setFocusRectangle(const Common::Rect& rect) {
@@ -515,6 +508,18 @@ void OSystem_DS::clearFocusRectangle() {
}
+void OSystem_DS::addAutoComplete(const char *word) {
+ DS::addAutoComplete((char *) word);
+}
+
+void OSystem_DS::clearAutoComplete() {
+ DS::clearAutoComplete();
+}
+
+void OSystem_DS::setCharactersEntered(int count) {
+ DS::setCharactersEntered(count);
+}
+
OSystem *OSystem_DS_create() {
return new OSystem_DS();
}
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index 58b940af2c..d943a362ca 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -41,11 +41,12 @@ class DSTimerManager : public DefaultTimerManager {
class OSystem_DS : public OSystem {
public:
+
static OSystem_DS *instance() { return _instance; }
int eventNum;
int lastPenFrame;
- Common::Event eventQueue[64];
+ Common::Event eventQueue[96];
int queuePos;
DSSaveFileManager saveManager;
@@ -53,9 +54,8 @@ public:
DSAudioMixer* _mixer;
DSTimerManager* _timer;
- Graphics::Surface _framebuffer;
-
static OSystem_DS* _instance;
+
typedef void (*SoundProc)(void *param, byte *buf, int len);
typedef int (*TimerProc)(int interval);
@@ -129,8 +129,7 @@ public:
void addEvent(Common::Event& e);
bool isEventQueueEmpty() { return queuePos == 0; }
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
+ virtual bool grabRawScreen(Graphics::Surface* surf);
virtual void setFocusRectangle(const Common::Rect& rect);
@@ -141,6 +140,14 @@ public:
virtual Audio::Mixer* getMixer() { return _mixer; }
virtual Common::TimerManager* getTimerManager() { return _timer; }
static int timerHandler(int t);
+
+
+ virtual void addAutoComplete(const char *word);
+ virtual void clearAutoComplete();
+ virtual void setCharactersEntered(int count);
+
+
+
};
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
@@ -162,9 +169,4 @@ void OSystem_DS::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b)
//consolePrintf("coltorgb\n");
}
-namespace DS
-{
-bool isCpuScalerEnabled();
-}
-
#endif
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp
index 8f7af668d8..26f03ca9d1 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.cpp
+++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp
@@ -23,6 +23,7 @@
#include "touchkeyboard.h"
#include "keyboard_raw.h"
#include "keyboard_pal_raw.h"
+#include "8x8font_tga_raw.h"
#include "dsmain.h"
#include "osystem_ds.h"
@@ -127,11 +128,22 @@ int keyboardY;
int mapBase;
int tileBase;
+u16* baseAddress;
+
bool shiftState;
bool capsLockState;
bool closed;
+char autoCompleteWord[NUM_WORDS][32];
+int autoCompleteCount;
+
+char autoCompleteBuffer[128];
+
+int selectedCompletion = -1;
+int charactersEntered = 0;
+
+
void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) {
/* for (int r = 0; r < 32 * 32; r++) {
((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++;
@@ -159,6 +171,26 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
BG_PALETTE_SUB[r] = ((u16 *) (keyboard_pal_raw))[r];
}
+ // this is the font
+ for (int tile = 0; tile < 94; tile++) {
+
+ u16* tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + (8192 + (tile * 32)));
+ u8* src = ((u8 *) (_8x8font_tga_raw)) + 18 + tile * 8;
+
+ for (int y = 0 ; y < 8; y++) {
+ for (int x = 0; x < 2; x++) {
+ *(tileAddr + (y * 2) + x) =(*(src + (y * 752) + (x * 4) + 0) & 0x0F)
+ | ((*(src + (y * 752) + (x * 4) + 1) & 0x0F) << 4)
+ | ((*(src + (y * 752) + (x * 4) + 2) & 0x0F) << 8)
+ | ((*(src + (y * 752) + (x * 4) + 3) & 0x0F) << 12);
+
+ }
+ }
+ }
+
+
+
+
for (int r = 0; r < 16; r++) {
int col = ((u16 *) (keyboard_pal_raw))[r];
@@ -167,17 +199,19 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
int blue = (col & 0x7C00) >> 10;
red = (red * 8) / 16;
- green = (green * 8) / 16;
+ green = (green * 24) / 16;
blue = (blue * 8) / 16;
+
+ if (green > 31) green = 31;
BG_PALETTE_SUB[16 + r] = red | (green << 5) | (blue << 10);
}
keyboardX = -2;
- keyboardY = 2;
+ keyboardY = 1;
- mapBase = mapBase;
- tileBase = tileBase;
+ DS::mapBase = mapBase;
+ DS::tileBase = tileBase;
shiftState = false;
capsLockState = false;
@@ -186,6 +220,7 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
int y = keyboardY;
u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase));
+ baseAddress = base;
for (int r = 0; r < DS_NUM_KEYS; r++) {
base[(y + keys[r].y) * 32 + x + keys[r].x] = keys[r].keyNum * 2;
@@ -198,6 +233,36 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) {
}
closed = false;
+ clearAutoComplete();
+}
+
+void drawAutoComplete() {
+
+ for (int y = 12; y < 24; y++) {
+ for (int x = 0; x < 32; x++) {
+ baseAddress[y * 32 + x] = 127;
+ }
+ }
+
+
+ for (int r = 0; r < autoCompleteCount; r++) {
+ int y = 12 + (r % 6) * 2;
+ int x = 0 + ((r / 6) * 16);
+
+ for (int p = 0; p < strlen(autoCompleteWord[r]); p++) {
+ char c = autoCompleteWord[r][p];
+
+ int tile = c - 32 + 255;
+
+ if (selectedCompletion == r) {
+ tile |= 0x1000;
+ }
+
+ baseAddress[y * 32 + x + p] = tile;
+
+
+ }
+ }
}
bool getKeyboardClosed() {
@@ -220,13 +285,106 @@ void setKeyHighlight(int key, bool highlight) {
}
}
+void addAutoComplete(char* word) {
+ if (autoCompleteCount == NUM_WORDS) return;
+ strcpy(&autoCompleteWord[autoCompleteCount++][0], word);
+ drawAutoComplete();
+}
+
+void setCharactersEntered(int count) {
+ charactersEntered = count;
+}
+
+void clearAutoComplete() {
+ autoCompleteCount = 0;
+ selectedCompletion = -1;
+ drawAutoComplete();
+}
+
+void typeCompletion(int current) {
+ Common::Event event;
+ OSystem_DS* system = OSystem_DS::instance();
+
+ strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]);
+ strcat(autoCompleteBuffer, " ");
+
+/* consolePrintf("Typing word: %s\n", autoCompleteWord[current]);
+
+ for (int r = charactersEntered; r < strlen(autoCompleteWord[current]); r++) {
+ event.kbd.keycode = autoCompleteWord[current][r];
+ event.kbd.ascii = autoCompleteWord[current][r];
+ event.type = Common::EVENT_KEYDOWN;
+ event.kbd.flags = 0;
+ system->addEvent(event);
+
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+ }
+
+ event.kbd.keycode = ' ';
+ event.kbd.ascii = ' ';
+
+ event.type = Common::EVENT_KEYDOWN;
+ system->addEvent(event);
+
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);*/
+}
+
+void updateTypeEvents()
+{
+ if (autoCompleteBuffer[0] != '\0')
+ {
+ Common::Event event;
+ OSystem_DS* system = OSystem_DS::instance();
+
+ event.kbd.keycode = autoCompleteBuffer[0];
+ event.kbd.ascii = autoCompleteBuffer[0];
+ event.type = Common::EVENT_KEYDOWN;
+ event.kbd.flags = 0;
+ system->addEvent(event);
+
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+
+ for (int r = 0; r < strlen(autoCompleteBuffer); r++)
+ {
+ autoCompleteBuffer[r] = autoCompleteBuffer[r + 1];
+ }
+ }
+}
+
+
void addKeyboardEvents() {
+ updateTypeEvents();
+
if (DS::getPenDown()) {
int x = IPC->touchXpx;
int y = IPC->touchYpx;
- int tx = (x >> 3) - keyboardX;
- int ty = (y >> 3) - keyboardY;
+ int tx = (x >> 3);
+ int ty = (y >> 3);
+
+ if (ty >= 12) {
+ int current = -1;
+
+ if (tx < 12) {
+ current = (ty - 12) / 2;
+ } else {
+ current = 6 + (ty - 12) / 2;
+ }
+
+ if (selectedCompletion == current) {
+ typeCompletion(current);
+ } else {
+ selectedCompletion = current;
+ }
+
+ drawAutoComplete();
+ }
+
+ tx -= keyboardX;
+ ty -= keyboardY;
// consolePrintf("x=%d y=%d\n", tx, ty);
@@ -241,8 +399,14 @@ void addKeyboardEvents() {
// Close button
DS::closed = true;
} else if ((keys[r].character >= '0') && (keys[r].character <= '9')) {
- event.kbd.ascii = keys[r].character;
- event.kbd.keycode = 0;
+
+ if (!DS::shiftState) {
+ event.kbd.ascii = keys[r].character;
+ event.kbd.keycode = 0;
+ } else {
+ event.kbd.keycode = SDLK_F1 - (keys[r].character - '1');
+ event.kbd.ascii = 0;
+ }
} else if ((keys[r].character >= 'A') && (keys[r].character <= 'Z')) {
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h
index e8f5fda37e..42051a1f11 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.h
+++ b/backends/platform/ds/arm9/source/touchkeyboard.h
@@ -25,11 +25,18 @@
namespace DS {
+static const int NUM_WORDS = 12;
+
+
void drawKeyboard(int tileBase, int mapBase, u16* saveSpace);
void restoreVRAM(int tileBase, int mapBase, u16* saveSpace);
void addKeyboardEvents();
bool getKeyboardClosed();
+void addAutoComplete(char* word);
+void clearAutoComplete();
+void setCharactersEntered(int count);
+
}
#endif
diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp
new file mode 100644
index 0000000000..a73656ea61
--- /dev/null
+++ b/backends/platform/ds/arm9/source/wordcompletion.cpp
@@ -0,0 +1,67 @@
+#include "wordcompletion.h"
+#include "engines/agi/agi.h"
+#include "osystem_ds.h"
+
+#ifndef DISABLE_AGI
+
+namespace DS {
+
+void findWordCompletions(char* input) {
+ int start = 0;
+ for (int r = strlen(input) - 1; r>0; r--) {
+ if (input[r] == ' ') {
+ start = r + 1;
+ break;
+ }
+ }
+
+ char word[32];
+ strcpy(word, &input[start]);
+
+ int fchr = word[0] - 'a';
+ int len = strlen(word);
+
+ OSystem_DS* system = (OSystem_DS *) g_system;
+ system->clearAutoComplete();
+ system->setCharactersEntered(strlen(word));
+
+ if (strlen(word) == 0) {
+ return;
+ }
+
+ uint8 *wordList = Agi::AgiEngine::getWordsData();
+ uint8 *wordListEnd = Agi::AgiEngine::getWordsData() + Agi::AgiEngine::getWordsDataSize();
+
+ /* Get the offset to the first word beginning with the
+ * right character
+ */
+ wordList += READ_BE_UINT16(wordList + 2 * fchr);
+
+ char currentWord[32];
+
+
+ while (wordList < wordListEnd) {
+ int pos = *wordList++; // Number of chars to keep from previous word
+
+ if (wordList == wordListEnd)
+ break;
+
+ char c;
+ do {
+ c = *wordList++;
+ currentWord[pos++] = (~c) & 0x7F;
+ } while ((c & 0x80) == 0); // Top bit indicates end of word
+ currentWord[pos++] = '\0';
+
+ if (!strncmp(currentWord, word, strlen(word))) {
+ system->addAutoComplete(currentWord);
+ }
+
+ wordList += 2; // Skip the two byte word id.
+
+ }
+
+}
+
+}
+#endif
diff --git a/backends/platform/ds/arm9/source/wordcompletion.h b/backends/platform/ds/arm9/source/wordcompletion.h
new file mode 100644
index 0000000000..b0d43713cc
--- /dev/null
+++ b/backends/platform/ds/arm9/source/wordcompletion.h
@@ -0,0 +1,8 @@
+
+
+
+namespace DS {
+
+extern void findWordCompletions(char* input);
+
+} \ No newline at end of file
diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp
index 59f695ebce..0c86bd97ae 100644
--- a/backends/platform/ds/arm9/source/zipreader.cpp
+++ b/backends/platform/ds/arm9/source/zipreader.cpp
@@ -31,7 +31,7 @@
ZipFile::ZipFile() {
// Locate a zip file in cartridge memory space
- consolePrintf("ZIP file check...");
+// consolePrintf("ZIP file check...");
char* p = (char *) ZF_SEARCH_START;
bool found = false;
@@ -52,9 +52,9 @@ ZipFile::ZipFile() {
}
if (_zipFile) {
- consolePrintf("Ok!\n");
+ consolePrintf("ZIP File found Ok!\n");
} else {
- consolePrintf("Not in use!\n");
+// consolePrintf("Not in use!\n");
return;
}
diff --git a/backends/platform/gp2x/build/build.sh b/backends/platform/gp2x/build/build.sh
index dc2f56cb18..1ea77f4937 100644
--- a/backends/platform/gp2x/build/build.sh
+++ b/backends/platform/gp2x/build/build.sh
@@ -10,6 +10,7 @@ export CXX=arm-open2x-linux-g++
export CC=arm-open2x-linux-gcc
export CXXFLAGS=-march=armv4t
export LDFLAGS=-static
+export ASFLAGS=-mfloat-abi=soft
cd ../../../..
diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh
index 93ae45f0e3..526742e2e7 100644
--- a/backends/platform/gp2x/build/bundle.sh
+++ b/backends/platform/gp2x/build/bundle.sh
@@ -19,6 +19,7 @@ cp ./scummvm.gpe ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ./scummvm.png ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ./README-GP2X.html ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ./README-GP2X ./scummvm-gp2x-`date '+%Y-%m-%d'`/
+cp ./mmuhack.o ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../scummvm.gp2x ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../AUTHORS ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../README ./scummvm-gp2x-`date '+%Y-%m-%d'`/
@@ -27,10 +28,22 @@ cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../gui/themes/modern.ini ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../gui/themes/modern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/
-
+cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/
echo Making Stripped GPE.
arm-open2x-linux-strip ./scummvm-gp2x-`date '+%Y-%m-%d'`/scummvm.gp2x
echo Building ZIP bundle.
-echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go.
+if [ -f /usr/bin/zip ]
+ then
+ rm ./"gp2xkernel-open2x-`date '+%Y-%m-%d'`.zip"
+ cd "scummvm-gp2x-`date '+%Y-%m-%d'`"
+ zip -r -9 "../scummvm-gp2x-`date '+%Y-%m-%d'`.zip" *
+ echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go.
+ cd ..
+ rm -R ./"scummvm-gp2x-`date '+%Y-%m-%d'`"
+ else
+ echo - /usr/bin/zip not found, ZIP bundle not created.
+ echo All included files can also be found in ./"scummvm-gp2x-`date '+%Y-%m-%d'`"
+ echo - Please use you preferred archive tool to bundle these files.
+fi
diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gp2x/build/config.sh
index 193210a1b8..f899c7665a 100644
--- a/backends/platform/gp2x/build/config.sh
+++ b/backends/platform/gp2x/build/config.sh
@@ -17,6 +17,6 @@ export DEFINES=-DNDEBUG
# Edit the configure line to suit.
cd ../../../..
-./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-mpeg2 --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6
+./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6
echo Generating config for GP2X complete. Check for errors.
diff --git a/backends/platform/gp2x/build/mmuhack.o b/backends/platform/gp2x/build/mmuhack.o
new file mode 100644
index 0000000000..475f4a54ae
--- /dev/null
+++ b/backends/platform/gp2x/build/mmuhack.o
Binary files differ
diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp
index 72b188afd2..ef39ab333e 100644
--- a/backends/platform/gp2x/events.cpp
+++ b/backends/platform/gp2x/events.cpp
@@ -72,7 +72,7 @@ static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode)
return key;
} else if (unicode) {
return unicode;
- } else if (key >= 'a' && key <= 'z' && mod & KMOD_SHIFT) {
+ } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
return key & ~0x20;
} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
return 0;
@@ -168,17 +168,10 @@ void OSystem_GP2X::handleKbdMouse() {
static byte SDLModToOSystemKeyFlags(SDLMod mod) {
byte b = 0;
-#ifdef LINUPY
- // Yopy has no ALT key, steal the SHIFT key
- // (which isn't used much anyway)
- if (mod & KMOD_SHIFT)
- b |= Common::KBD_ALT;
-#else
if (mod & KMOD_SHIFT)
b |= Common::KBD_SHIFT;
if (mod & KMOD_ALT)
b |= Common::KBD_ALT;
-#endif
if (mod & KMOD_CTRL)
b |= Common::KBD_CTRL;
@@ -246,7 +239,7 @@ void OSystem_GP2X::moveStick() {
//int GP2X_BUTTON_STATE_B = FALSE;
//int GP2X_BUTTON_STATE_Y = FALSE;
//int GP2X_BUTTON_STATE_X = FALSE;
- int GP2X_BUTTON_STATE_L = FALSE;
+ int GP2X_BUTTON_STATE_L = FALSE;
//int GP2X_BUTTON_STATE_R = FALSE;
//int GP2X_BUTTON_STATE_START = FALSE;
//int GP2X_BUTTON_STATE_SELECT = FALSE;
@@ -306,6 +299,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP)
GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed)
GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis.
+ GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games)
*/
while(SDL_PollEvent(&ev)) {
@@ -341,45 +335,13 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
break;
}
- // Ctrl-m toggles mouse capture
- //if (b == Common::KBD_CTRL && ev.key.keysym.sym == 'm') {
- // toggleMouseGrab();
- // break;
- //}
-
-//#ifdef MACOSX
-// // On Macintosh', Cmd-Q quits
-// if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') {
-// event.type = Common::EVENT_QUIT;
-// return true;
-// }
-//#elif defined(UNIX)
-// // On other unices, Control-Q quits
-// if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') {
-// event.type = Common::EVENT_QUIT;
-// return true;
-// }
-//#else
-// // Ctrl-z and Alt-X quit
-// if ((b == Common::KBD_CTRL && ev.key.keysym.sym == 'z') || (b == Common::KBD_ALT && ev.key.keysym.sym == 'x')) {
-// event.type = Common::EVENT_QUIT;
-// return true;
-// }
-//#endif
-//
-// // Ctrl-Alt-<key> will change the GFX mode
-// if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
-//
-// handleScalerHotkeys(ev.key);
-// break;
-// }
const bool event_complete = remapKey(ev,event);
if (event_complete)
return true;
event.type = Common::EVENT_KEYDOWN;
- event.kbd.keycode = ev.key.keysym.sym;
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
return true;
@@ -392,7 +354,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
return true;
event.type = Common::EVENT_KEYUP;
- event.kbd.keycode = ev.key.keysym.sym;
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
@@ -484,8 +446,15 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
}
break;
case GP2X_BUTTON_A:
+ if (GP2X_BUTTON_STATE_L == TRUE) {
+ event.type = Common::EVENT_PREDICTIVE_DIALOG;
+ } else {
event.kbd.keycode = Common::KEYCODE_PERIOD;
event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0);
+ }
+// event.kbd.keycode = Common::KEYCODE_PERIOD;
+// event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0);
+
break;
case GP2X_BUTTON_Y:
if (GP2X_BUTTON_STATE_L == TRUE) {
@@ -606,10 +575,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
axis = 0;
if ( ev.jaxis.axis == JOY_XAXIS) {
-#ifdef JOY_ANALOG
- _km.x_vel = axis/2000;
- _km.x_down_count = 0;
-#else
if (axis != 0) {
_km.x_vel = (axis > 0) ? 1:-1;
_km.x_down_count = 1;
@@ -617,7 +582,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
_km.x_vel = 0;
_km.x_down_count = 0;
}
-#endif
} else if (ev.jaxis.axis == JOY_YAXIS) {
#ifndef JOY_INVERT_Y
diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h
index 68f2fb997e..a48239222b 100644
--- a/backends/platform/gp2x/gp2x-common.h
+++ b/backends/platform/gp2x/gp2x-common.h
@@ -181,7 +181,6 @@ public:
virtual bool setGraphicsMode(int mode);
virtual int getGraphicsMode() const;
- //virtual void setWindowCaption(const char *caption);
virtual bool openCD(int drive);
virtual int getOutputSampleRate() const;
@@ -267,6 +266,9 @@ protected:
int _mode;
int _transactionMode;
bool _fullscreen;
+
+ bool _screenIsLocked;
+ Graphics::Surface _framebuffer;
/** Current video mode flags (see DF_* constants) */
uint32 _modeFlags;
@@ -382,14 +384,13 @@ protected:
/** Set the position of the virtual mouse cursor. */
void setMousePos(int x, int y);
- virtual void fillMouseEvent(Common::Event &event, int x, int y);
- //void toggleMouseGrab();
+ void fillMouseEvent(Common::Event &event, int x, int y);
- virtual void internUpdateScreen();
+ void internUpdateScreen();
- virtual void loadGFXMode();
- virtual void unloadGFXMode();
- virtual void hotswapGFXMode();
+ void loadGFXMode();
+ void unloadGFXMode();
+ void hotswapGFXMode();
void setFullscreenMode(bool enable);
void setAspectRatioCorrection(bool enable);
diff --git a/backends/platform/gp2x/gp2x-hw.cpp b/backends/platform/gp2x/gp2x-hw.cpp
index d1b6f80a1e..d322aa5d08 100644
--- a/backends/platform/gp2x/gp2x-hw.cpp
+++ b/backends/platform/gp2x/gp2x-hw.cpp
@@ -33,17 +33,20 @@
#include "gp2x-common.h"
#include "gp2x-hw.h"
+#include "gp2x-mem.h"
-// Linux includes to let us goof about with the system.
+// Linux includes to let us goof about with the system in a 'standard' way.
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second;
-static volatile unsigned short *gp2x_memregs;
+#include <sys/time.h>
+#include <unistd.h>
/* system registers */
static struct
@@ -67,19 +70,27 @@ void GP2X_device_init() {
void GP2X_device_deinit() {
// Close devices
- if (gp2x_dev[0]) close(gp2x_dev[0]);
- if (gp2x_dev[1]) close(gp2x_dev[1]);
- if (gp2x_dev[2]) close(gp2x_dev[2]);
-
- MEM_REG[0x91c>>1]=system_reg.SYSCSETREG;
- MEM_REG[0x910>>1]=system_reg.FPLLVSETREG;
- MEM_REG[0x3B40>>1]=system_reg.DUALINT920;
- MEM_REG[0x3B42>>1]=system_reg.DUALINT940;
- MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940;
- MEM_REG[0x904>>1]=system_reg.SYSCLKENREG;
- MEM_REG[0x924>>1]=dispclockdiv;
-}
+ {
+ int i;
+ for(i=0;i<8;i++)
+ {
+ if(gp2x_dev[i])
+ {
+ close(gp2x_dev[i]);
+ }
+ }
+ }
+
+ MEM_REG[0x91c>>1] = system_reg.SYSCSETREG;
+ MEM_REG[0x910>>1] = system_reg.FPLLVSETREG;
+ MEM_REG[0x3B40>>1] = system_reg.DUALINT920;
+ MEM_REG[0x3B42>>1] = system_reg.DUALINT940;
+ MEM_REG[0x3B48>>1] = system_reg.DUALCTRL940;
+ MEM_REG[0x904>>1] = system_reg.SYSCLKENREG;
+ MEM_REG[0x924>>1] = dispclockdiv;
+ unpatchMMU();
+}
// Vairous mixer level fudges.
// TODO: Clean up and merge quick hacks.
diff --git a/backends/platform/gp2x/gp2x-hw.h b/backends/platform/gp2x/gp2x-hw.h
index bb681154d7..0427698bc4 100644
--- a/backends/platform/gp2x/gp2x-hw.h
+++ b/backends/platform/gp2x/gp2x-hw.h
@@ -65,7 +65,6 @@ extern void GP2X_mixer_move_volume(int);
extern void GP2X_setCpuspeed(unsigned int cpuspeed);
extern int GP2X_getBattLevel();
-
extern void save_system_regs(void); /* save some registers */
extern void set_display_clock_div(unsigned div);
extern void set_FCLK(unsigned MHZ); /* adjust the clock frequency (in Mhz units) */
diff --git a/backends/platform/gp2x/gp2x-mem.c b/backends/platform/gp2x/gp2x-mem.c
index f129deb783..1c2c1562a8 100644
--- a/backends/platform/gp2x/gp2x-mem.c
+++ b/backends/platform/gp2x/gp2x-mem.c
@@ -39,20 +39,22 @@
#include "gp2x-mem.h"
-void InitRam (void)
-{
- if(!gp2x_dev)
- {
- gp2x_dev = open("/dev/mem", O_RDWR);
- gp2x_ram = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0x03000000);
- gp2x_memregs = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0xc0000000);
- }
-}
-
-void CloseRam (void)
-{
- if(gp2x_dev) close(gp2x_dev);
-}
+char uname[256];
+
+//void InitRam (void)
+//{
+// if(!gp2x_dev)
+// {
+// gp2x_dev = open("/dev/mem", O_RDWR);
+// gp2x_ram = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0x03000000);
+// gp2x_memregs = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0xc0000000);
+// }
+//}
+
+//void CloseRam (void)
+//{
+// if(gp2x_dev) close(gp2x_dev);
+//}
/*
****** [BEGIN] Squidge's MMU hack code ******
@@ -201,34 +203,30 @@ int hackpgtable (void)
// do this in user mode, so we have to patch the kernel to get it to run it for us in supervisor mode. We dothis
// at the moment by overwriting the sys_newuname function and then calling it.
- lseek (gp2x_dev, 0x6ec00, SEEK_SET); // fixme: We should ask the kernel for this address rather than assuming it...
- read (gp2x_dev, &oldc1, 4);
- read (gp2x_dev, &oldc2, 4);
- read (gp2x_dev, &oldc3, 4);
- read (gp2x_dev, &oldc4, 4);
-
- printf ("0:%08X %08X - %08X %08X\n", oldc1, oldc2, newc1, newc2);
-
+ lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); // fixme: We should ask the kernel for this address rather than assuming it...
+ read (gp2x_dev[2], &oldc1, 4);
+ read (gp2x_dev[2], &oldc2, 4);
+ read (gp2x_dev[2], &oldc3, 4);
+ read (gp2x_dev[2], &oldc4, 4);
+ //printf ("0:%08X %08X - %08X %08X\n", oldc1, oldc2, newc1, newc2);
+ //printf ("point1 %d\n",a);
- printf ("point1 %d\n",a);
do {
- lseek (gp2x_dev, 0x6ec00, SEEK_SET);
- a+=write (gp2x_dev, &newc1, 4);
- a+=write (gp2x_dev, &newc2, 4);
+ lseek (gp2x_dev[2], 0x6ec00, SEEK_SET);
+ a+=write (gp2x_dev[2], &newc1, 4);
+ a+=write (gp2x_dev[2], &newc2, 4);
SDL_Delay(200);
try++;
- ttb = myuname(name);
- printf ("2:%08X try %d\n", ttb,try);
+ ttb = myuname(uname);
+ //printf ("2:%08X try %d\n", ttb,try);
} while (ttb==0 && try<4);
+ lseek (gp2x_dev[2], 0x6ec00, SEEK_SET);
+ a+=write (gp2x_dev[2], &oldc1, 4);
+ a+=write (gp2x_dev[2], &oldc2, 4);
-
- lseek (gp2x_dev, 0x6ec00, SEEK_SET);
- a+=write (gp2x_dev, &oldc1, 4);
- a+=write (gp2x_dev, &oldc2, 4);
-
- printf ("2:%08X %d\n", ttb,a);
+ //printf ("2:%08X %d\n", ttb,a);
if (ttb!=0) {
@@ -243,28 +241,28 @@ int hackpgtable (void)
unsigned int tlbc3 = 0xee080f17; // mcr 15, 0, r0, cr8, cr7, 0
unsigned int tlbc4 = 0xe1a0f00e; // mov pc, lr
- lseek (gp2x_dev, 0x6ec00, SEEK_SET);
- write (gp2x_dev, &tlbc1, 4);
- write (gp2x_dev, &tlbc2, 4);
- write (gp2x_dev, &tlbc3, 4);
- write (gp2x_dev, &tlbc4, 4);
+ lseek (gp2x_dev[2], 0x6ec00, SEEK_SET);
+ write (gp2x_dev[2], &tlbc1, 4);
+ write (gp2x_dev[2], &tlbc2, 4);
+ write (gp2x_dev[2], &tlbc3, 4);
+ write (gp2x_dev[2], &tlbc4, 4);
SDL_Delay(200);
- ttx = myuname(name);
+ ttx = myuname(uname);
printf ("Return from uname: %08X\n", ttx);
- lseek (gp2x_dev, 0x6ec00, SEEK_SET);
- write (gp2x_dev, &oldc1, 4);
- write (gp2x_dev, &oldc2, 4);
- write (gp2x_dev, &oldc3, 4);
- write (gp2x_dev, &oldc4, 4);
- lseek (gp2x_dev, 0x0, SEEK_SET);
+ lseek (gp2x_dev[2], 0x6ec00, SEEK_SET);
+ write (gp2x_dev[2], &oldc1, 4);
+ write (gp2x_dev[2], &oldc2, 4);
+ write (gp2x_dev[2], &oldc3, 4);
+ write (gp2x_dev[2], &oldc4, 4);
+ lseek (gp2x_dev[2], 0x0, SEEK_SET);
return 0;
}
- lseek (gp2x_dev, 0x0, SEEK_SET);
+ lseek (gp2x_dev[2], 0x0, SEEK_SET);
return 1;
//printf ("Restored contents\n");
@@ -292,10 +290,34 @@ void SetClock (unsigned c)
gp2x_memregs[0x910>>1] = v;
}
-void MMUpatch (void)
+void patchMMU (void)
{
- volatile unsigned int *secbuf = (unsigned int *)malloc (204800);
+ //volatile unsigned int *secbuf = (unsigned int *)malloc (204800);
- // Squidge's MMU hack
- hackpgtable();
+ printf ("Reconfiguring cached memory regions...\n");
+
+ //hackpgtable();
+ //printf ("Sucess...\n");
+
+ system("/sbin/rmmod mmuhack");
+ system("/sbin/insmod -f mmuhack.o");
+
+ int mmufd = open("/dev/mmuhack", O_RDWR);
+
+ if(mmufd < 0)
+ {
+ printf ("Upper memory uncached (attempt failed, access to upper memory will be slower)...\n");
+ }
+ else
+ {
+ printf ("Upper memory cached...\n");
+ close(mmufd);
+ }
+}
+
+void unpatchMMU (void)
+{
+ printf ("Restoreing cached memory regions...\n");
+ system("/sbin/rmmod mmuhack");
+ return 1;
}
diff --git a/backends/platform/gp2x/gp2x-mem.h b/backends/platform/gp2x/gp2x-mem.h
index bf2d050623..b4df7b3a00 100644
--- a/backends/platform/gp2x/gp2x-mem.h
+++ b/backends/platform/gp2x/gp2x-mem.h
@@ -39,17 +39,20 @@ extern "C" {
// Use Squidge's MMU patch rather then myown (his is neater).
// The effect if not that great but cacheing the upper RAM is no bad thing (tm) ;).
-void InitRam (void);
-void CloseRam (void);
+//extern void InitRam (void);
+//extern void CloseRam (void);
// Set ARM920t clock frequency
-void SetClock (unsigned c);
-void MMUpatch (void);
+extern void SetClock (unsigned c);
+extern void patchMMU (void);
+extern void unpatchMMU (void);
#define SYS_CLK_FREQ 7372800
-char name[256];
-unsigned long gp2x_dev;
-volatile unsigned short *gp2x_ram, *gp2x_memregs;
+//unsigned long gp2x_dev;
+//volatile unsigned short *gp2x_ram, *gp2x_memregs;
+
+static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second;
+static volatile unsigned short *gp2x_ram, *gp2x_memregs;
#ifdef __cplusplus
}
diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp
index 42a9345762..3cf5df2e3a 100644
--- a/backends/platform/gp2x/gp2x.cpp
+++ b/backends/platform/gp2x/gp2x.cpp
@@ -60,11 +60,6 @@ static Uint32 timer_handler(Uint32 interval, void *param) {
}
int main(int argc, char *argv[]) {
-
- // Setup GP2X upper 32MB caching
- //InitRam();
- //MMUpatch();
-
extern OSystem *OSystem_GP2X_create();
g_system = OSystem_GP2X_create();
assert(g_system);
@@ -82,7 +77,7 @@ OSystem *OSystem_GP2X_create() {
void OSystem_GP2X::initBackend() {
assert(!_inited);
- ConfMan.set("joystick_num", 0);
+ ConfMan.setInt("joystick_num", 0);
int joystick_num = ConfMan.getInt("joystick_num");
uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
@@ -96,6 +91,7 @@ void OSystem_GP2X::initBackend() {
error("Could not initialize SDL: %s", SDL_GetError());
}
+ SDL_ShowCursor(SDL_DISABLE);
// Setup default save path to be workingdir/saves
#ifndef PATH_MAX
@@ -187,19 +183,10 @@ void OSystem_GP2X::initBackend() {
// enable joystick
if (joystick_num > -1 && SDL_NumJoysticks() > 0) {
- printf("Using joystick: %s\n", SDL_JoystickName(0));
+ //printf("Using joystick: %s\n", SDL_JoystickName(0));
_joystick = SDL_JoystickOpen(joystick_num);
}
- // Initialise any GP2X specific stuff we may want (Volume, Batt Status etc.)
- GP2X_device_init();
-
- // Set Default hardware mixer volume to a plesent level.
- // This is done to 'reset' volume level if set by other apps.
- GP2X_mixer_set_volume(70, 70);
-
- SDL_ShowCursor(SDL_DISABLE);
-
// Create the savefile manager, if none exists yet (we check for this to
// allow subclasses to provide their own).
if (_savefile == 0) {
@@ -225,6 +212,14 @@ void OSystem_GP2X::initBackend() {
// switch. But it's a long term goal to do just that!
_timer = new DefaultTimerManager();
_timerID = SDL_AddTimer(10, &timer_handler, _timer);
+
+ // Initialise any GP2X specific stuff we may want (Volume, Batt Status etc.)
+ GP2X_device_init();
+
+ // Set Default hardware mixer volume to a plesent level.
+ // This is done to 'reset' volume level if set by other apps.
+ GP2X_mixer_set_volume(70, 70);
+
}
OSystem::initBackend();
@@ -321,6 +316,9 @@ void OSystem_GP2X::setFeatureState(Feature f, bool enable) {
else
_modeFlags &= ~DF_WANT_RECT_OPTIM;
break;
+ case kFeatureDisableKeyFiltering:
+ // TODO: Extend as more support for this is added to engines.
+ return;
default:
break;
}
diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp
index c3ed5c627c..1aa7519f86 100644
--- a/backends/platform/gp2x/graphics.cpp
+++ b/backends/platform/gp2x/graphics.cpp
@@ -29,10 +29,10 @@
*/
#include "backends/platform/gp2x/gp2x-common.h"
-#include "graphics/scaler.h"
#include "common/util.h"
#include "graphics/font.h"
#include "graphics/fontman.h"
+#include "graphics/scaler.h"
#include "graphics/surface.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
@@ -236,17 +236,12 @@ void OSystem_GP2X::initSize(uint w, uint h){
}
void OSystem_GP2X::loadGFXMode() {
-
- //enable 320x240 image to fit the 320x240 display area (aka, disable scaling)
- //gp2x_video_RGB_setscaling(320,240);
-
assert(_inited);
_forceFull = true;
_modeFlags |= DF_UPDATE_EXPAND_1_PIXEL;
int hwW, hwH;
-#ifndef __MAEMO__
_overlayWidth = _screenWidth * _scaleFactor;
_overlayHeight = _screenHeight * _scaleFactor;
@@ -258,10 +253,6 @@ void OSystem_GP2X::loadGFXMode() {
hwW = _screenWidth * _scaleFactor;
hwH = effectiveScreenHeight();
-#else
- hwW = _overlayWidth;
- hwH = _overlayHeight;
-#endif
//
// Create the surface that contains the 8 bit game data
@@ -349,7 +340,6 @@ void OSystem_GP2X::loadGFXMode() {
_km.y_max = effectiveScreenHeight() - 1;
_km.delay_time = 25;
_km.last_time = 0;
-
}
void OSystem_GP2X::unloadGFXMode() {
@@ -691,8 +681,10 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in
assert (_transactionMode == kTransactionNone);
assert(src);
- if (_screen == NULL)
+ if (_screen == NULL) {
+ warning("OSystem_GP2X::copyRectToScreen: _screen == NULL");
return;
+ }
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
@@ -757,6 +749,19 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in
}
Graphics::Surface *OSystem_GP2X::lockScreen() {
+ assert (_transactionMode == kTransactionNone);
+
+ // Lock the graphics mutex
+ lockMutex(_graphicsMutex);
+
+ // paranoia check
+ assert(!_screenIsLocked);
+ _screenIsLocked = true;
+
+ // Try to lock the screen surface
+ if (SDL_LockSurface(_screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
_framebuffer.pixels = _screen->pixels;
_framebuffer.w = _screen->w;
_framebuffer.h = _screen->h;
@@ -767,8 +772,20 @@ Graphics::Surface *OSystem_GP2X::lockScreen() {
}
void OSystem_GP2X::unlockScreen() {
- // Force screen update
+ assert (_transactionMode == kTransactionNone);
+
+ // paranoia check
+ assert(_screenIsLocked);
+ _screenIsLocked = false;
+
+ // Unlock the screen surface
+ SDL_UnlockSurface(_screen);
+
+ // Trigger a full screen update
_forceFull = true;
+
+ // Finally unlock the graphics mutex
+ unlockMutex(_graphicsMutex);
}
void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {
@@ -818,11 +835,9 @@ void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates
h = height - y;
}
-#ifndef DISABLE_SCALERS
if (_adjustAspectRatio && !_overlayVisible && !realCoordinates) {
makeRectStretchable(x, y, w, h);
}
-#endif
if (w == width && h == height) {
_forceFull = true;
@@ -851,7 +866,7 @@ void OSystem_GP2X::makeChecksums(const byte *buf) {
/* the 8x8 blocks in buf are enumerated starting in the top left corner and
* reading each line at a time from left to right */
for (y = 0; y != last_y; y++, buf += _screenWidth * (8 - 1))
- for (x = 0; x != last_x; x++, buf += 8) { // Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
+ for (x = 0; x != last_x; x++, buf += 8) {
// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
// This computes the Adler32 checksum of a 8x8 pixel block. Note
// that we can do the modulo operation (which is the slowest part)
@@ -1165,8 +1180,6 @@ bool OSystem_GP2X::showMouse(bool visible) {
bool last = _mouseVisible;
_mouseVisible = visible;
- //updateScreen();
-
return last;
}
@@ -1174,7 +1187,6 @@ void OSystem_GP2X::setMousePos(int x, int y) {
if (x != _mouseCurState.x || y != _mouseCurState.y) {
_mouseCurState.x = x;
_mouseCurState.y = y;
- //updateScreen();
}
}
@@ -1521,7 +1533,6 @@ void OSystem_GP2X::drawMouse() {
zoomdst.h = (tmpScreenHeight);
SDL_GP2X_Display(&zoomdst);
-
};
@@ -1545,6 +1556,8 @@ void OSystem_GP2X::displayMessageOnOSD(const char *msg) {
assert (_transactionMode == kTransactionNone);
assert(msg);
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+
uint i;
// Lock the OSD surface for drawing
@@ -1696,7 +1709,5 @@ void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) {
displayMessageOnOSD(buffer);
}
}
-
}
-
}
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 32290bddea..6572166e91 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -332,6 +332,16 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) {
OSystem_PS2::~OSystem_PS2(void) {
}
+void OSystem_PS2::initBackend() {
+ // FIXME: Should probably move lots of stuff from the constructor to here
+ _mixer = new Audio::Mixer();
+ _timer = new DefaultTimerManager();
+ setSoundCallback(Audio::Mixer::mixCallback, _mixer);
+ setTimerCallback(&timer_handler, 10);
+
+ OSystem::initBackend();
+}
+
void OSystem_PS2::initTimer(void) {
// first setup the two threads that get activated by the timer:
// the timerthread and the soundthread
diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h
index b5c84d3b95..033431a6fd 100644
--- a/backends/platform/ps2/systemps2.h
+++ b/backends/platform/ps2/systemps2.h
@@ -48,6 +48,9 @@ class OSystem_PS2 : public OSystem {
public:
OSystem_PS2(const char *elfPath);
virtual ~OSystem_PS2(void);
+
+ virtual void initBackend();
+
virtual void initSize(uint width, uint height);
virtual int16 getHeight(void);
@@ -103,6 +106,8 @@ public:
virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b);
virtual Common::SaveFileManager *getSavefileManager();
+ virtual Audio::Mixer *getMixer() { return _mixer; }
+ virtual Common::TimerManager *getTimerManager() { return _timer; }
void timerThread(void);
void soundThread(void);
@@ -129,6 +134,8 @@ private:
bool _useMouse, _useKbd, _useHdd, _usbMassLoaded, _usbMassConnected;
Ps2SaveFileManager *_saveManager;
+ Audio::Mixer *_mixer;
+ Common::TimerManager *_timer;
Gs2dScreen *_screen;
Ps2Input *_input;
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index d5d3669a22..7c0932dc20 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -38,15 +38,6 @@ enum GraphicModeID {
CENTERED_362X272
};
-namespace Graphics {
- struct Surface;
-}
-
-namespace Common {
- class SaveFileManager;
- class TimerManager;
-}
-
class OSystem_PSP : public OSystem {
public:
static const OSystem::GraphicsMode s_supportedGraphicsModes[];
diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp
index 2b3c2c18fe..19fb2372df 100644
--- a/backends/platform/sdl/events.cpp
+++ b/backends/platform/sdl/events.cpp
@@ -259,7 +259,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) {
handleScalerHotkeys(ev.key);
break;
}
- const bool event_complete = remapKey(ev,event);
+ const bool event_complete = remapKey(ev, event);
if (event_complete)
return true;
@@ -445,7 +445,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) {
return false;
}
-bool OSystem_SDL::remapKey(SDL_Event &ev,Common::Event &event) {
+bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) {
#ifdef LINUPY
// On Yopy map the End button to quit
if ((ev.key.keysym.sym == 293)) {
diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile
index 0d9556e967..a4b4fa4f12 100644
--- a/backends/platform/wince/Makefile
+++ b/backends/platform/wince/Makefile
@@ -51,7 +51,7 @@ USE_ZLIB = 1
#DISABLE_HQ_SCALERS = 1
USE_ARM_SOUND_ASM = 1
-USE_ARM_SMUSH = 1
+USE_ARM_SMUSH_ASM = 1
########################################################################
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 8c9b0ffd2a..b58dd87d93 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -187,16 +187,21 @@ void DefaultSaveFileManager::listSavefiles(const char *prefix , bool *marks, int
search += '*'; //match all files that start with the given prefix
search.c_str(); //FIXME: subtle bug? removing this line will break things. Looks like the string isn't getting updated.
+ assert(marks);
memset(marks, false, num * sizeof(bool)); //assume no savegames for this title
if(savePath.lookupFile(savefiles, savePath, search, false, true)) {
char slot[2];
+ int slotNum;
for(FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); file++) {
//TODO: check if this is the behavior for all engines
//Obtain the last 2 digits of the filename, since they correspond to the save slot
slot[0] = file->getName()[file->getName().size()-2];
slot[1] = file->getName()[file->getName().size()-1];
- marks[atoi(slot)] = true; //mark this slot as valid
+
+ slotNum = atoi(slot);
+ if(slotNum >= 0 && slotNum < num)
+ marks[slotNum] = true; //mark this slot as valid
}
}
}
diff --git a/base/main.cpp b/base/main.cpp
index 85e711bce1..d8239db6e4 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -203,6 +203,9 @@ static int runGame(const Plugin *plugin, OSystem &system, const Common::String &
// the command line arugments here
Common::enableSpecialDebugLevelList(edebuglevels);
+ // Inform backend that the engine is about to be run
+ system.engineInit();
+
int result;
// Init the engine (this might change the screen parameters)
@@ -216,6 +219,9 @@ static int runGame(const Plugin *plugin, OSystem &system, const Common::String &
// TODO: Set an error flag, notify user about the problem
}
+ // Inform backend that the engine finished
+ system.engineDone();
+
// We clear all debug levels again even though the engine should do it
Common::clearAllSpecialDebugLevels();
diff --git a/common/frac.h b/common/frac.h
new file mode 100644
index 0000000000..b1e6c518d1
--- /dev/null
+++ b/common/frac.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_FRAC_H
+#define COMMON_FRAC_H
+
+#include "common/scummsys.h"
+
+/**
+ * The precision of the fractional (fixed point) type we define below.
+ * Normally you should never have to modify this value.
+ */
+enum {
+ FRAC_BITS = 16,
+ FRAC_LO_MASK = ((1L << FRAC_BITS) - 1),
+ FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS,
+
+ FRAC_ONE = (1L << FRAC_BITS), // 1.0
+ FRAC_HALF = (1L << (FRAC_BITS-1)) // 0.5
+};
+
+/**
+ * Fixed-point fractions, used by the sound rate converter and other code.
+ */
+typedef int32 frac_t;
+
+inline frac_t doubleToFrac(double value) { return (frac_t)(value * FRAC_ONE); }
+inline double fracToDouble(frac_t value) { return ((double)value) / FRAC_ONE; }
+
+inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; }
+inline int16 fracToInt(frac_t value) { return value >> FRAC_BITS; }
+
+#endif
diff --git a/common/savefile.h b/common/savefile.h
index e1a54638b5..612d6ae210 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -99,7 +99,7 @@ public:
* TODO: Or even replace it with a better API. For example, one that
* returns a list of strings for all present file names.
*/
- virtual void listSavefiles(const char * /* prefix */, bool *marks, int num) = 0;
+ virtual void listSavefiles(const char *prefix , bool *marks, int num) = 0;
/**
* Get the path to the save game directory.
diff --git a/common/scummsys.h b/common/scummsys.h
index 4cb8d5d8e9..fb81bcb25a 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -313,8 +313,10 @@
//
#if defined(__GNUC__)
#define NORETURN __attribute__((__noreturn__))
+ #define PACKED_STRUCT __attribute__((packed))
#define GCC_PRINTF(x,y) __attribute__((format(printf, x, y)))
#else
+ #define PACKED_STRUCT
#define GCC_PRINTF(x,y)
#endif
diff --git a/common/system.h b/common/system.h
index 95f970d956..79680c4655 100644
--- a/common/system.h
+++ b/common/system.h
@@ -73,6 +73,18 @@ public:
*/
virtual void initBackend() { }
+ /**
+ * Allows the backend to perform engine specific init.
+ * Called just before the engine is run.
+ */
+ virtual void engineInit() { }
+
+ /**
+ * Allows the backend to perform engine specific de-init.
+ * Called after the engine finishes.
+ */
+ virtual void engineDone() { }
+
/** @name Feature flags */
//@{
@@ -587,11 +599,6 @@ public:
*/
virtual int16 getOverlayWidth() { return getWidth(); }
- virtual int screenToOverlayX(int x) { return x; }
- virtual int screenToOverlayY(int y) { return y; }
- virtual int overlayToScreenX(int x) { return x; }
- virtual int overlayToScreenY(int y) { return y; }
-
/**
* Convert the given RGB triplet into an OverlayColor. A OverlayColor can
* be 8bit, 16bit or 32bit, depending on the target system. The default
diff --git a/configure b/configure
index 8419ee642f..85e4343e11 100755
--- a/configure
+++ b/configure
@@ -63,11 +63,15 @@ _build_agi=yes
_build_touche=yes
_build_parallaction=yes
_build_cruise=no
+_build_hq_scalers=yes
+_build_scalers=yes
+
+_endian=unknown
_need_memalign=no
+_have_x86=no
_build_plugins=no
_nasm=auto
-_build_hq_scalers=yes
-_build_scalers=yes
+
# more defaults
_backend=sdl
_ranlib=ranlib
@@ -89,7 +93,6 @@ _nasmpath="$PATH"
NASMFLAGS=""
NASM=""
_prefix=/usr/local
-_have_x86=""
_srcdir=`dirname $0`
@@ -105,9 +108,6 @@ _host_cpu=""
_host_vendor=""
_host_os=""
-# config.h defaults
-_def_linupy="#undef LINUPY"
-
cc_check() {
echo >> "$TMPLOG"
cat "$TMPC" >> "$TMPLOG"
@@ -124,20 +124,47 @@ echocheck () {
echo_n "Checking for $@... "
}
-# Add a boolean flag to config.mk. Takes two parameters:
-# The first one can be set to 'yes' to "comment out" the flag,
-# i.e. make it ineffective, use 'no' otherwise.
-# The second param is the name of the flag to set.
-#
-# For now the variable is always set to 1, but we could add
-# another parameter for that...
-add_flag_to_config_mk_if_no() {
+# Add a line of data to config.mk.
+add_line_to_config_mk() {
+ _config_mk_data="$_config_mk_data"'
+'"$1"
+}
+
+# Add a line of data to h.mk.
+add_line_to_config_h() {
+ _config_h_data="$_config_h_data"'
+'"$1"
+}
+
+add_to_config_h_if_yes() {
+ if test "$1" = yes ; then
+ add_line_to_config_h "$2"
+ else
+ add_line_to_config_h "/* $2 */"
+ fi
+}
+
+# Conditionally add a line of data to config.mk. Takes two parameters:
+# The first one can be set to 'no' to "comment out" the line, i.e.
+# make it ineffective, use 'yes' otherwise.
+# The second param is the line to insert.
+add_to_config_mk_if_yes() {
+ if test "$1" = yes ; then
+ add_line_to_config_mk "$2"
+ else
+ add_line_to_config_mk "# $2"
+ fi
+}
+
+# Conditionally add a line of data to config.mk. Takes two parameters:
+# The first one can be set to 'yes' to "comment out" the line, i.e.
+# make it ineffective, use 'no' otherwise.
+# The second param is the line to insert.
+add_to_config_mk_if_no() {
if test "$1" = no ; then
- _config_mk_data="$_config_mk_data"'
-'"$2 = 1"
+ add_line_to_config_mk "$2"
else
- _config_mk_data="$_config_mk_data"'
-'"# $2 = 1"
+ add_line_to_config_mk "# $2"
fi
}
@@ -680,31 +707,31 @@ if test "$_cxx_major" -ge "3" ; then
CXXFLAGS="$CXXFLAGS -ansi -W -Wno-unused-parameter"
;;
esac
- add_flag_to_config_mk_if_no no 'HAVE_GCC3'
+ add_line_to_config_mk 'HAVE_GCC3 = 1'
fi;
#
# Engine selection
#
-add_flag_to_config_mk_if_no $_build_scumm 'DISABLE_SCUMM'
-add_flag_to_config_mk_if_no $_build_scumm_7_8 'DISABLE_SCUMM_7_8'
-add_flag_to_config_mk_if_no $_build_he 'DISABLE_HE'
-add_flag_to_config_mk_if_no $_build_agos 'DISABLE_AGOS'
-add_flag_to_config_mk_if_no $_build_sky 'DISABLE_SKY'
-add_flag_to_config_mk_if_no $_build_sword1 'DISABLE_SWORD1'
-add_flag_to_config_mk_if_no $_build_sword2 'DISABLE_SWORD2'
-add_flag_to_config_mk_if_no $_build_queen 'DISABLE_QUEEN'
-add_flag_to_config_mk_if_no $_build_kyra 'DISABLE_KYRA'
-add_flag_to_config_mk_if_no $_build_saga 'DISABLE_SAGA'
-add_flag_to_config_mk_if_no $_build_gob 'DISABLE_GOB'
-add_flag_to_config_mk_if_no $_build_lure 'DISABLE_LURE'
-add_flag_to_config_mk_if_no $_build_cine 'DISABLE_CINE'
-add_flag_to_config_mk_if_no $_build_agi 'DISABLE_AGI'
-add_flag_to_config_mk_if_no $_build_touche 'DISABLE_TOUCHE'
-add_flag_to_config_mk_if_no $_build_parallaction 'DISABLE_PARALLACTION'
-add_flag_to_config_mk_if_no $_build_cruise 'DISABLE_CRUISE'
-add_flag_to_config_mk_if_no $_build_hq_scalers 'DISABLE_HQ_SCALERS'
-add_flag_to_config_mk_if_no $_build_scalers 'DISABLE_SCALERS'
+add_to_config_mk_if_no $_build_scumm 'DISABLE_SCUMM = 1'
+add_to_config_mk_if_no $_build_scumm_7_8 'DISABLE_SCUMM_7_8 = 1'
+add_to_config_mk_if_no $_build_he 'DISABLE_HE = 1'
+add_to_config_mk_if_no $_build_agos 'DISABLE_AGOS = 1'
+add_to_config_mk_if_no $_build_sky 'DISABLE_SKY = 1'
+add_to_config_mk_if_no $_build_sword1 'DISABLE_SWORD1 = 1'
+add_to_config_mk_if_no $_build_sword2 'DISABLE_SWORD2 = 1'
+add_to_config_mk_if_no $_build_queen 'DISABLE_QUEEN = 1'
+add_to_config_mk_if_no $_build_kyra 'DISABLE_KYRA = 1'
+add_to_config_mk_if_no $_build_saga 'DISABLE_SAGA = 1'
+add_to_config_mk_if_no $_build_gob 'DISABLE_GOB = 1'
+add_to_config_mk_if_no $_build_lure 'DISABLE_LURE = 1'
+add_to_config_mk_if_no $_build_cine 'DISABLE_CINE = 1'
+add_to_config_mk_if_no $_build_agi 'DISABLE_AGI = 1'
+add_to_config_mk_if_no $_build_touche 'DISABLE_TOUCHE = 1'
+add_to_config_mk_if_no $_build_parallaction 'DISABLE_PARALLACTION = 1'
+add_to_config_mk_if_no $_build_cruise 'DISABLE_CRUISE = 1'
+add_to_config_mk_if_no $_build_hq_scalers 'DISABLE_HQ_SCALERS = 1'
+add_to_config_mk_if_no $_build_scalers 'DISABLE_SCALERS = 1'
if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
@@ -712,39 +739,43 @@ if test -n "$_host"; then
linupy|arm-riscos)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
DEFINES="$DEFINES -DUNIX"
- _def_endianness='#define SCUMM_LITTLE_ENDIAN'
- _def_align='#define SCUMM_NEED_ALIGNMENT'
- _def_linupy="#define DLINUPY"
+ _endian=little
+ _need_memalign=yes
+ add_line_to_config_h "#define LINUPY"
type_1_byte='char'
type_2_byte='short'
type_4_byte='int'
;;
arm-linux|arm-linux-gnueabi|arm-*-linux-gnueabi)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
- DEFINES="$DEFINES -DUNIX -DUSE_ARM_SOUND_ASM"
+ DEFINES="$DEFINES -DUNIX -DUSE_ARM_SOUND_ASM -DUSE_ARM_SMUSH_ASM"
#not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen
- _def_endianness='#define SCUMM_LITTLE_ENDIAN'
- _def_align='#define SCUMM_NEED_ALIGNMENT'
+ _endian=little
+ _need_memalign=yes
type_1_byte='char'
type_2_byte='short'
type_4_byte='int'
+ add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
;;
gp2x)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
- DEFINES="$DEFINES -DUNIX -DGP2X -DUSE_ARM_SOUND_ASM"
- _def_endianness='#define SCUMM_LITTLE_ENDIAN'
- _def_align='#define SCUMM_NEED_ALIGNMENT'
+ DEFINES="$DEFINES -DUNIX -DGP2X -DUSE_ARM_SOUND_ASM -DUSE_ARM_SMUSH_ASM"
+ _endian=little
+ _need_memalign=yes
type_1_byte='char'
type_2_byte='short'
type_4_byte='int'
+ add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
+ add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
_backend="gp2x"
_mak_hq_scalers='DISABLE_HQ_SCALERS = 1'
_build_hq_scalers="no"
;;
ppc-amigaos)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
- _def_endianness='#define SCUMM_BIG_ENDIAN'
- _def_align='#define SCUMM_NEED_ALIGNMENT'
+ _endian=big
+ _need_memalign=yes
type_1_byte='char'
type_2_byte='short'
type_4_byte='long'
@@ -754,8 +785,8 @@ if test -n "$_host"; then
m68k-atari-mint)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
- _def_endianness='#define SCUMM_BIG_ENDIAN'
- _def_align='#define SCUMM_NEED_ALIGNMENT'
+ _endian=big
+ _need_memalign=yes
type_1_byte='char'
type_2_byte='short'
type_4_byte='long'
@@ -765,9 +796,7 @@ if test -n "$_host"; then
i586-mingw32msvc)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
DEFINES="$DEFINES -DWIN32"
- _def_x86='#define HAVE_X86'
- _def_endianness='#define SCUMM_LITTLE_ENDIAN'
- _def_align='#undef SCUMM_NEED_ALIGNMENT'
+ _endian=little
_have_x86=yes
type_1_byte='char'
type_2_byte='short'
@@ -851,19 +880,8 @@ int main(int argc, char **argv)
}
EOF
$CXX $CXXFLAGS -o tmp_endianness_check$EXEEXT tmp_endianness_check.cpp
- endianness=`./tmp_endianness_check`
- echo $endianness;
- case $endianness in
- big)
- _def_endianness='#define SCUMM_BIG_ENDIAN'
- ;;
- little)
- _def_endianness='#define SCUMM_LITTLE_ENDIAN'
- ;;
- *)
- exit 1
- ;;
- esac
+ _endian=`./tmp_endianness_check`
+ echo $_endian;
rm -f tmp_endianness_check$EXEEXT tmp_endianness_check.cpp
#
@@ -878,12 +896,6 @@ EOF
_have_x86=no
;;
esac
-
- if test "$_have_x86" = yes ; then
- _def_x86='#define HAVE_X86'
- else
- _def_x86='#undef HAVE_X86'
- fi
echo "$_have_x86"
#
@@ -931,12 +943,6 @@ EOF
cc_check && $TMPO && _need_memalign=no
;;
esac
-
- if test "$_need_memalign" = yes ; then
- _def_align='#define SCUMM_NEED_ALIGNMENT'
- else
- _def_align='#undef SCUMM_NEED_ALIGNMENT'
- fi
echo "$_need_memalign"
#
@@ -963,12 +969,34 @@ EOF
fi
#
+# Add the results of the above checks to config.h
+#
+case $_endian in
+ big)
+ add_line_to_config_h '/* #define SCUMM_LITTLE_ENDIAN */'
+ add_line_to_config_h '#define SCUMM_BIG_ENDIAN'
+ ;;
+ little)
+ add_line_to_config_h '#define SCUMM_LITTLE_ENDIAN'
+ add_line_to_config_h '/* #define SCUMM_BIG_ENDIAN */'
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+
+add_to_config_h_if_yes $_have_x86 '#define HAVE_X86'
+
+add_to_config_h_if_yes $_need_memalign '#define SCUMM_NEED_ALIGNMENT'
+
+
+#
# Check whether plugin support is requested and possible
#
echo_n "Checking whether building plugins was requested... "
echo "$_build_plugins"
_mak_plugins=
-_def_plugin=
+_def_plugin="/* -> plugins disabled */"
if test "$_build_plugins" = yes ; then
echo_n "Checking whether building plugins is supported... "
@@ -1056,10 +1084,10 @@ fi
#
if test "$_mt32emu" = no ; then
_def_mt32emu='#undef USE_MT32EMU'
- add_flag_to_config_mk_if_no yes 'USE_MT32EMU'
+ add_to_config_mk_if_no yes 'USE_MT32EMU = 1'
else
_def_mt32emu='#define USE_MT32EMU'
- add_flag_to_config_mk_if_no no 'USE_MT32EMU'
+ add_to_config_mk_if_no no 'USE_MT32EMU = 1'
fi
#
@@ -1079,10 +1107,10 @@ if test "$_vorbis" = yes ; then
_def_vorbis='#define USE_VORBIS'
LIBS="$LIBS $OGG_LIBS $VORBIS_LIBS -lvorbisfile -lvorbis -logg"
INCLUDES="$INCLUDES $OGG_CFLAGS $VORBIS_CFLAGS"
- add_flag_to_config_mk_if_no no 'USE_VORBIS'
+ add_to_config_mk_if_no no 'USE_VORBIS = 1'
else
_def_vorbis='#undef USE_VORBIS'
- add_flag_to_config_mk_if_no yes 'USE_VORBIS'
+ add_to_config_mk_if_no yes 'USE_VORBIS = 1'
fi
echo "$_vorbis"
@@ -1104,13 +1132,13 @@ if test "$_tremor" = yes && test "$_vorbis" = no; then
_def_vorbis='#define USE_VORBIS'
LIBS="$LIBS $TREMOR_LIBS -lvorbisidec"
INCLUDES="$INCLUDES $TREMOR_CFLAGS"
- add_flag_to_config_mk_if_no no 'USE_TREMOR'
+ add_to_config_mk_if_no no 'USE_TREMOR = 1'
else
if test "$_vorbis" = yes; then
_tremor="no (Ogg Vorbis/Tremor support is mutually exclusive)"
fi
_def_tremor='#undef USE_TREMOR'
- add_flag_to_config_mk_if_no yes 'USE_TREMOR'
+ add_to_config_mk_if_no yes 'USE_TREMOR = 1'
fi
echo "$_tremor"
@@ -1131,10 +1159,10 @@ if test "$_flac" = yes ; then
_def_flac='#define USE_FLAC'
LIBS="$LIBS $FLAC_LIBS $OGG_LIBS -lFLAC -logg"
INCLUDES="$INCLUDES $FLAC_CFLAGS"
- add_flag_to_config_mk_if_no no 'USE_FLAC'
+ add_to_config_mk_if_no no 'USE_FLAC = 1'
else
_def_flac='#undef USE_FLAC'
- add_flag_to_config_mk_if_no yes 'USE_FLAC'
+ add_to_config_mk_if_no yes 'USE_FLAC = 1'
fi
echo "$_flac"
@@ -1154,10 +1182,10 @@ if test "$_mad" = yes ; then
_def_mad='#define USE_MAD'
LIBS="$LIBS $MAD_LIBS -lmad"
INCLUDES="$INCLUDES $MAD_CFLAGS"
- add_flag_to_config_mk_if_no no 'USE_MAD'
+ add_to_config_mk_if_no no 'USE_MAD = 1'
else
_def_mad='#undef USE_MAD'
- add_flag_to_config_mk_if_no yes 'USE_MAD'
+ add_to_config_mk_if_no yes 'USE_MAD = 1'
fi
echo "$_mad"
@@ -1243,10 +1271,10 @@ if test "$_mpeg2" = yes ; then
_def_mpeg2='#define USE_MPEG2'
INCLUDES="$INCLUDES $MPEG2_CFLAGS"
LIBS="$LIBS $MPEG2_LIBS -lmpeg2"
- add_flag_to_config_mk_if_no no 'USE_MPEG2'
+ add_to_config_mk_if_no no 'USE_MPEG2 = 1'
else
_def_mpeg2='#undef USE_MPEG2'
- add_flag_to_config_mk_if_no yes 'USE_MPEG2'
+ add_to_config_mk_if_no yes 'USE_MPEG2 = 1'
fi
echo "$_mpeg2"
rm -f $TMPC $TMPO$EXEEXT
@@ -1280,13 +1308,8 @@ if test "$_have_x86" = yes ; then
CheckNASM
fi
-if test "$_nasm" = yes ; then
- _def_nasm='#define USE_NASM'
- add_flag_to_config_mk_if_no no 'HAVE_NASM'
-else
- _def_nasm='#undef USE_NASM'
- add_flag_to_config_mk_if_no yes 'HAVE_NASM'
-fi
+add_to_config_h_if_yes $_nasm '#define USE_NASM'
+add_to_config_mk_if_yes $_nasm 'HAVE_NASM = 1'
#
# figure out installation directories
@@ -1429,11 +1452,7 @@ cat > config.h << EOF
#ifndef CONFIG_H
#define CONFIG_H
-$_def_endianness
-$_def_align
-$_def_x86
-
-$_def_linupy
+$_config_h_data
/* Data types */
typedef unsigned $type_1_byte byte;
@@ -1456,9 +1475,6 @@ $_def_mpeg2
$_def_fluidsynth
$_def_mt32emu
-/* Whether we should use i386 assembly routines */
-$_def_nasm
-
/* Plugin settings */
$_def_plugin
diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj
index 2f59d57b18..9c41118229 100644
--- a/dists/msvc8/scummvm.vcproj
+++ b/dists/msvc8/scummvm.vcproj
@@ -299,6 +299,10 @@
>
</File>
<File
+ RelativePath="..\..\common\frac.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\fs.cpp"
>
</File>
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 74795271fc..0839b7de99 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -334,7 +334,7 @@ void AgiEngine::replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
case ADD_PIC:
debugC(8, kDebugLevelMain, "--- decoding picture %d ---", p1);
agiLoadResource(rPICTURE, p1);
- _picture->decodePicture(p1, p2);
+ _picture->decodePicture(p1, p2, p3 != 0);
break;
case ADD_VIEW:
agiLoadResource(rVIEW, p1);
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 56ae1288b8..01db2acb23 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -247,6 +247,18 @@ enum {
};
/**
+ * Different monitor types.
+ * Used with AGI variable 26 i.e. vMonitor.
+ */
+enum AgiMonitorType {
+ kAgiMonitorCga = 0,
+ // kAgiMonitorTandy = 1, // Not sure about this
+ kAgiMonitorHercules = 2,
+ kAgiMonitorEga = 3
+ // kAgiMonitorVga = 4 // Not sure about this
+};
+
+/**
* AGI flags
*/
enum {
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 22d2582021..bd8fcb0394 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -367,7 +367,26 @@ int AgiEngine::runGame() {
setvar(vComputer, 0); /* IBM PC (4 = Atari ST) */
setvar(vSoundgen, 1); /* IBM PC SOUND */
- setvar(vMonitor, 0x3); /* EGA monitor */
+
+ // Set monitor type (v26 i.e. vMonitor)
+ switch (_renderMode) {
+ case Common::kRenderCGA:
+ setvar(vMonitor, kAgiMonitorCga);
+ break;
+ case Common::kRenderHercG:
+ case Common::kRenderHercA:
+ setvar(vMonitor, kAgiMonitorHercules);
+ break;
+ // Don't know if Amiga AGI games use a different value than kAgiMonitorEga
+ // for vMonitor so I just use kAgiMonitorEga for them (As was done before too).
+ case Common::kRenderAmiga:
+ case Common::kRenderDefault:
+ case Common::kRenderEGA:
+ default:
+ setvar(vMonitor, kAgiMonitorEga);
+ break;
+ }
+
setvar(vMaxInputChars, 38);
_game.inputMode = INPUT_NONE;
_game.inputEnabled = 0;
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 2d64a4352e..54f1783d83 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -624,8 +624,7 @@ int GfxMgr::keypress() {
/**
* Initialize the color palette
* This function initializes the color palette using the specified 16-color
- * RGB palette and creates 16 extra palette entries with translucent colors
- * for the interpreter console.
+ * RGB palette.
* @param p A pointer to the 16-color RGB palette.
*/
void GfxMgr::initPalette(uint8 *p) {
@@ -633,7 +632,6 @@ void GfxMgr::initPalette(uint8 *p) {
for (i = 0; i < 48; i++) {
_palette[i] = p[i];
- _palette[i + 48] = (p[i] + 0x30) >> 2;
}
}
@@ -642,13 +640,13 @@ void GfxMgr::gfxSetPalette() {
byte pal[256 * 4];
if (!(_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < 16; i++) {
pal[i * 4 + 0] = _palette[i * 3 + 0] << 2;
pal[i * 4 + 1] = _palette[i * 3 + 1] << 2;
pal[i * 4 + 2] = _palette[i * 3 + 2] << 2;
pal[i * 4 + 3] = 0;
}
- g_system->setPalette(pal, 0, 32);
+ g_system->setPalette(pal, 0, 16);
} else {
for (i = 0; i < 256; i++) {
pal[i * 4 + 0] = vgaPalette[i * 3 + 0];
@@ -715,19 +713,107 @@ void GfxMgr::gfxPutBlock(int x1, int y1, int x2, int y2) {
g_system->copyRectToScreen(_screen + y1 * 320 + x1, 320, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
}
-static const byte mouseCursorArrow[] = {
- // This is the same arrow cursor that was later used in early SCI games
- 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00,
- 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00,
- 0x7F, 0x80, 0x7F, 0xC0, 0x7C, 0x00, 0x46, 0x00,
- 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80,
- 0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00,
- 0x84, 0x00, 0x82, 0x00, 0x81, 0x00, 0x80, 0x80,
- 0x80, 0x40, 0x80, 0x20, 0x82, 0x00, 0xA9, 0x00,
- 0xC9, 0x00, 0x04, 0x80, 0x04, 0x80, 0x02, 0x40
+/**
+ * A black and white SCI-style arrow cursor (11x16).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = White (#FFFFFF in 24-bit RGB).
+ */
+static const byte sciMouseCursor[] = {
+ 1,1,0,0,0,0,0,0,0,0,0,
+ 1,2,1,0,0,0,0,0,0,0,0,
+ 1,2,2,1,0,0,0,0,0,0,0,
+ 1,2,2,2,1,0,0,0,0,0,0,
+ 1,2,2,2,2,1,0,0,0,0,0,
+ 1,2,2,2,2,2,1,0,0,0,0,
+ 1,2,2,2,2,2,2,1,0,0,0,
+ 1,2,2,2,2,2,2,2,1,0,0,
+ 1,2,2,2,2,2,2,2,2,1,0,
+ 1,2,2,2,2,2,2,2,2,2,1,
+ 1,2,2,2,2,2,1,0,0,0,0,
+ 1,2,1,0,1,2,2,1,0,0,0,
+ 1,1,0,0,1,2,2,1,0,0,0,
+ 0,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,0,1,2,2,1,0
+};
+
+/**
+ * RGBA-palette for the black and white SCI-style arrow cursor.
+ */
+static const byte sciMouseCursorPalette[] = {
+ 0x00, 0x00, 0x00, 0x00, // Black
+ 0xFF, 0xFF, 0xFF, 0x00 // White
+};
+
+/**
+ * An Amiga-style arrow cursor (8x11).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = Red (#DE2021 in 24-bit RGB).
+ * 3 = Light red (#FFCFAD in 24-bit RGB).
+ */
+static const byte amigaMouseCursor[] = {
+ 2,3,1,0,0,0,0,0,
+ 2,2,3,1,0,0,0,0,
+ 2,2,2,3,1,0,0,0,
+ 2,2,2,2,3,1,0,0,
+ 2,2,2,2,2,3,1,0,
+ 2,2,2,2,2,2,3,1,
+ 2,0,2,2,3,1,0,0,
+ 0,0,0,2,3,1,0,0,
+ 0,0,0,2,2,3,1,0,
+ 0,0,0,0,2,3,1,0,
+ 0,0,0,0,2,2,3,1
+};
+
+/**
+ * RGBA-palette for the Amiga-style arrow cursor
+ * and the Amiga-style busy cursor.
+ */
+static const byte amigaMouseCursorPalette[] = {
+ 0x00, 0x00, 0x00, 0x00, // Black
+ 0xDE, 0x20, 0x21, 0x00, // Red
+ 0xFF, 0xCF, 0xAD, 0x00 // Light red
};
/**
+ * An Amiga-style busy cursor showing an hourglass (13x16).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = Red (#DE2021 in 24-bit RGB).
+ * 3 = Light red (#FFCFAD in 24-bit RGB).
+ */
+static const byte busyAmigaMouseCursor[] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,1,
+ 0,1,3,3,3,3,3,3,3,3,3,1,0,
+ 0,0,1,3,3,3,3,3,3,3,1,0,0,
+ 0,0,0,1,3,3,3,3,3,1,0,0,0,
+ 0,0,0,0,1,3,3,3,1,0,0,0,0,
+ 0,0,0,0,0,1,3,1,0,0,0,0,0,
+ 0,0,0,0,0,1,3,1,0,0,0,0,0,
+ 0,0,0,0,1,2,3,2,1,0,0,0,0,
+ 0,0,0,1,2,2,3,2,2,1,0,0,0,
+ 0,0,1,2,2,2,3,2,2,2,1,0,0,
+ 0,1,2,2,2,3,3,3,2,2,2,1,0,
+ 1,3,3,3,3,3,3,3,3,3,3,3,1,
+ 1,3,3,3,3,3,3,3,3,3,3,3,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+void GfxMgr::setCursor(bool amigaStyleCursor) {
+ if (!amigaStyleCursor) {
+ CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4);
+ CursorMan.replaceCursor(sciMouseCursor, 11, 16, 1, 1, 0);
+ } else { // amigaStyleCursor
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ CursorMan.replaceCursor(amigaMouseCursor, 8, 11, 1, 1, 0);
+ }
+}
+
+/**
* Initialize graphics device.
*
* @see deinit_video()
@@ -743,31 +829,7 @@ int GfxMgr::initVideo() {
gfxSetPalette();
- byte mouseCursor[16 * 16];
- const byte *src = mouseCursorArrow;
- for (int i = 0; i < 32; ++i) {
- int offs = i * 8;
- for (byte mask = 0x80; mask != 0; mask >>= 1) {
- if (src[0] & mask) {
- mouseCursor[offs] = 2;
- } else if (src[32] & mask) {
- mouseCursor[offs] = 0;
- } else {
- mouseCursor[offs] = 0xFF;
- }
- ++offs;
- }
- ++src;
- }
-
- const byte cursorPalette[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 255, 255, 255, 0
- };
-
- CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
- CursorMan.replaceCursor(mouseCursor, 16, 16, 1, 1);
+ setCursor(_vm->_renderMode == Common::kRenderAmiga);
return errOK;
}
@@ -804,23 +866,26 @@ int GfxMgr::deinitMachine() {
* @param x x coordinate of the row start (AGI coord.)
* @param y y coordinate of the row start (AGI coord.)
* @param n number of pixels in the row
- * @param p pointer to the row start in the AGI screen
+ * @param p pointer to the row start in the AGI screen (Always use sbuf16c as base, not sbuf256c)
+ * FIXME: CGA rendering doesn't work correctly with AGI256 or AGI256-2.
*/
void GfxMgr::putPixelsA(int x, int y, int n, uint8 *p) {
+ const uint rShift = _vm->_debug.priority ? 4 : 0; // Priority information is in the top 4 bits of a byte taken from sbuf16c.
+
+ // Choose the correct screen to read from. If AGI256 or AGI256-2 is used and we're not trying to show the priority information,
+ // then choose the 256 color screen, otherwise choose the 16 color screen (Which also has the priority information).
+ p += _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? FROM_SBUF16_TO_SBUF256_OFFSET : 0;
+
if (_vm->_renderMode == Common::kRenderCGA) {
for (x *= 2; n--; p++, x += 2) {
register uint16 q = (cgaMap[(*p & 0xf0) >> 4] << 4) | cgaMap[*p & 0x0f];
- if (_vm->_debug.priority)
- q >>= 4;
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & 0x0f0f;
+ *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & 0x0f0f;
}
} else {
- const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) ? 0xffff : 0x0f0f;
+ const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? 0xffff : 0x0f0f;
for (x *= 2; n--; p++, x += 2) {
register uint16 q = ((uint16) * p << 8) | *p;
- if (_vm->_debug.priority)
- q >>= 4;
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & mask;
+ *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & mask;
}
}
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index cdbae8d6e6..b1f9c0e1d7 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -41,7 +41,7 @@ class GfxMgr {
private:
AgiEngine *_vm;
- uint8 _palette[32 * 3];
+ uint8 _palette[16 * 3];
uint8 *_agiScreen;
unsigned char *_screen;
@@ -87,6 +87,7 @@ public:
void putPixel(int, int, int);
void putBlock(int x1, int y1, int x2, int y2);
void gfxSetPalette();
+ void setCursor(bool amigaStyleCursor = false);
int keypress();
int getKey();
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 17865e1f3a..3acc81ddff 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -29,6 +29,9 @@
#include "agi/graphics.h"
#include "agi/keyboard.h"
#include "agi/menu.h"
+#ifdef __DS__
+#include "wordcompletion.h"
+#endif
namespace Agi {
@@ -308,6 +311,9 @@ void AgiEngine::handleKeys(int key) {
debugC(3, kDebugLevelInput, "clear lines");
clearLines(l, l + 1, bg);
flushLines(l, l + 1);
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
break;
case KEY_ESCAPE:
@@ -324,6 +330,10 @@ void AgiEngine::handleKeys(int key) {
_game.inputBuffer[--_game.cursorPos] = 0;
/* Print cursor */
_gfx->printCharacter(_game.cursorPos + 1, l, _game.cursorChar, fg, bg);
+
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
break;
default:
/* Ignore invalid keystrokes */
@@ -337,6 +347,10 @@ void AgiEngine::handleKeys(int key) {
_game.inputBuffer[_game.cursorPos++] = key;
_game.inputBuffer[_game.cursorPos] = 0;
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
+
/* echo */
_gfx->printCharacter(_game.cursorPos, l, _game.inputBuffer[_game.cursorPos - 1], fg, bg);
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index c51514f237..588ee1dd30 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -153,6 +153,18 @@ cmd(toggle_v) {
cmd(new_room) {
g_agi->newRoom(p0);
+
+ // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush.
+ // Intro was skipped because the enter-keypress finalizing the entering
+ // of the copy protection string (Copy protection is in logic.128) was
+ // left over to the intro scene (Starts with room 73 i.e. logic.073).
+ // The intro scene checks for any keys pressed and if it finds any it
+ // jumps to the game's start (Room 1 i.e. logic.001). We clear the
+ // keyboard buffer when the intro sequence's first room (Room 73) is
+ // loaded so that no keys from the copy protection scene can be left
+ // over to cause the intro to skip to the game's start.
+ if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73)
+ game.keypress = 0;
}
cmd(new_room_f) {
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index cd8ef83de0..144e965465 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -652,7 +652,7 @@ int PictureMgr::decodePicture(int n, int clear, bool agi256) {
if (clear)
_vm->clearImageStack();
- _vm->recordImageStackCall(ADD_PIC, n, clear, 0, 0, 0, 0, 0);
+ _vm->recordImageStackCall(ADD_PIC, n, clear, agi256, 0, 0, 0, 0);
return errOK;
}
@@ -686,7 +686,7 @@ void PictureMgr::showPic() {
i = 0;
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (y = 0; y < _HEIGHT; y++) {
- _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf[i]);
+ _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf16c[i]);
i += _WIDTH;
}
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index ab5f818d17..9144dae96c 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -519,41 +519,48 @@ int AgiEngine::selectSlot() {
_gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
AllowSyntheticEvents on(this);
+ int oldFirstSlot = _firstSlot + 1;
+ int oldActive = active + 1;
for (;;) {
- char dstr[64];
- for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
- sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]);
- printText(dstr, 0, hm + 1, vm + 4 + i,
- (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
- i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
- }
+ int sbPos;
- char upArrow[] = "^";
- char downArrow[] = "v";
- char scrollBar[] = " ";
+ if (oldFirstSlot != _firstSlot || oldActive != active) {
+ char dstr[64];
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
+ sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]);
+ printText(dstr, 0, hm + 1, vm + 4 + i,
+ (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
+ i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
+ }
- int sbPos;
+ char upArrow[] = "^";
+ char downArrow[] = "v";
+ char scrollBar[] = " ";
+
+ // Use the extreme scrollbar positions only if the
+ // extreme slots are in sight.
+
+ if (_firstSlot == 0)
+ sbPos = 1;
+ else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS)
+ sbPos = NUM_VISIBLE_SLOTS - 2;
+ else {
+ sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1);
+ if (sbPos >= NUM_VISIBLE_SLOTS - 3)
+ sbPos = NUM_VISIBLE_SLOTS - 3;
+ }
- // Use the extreme scrollbar positions only if the extreme
- // slots are in sight.
-
- if (_firstSlot == 0)
- sbPos = 1;
- else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS)
- sbPos = NUM_VISIBLE_SLOTS - 2;
- else {
- sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1);
- if (sbPos >= NUM_VISIBLE_SLOTS - 3)
- sbPos = NUM_VISIBLE_SLOTS - 3;
- }
+ for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
+ printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
- for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
- printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
+ printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
+ printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
+ printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
- printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
- printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
- printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
+ oldActive = active;
+ oldFirstSlot = _firstSlot;
+ }
_gfx->pollTimer(); /* msdos driver -> does nothing */
key = doPollKeyboard();
diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp
index 3d69968075..006e3dddee 100644
--- a/engines/agi/sprite.cpp
+++ b/engines/agi/sprite.cpp
@@ -215,7 +215,8 @@ void SpritesMgr::objsRestoreArea(Sprite *s) {
int y, offset;
int16 xPos = s->xPos, yPos = s->yPos;
int16 xSize = s->xSize, ySize = s->ySize;
- uint8 *p0, *q;
+ uint8 *q;
+ uint32 pos0;
if (xPos + xSize > _WIDTH)
xSize = _WIDTH - xPos;
@@ -236,14 +237,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) {
if (xSize <= 0 || ySize <= 0)
return;
- p0 = &_vm->_game.sbuf[xPos + yPos * _WIDTH];
+ pos0 = xPos + yPos * _WIDTH;
q = s->buffer;
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (y = 0; y < ySize; y++) {
- memcpy(p0, q, xSize);
- _gfx->putPixelsA(xPos, yPos + y + offset, xSize, p0);
+ memcpy(&_vm->_game.sbuf[pos0], q, xSize);
+ _gfx->putPixelsA(xPos, yPos + y + offset, xSize, &_vm->_game.sbuf16c[pos0]);
q += xSize;
- p0 += _WIDTH;
+ pos0 += _WIDTH;
}
}
@@ -728,7 +729,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) {
debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2);
w = x2 - x1 + 1;
- q = &_vm->_game.sbuf[x1 + _WIDTH * y1];
+ q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1];
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (i = y1; i <= y2; i++) {
_gfx->putPixelsA(x1, i + offset, w, q);
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 5fc3c3bca9..ed33b9463a 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -88,7 +88,7 @@ void AgiEngine::unloadWords() {
* Uses an algorithm hopefully like the one Sierra used. Returns the ID
* of the word and the length in flen. Returns -1 if not found.
*
- * Thomas Åkesson, November 2001
+ * Thomas Akesson, November 2001
*/
int AgiEngine::findWord(char *word, int *flen) {
int mchr = 0; /* matched chars */
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index c98257f028..ae7f692c3f 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -110,8 +110,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_debugger = 0;
- _keyPressed = 0;
-
_gameFile = 0;
_opcode = 0;
@@ -746,10 +744,12 @@ void AGOSEngine_Simon2::setupGame() {
_tableIndexBase = 1580 / 4;
_textIndexBase = 1500 / 4;
_numVideoOpcodes = 75;
-#ifndef PALMOS_68K
- _vgaMemSize = 2000000;
-#else
+#if defined(__DS__)
+ _vgaMemSize = 1300000;
+#elif defined(PALMOS_68K)
_vgaMemSize = gVars->memory[kMemSimon2Games];
+#else
+ _vgaMemSize = 2000000;
#endif
_itemMemSize = 20000;
_tableMemSize = 100000;
@@ -958,8 +958,8 @@ GUI::Debugger *AGOSEngine::getDebugger() {
}
void AGOSEngine::pause() {
- _keyPressed = 1;
- _pause = 1;
+ _keyPressed.reset();
+ _pause = true;
bool ambient_status = _ambientPaused;
bool music_status = _musicPaused;
@@ -969,8 +969,8 @@ void AGOSEngine::pause() {
while (_pause) {
delay(1);
- if (_keyPressed == 'p')
- _pause = 0;
+ if (_keyPressed.keycode == Common::KEYCODE_p)
+ _pause = false;
}
_midi.pause(music_status);
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index e487c38cc7..d233d0bfeb 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -28,6 +28,7 @@
#include "engines/engine.h"
+#include "common/keyboard.h"
#include "common/rect.h"
#include "common/util.h"
@@ -216,7 +217,7 @@ protected:
const GameSpecificSettings *gss;
- byte _keyPressed;
+ Common::KeyState _keyPressed;
Common::File *_gameFile;
@@ -875,8 +876,8 @@ public:
void vc36_setWindowImage();
void vc38_ifVarNotZero();
void vc39_setVar();
- void vc40();
- void vc41();
+ void vc40_scrollRight();
+ void vc41_scrollLeft();
void vc42_delayIfNotEQ();
// Video Script Opcodes, Elvira 1
@@ -1316,7 +1317,9 @@ public:
void oe2_moveDirn();
void oe2_doClass();
void oe2_pObj();
+ void oe2_isCalled();
void oe2_loadGame();
+ void oe2_menu();
void oe2_drawItem();
void oe2_doTable();
void oe2_pauseGame();
@@ -1410,7 +1413,6 @@ public:
void oww_setLongText();
void oww_printLongText();
void oww_whereTo();
- void oww_menu();
void oww_textMenu();
void oww_pauseGame();
void oww_boxMessage();
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 8748cff54e..8d5238259d 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -130,8 +130,11 @@ void MoviePlayer::play() {
return;
}
- if (!_fd) {
- return;
+ if (_omniTVFile) {
+ // Clear any paused OmniTV video
+ _mixer->stopHandle(_omniTVSound);
+ delete _omniTVFile;
+ _omniTVFile = 0;
}
_leftButtonDown = false;
diff --git a/engines/agos/contain.cpp b/engines/agos/contain.cpp
index b5ca344905..891ac36d30 100644
--- a/engines/agos/contain.cpp
+++ b/engines/agos/contain.cpp
@@ -34,8 +34,8 @@ int AGOSEngine::canPlace(Item *x, Item *y) {
Item *z = derefItem(x->parent);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(y, 3);
- SubContainer *c = (SubContainer *)findChildOfType(y, 7);
+ SubPlayer *p = (SubPlayer *)findChildOfType(y, kPlayerType);
+ SubContainer *c = (SubContainer *)findChildOfType(y, kContainerType);
int cap = 0;
int wt;
@@ -59,7 +59,7 @@ int AGOSEngine::canPlace(Item *x, Item *y) {
return -2; /* Too heavy */
}
} else {
- SubObject *o = (SubObject *)findChildOfType(y, 2);
+ SubObject *o = (SubObject *)findChildOfType(y, kObjectType);
int ct;
int cap = 0;
@@ -120,11 +120,11 @@ int AGOSEngine::sizeRec(Item *x, int d) {
}
int AGOSEngine::sizeOfRec(Item *i, int d) {
- SubObject *o = (SubObject *)findChildOfType(i, 2);
+ SubObject *o = (SubObject *)findChildOfType(i, kObjectType);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(i, 3);
- SubContainer *c = (SubContainer *)findChildOfType(i, 7);
+ SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType);
+ SubContainer *c = (SubContainer *)findChildOfType(i, kContainerType);
if ((c) && (c->flags & 1)) {
if (o)
@@ -174,10 +174,10 @@ int AGOSEngine::weightRec(Item *x, int d) {
}
int AGOSEngine::weightOf(Item *x) {
- SubObject *o = (SubObject *)findChildOfType(x, 2);
+ SubObject *o = (SubObject *)findChildOfType(x, kObjectType);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(x, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(x, kPlayerType);
if (o)
return o->objectWeight;
if (p)
diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp
index ce50460621..3fc5a1f967 100644
--- a/engines/agos/debugger.cpp
+++ b/engines/agos/debugger.cpp
@@ -174,7 +174,7 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) {
prop = atoi(argv[2]);
if (obj >= 1 && obj < _vm->_itemArraySize) {
- SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), 2);
+ SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), kObjectType);
if (o != NULL) {
if (o->objectFlags & (1 << prop) && prop < 16) {
uint offs = _vm->getOffsetOfChild2Param(o, 1 << prop);
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index cb6123dc54..5efcaa3b86 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -426,7 +426,7 @@ static const AGOSGameDescription gameDescriptions[] = {
{ "gamepc", GAME_BASEFILE, "4bf28ab00f5324fd938e632595742382", -1},
{ "icon.dat", GAME_ICONFILE, "83a7278bff55c82fbb3aef92981866c9", -1},
{ "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1},
- { "start", GAME_RESTFILE, "4d380a35ba941d03ee5084c71d20055b", -1},
+ { "start", GAME_RESTFILE, "016107aced82d0cc5d758a9fba716270", -1},
{ "stripped.txt", GAME_STRFILE, "c3a8f644551a27c8a2fec0f8070b46b7", -1},
{ "tbllist", GAME_TBLFILE, "8252660df0edbdbc3e6377e155bbd0c5", -1},
{ NULL, 0, NULL, 0}
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index 32329f34d9..5c673de700 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -500,10 +500,7 @@ void AGOSEngine::delay(uint amount) {
}
// Make sure backspace works right (this fixes a small issue on OS X)
- if (event.kbd.keycode == Common::KEYCODE_BACKSPACE)
- _keyPressed = 8;
- else
- _keyPressed = (byte)event.kbd.ascii;
+ _keyPressed = event.kbd;
break;
case Common::EVENT_MOUSEMOVE:
break;
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index ef0791dc10..0f1c234b79 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -195,7 +195,8 @@ void AGOSEngine::waitForInput() {
_dragAccept = 1;
for (;;) {
- if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && _keyPressed == 35)
+ if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
+ _keyPressed.keycode == Common::KEYCODE_HASH)
displayBoxStars();
if (processSpecialKeys()) {
if ((getGameType() == GType_PP && getGameId() != GID_DIMP) ||
@@ -238,7 +239,6 @@ void AGOSEngine::waitForInput() {
_dragMode = 0;
_dragCount = 0;
_dragEnd = 0;
- continue;
}
} while (!_dragEnd);
@@ -472,39 +472,39 @@ bool AGOSEngine::processSpecialKeys() {
}
}
- switch (_keyPressed) {
- case 17: // Up
+ switch (_keyPressed.keycode) {
+ case Common::KEYCODE_UP:
if (getGameType() == GType_PP)
_verbHitArea = 302;
else if (getGameType() == GType_WW)
_verbHitArea = 239;
verbCode = true;
break;
- case 18: // Down
+ case Common::KEYCODE_DOWN:
if (getGameType() == GType_PP)
_verbHitArea = 304;
else if (getGameType() == GType_WW)
_verbHitArea = 241;
verbCode = true;
break;
- case 19: // Right
+ case Common::KEYCODE_RIGHT:
if (getGameType() == GType_PP)
_verbHitArea = 303;
else if (getGameType() == GType_WW)
_verbHitArea = 240;
verbCode = true;
break;
- case 20: // Left
+ case Common::KEYCODE_LEFT:
if (getGameType() == GType_PP)
_verbHitArea = 301;
else if (getGameType() == GType_WW)
_verbHitArea = 242;
verbCode = true;
break;
- case 27: // escape
+ case Common::KEYCODE_ESCAPE:
_exitCutscene = true;
break;
- case 59: // F1
+ case Common::KEYCODE_F1:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 50);
vcWriteVar(86, 0);
@@ -513,7 +513,7 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 0);
}
break;
- case 60: // F2
+ case Common::KEYCODE_F2:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 75);
vcWriteVar(86, 1);
@@ -522,7 +522,7 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 1);
}
break;
- case 61: // F3
+ case Common::KEYCODE_F3:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 125);
vcWriteVar(86, 2);
@@ -531,19 +531,19 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 2);
}
break;
- case 63: // F5
+ case Common::KEYCODE_F5:
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF)
_exitCutscene = true;
break;
- case 65: // F7
+ case Common::KEYCODE_F7:
if (getGameType() == GType_FF && getBitFlag(76))
_variableArray[254] = 70;
break;
- case 67: // F9
+ case Common::KEYCODE_F9:
if (getGameType() == GType_FF)
setBitFlag(73, !getBitFlag(73));
break;
- case 37: // F12
+ case Common::KEYCODE_F12:
if (getGameType() == GType_PP && getGameId() != GID_DIMP) {
if (!getBitFlag(110)) {
setBitFlag(107, !getBitFlag(107));
@@ -551,73 +551,77 @@ bool AGOSEngine::processSpecialKeys() {
}
}
break;
- case 'p':
+ case Common::KEYCODE_p:
pause();
break;
- case 't':
+ case Common::KEYCODE_t:
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) ||
((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) {
if (_speech)
_subtitles ^= 1;
}
break;
- case 'v':
+ case Common::KEYCODE_v:
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) {
if (_subtitles)
_speech ^= 1;
}
- case '+':
+ case Common::KEYCODE_PLUS:
+ case Common::KEYCODE_KP_PLUS:
if (_midiEnabled) {
_midi.setVolume(_midi.getVolume() + 16);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16);
break;
- case '-':
+ case Common::KEYCODE_MINUS:
+ case Common::KEYCODE_KP_MINUS:
if (_midiEnabled) {
_midi.setVolume(_midi.getVolume() - 16);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16);
break;
- case 'm':
+ case Common::KEYCODE_m:
_musicPaused ^= 1;
if (_midiEnabled) {
_midi.pause(_musicPaused);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (_musicPaused) ? 0 : ConfMan.getInt("music_volume"));
break;
- case 's':
+ case Common::KEYCODE_s:
if (getGameId() == GID_SIMON1DOS) {
_midi._enable_sfx ^= 1;
} else {
_sound->effectsPause(_effectsPaused ^= 1);
}
break;
- case 'b':
+ case Common::KEYCODE_b:
_sound->ambientPause(_ambientPaused ^= 1);
break;
- case 'r':
+ case Common::KEYCODE_r:
if (_debugMode)
_startMainScript ^= 1;
break;
- case 'o':
+ case Common::KEYCODE_o:
if (_debugMode)
_continousMainScript ^= 1;
break;
- case 'a':
+ case Common::KEYCODE_a:
if (_debugMode)
_startVgaScript ^= 1;
break;
- case 'g':
+ case Common::KEYCODE_g:
if (_debugMode)
_continousVgaScript ^= 1;
break;
- case 'd':
+ case Common::KEYCODE_d:
if (_debugMode)
_dumpImages ^=1;
break;
+ default:
+ break;
}
- _keyPressed = 0;
+ _keyPressed.reset();
return verbCode;
}
diff --git a/engines/agos/intern.h b/engines/agos/intern.h
index a863dc7c0f..44d38fbeed 100644
--- a/engines/agos/intern.h
+++ b/engines/agos/intern.h
@@ -28,6 +28,20 @@
namespace AGOS {
+enum ChildType {
+ kRoomType = 1,
+ kObjectType = 2,
+ kPlayerType = 3,
+ kGenExitType = 4, // Elvira 1 specific
+ kSuperRoomType = 4, // Elvira 2 specific
+
+ kContainerType = 7,
+ kChainType = 8,
+ kUserFlagType = 9,
+
+ kInheritType = 255
+};
+
struct Child {
Child *next;
uint16 type;
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp
index a911bee5a5..9a46b6e8ac 100644
--- a/engines/agos/items.cpp
+++ b/engines/agos/items.cpp
@@ -66,7 +66,7 @@ bool AGOSEngine::hasIcon(Item *item) {
if (getGameType() == GType_ELVIRA1) {
return (getUserFlag(item, 7) != 0);
} else {
- SubObject *child = (SubObject *)findChildOfType(item, 2);
+ SubObject *child = (SubObject *)findChildOfType(item, kObjectType);
return (child && (child->objectFlags & kOFIcon) != 0);
}
}
@@ -75,7 +75,7 @@ uint AGOSEngine::itemGetIconNumber(Item *item) {
if (getGameType() == GType_ELVIRA1) {
return getUserFlag(item, 7);
} else {
- SubObject *child = (SubObject *)findChildOfType(item, 2);
+ SubObject *child = (SubObject *)findChildOfType(item, kObjectType);
uint offs;
if (child == NULL || !(child->objectFlags & kOFIcon))
@@ -97,7 +97,7 @@ void AGOSEngine::createPlayer() {
_currentPlayer->adjective = -1;
_currentPlayer->noun = 10000;
- p = (SubPlayer *)allocateChildBlock(_currentPlayer, 3, sizeof(SubPlayer));
+ p = (SubPlayer *)allocateChildBlock(_currentPlayer, kPlayerType, sizeof(SubPlayer));
if (p == NULL)
error("createPlayer: player create failure");
@@ -135,14 +135,14 @@ Child *AGOSEngine::findChildOfType(Item *i, uint type) {
int AGOSEngine::getUserFlag(Item *item, int a) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
if (a < 0 || a > 7)
return 0;
- return subUserFlag->userFlags[a];
+ return subUserFlag->userFlags[a];
}
int AGOSEngine::getUserFlag1(Item *item, int a) {
@@ -151,7 +151,7 @@ int AGOSEngine::getUserFlag1(Item *item, int a) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return -1;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
@@ -164,9 +164,9 @@ int AGOSEngine::getUserFlag1(Item *item, int a) {
void AGOSEngine::setUserFlag(Item *item, int a, int b) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL) {
- subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
+ subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag));
}
if (a < 0 || a > 7)
@@ -178,7 +178,7 @@ void AGOSEngine::setUserFlag(Item *item, int a, int b) {
int AGOSEngine::getUserItem(Item *item, int n) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
@@ -191,9 +191,9 @@ int AGOSEngine::getUserItem(Item *item, int n) {
void AGOSEngine::setUserItem(Item *item, int n, int m) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL) {
- subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
+ subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag));
}
if (n == 0)
@@ -201,15 +201,15 @@ void AGOSEngine::setUserItem(Item *item, int n, int m) {
}
bool AGOSEngine::isRoom(Item *item) {
- return findChildOfType(item, 1) != NULL;
+ return findChildOfType(item, kRoomType) != NULL;
}
bool AGOSEngine::isObject(Item *item) {
- return findChildOfType(item, 2) != NULL;
+ return findChildOfType(item, kObjectType) != NULL;
}
bool AGOSEngine::isPlayer(Item *item) {
- return findChildOfType(item, 3) != NULL;
+ return findChildOfType(item, kPlayerType) != NULL;
}
uint AGOSEngine::getOffsetOfChild2Param(SubObject *child, uint prop) {
diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp
index 6dd1a356d8..81df34c311 100644
--- a/engines/agos/menus.cpp
+++ b/engines/agos/menus.cpp
@@ -199,7 +199,7 @@ uint AGOSEngine::menuFor_e2(Item *item) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return 0xFFFF;
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFMenu) {
uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
return subObject->objectFlagValue[offs];
@@ -216,7 +216,7 @@ uint AGOSEngine::menuFor_ww(Item *item, uint id) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return _agosMenu;
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFMenu) {
uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
return subObject->objectFlagValue[offs];
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 787596a966..c7ad0ee8b7 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -464,37 +464,37 @@ void AGOSEngine_Feeble::saveUserGame(int slot) {
windowPutChar(window, 0x7f);
for (;;) {
- _keyPressed = 0;
+ _keyPressed.reset();
delay(1);
- if (_keyPressed == 0 || _keyPressed >= 127)
+ if (_keyPressed.ascii == 0 || _keyPressed.ascii >= 127)
continue;
window->textColumn -= getFeebleFontSize(127);
name[len] = 0;
windowBackSpace(_windowArray[3]);
- if (_keyPressed == 27) {
- _variableArray[55] = _keyPressed;
+ if (_keyPressed.keycode == Common::KEYCODE_ESCAPE) {
+ _variableArray[55] = 27;
break;
}
- if (_keyPressed == 10 || _keyPressed == 13) {
+ if (_keyPressed.keycode == Common::KEYCODE_KP_ENTER || _keyPressed.keycode == Common::KEYCODE_RETURN) {
if (!saveGame(readVariable(55), name))
_variableArray[55] = (int16)0xFFFF;
else
_variableArray[55] = 0;
break;
}
- if (_keyPressed == 8 && len != 0) {
+ if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && len != 0) {
len--;
byte chr = name[len];
window->textColumn -= getFeebleFontSize(chr);
name[len] = 0;
windowBackSpace(_windowArray[3]);
}
- if (_keyPressed >= 32 && window->textColumn + 26 <= window->width) {
- name[len++] = _keyPressed;
- windowPutChar(_windowArray[3], _keyPressed);
+ if (_keyPressed.ascii >= 32 && window->textColumn + 26 <= window->width) {
+ name[len++] = _keyPressed.ascii;
+ windowPutChar(_windowArray[3], _keyPressed.ascii);
}
windowPutChar(window, 0x7f);
diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp
index 394c4956ae..4898cc9a45 100644
--- a/engines/agos/res.cpp
+++ b/engines/agos/res.cpp
@@ -350,13 +350,13 @@ void AGOSEngine::readItemFromGamePc(Common::SeekableReadStream *in, Item *item)
}
void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) {
- if (type == 1) {
- SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, 1, sizeof(SubRoom));
+ if (type == kRoomType) {
+ SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, sizeof(SubRoom));
subRoom->roomShort = in->readUint32BE();
subRoom->roomLong = in->readUint32BE();
subRoom->flags = in->readUint16BE();
- } else if (type == 2) {
- SubObject *subObject = (SubObject *)allocateChildBlock(item, 2, sizeof(SubObject));
+ } else if (type == kObjectType) {
+ SubObject *subObject = (SubObject *)allocateChildBlock(item, kObjectType, sizeof(SubObject));
in->readUint32BE();
in->readUint32BE();
in->readUint32BE();
@@ -364,8 +364,8 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
subObject->objectSize = in->readUint16BE();
subObject->objectWeight = in->readUint16BE();
subObject->objectFlags = in->readUint16BE();
- } else if (type == 4) {
- SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, 4, sizeof(SubGenExit));
+ } else if (type == kGenExitType) {
+ SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, kGenExitType, sizeof(SubGenExit));
genExit->dest[0] = (uint16)fileReadItemID(in);
genExit->dest[1] = (uint16)fileReadItemID(in);
genExit->dest[2] = (uint16)fileReadItemID(in);
@@ -378,14 +378,14 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
- } else if (type == 7) {
- SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer));
+ } else if (type == kContainerType) {
+ SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer));
container->volume = in->readUint16BE();
container->flags = in->readUint16BE();
- } else if (type == 8) {
- SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain));
+ } else if (type == kChainType) {
+ SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain));
chain->chChained = (uint16)fileReadItemID(in);
- } else if (type == 9) {
+ } else if (type == kUserFlagType) {
setUserFlag(item, 0, in->readUint16BE());
setUserFlag(item, 1, in->readUint16BE());
setUserFlag(item, 2, in->readUint16BE());
@@ -394,13 +394,13 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
setUserFlag(item, 5, in->readUint16BE());
setUserFlag(item, 6, in->readUint16BE());
setUserFlag(item, 7, in->readUint16BE());
- SubUserFlag *subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
subUserFlag->userItems[0] = (uint16)fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
- } else if (type == 255) {
- SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit));
+ } else if (type == kInheritType) {
+ SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit));
inherit->inMaster = (uint16)fileReadItemID(in);
} else {
error("readItemChildren: invalid type %d", type);
@@ -408,7 +408,7 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
}
void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) {
- if (type == 1) {
+ if (type == kRoomType) {
uint fr1 = in->readUint16BE();
uint fr2 = in->readUint16BE();
uint i, size;
@@ -420,14 +420,14 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (j & 3)
size += sizeof(subRoom->roomExit[0]);
- subRoom = (SubRoom *)allocateChildBlock(item, 1, size);
+ subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, size);
subRoom->subroutine_id = fr1;
subRoom->roomExitStates = fr2;
for (i = k = 0, j = fr2; i != 6; i++, j >>= 2)
if (j & 3)
subRoom->roomExit[k++] = (uint16)fileReadItemID(in);
- } else if (type == 2) {
+ } else if (type == kObjectType) {
uint32 fr = in->readUint32BE();
uint i, k, size;
SubObject *subObject;
@@ -437,7 +437,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (fr & (1 << i))
size += sizeof(subObject->objectFlagValue[0]);
- subObject = (SubObject *)allocateChildBlock(item, 2, size);
+ subObject = (SubObject *)allocateChildBlock(item, kObjectType, size);
subObject->objectFlags = fr;
k = 0;
@@ -450,7 +450,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (getGameType() != GType_ELVIRA2)
subObject->objectName = (uint16)in->readUint32BE();
- } else if (type == 4) {
+ } else if (type == kSuperRoomType) {
assert(getGameType() == GType_ELVIRA2);
uint i, j, k, size;
@@ -467,7 +467,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
for (i = 0; i != j; i++)
size += sizeof(subSuperRoom->roomExitStates[0]);
- subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, 4, size);
+ subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, kSuperRoomType, size);
subSuperRoom->subroutine_id = id;
subSuperRoom->roomX = x;
subSuperRoom->roomY = y;
@@ -475,20 +475,20 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
for (i = k = 0; i != j; i++)
subSuperRoom->roomExitStates[k++] = in->readUint16BE();
- } else if (type == 7) {
- SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer));
+ } else if (type == kContainerType) {
+ SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer));
container->volume = in->readUint16BE();
container->flags = in->readUint16BE();
- } else if (type == 8) {
- SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain));
+ } else if (type == kChainType) {
+ SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain));
chain->chChained = (uint16)fileReadItemID(in);
- } else if (type == 9) {
+ } else if (type == kUserFlagType) {
setUserFlag(item, 0, in->readUint16BE());
setUserFlag(item, 1, in->readUint16BE());
setUserFlag(item, 2, in->readUint16BE());
setUserFlag(item, 3, in->readUint16BE());
- } else if (type == 255) {
- SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit));
+ } else if (type == kInheritType) {
+ SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit));
inherit->inMaster = (uint16)fileReadItemID(in);
} else {
error("readItemChildren: invalid type %d", type);
diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp
index af1bd0fe93..5e612080df 100644
--- a/engines/agos/rooms.cpp
+++ b/engines/agos/rooms.cpp
@@ -49,7 +49,7 @@ uint16 AGOSEngine::getDoorState(Item *item, uint16 d) {
uint16 mask = 3;
uint16 n;
- SubRoom *subRoom = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
if (subRoom == NULL)
return 0;
@@ -66,7 +66,7 @@ uint16 AGOSEngine::getExitOf(Item *item, uint16 d) {
uint16 x;
uint16 y = 0;
- subRoom = (SubRoom *)findChildOfType(item, 1);
+ subRoom = (SubRoom *)findChildOfType(item, kRoomType);
if (subRoom == NULL)
return 0;
x = d;
@@ -93,7 +93,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
uint16 d1;
uint16 y = 0;
- r = (SubRoom *)findChildOfType(i, 1);
+ r = (SubRoom *)findChildOfType(i, kRoomType);
if (r == NULL)
return;
d1 = d;
@@ -107,7 +107,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
j = derefItem(r->roomExit[d1]);
if (j == NULL)
return;
- r1 = (SubRoom *)findChildOfType(j, 1);
+ r1 = (SubRoom *)findChildOfType(j, kRoomType);
if (r1 == NULL)
return;
d = getBackExit(d);
@@ -130,7 +130,7 @@ Item *AGOSEngine::getDoorOf(Item *i, uint16 d) {
SubGenExit *g;
Item *x;
- g = (SubGenExit *)findChildOfType(i, 4);
+ g = (SubGenExit *)findChildOfType(i, kGenExitType);
if (g == NULL)
return 0;
@@ -146,7 +146,7 @@ Item *AGOSEngine::getExitOf_e1(Item *item, uint16 d) {
SubGenExit *g;
Item *x;
- g = (SubGenExit *)findChildOfType(item, 4);
+ g = (SubGenExit *)findChildOfType(item, kGenExitType);
if (g == NULL)
return 0;
@@ -192,10 +192,10 @@ void AGOSEngine_Elvira2::moveDirn(Item *i, uint x) {
return;
p = derefItem(i->parent);
- if (findChildOfType(p, 4)) {
+ if (findChildOfType(p, kSuperRoomType)) {
n = getExitState(p, _superRoomNumber,x);
if (n == 1) {
- sr = (SubSuperRoom *)findChildOfType(p, 4);
+ sr = (SubSuperRoom *)findChildOfType(p, kSuperRoomType);
switch (x) {
case 0: a = -(sr->roomX); break;
case 1: a = 1; break;
@@ -319,7 +319,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
uint16 mask = 3;
uint16 n;
- sr = (SubSuperRoom *)findChildOfType(i, 4);
+ sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr == NULL)
return 0;
@@ -331,7 +331,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
}
void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr)
changeExitStates(sr, n, d, s);
}
@@ -339,7 +339,7 @@ void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) {
uint16 mask = 3;
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr) {
n--;
d <<= 1;
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index eb2266550a..32b767073a 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -257,12 +257,12 @@ restart:
for (;;) {
windowPutChar(window, 128);
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
delay(10);
- if (_keyPressed && _keyPressed < 128) {
- i = _keyPressed;
+ if (_keyPressed.ascii && _keyPressed.ascii < 128) {
+ i = _keyPressed.ascii;
break;
}
}
@@ -490,16 +490,16 @@ int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) {
HitArea *ha;
*b = true;
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
do {
- if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) {
+ if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
*b = false;
- return _keyPressed;
+ return _keyPressed.ascii;
}
delay(10);
} while (_lastHitArea3 == 0);
@@ -759,16 +759,16 @@ int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) {
listSaveGames(buf);
}
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
do {
- if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) {
+ if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
*b = false;
- return _keyPressed;
+ return _keyPressed.ascii;
}
delay(10);
} while (_lastHitArea3 == 0);
@@ -999,13 +999,13 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
item->state = f->readUint16BE();
item->classFlags = f->readUint16BE();
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
o->objectSize = f->readUint16BE();
o->objectWeight = f->readUint16BE();
}
- SubPlayer *p = (SubPlayer *)findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p) {
p->score = f->readUint32BE();
p->level = f->readUint16BE();
@@ -1014,7 +1014,7 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
p->strength = f->readUint16BE();
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 8; i++) {
u->userFlags[i] = f->readUint16BE();
@@ -1083,13 +1083,13 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
f->writeUint16BE(item->state);
f->writeUint16BE(item->classFlags);
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
f->writeUint16BE(o->objectSize);
f->writeUint16BE(o->objectWeight);
}
- SubPlayer *p = (SubPlayer *)findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p) {
f->writeUint32BE(p->score);
f->writeUint16BE(p->level);
@@ -1098,7 +1098,7 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
f->writeUint16BE(p->strength);
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 8; i++) {
f->writeUint16BE(u->userFlags[i]);
@@ -1204,19 +1204,19 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
item->state = f->readUint16BE();
item->classFlags = f->readUint16BE();
- SubRoom *r = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
if (r) {
r->roomExitStates = f->readUint16BE();
}
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
if (sr) {
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
for (i = j = 0; i != n; i++)
sr->roomExitStates[j++] = f->readUint16BE();
}
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
o->objectFlags = f->readUint32BE();
i = o->objectFlags & 1;
@@ -1228,7 +1228,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
}
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 4; i++) {
u->userFlags[i] = f->readUint16BE();
@@ -1283,9 +1283,12 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
Common::OutSaveFile *f;
uint item_index, num_item, i, j;
TimeEvent *te;
- uint32 curTime = 0;
uint32 gsc = _gameStoppedClock;
+ uint32 curTime = 0;
+ if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2)
+ curTime = time(NULL);
+
_lockWord |= 0x100;
f = _saveFileMan->openForSaving(genSaveName(slot));
@@ -1299,7 +1302,6 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
// No caption
} else if (getGameType() == GType_FF) {
f->write(caption, 100);
- curTime = time(NULL);
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
f->write(caption, 18);
} else {
@@ -1308,7 +1310,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
f->writeUint32BE(_itemArrayInited - 1);
f->writeUint32BE(0xFFFFFFFF);
- f->writeUint32BE(0);
+ f->writeUint32BE(curTime);
f->writeUint32BE(0);
i = 0;
@@ -1345,19 +1347,19 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
f->writeUint16BE(item->state);
f->writeUint16BE(item->classFlags);
- SubRoom *r = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
if (r) {
f->writeUint16BE(r->roomExitStates);
}
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
if (sr) {
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
for (i = j = 0; i != n; i++)
f->writeUint16BE(sr->roomExitStates[j++]);
}
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
f->writeUint32BE(o->objectFlags);
i = o->objectFlags & 1;
@@ -1369,7 +1371,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
}
}
- SubUserFlag *u = (SubUserFlag *)findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 4; i++) {
f->writeUint16BE(u->userFlags[i]);
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index c5cf6c5872..ace0b9d50f 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -206,7 +206,7 @@ void AGOSEngine::o_state() {
void AGOSEngine::o_oflag() {
// 28: item has prop
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
uint num = getVarOrByte();
setScriptCondition(subObject != NULL && (subObject->objectFlags & (1 << num)) != 0);
}
@@ -326,7 +326,7 @@ void AGOSEngine::o_goto() {
void AGOSEngine::o_oset() {
// 56: set child2 fr bit
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
int value = getVarOrByte();
if (subObject != NULL && value >= 16)
subObject->objectFlags |= (1 << value);
@@ -334,7 +334,7 @@ void AGOSEngine::o_oset() {
void AGOSEngine::o_oclear() {
// 57: clear child2 fr bit
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
int value = getVarOrByte();
if (subObject != NULL && value >= 16)
subObject->objectFlags &= ~(1 << value);
@@ -426,7 +426,7 @@ void AGOSEngine::o_if2() {
void AGOSEngine::o_isCalled() {
// 79: childstruct fr2 is
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
uint stringId = getNextStringID();
setScriptCondition((subObject != NULL) && subObject->objectName == stringId);
}
@@ -753,7 +753,7 @@ void AGOSEngine::o_setAdjNoun() {
void AGOSEngine::o_saveUserGame() {
// 132: save user game
if (getGameId() == GID_SIMON1CD32) {
- // The Amiga CD32 version of Simon the Sorcerer 1uses a single slot
+ // The Amiga CD32 version of Simon the Sorcerer 1 uses a single slot
if (!saveGame(0, "Default Saved Game")) {
vc33_setMouseOn();
fileError(_windowArray[5], true);
@@ -799,7 +799,7 @@ void AGOSEngine::o_freezeZones() {
freezeBottom();
if (!_copyProtection && !(getFeatures() & GF_TALKIE)) {
- if ((getGameType() == GType_SIMON1 && _subroutine == 2924) ||
+ if ((getGameType() == GType_SIMON1 && _subroutine == 2924) ||
(getGameType() == GType_SIMON2 && _subroutine == 1322)) {
_variableArray[134] = 3;
_variableArray[135] = 3;
@@ -985,10 +985,10 @@ Child *nextSub(Child *sub, int16 key) {
}
void AGOSEngine::synchChain(Item *i) {
- SubChain *c = (SubChain *)findChildOfType(i, 8);
+ SubChain *c = (SubChain *)findChildOfType(i, kChainType);
while (c) {
setItemState(derefItem(c->chChained), i->state);
- c = (SubChain *)nextSub((Child *)c, 8);
+ c = (SubChain *)nextSub((Child *)c, kChainType);
}
}
diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp
index b003a7262f..5a1d7d104b 100644
--- a/engines/agos/script_e1.cpp
+++ b/engines/agos/script_e1.cpp
@@ -419,7 +419,7 @@ void AGOSEngine_Elvira1::oe1_notPresent() {
void AGOSEngine_Elvira1::oe1_worn() {
// 4: worn
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (item->parent != getItem1ID() || subObject == NULL)
setScriptCondition(false);
@@ -430,7 +430,7 @@ void AGOSEngine_Elvira1::oe1_worn() {
void AGOSEngine_Elvira1::oe1_notWorn() {
// 5: not worn
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (item->parent != getItem1ID() || subObject == NULL)
setScriptCondition(false);
@@ -532,7 +532,7 @@ void AGOSEngine_Elvira1::oe1_moveDirn() {
void AGOSEngine_Elvira1::oe1_score() {
// 90: score
- SubPlayer *p = (SubPlayer *) findChildOfType(me(), 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(me(), kPlayerType);
showMessageFormat("Your score is %ld.\n", p->score);
}
@@ -542,9 +542,9 @@ void AGOSEngine_Elvira1::oe1_look() {
if (i == NULL)
return;
- SubRoom *r = (SubRoom *)findChildOfType(i, 1);
- SubObject *o = (SubObject *)findChildOfType(i, 2);
- SubPlayer *p = (SubPlayer *)findChildOfType(i, 3);
+ SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType);
+ SubObject *o = (SubObject *)findChildOfType(i, kObjectType);
+ SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType);
if (p == NULL)
return;
@@ -594,7 +594,7 @@ void AGOSEngine_Elvira1::oe1_doClass() {
void AGOSEngine_Elvira1::oe1_pObj() {
// 112: print object
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
getVarOrWord();
if (subObject != NULL)
@@ -624,7 +624,7 @@ void AGOSEngine_Elvira1::oe1_isCalled() {
void AGOSEngine_Elvira1::oe1_cFlag() {
// 162: check container flag
- SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), 7);
+ SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), kContainerType);
uint bit = getVarOrWord();
if (c == NULL)
@@ -678,7 +678,7 @@ void AGOSEngine_Elvira1::oe1_doorExit() {
int16 f = getVarOrWord();
int16 ct = 0;
- c = (SubChain *)findChildOfType(d, 8);
+ c = (SubChain *)findChildOfType(d, kChainType);
if (c)
a = derefItem(c->chChained);
while (ct < 6) {
@@ -986,7 +986,7 @@ void AGOSEngine_Elvira1::oe1_printMonsterHit() {
}
int16 AGOSEngine::levelOf(Item *item) {
- SubPlayer *p = (SubPlayer *) findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p == NULL)
return 0;
@@ -998,7 +998,7 @@ int16 AGOSEngine::moreText(Item *i) {
i = derefItem(i->next);
while (i) {
- o = (SubObject *)findChildOfType(i, 2);
+ o = (SubObject *)findChildOfType(i, kObjectType);
if ((o) && (o->objectFlags & 1))
goto l1;
if (i != me())
@@ -1014,7 +1014,7 @@ void AGOSEngine::lobjFunc(Item *i, const char *f) {
SubObject *o;
while (i) {
- o = (SubObject *)findChildOfType(i, 2);
+ o = (SubObject *)findChildOfType(i, kObjectType);
if ((o) && (o->objectFlags & 1))
goto l1;
if (i == me())
diff --git a/engines/agos/script_e2.cpp b/engines/agos/script_e2.cpp
index 00f0848ed9..77df3feecb 100644
--- a/engines/agos/script_e2.cpp
+++ b/engines/agos/script_e2.cpp
@@ -132,7 +132,7 @@ void AGOSEngine_Elvira2::setupOpcodes() {
OPCODE(o_when),
OPCODE(o_if1),
OPCODE(o_if2),
- OPCODE(oe1_isCalled),
+ OPCODE(oe2_isCalled),
/* 80 */
OPCODE(o_is),
OPCODE(o_invalid),
@@ -165,7 +165,7 @@ void AGOSEngine_Elvira2::setupOpcodes() {
OPCODE(o_cls),
/* 104 */
OPCODE(o_closeWindow),
- OPCODE(o_invalid),
+ OPCODE(oe2_menu),
OPCODE(o_invalid),
OPCODE(o_addBox),
/* 108 */
@@ -309,12 +309,19 @@ void AGOSEngine_Elvira2::oe2_doClass() {
void AGOSEngine_Elvira2::oe2_pObj() {
// 73: print object
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText)
showMessageFormat("%s\n", (const char *)getStringPtrByID(subObject->objectFlagValue[0])); // Difference
}
+void AGOSEngine_Elvira2::oe2_isCalled() {
+ // 79: childstruct fr2 is
+ Item *i = getNextItemPtr();
+ uint stringId = getNextStringID();
+ setScriptCondition(i->itemName == stringId);
+}
+
void AGOSEngine_Elvira2::oe2_loadGame() {
// 89: load game
uint16 stringId = getNextStringID();
@@ -326,6 +333,11 @@ void AGOSEngine_Elvira2::oe2_loadGame() {
}
}
+void AGOSEngine_Elvira2::oe2_menu() {
+ // 105: set agos menu
+ _agosMenu = getVarOrByte();
+}
+
void AGOSEngine_Elvira2::oe2_drawItem() {
// 113: draw item
Item *i = getNextItemPtr();
@@ -341,7 +353,7 @@ void AGOSEngine_Elvira2::oe2_doTable() {
// 143: start item sub
Item *i = getNextItemPtr();
- SubRoom *r = (SubRoom *)findChildOfType(i, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType);
if (r != NULL) {
Subroutine *sub = getSubroutineByID(r->subroutine_id);
if (sub) {
@@ -351,7 +363,7 @@ void AGOSEngine_Elvira2::oe2_doTable() {
}
if (getGameType() == GType_ELVIRA2) {
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr != NULL) {
Subroutine *sub = getSubroutineByID(sr->subroutine_id);
if (sub) {
@@ -478,7 +490,7 @@ void AGOSEngine_Elvira2::oe2_bNotZero() {
void AGOSEngine_Elvira2::oe2_getOValue() {
// 157: get item int prop
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
uint prop = getVarOrByte();
if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) {
@@ -492,7 +504,7 @@ void AGOSEngine_Elvira2::oe2_getOValue() {
void AGOSEngine_Elvira2::oe2_setOValue() {
// 158: set item prop
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
uint prop = getVarOrByte();
int value = getVarOrWord();
@@ -640,6 +652,16 @@ void AGOSEngine_Elvira2::oe2_isAdjNoun() {
// 179: item unk1 unk2 is
Item *item = getNextItemPtr();
int16 a = getNextWord(), b = getNextWord();
+
+ if (getGameType() == GType_ELVIRA2) {
+ // WORKAROUND: A NULL item can occur when interacting with Wine Bottles
+ if (item == NULL) {
+ warning("Please report where exactly this occurs in Elvira 2");
+ setScriptCondition(false);
+ return;
+ }
+ }
+
setScriptCondition(item->adjective == a && item->noun == b);
}
@@ -707,7 +729,7 @@ void AGOSEngine_Elvira2::printStats() {
if (val > 9999)
val = 9999;
writeChar(window, 30, y, 6, val / 100);
- writeChar(window, 32, y, 2, val / 10);
+ writeChar(window, 32, y, 2, val % 100);
mouseOn();
}
diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp
index c3e6dc5192..8b7af31a66 100644
--- a/engines/agos/script_ff.cpp
+++ b/engines/agos/script_ff.cpp
@@ -528,7 +528,7 @@ void AGOSEngine_Feeble::off_screenTextPObj() {
TextLocation *tl = NULL;
char buf[256];
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText) {
string_ptr = (const char *)getStringPtrByID(subObject->objectFlagValue[0]);
tl = getTextLocation(vgaSpriteId);
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 93b907e688..1a4f956b8b 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -311,29 +311,29 @@ void AGOSEngine_Simon1::os1_pauseGame() {
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
// If all else fails, use English as fallback.
- byte keyYes = 'y';
- byte keyNo = 'n';
+ Common::KeyCode keyYes = Common::KEYCODE_y;
+ Common::KeyCode keyNo = Common::KEYCODE_n;
switch (_language) {
case Common::RU_RUS:
break;
case Common::PL_POL:
- keyYes = 't';
+ keyYes = Common::KEYCODE_t;
break;
case Common::HB_ISR:
- keyYes = 'f';
+ keyYes = Common::KEYCODE_f;
break;
case Common::ES_ESP:
- keyYes = 's';
+ keyYes = Common::KEYCODE_s;
break;
case Common::IT_ITA:
- keyYes = 's';
+ keyYes = Common::KEYCODE_s;
break;
case Common::FR_FRA:
- keyYes = 'o';
+ keyYes = Common::KEYCODE_o;
break;
case Common::DE_DEU:
- keyYes = 'j';
+ keyYes = Common::KEYCODE_j;
break;
default:
break;
@@ -343,17 +343,17 @@ void AGOSEngine_Simon1::os1_pauseGame() {
delay(1);
#ifdef _WIN32_WCE
if (isSmartphone()) {
- if (_keyPressed) {
- if (_keyPressed == 13)
+ if (_keyPressed.keycode) {
+ if (_keyPressed.keycode == Common::KEYCODE_RETURN)
shutdown();
else
break;
}
}
#endif
- if (_keyPressed == keyYes || _keyPressed == (keyYes - 32))
+ if (_keyPressed.keycode == keyYes)
shutdown();
- else if (_keyPressed == keyNo || _keyPressed == (keyNo - 32))
+ else if (_keyPressed.keycode == keyNo)
break;
}
@@ -419,7 +419,7 @@ void AGOSEngine_Simon1::os1_screenTextPObj() {
uint vgaSpriteId = getVarOrByte();
uint color = getVarOrByte();
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (getFeatures() & GF_TALKIE) {
if (subObject != NULL && subObject->objectFlags & kOFVoice) {
uint offs = getOffsetOfChild2Param(subObject, kOFVoice);
diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp
index dfc1200d7c..00addce396 100644
--- a/engines/agos/script_s2.cpp
+++ b/engines/agos/script_s2.cpp
@@ -355,7 +355,7 @@ void AGOSEngine_Simon2::os2_screenTextPObj() {
uint vgaSpriteId = getVarOrByte();
uint color = getVarOrByte();
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (getFeatures() & GF_TALKIE) {
if (subObject != NULL && subObject->objectFlags & kOFVoice) {
uint speechId = subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFVoice)];
diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp
index 377b49ae3f..fc472fd3c3 100644
--- a/engines/agos/script_ww.cpp
+++ b/engines/agos/script_ww.cpp
@@ -167,7 +167,7 @@ void AGOSEngine_Waxworks::setupOpcodes() {
OPCODE(o_cls),
/* 104 */
OPCODE(o_closeWindow),
- OPCODE(oww_menu),
+ OPCODE(oe2_menu),
OPCODE(oww_textMenu),
OPCODE(o_addBox),
/* 108 */
@@ -355,11 +355,6 @@ void AGOSEngine_Waxworks::oww_whereTo() {
_objectItem = derefItem(getExitOf(i, d));
}
-void AGOSEngine_Waxworks::oww_menu() {
- // 105: set agos menu
- _agosMenu = getVarOrByte();
-}
-
void AGOSEngine_Waxworks::oww_textMenu() {
// 106: set text menu
byte slot = getVarOrByte();
@@ -419,7 +414,7 @@ void AGOSEngine_Waxworks::oww_printBox() {
void AGOSEngine_Waxworks::oww_boxPObj() {
// 188: print object name to box
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText)
boxTextMsg((const char *)getStringPtrByID(subObject->objectFlagValue[0]));
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index 483f101889..521a3ab6ea 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -274,7 +274,7 @@ bool AGOSEngine::printNameOf(Item *item, uint x, uint y) {
if (item == 0 || item == _dummyItem2 || item == _dummyItem3)
return false;
- subObject = (SubObject *)findChildOfType(item, 2);
+ subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject == NULL)
return false;
@@ -370,10 +370,12 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin
if (y < 2)
y = 2;
- if (getGameType() == GType_SIMON1)
- animate(windowNum, 2, 199 + vgaSpriteId, x, y, 12);
- else
+ if (getGameType() == GType_SIMON1) {
+ uint16 id = 199 + vgaSpriteId;
+ animate(windowNum, id / 100, id, x, y, 12);
+ } else {
animate(windowNum, 2, vgaSpriteId, x, y, 12);
+ }
}
// The Feeble Files specific
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index 2b8f6d3a09..38c401a80d 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -70,8 +70,8 @@ void AGOSEngine::setupVideoOpcodes(VgaOpcodeProc *op) {
op[36] = &AGOSEngine::vc36_setWindowImage;
op[38] = &AGOSEngine::vc38_ifVarNotZero;
op[39] = &AGOSEngine::vc39_setVar;
- op[40] = &AGOSEngine::vc40;
- op[41] = &AGOSEngine::vc41;
+ op[40] = &AGOSEngine::vc40_scrollRight;
+ op[41] = &AGOSEngine::vc41_scrollLeft;
op[42] = &AGOSEngine::vc42_delayIfNotEQ;
op[43] = &AGOSEngine::vc43_ifBitSet;
op[44] = &AGOSEngine::vc44_ifBitClear;
@@ -124,8 +124,8 @@ void AGOSEngine_Elvira1::setupVideoOpcodes(VgaOpcodeProc *op) {
op[41] = &AGOSEngine::vc37_pokePalette;
op[51] = &AGOSEngine::vc38_ifVarNotZero;
op[52] = &AGOSEngine::vc39_setVar;
- op[53] = &AGOSEngine::vc40;
- op[54] = &AGOSEngine::vc41;
+ op[53] = &AGOSEngine::vc40_scrollRight;
+ op[54] = &AGOSEngine::vc41_scrollLeft;
op[56] = &AGOSEngine::vc42_delayIfNotEQ;
}
@@ -1257,57 +1257,38 @@ void AGOSEngine::vc39_setVar() {
vcWriteVar(var, value);
}
-void AGOSEngine::vc40() {
+void AGOSEngine::vc40_scrollRight() {
uint16 var = vcReadNextWord();
int16 value = vcReadVar(var) + vcReadNextWord();
if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) {
- int16 tmp;
- if (_scrollCount != 0) {
- if (_scrollCount >= 0)
- goto no_scroll;
+ if ((_scrollCount < 0) || (_scrollCount == 0 && _scrollFlag == 0)) {
_scrollCount = 0;
- } else {
- if (_scrollFlag != 0)
- goto no_scroll;
- }
-
- if (value - _scrollX >= 30) {
- _scrollCount = 20;
- tmp = _scrollXMax - _scrollX;
- if (tmp < 20)
- _scrollCount = tmp;
- addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ if (value - _scrollX >= 30) {
+ _scrollCount = MIN(20, _scrollXMax - _scrollX);
+ addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ }
}
}
-no_scroll:;
vcWriteVar(var, value);
}
-void AGOSEngine::vc41() {
+void AGOSEngine::vc41_scrollLeft() {
uint16 var = vcReadNextWord();
int16 value = vcReadVar(var) - vcReadNextWord();
if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) {
- if (_scrollCount != 0) {
- if (_scrollCount < 0)
- goto no_scroll;
- _scrollCount = 0;
- } else {
- if (_scrollFlag != 0)
- goto no_scroll;
- }
- if ((uint16)(value - _scrollX) < 11) {
- _scrollCount = -20;
- if (_scrollX < 20)
- _scrollCount = -_scrollX;
- addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ if ((_scrollCount > 0) || (_scrollCount == 0 && _scrollFlag == 0)) {
+ _scrollCount = 0;
+ if ((uint16)(value - _scrollX) < 11) {
+ _scrollCount = -MIN(20, (int)_scrollX);
+ addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ }
}
}
-no_scroll:;
vcWriteVar(var, value);
}
diff --git a/engines/agos/vga.h b/engines/agos/vga.h
index 37c5d37106..1994f59f7f 100644
--- a/engines/agos/vga.h
+++ b/engines/agos/vga.h
@@ -40,20 +40,20 @@ struct VgaFileHeader2_Feeble {
uint16 x_4;
uint16 animationTable;
uint16 x_5;
-};
+} PACKED_STRUCT;
struct ImageHeader_Feeble {
uint16 id;
uint16 x_1;
uint16 scriptOffs;
uint16 x_2;
-};
+} PACKED_STRUCT;
struct AnimationHeader_Feeble {
uint16 scriptOffs;
uint16 x_2;
uint16 id;
-};
+} PACKED_STRUCT;
// Simon 1/2
struct ImageHeader_Simon {
@@ -61,13 +61,13 @@ struct ImageHeader_Simon {
uint16 color;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
struct AnimationHeader_Simon {
uint16 id;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
// Elvira 1/2 and Waxworks
@@ -76,14 +76,14 @@ struct ImageHeader_WW {
uint16 color;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
struct AnimationHeader_WW {
uint16 id;
uint16 x_1;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
// Common
struct VgaFileHeader2_Common {
@@ -96,7 +96,7 @@ struct VgaFileHeader2_Common {
uint16 x_4;
uint16 animationTable;
uint16 x_5;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 281c4807b8..49b10b6b14 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -2458,6 +2458,7 @@ void drawFailureMessage(byte cmd) {
void drawOverlays(void) {
overlayHeadElement *currentOverlay;
+ overlayHeadElement *nextOverlay;
backupOverlayPage();
@@ -2468,6 +2469,8 @@ void drawOverlays(void) {
currentOverlay = currentOverlay->next;
while (currentOverlay) {
+ nextOverlay = currentOverlay->next;
+
switch (currentOverlay->type) {
case 0: // sprite
{
@@ -2630,7 +2633,7 @@ void drawOverlays(void) {
}
}
- currentOverlay = currentOverlay->next;
+ currentOverlay = nextOverlay;
}
}
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index d6b2c9ec93..ffda142e66 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -177,12 +177,12 @@ int loadSavegameData(int saveGameIdx) {
fileHandle = fopen(buffer, "rb");
if (!fileHandle) {
- printInfoBlackBox("Sauvegarde non trouvée...");
+ printInfoBlackBox("Savegame not found...");
waitForPlayerInput();
return (-1);
}
- printInfoBlackBox("Chargement en cours...");
+ printInfoBlackBox("Loading in progress...");
fread(saveIdentBuffer, 6, 1, fileHandle);
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 05e2235cc9..f2b7198510 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -54,7 +54,8 @@ Engine::Engine(OSystem *syst)
_eventMan(_system->getEventManager()),
_saveFileMan(_system->getSavefileManager()),
_targetName(ConfMan.getActiveDomainName()),
- _gameDataPath(ConfMan.get("path")) {
+ _gameDataPath(ConfMan.get("path")),
+ _pauseLevel(0) {
g_engine = this;
_autosavePeriod = ConfMan.getInt("autosave_period");
@@ -180,3 +181,23 @@ void Engine::GUIErrorMessage(const Common::String msg) {
GUI::MessageDialog dialog(msg);
dialog.runModal();
}
+
+void Engine::pauseEngine(bool pause) {
+ assert((pause && _pauseLevel >= 0) || (!pause && _pauseLevel));
+
+ if (pause)
+ _pauseLevel++;
+ else
+ _pauseLevel--;
+
+ if (_pauseLevel == 1) {
+ pauseEngineIntern(true);
+ } else if (_pauseLevel == 0) {
+ pauseEngineIntern(false);
+ }
+}
+
+void Engine::pauseEngineIntern(bool pause) {
+ // By default, just (un)pause all digital sounds
+ _mixer->pauseAll(pause);
+}
diff --git a/engines/engine.h b/engines/engine.h
index 7b40a377ef..f9aeb7718f 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -56,7 +56,18 @@ protected:
const Common::String _gameDataPath;
private:
+ /**
+ * The autosave interval, given in second. Used by shouldPerformAutoSave.
+ */
int _autosavePeriod;
+
+ /**
+ * The pause level, 0 means 'running', a positive value indicates
+ * how often the engine has been paused (and hence how often it has
+ * to be un-paused before it resumes running). This makes it possible
+ * to nest code which pauses the engine.
+ */
+ int _pauseLevel;
public:
Engine(OSystem *syst);
@@ -79,22 +90,49 @@ public:
/** Specific for each engine: prepare error string. */
virtual void errorString(const char *buf_input, char *buf_output);
+ /**
+ * Return the engine's debugger instance, if any. Used by error() to
+ * invoke the debugger when a severe error is reported.
+ */
+ virtual GUI::Debugger *getDebugger() { return 0; }
+
+ /**
+ * Pause or resume the engine. This should stop/resume any audio playback
+ * and other stuff. Called right before the system runs a global dialog
+ * (like a global pause, main menu, options or 'confirm exit' dialog).
+ *
+ * This is a convenience tracker which automatically keeps track on how
+ * often the engine has been paused, ensuring that after pausing an engine
+ * e.g. twice, it has to be unpaused twice before actuallying resuming.
+ *
+ * @param pause true to pause the engine, false to resume it
+ */
+ void pauseEngine(bool pause);
+
+ /**
+ * Return whether the engine is currently paused or not.
+ */
+ bool isPaused() const { return _pauseLevel != 0; }
+
+public:
+
+ /** Setup the backend's graphics mode. */
void initCommonGFX(bool defaultTo1XScaler);
/** On some systems, check if the game appears to be run from CD. */
void checkCD();
- /* Indicate if an autosave should be performed. */
+ /** Indicate whether an autosave should be performed. */
bool shouldPerformAutoSave(int lastSaveTime);
/** Initialized graphics and shows error message. */
void GUIErrorMessage(const Common::String msg);
-
+
/**
- * Return the engine's debugger instance, if any. Used by error() to
- * invoke the debugger when a severe error is reported.
+ * Actual implementation of pauseEngine by subclasses. See there
+ * for details.
*/
- virtual GUI::Debugger *getDebugger() { return 0; }
+ virtual void pauseEngineIntern(bool pause);
};
extern Engine *g_engine;
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 9dfbf534d4..1c275185ca 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -757,14 +757,30 @@ static const GOBGameDescription gameDescriptions[] = {
{
"gob3",
"",
- AD_ENTRY1("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42"),
- UNK_LANG,
+ AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
+ EN_GRB,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
GF_GOB3,
"intro"
},
+ { // Supplied by fac76 in bug report #1742716
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {NULL, 0, NULL, 0}
+ },
+ EN_GRB,
+ kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ GF_GOB3,
+ "intro"
+ },
{
{
"gob3",
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 4a1796c6d9..2181d219f2 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -48,7 +48,7 @@ public:
uint16 funcEnter;
uint16 funcLeave;
uint16 funcSub;
- };
+ } PACKED_STRUCT;
#define szGame_TotResItem (4 + 2 + 2 + 2)
struct TotResItem {
@@ -57,7 +57,7 @@ public:
int16 size;
int16 width;
int16 height;
- };
+ } PACKED_STRUCT;
#define szGame_TotResTable (2 + 1)
struct TotResTable {
@@ -65,7 +65,7 @@ public:
byte unknown;
TotResItem *items;
byte *dataPtr;
- };
+ } PACKED_STRUCT;
#define szGame_ExtItem (4 + 2 + 2 + 2)
struct ExtItem {
@@ -73,34 +73,34 @@ public:
uint16 size;
int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag
int16 height; // not zero
- };
+ } PACKED_STRUCT;
#define szGame_ExtTable (2 + 1)
struct ExtTable {
int16 itemsCount;
byte unknown;
ExtItem* items;
- };
+ } PACKED_STRUCT;
#define szGame_TotTextItem (2 + 2)
struct TotTextItem {
int16 offset;
int16 size;
- };
+ } PACKED_STRUCT;
#define szGame_TotTextTable (2)
struct TotTextTable {
int16 itemsCount;
TotTextItem *items;
byte *dataPtr;
- };
+ } PACKED_STRUCT;
struct InputDesc {
int16 fontIndex;
int16 backColor;
int16 frontColor;
byte *ptr;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index 61ac9dff5e..38c19a48d3 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -51,7 +51,7 @@ public:
int16 freq; // high/low byte * 100 - frequency
int16 repCount; // high/low byte - repeat count
int16 sndFrame;
- };
+ } PACKED_STRUCT;
typedef Gob_State *Gob_PState;
@@ -90,12 +90,12 @@ public:
char multObjIndex;
char unk14;
char visible;
- };
+ } PACKED_STRUCT;
struct Gob_Pos {
char x;
char y;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/imd.h b/engines/gob/imd.h
index 3d04f18c6d..27d95cd579 100644
--- a/engines/gob/imd.h
+++ b/engines/gob/imd.h
@@ -41,7 +41,7 @@ public:
int16 top;
int16 right;
int16 bottom;
- };
+ } PACKED_STRUCT;
struct Imd {
int16 handle;
@@ -65,7 +65,7 @@ public:
int32 frameDataSize;
int32 vidBufferSize;
Video::Color *extraPalette;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index fcf825b4c3..a3277047e7 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1647,6 +1647,13 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
lastCalled = now;
_noBusyWait = false;
+ // WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
+ // to become 5000. We deliberately slow down busy-waiting, so we shorten
+ // the counting, too.
+ if (((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
+ (VAR(59) < 4000) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
+ WRITE_VAR(59, 4000);
+
switch (cmd) {
case 0:
_vm->_draw->_showCursor &= ~2;
diff --git a/engines/gob/map.h b/engines/gob/map.h
index 9b45c5c04e..0e0a80aad3 100644
--- a/engines/gob/map.h
+++ b/engines/gob/map.h
@@ -51,7 +51,7 @@ public:
int16 x;
int16 y;
int16 notWalkable;
- };
+ } PACKED_STRUCT;
#define szMap_ItemPos 3
@@ -59,7 +59,7 @@ public:
int8 x;
int8 y;
int8 orient;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index 194126cd8b..edfbb682ea 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -63,7 +63,7 @@ public:
int8 redrawAnimation;
int8 redrawLayer;
uint8 redrawFrame;
- };
+ } PACKED_STRUCT;
struct Mult_GobState {
int16 animation; // .
@@ -74,7 +74,7 @@ public:
int16 freq; // |- [1+]
int8 repCount; // |
uint8 speaker; // '
- };
+ } PACKED_STRUCT;
struct Mult_Object {
int32 *pPosX;
@@ -104,12 +104,12 @@ public:
int16 newTop;
int16 newRight;
int16 newBottom;
- };
+ } PACKED_STRUCT;
struct Mult_StaticKey {
int16 frame;
int16 layer;
- };
+ } PACKED_STRUCT;
struct Mult_AnimKey {
int16 frame;
@@ -117,14 +117,14 @@ public:
int16 posX;
int16 posY;
int16 order;
- };
+ } PACKED_STRUCT;
struct Mult_TextKey {
int16 frame;
int16 cmd;
char unknown[18];
byte script[6];
- };
+ } PACKED_STRUCT;
struct Mult_PalKey {
int16 frame;
@@ -133,14 +133,14 @@ public:
int16 unknown0;
int16 unknown1;
int8 subst[16][4];
- };
+ } PACKED_STRUCT;
struct Mult_PalFadeKey {
int16 frame;
int16 fade;
int16 palIndex;
int8 flag;
- };
+ } PACKED_STRUCT;
struct Mult_SndKey {
int16 frame;
@@ -150,7 +150,7 @@ public:
int16 repCount;
int16 resId;
int16 soundIndex;
- };
+ } PACKED_STRUCT;
struct Mult_ImdKey {
int16 frame;
@@ -162,7 +162,7 @@ public:
int16 lastFrame;
int8 palStart;
int8 palEnd;
- };
+ } PACKED_STRUCT;
struct Mult_Data {
int16 palFadeKeysCount;
@@ -212,7 +212,7 @@ public:
char *imdFiles;
char *somepointer10; // ?
byte *execPtr;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp
index 6e678c103e..0f38827363 100644
--- a/engines/gob/music.cpp
+++ b/engines/gob/music.cpp
@@ -268,20 +268,20 @@ void Adlib::setKey(byte voice, byte note, bool on, bool spec) {
// 0x3A donne 0x2AF;
// 3A
// << 7 = 1D00
- // + E000 = FD00 négatif
+ // + E000 = FD00 negatif
// * 19 = xB500
// / 2000 = -2 => Ligne 17h, colonne -1
// 2E
// << 7 = 1700
- // + E000 = F700 négatif
+ // + E000 = F700 negatif
// * 19 = x1F00
// / 2000 =
short a;
short lin;
short col;
- a = (note << 7) + 0xE000; // Volontairement tronqué
+ a = (note << 7) + 0xE000; // Volontairement tronque
a = (short)((long)a * 25 / 0x2000);
if (a < 0) {
col = - ((24 - a) / 25);
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index 3f8aeb81bd..b376a8a75c 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -258,7 +258,10 @@ bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
}
in->seek(1040 + varSize * 2);
- return loadSprite(*in, size);
+
+ bool success = loadSprite(*in, size);
+ delete in;
+ return success;
} else
warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)",
diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h
index 32ff727c46..acb7aecba7 100644
--- a/engines/gob/scenery.h
+++ b/engines/gob/scenery.h
@@ -38,7 +38,7 @@ public:
int16 right; //These are stored in Little Endian format
int16 top; //And should be converted by client code when accessed
int16 bottom; //i.e. use FROM_LE_16()
- };
+ } PACKED_STRUCT;
struct StaticPlane {
int8 pictIndex;
@@ -47,13 +47,13 @@ public:
int16 destX;
int16 destY;
int8 transp;
- };
+ } PACKED_STRUCT;
struct StaticLayer {
int16 backResId;
int16 planeCount;
StaticPlane *planes;
- };
+ } PACKED_STRUCT;
// Animations
@@ -63,7 +63,7 @@ public:
int8 destX;
int8 destY;
int8 notFinal;
- };
+ } PACKED_STRUCT;
struct AnimLayer {
int16 unknown0;
@@ -74,7 +74,7 @@ public:
int8 transp;
int16 framesCount;
AnimFramePiece *frames;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp
index e3a4715920..b47e6795ac 100644
--- a/engines/gob/sound.cpp
+++ b/engines/gob/sound.cpp
@@ -35,8 +35,6 @@
namespace Gob {
-#define FRAC_BITS 16
-
void SoundDesc::set(SoundType type, SoundSource src,
byte *data, uint32 dSize) {
@@ -176,7 +174,6 @@ Snd::Snd(GobEngine *vm) : _vm(vm) {
_offset = 0;
_offsetFrac = 0;
_offsetInc = 0;
- _offsetIncFrac = 0;
_cur = 0;
_last = 0;
@@ -325,10 +322,7 @@ void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
_offset = 0;
_offsetFrac = 0;
-
- uint32 incr = (_freq << FRAC_BITS) / _rate;
- _offsetInc = incr >> FRAC_BITS;
- _offsetIncFrac = incr & ((1UL << FRAC_BITS) - 1);
+ _offsetInc = (_freq << FRAC_BITS) / _rate;
_last = _cur;
_cur = _data[0];
@@ -393,9 +387,6 @@ void Snd::checkEndSample() {
int Snd::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock slock(_mutex);
- int16 val;
- uint32 tmp, oldOffset;
-
for (int i = 0; i < numSamples; i++) {
if (!_data)
return i;
@@ -406,19 +397,18 @@ int Snd::readBuffer(int16 *buffer, const int numSamples) {
// Linear interpolation. See sound/rate.cpp
- val = (_last + (((_cur - _last) * _offsetFrac +
- (1UL << (FRAC_BITS - 1))) >> FRAC_BITS)) << 8;
- *buffer++ = (((int32) val) * _fadeVol) >> 16;
+ int32 val = (_last + (((_cur - _last) * _offsetFrac +
+ FRAC_HALF) >> FRAC_BITS)) << 8;
+ *buffer++ = (val * _fadeVol) >> 16;
- oldOffset = _offset;
-
- tmp = _offsetFrac + _offsetIncFrac;
- _offset += _offsetInc + (tmp >> FRAC_BITS);
- _offsetFrac = tmp & ((1UL << FRAC_BITS) - 1);
+ _offsetFrac += _offsetInc;
- if (oldOffset < _offset) {
+ // Was there an integral change?
+ if (fracToInt(_offsetFrac) > 0) {
_last = _cur;
- _cur = _data[oldOffset];
+ _cur = _data[_offset];
+ _offset += fracToInt(_offsetFrac);
+ _offsetFrac &= FRAC_LO_MASK;
}
if (_fade) {
diff --git a/engines/gob/sound.h b/engines/gob/sound.h
index 76b9f2b159..15909f5452 100644
--- a/engines/gob/sound.h
+++ b/engines/gob/sound.h
@@ -27,6 +27,7 @@
#define GOB_SOUND_H
#include "common/mutex.h"
+#include "common/frac.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
@@ -175,9 +176,8 @@ protected:
int32 _repCount;
uint32 _offset;
- uint32 _offsetFrac;
- uint32 _offsetInc;
- uint32 _offsetIncFrac;
+ frac_t _offsetFrac;
+ frac_t _offsetInc;
int16 _cur;
int16 _last;
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 0bc87f42d5..6f88a5a993 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -235,7 +235,7 @@ void Video::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1,
/*
* The original's version of the Bresenham Algorithm was a bit "unclean"
- * and produced strange edges at 45°, 135°, 225° and 315°, so using the
+ * and produced strange edges at 45, 135, 225 and 315 degrees, so using the
* version found in the Wikipedia article about the
* "Bresenham's line algorithm" instead
*/
diff --git a/engines/gob/video.h b/engines/gob/video.h
index faa9555abb..51d02bd219 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -85,7 +85,7 @@ public:
byte red;
byte green;
byte blue;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index 8cafb54fb8..6fc347158f 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -230,14 +230,14 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
drawJewelsFadeOutEnd(jewel);
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[3] = 0;
- _scriptClick->variables[6] = jewel;
+ _scriptClick->regs[3] = 0;
+ _scriptClick->regs[6] = jewel;
_scriptInterpreter->startScript(_scriptClick, 4);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
- if (_scriptClick->variables[3])
+ if (_scriptClick->regs[3])
return 1;
_unkAmuletVar = 1;
diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp
index 249a5f6c21..1664ce144f 100644
--- a/engines/kyra/kyra.cpp
+++ b/engines/kyra/kyra.cpp
@@ -923,16 +923,16 @@ int KyraEngine::processInputHelper(int xpos, int ypos) {
int KyraEngine::clickEventHandler(int xpos, int ypos) {
debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler(%d, %d)", xpos, ypos);
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[1] = xpos;
- _scriptClick->variables[2] = ypos;
- _scriptClick->variables[3] = 0;
- _scriptClick->variables[4] = _itemInHand;
+ _scriptClick->regs[1] = xpos;
+ _scriptClick->regs[2] = ypos;
+ _scriptClick->regs[3] = 0;
+ _scriptClick->regs[4] = _itemInHand;
_scriptInterpreter->startScript(_scriptClick, 1);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
- return _scriptClick->variables[3];
+ return _scriptClick->regs[3];
}
void KyraEngine::updateMousePointer(bool forceUpdate) {
@@ -1068,10 +1068,10 @@ void KyraEngine::clickEventHandler2() {
Common::Point mouse = getMousePos();
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[0] = _currentCharacter->sceneId;
- _scriptClick->variables[1] = mouse.x;
- _scriptClick->variables[2] = mouse.y;
- _scriptClick->variables[4] = _itemInHand;
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[1] = mouse.x;
+ _scriptClick->regs[2] = mouse.y;
+ _scriptClick->regs[4] = _itemInHand;
_scriptInterpreter->startScript(_scriptClick, 6);
while (_scriptInterpreter->validScript(_scriptClick))
@@ -1132,9 +1132,9 @@ void KyraEngine::runNpcScript(int func) {
debugC(9, kDebugLevelMain, "KyraEngine::runNpcScript(%d)", func);
_scriptInterpreter->initScript(_npcScript, _npcScriptData);
_scriptInterpreter->startScript(_npcScript, func);
- _npcScript->variables[0] = _currentCharacter->sceneId;
- _npcScript->variables[4] = _itemInHand;
- _npcScript->variables[5] = func;
+ _npcScript->regs[0] = _currentCharacter->sceneId;
+ _npcScript->regs[4] = _itemInHand;
+ _npcScript->regs[5] = func;
while (_scriptInterpreter->validScript(_npcScript))
_scriptInterpreter->runScript(_npcScript);
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 319845c22c..2425444be1 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -195,15 +195,22 @@ uint8 *Resource::fileData(const char *file, uint32 *size) const {
if (!(*cur)->isOpen())
continue;
- uint32 fileSize = (*cur)->getFileSize(fileHash);
- if (!fileSize)
- continue;
+ uint8* result = (*cur)->getFile(fileHash);
+
+ if (result) {
+ uint32 fileSize = (*cur)->getFileSize(fileHash);
+
+ if (!fileSize)
+ continue;
+
+ if (size)
+ *size = fileSize;
+
+ return result;
+ }
- if (size)
- *size = fileSize;
- return (*cur)->getFile(fileHash);
}
}
@@ -221,13 +228,15 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh
if (!(*start)->isOpen())
continue;
- *size = (*start)->getFileSize(fileHash);
+ if ((*start)->getFileHandle(fileHash, filehandle)) {
+
+ *size = (*start)->getFileSize(fileHash);
- if (!(*size))
- continue;
+ if (!(*size))
+ continue;
- if ((*start)->getFileHandle(fileHash, filehandle))
return true;
+ }
}
return false;
diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp
index 2ba1870fcd..a92fd9ce7c 100644
--- a/engines/kyra/scene.cpp
+++ b/engines/kyra/scene.cpp
@@ -450,8 +450,8 @@ void KyraEngine::startSceneScript(int brandonAlive) {
_scriptInterpreter->unloadScript(_scriptClickData);
_scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes);
_scriptInterpreter->startScript(_scriptClick, 0);
- _scriptClick->variables[0] = _currentCharacter->sceneId;
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[7] = brandonAlive;
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
@@ -620,8 +620,8 @@ void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
if (unk1 && brandonAlive == 0)
moveCharacterToPos(0, facing, xpos2, ypos2);
- _scriptClick->variables[4] = _itemInHand;
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[4] = _itemInHand;
+ _scriptClick->regs[7] = brandonAlive;
_scriptInterpreter->startScript(_scriptClick, 3);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
@@ -852,7 +852,7 @@ void KyraEngine::initSceneScreen(int brandonAlive) {
if (!_scriptInterpreter->startScript(_scriptClick, 2))
error("Could not start script function 2 of scene script");
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[7] = brandonAlive;
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 02eb1c9ea7..641a034eab 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -504,7 +504,12 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) {
dstPage += SCREEN_W;
}
addDirtyRect(0, y, SCREEN_W, h);
- clearOverlayRect(0, 0, y, SCREEN_W, h);
+ // This would remove the text in the end sequence of
+ // the FM-Towns version.
+ // Since this method is just used for the Seqplayer
+ // this shouldn't be a problem anywhere else, so it's
+ // safe to disable the call here.
+ //clearOverlayRect(0, 0, y, SCREEN_W, h);
}
void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) {
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index c2ec984d5c..b43cd3b471 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -49,12 +49,12 @@ ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) {
COMMAND(c1_push),
// 0x04
COMMAND(c1_push),
- COMMAND(c1_pushVar),
+ COMMAND(c1_pushReg),
COMMAND(c1_pushBPNeg),
COMMAND(c1_pushBPAdd),
// 0x08
COMMAND(c1_popRetOrPos),
- COMMAND(c1_popVar),
+ COMMAND(c1_popReg),
COMMAND(c1_popBPNeg),
COMMAND(c1_popBPAdd),
// 0x0C
@@ -324,8 +324,8 @@ void ScriptHelper::c1_push(ScriptState* script) {
script->stack[--script->sp] = _parameter;
}
-void ScriptHelper::c1_pushVar(ScriptState* script) {
- script->stack[--script->sp] = script->variables[_parameter];
+void ScriptHelper::c1_pushReg(ScriptState* script) {
+ script->stack[--script->sp] = script->regs[_parameter];
}
void ScriptHelper::c1_pushBPNeg(ScriptState* script) {
@@ -359,8 +359,8 @@ void ScriptHelper::c1_popRetOrPos(ScriptState* script) {
}
}
-void ScriptHelper::c1_popVar(ScriptState* script) {
- script->variables[_parameter] = script->stack[script->sp++];
+void ScriptHelper::c1_popReg(ScriptState* script) {
+ script->regs[_parameter] = script->stack[script->sp++];
}
void ScriptHelper::c1_popBPNeg(ScriptState* script) {
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index dfca7700a1..5e43039110 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -70,8 +70,8 @@ struct ScriptState {
int16 retValue;
uint16 bp;
uint16 sp;
- int16 variables[30];
- int16 stack[61];
+ int16 regs[30]; // VM registers
+ int16 stack[61]; // VM stack
};
class ScriptHelper {
@@ -99,7 +99,7 @@ protected:
typedef void (ScriptHelper::*CommandProc)(ScriptState*);
struct CommandEntry {
CommandProc proc;
- const char* desc;
+ const char *desc;
};
const CommandEntry *_commands;
@@ -109,11 +109,11 @@ private:
void c1_pushRetOrPos(ScriptState*);
void c1_push(ScriptState*);
//void c1_push(); same as 03
- void c1_pushVar(ScriptState*);
+ void c1_pushReg(ScriptState*);
void c1_pushBPNeg(ScriptState*);
void c1_pushBPAdd(ScriptState*);
void c1_popRetOrPos(ScriptState*);
- void c1_popVar(ScriptState*);
+ void c1_popReg(ScriptState*);
void c1_popBPNeg(ScriptState*);
void c1_popBPAdd(ScriptState*);
void c1_addSP(ScriptState*);
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index 8e604b972b..87123222fb 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -1379,8 +1379,8 @@ int KyraEngine_v1::o1_waitForConfirmationMouseClick(ScriptState *script) {
processButtonList(_buttonList);
_skipFlag = false;
Common::Point mouse = getMousePos();
- script->variables[1] = mouse.x;
- script->variables[2] = mouse.y;
+ script->regs[1] = mouse.x;
+ script->regs[2] = mouse.y;
return 0;
}
diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp
index e2f92c9925..72d19ffd32 100644
--- a/engines/kyra/sound_digital.cpp
+++ b/engines/kyra/sound_digital.cpp
@@ -29,7 +29,7 @@
namespace Kyra {
-// Thanks to Torbjörn Andersson (eriktorbjorn) for his aud player on which
+// Thanks to Torbjorn Andersson (eriktorbjorn) for his aud player on which
// this code is based on
// TODO: cleanup of whole AUDStream
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 59581b9c7d..b5e4aef724 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -47,7 +47,7 @@ struct VersionStructure {
uint16 id;
byte vMajor;
byte vMinor;
-};
+} PACKED_STRUCT;
struct FileEntry {
uint16 id;
@@ -55,7 +55,7 @@ struct FileEntry {
byte sizeExtension;
uint16 size;
uint16 offset;
-};
+} PACKED_STRUCT;
struct HotspotResource {
uint16 hotspotId;
@@ -91,7 +91,7 @@ struct HotspotResource {
uint16 delayCtr;
byte flags2;
byte hdrFlags;
-};
+} PACKED_STRUCT;
struct HotspotAnimResource {
uint16 animRecordId;
@@ -105,18 +105,18 @@ struct HotspotAnimResource {
uint8 downFrame;
uint8 leftFrame;
uint8 rightFrame;
-};
+} PACKED_STRUCT;
struct MovementResource {
uint16 frameNumber;
int16 xChange;
int16 yChange;
-};
+} PACKED_STRUCT;
struct RoomRect {
int16 xs, xe;
int16 ys, ye;
-};
+} PACKED_STRUCT;
struct RoomResource {
uint16 roomNumber;
@@ -133,7 +133,7 @@ struct RoomResource {
uint8 areaFlag;
RoomRect walkBounds;
uint16 numExits;
-};
+} PACKED_STRUCT;
struct RoomExitResource {
int16 xs, xe, ys, ye;
@@ -141,12 +141,12 @@ struct RoomExitResource {
uint8 newRoom;
uint8 direction;
int16 newRoomX, newRoomY;
-};
+} PACKED_STRUCT;
struct HotspotOverrideResource {
uint16 hotspotId;
int16 xs, xe, ys, ye;
-};
+} PACKED_STRUCT;
struct RoomExitHotspotResource {
uint16 hotspotId;
@@ -154,7 +154,7 @@ struct RoomExitHotspotResource {
int16 ys, ye;
uint16 cursorNum;
uint16 destRoomNumber;
-};
+} PACKED_STRUCT;
struct RoomExitJoinResource {
uint16 hotspot1Id;
@@ -168,41 +168,41 @@ struct RoomExitJoinResource {
uint8 h2OpenSound;
uint8 h2CloseSound;
byte blocked;
-};
+} PACKED_STRUCT;
struct HotspotActionResource {
byte action;
uint16 sequenceOffset;
-};
+} PACKED_STRUCT;
struct TalkHeaderResource {
uint16 hotspotId;
uint16 offset;
-};
+} PACKED_STRUCT;
struct TalkDataHeaderResource {
uint16 recordId;
uint16 listOffset;
uint16 responsesOffset;
-};
+} PACKED_STRUCT;
struct TalkDataResource {
uint16 preSequenceId;
uint16 descId;
uint16 postSequenceId;
-};
+} PACKED_STRUCT;
struct TalkResponseResource {
uint16 sequenceId1;
uint16 sequenceId2;
uint16 sequenceId3;
-};
+} PACKED_STRUCT;
struct RoomExitCoordinateResource {
int16 x;
int16 y;
uint16 roomNumber;
-};
+} PACKED_STRUCT;
#define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6
#define ROOM_EXIT_COORDINATES_NUM_ROOMS 52
@@ -210,20 +210,20 @@ struct RoomExitCoordinateResource {
struct RoomExitCoordinateEntryResource {
uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS];
RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES];
-};
+} PACKED_STRUCT;
#define MAX_SCHEDULE_ENTRY_PARAMS 5
struct CharacterScheduleResource {
uint16 action;
uint16 params[MAX_SCHEDULE_ENTRY_PARAMS];
-};
+} PACKED_STRUCT;
struct RoomExitIndexedHotspotResource {
uint8 roomNumber;
uint8 hotspotIndex;
uint16 hotspotId;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
index 33caaa1b58..d4f538c451 100644
--- a/engines/parallaction/animation.cpp
+++ b/engines/parallaction/animation.cpp
@@ -166,15 +166,19 @@ void jobDisplayAnimations(void *parm, Job *j) {
if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
v14._width = v18->width();
v14._height = v18->height();
- v14._data0 = v18->getFrameData(v18->_frame);
-// v14._data1 = v18->_cnv->field_8[v18->_frame];
+
+ int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
+
+ v14._data0 = v18->getFrameData(frame);
+// v14._data1 = v18->_cnv->field_8[frame];
if (v18->_flags & kFlagsNoMasked)
_si = 3;
else
_si = _vm->_gfx->queryMask(v18->_top + v18->height());
- debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height, v14._data0);
+ debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height,
+ frame, v18->getFrameNum(), v14._data0);
_vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
}
diff --git a/engines/parallaction/archive.cpp b/engines/parallaction/archive.cpp
index b678b6df3c..9eef3f44e9 100644
--- a/engines/parallaction/archive.cpp
+++ b/engines/parallaction/archive.cpp
@@ -37,7 +37,7 @@ namespace Parallaction {
// Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of
// Nippon Safes used different internal offsets than all the other archives.
//
-// When an archive is opened in the Amiga demo, its size is checked against
+// When an archive is opened in the Amiga demo, its size is checked against
// SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used.
//
// When an archive is opened in Amiga multi-lingual version, the header is
@@ -72,6 +72,8 @@ void Archive::open(const char *file) {
if (!_archive.open(path))
error("archive '%s' not found", path);
+ _archiveName = file;
+
bool isSmallArchive = false;
if (_vm->getPlatform() == Common::kPlatformAmiga) {
if (_vm->getFeatures() & GF_DEMO) {
@@ -105,8 +107,12 @@ void Archive::close() {
resetArchivedFile();
_archive.close();
+ _archiveName.clear();
}
+Common::String Archive::name() const {
+ return _archiveName;
+}
bool Archive::openArchivedFile(const char *filename) {
debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp
index 1154250ffa..be92ca1daa 100644
--- a/engines/parallaction/callables.cpp
+++ b/engines/parallaction/callables.cpp
@@ -253,7 +253,7 @@ void _c_endComment(void *param) {
_vm->_gfx->floodFill(Gfx::kBitFront, r, 1);
_vm->_gfx->setFont(kFontDialogue);
- _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 130, 0);
+ _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 0, 130);
_vm->_gfx->updateScreen();
uint32 di = 0;
diff --git a/engines/parallaction/defs.h b/engines/parallaction/defs.h
index d7dc3388e7..c41130670e 100644
--- a/engines/parallaction/defs.h
+++ b/engines/parallaction/defs.h
@@ -28,6 +28,7 @@
#include "common/stdafx.h"
#include "common/list.h"
+#include "common/rect.h"
namespace Parallaction {
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index b3de3e5da3..7d2224164a 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -46,10 +46,6 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
-
-void enterDialogue();
-void exitDialogue();
-
int16 selectAnswer(Question *q, StaticCnv*);
int16 getHoverAnswer(int16 x, int16 y, Question *q);
@@ -62,110 +58,109 @@ int16 _answerBalloonH[10] = { 0 };
Dialogue *Parallaction::parseDialogue(Script &script) {
// printf("parseDialogue()\n");
- uint16 num_questions = 0;
- uint16 v50[20];
- Table _questions_names(20);
- Question *_questions[20];
+ uint16 numQuestions = 0;
- for (uint16 _si = 0; _si < 20; _si++) {
- v50[_si] = 0;
- }
+ Dialogue *dialogue = new Dialogue;
+
+ Table forwards(20);
fillBuffers(script, true);
while (scumm_stricmp(_tokens[0], "enddialogue")) {
if (scumm_stricmp(_tokens[0], "Question")) continue;
- _questions[num_questions] = new Dialogue;
- Dialogue *vB4 = _questions[num_questions];
+ Question *question = new Question;
+ dialogue->_questions[numQuestions] = question;
- _questions_names.addData(_tokens[1]);
+ forwards.addData(_tokens[1]);
- vB4->_text = parseDialogueString(script);
-// printf("Question: '%s'\n", vB4->_text);
+ question->_text = parseDialogueString(script);
fillBuffers(script, true);
- vB4->_mood = atoi(_tokens[0]);
+ question->_mood = atoi(_tokens[0]);
- uint16 _di = 0;
+ uint16 numAnswers = 0;
fillBuffers(script, true);
while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
- vB4->_answers[_di] = new Answer;
+ Answer *answer = new Answer;
+ question->_answers[numAnswers] = answer;
if (_tokens[1][0]) {
- Table* v60 = _localFlagNames;
- uint16 v56 = 1;
+ Table* flagNames;
+ uint16 token;
if (!scumm_stricmp(_tokens[1], "global")) {
- v56 = 2;
- v60 = _globalTable;
- vB4->_answers[_di]->_yesFlags |= kFlagsGlobal;
+ token = 2;
+ flagNames = _globalTable;
+ answer->_yesFlags |= kFlagsGlobal;
+ } else {
+ token = 1;
+ flagNames = _localFlagNames;
}
do {
- if (!scumm_strnicmp(_tokens[v56], "no", 2)) {
- byte _al = v60->lookup(_tokens[v56]+2);
- vB4->_answers[_di]->_noFlags |= 1 << (_al - 1);
+ if (!scumm_strnicmp(_tokens[token], "no", 2)) {
+ byte _al = flagNames->lookup(_tokens[token]+2);
+ answer->_noFlags |= 1 << (_al - 1);
} else {
- byte _al = v60->lookup(_tokens[v56]);
- vB4->_answers[_di]->_yesFlags |= 1 << (_al - 1);
+ byte _al = flagNames->lookup(_tokens[token]);
+ answer->_yesFlags |= 1 << (_al - 1);
}
- v56++;
+ token++;
- } while (!scumm_stricmp(_tokens[v56++], "|"));
+ } while (!scumm_stricmp(_tokens[token++], "|"));
}
- vB4->_answers[_di]->_text = parseDialogueString(script);
-
-// printf("answer[%i]: '%s'\n", _di, vB4->_answers[_di]);
+ answer->_text = parseDialogueString(script);
fillBuffers(script, true);
- vB4->_answers[_di]->_mood = atoi(_tokens[0]);
- vB4->_answers[_di]->_following._name = parseDialogueString(script);
+ answer->_mood = atoi(_tokens[0]);
+ answer->_following._name = parseDialogueString(script);
fillBuffers(script, true);
if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, vB4->_answers[_di]->_commands);
+ parseCommands(script, answer->_commands);
fillBuffers(script, true);
}
- _di++;
+ numAnswers++;
}
fillBuffers(script, true);
- num_questions++;
+ numQuestions++;
}
- for (uint16 _si = 0; _si <num_questions; _si++) {
+ // link questions
+ byte v50[20];
+ memset(v50, 0, 20);
- for (uint16 v5A = 0; v5A < 5; v5A++) {
- if (_questions[_si]->_answers[v5A] == 0) continue;
+ for (uint16 i = 0; i < numQuestions; i++) {
+ Question *question = dialogue->_questions[i];
- int16 v58 = _questions_names.lookup(_questions[_si]->_answers[v5A]->_following._name);
- free(_questions[_si]->_answers[v5A]->_following._name);
+ for (uint16 j = 0; j < NUM_ANSWERS; j++) {
+ Answer *answer = question->_answers[j];
+ if (answer == 0) continue;
- if (v58 == -1) {
- _questions[_si]->_answers[v5A]->_following._question = 0;
- } else {
- _questions[_si]->_answers[v5A]->_following._question = _questions[v58-1];
+ int16 index = forwards.lookup(answer->_following._name);
+ free(answer->_following._name);
+
+ if (index == -1)
+ answer->_following._question = 0;
+ else
+ answer->_following._question = dialogue->_questions[index - 1];
- if (v50[v58]) {
- _questions[_si]->_answers[v5A]->_mood |= 0x10;
- }
- v50[v58] = 1;
- }
}
}
- return _questions[0];
+ return dialogue;
}
@@ -183,7 +178,7 @@ char *Parallaction::parseDialogueString(Script &script) {
} while (strlen(vD0) == 0);
vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
- // this is critical for Gfx::displayBalloonString to work properly
+ // this is critical for Gfx::displayWrappedString to work properly
char *vCC = (char*)malloc(strlen(vD0)+1);
strcpy(vCC, vD0);
@@ -191,23 +186,71 @@ char *Parallaction::parseDialogueString(Script &script) {
return vCC;
}
-uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
+class DialogueManager {
+
+ Parallaction *_vm;
+ SpeakData *_data;
+ Dialogue *_dialogue;
+
+ bool _askPassword;
+
+ bool isNpc;
+ Cnv *_questioner;
+ Cnv *_answerer;
+
+ Question *_q;
+
+public:
+ DialogueManager(Parallaction *vm, SpeakData *data) : _vm(vm), _data(data) {
+ _dialogue = _data->_dialogue;
+ isNpc = scumm_stricmp(_data->_name, "yourself") && _data->_name[0] != '\0';
+ _questioner = isNpc ? _vm->_disk->loadTalk(_data->_name) : _vm->_char._talk;
+ _answerer = _vm->_char._talk;
+ }
+
+ ~DialogueManager() {
+ if (isNpc) {
+ delete _questioner;
+ }
+ }
+
+ void run();
+
+protected:
+ void clear() {
+ _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ }
+
+ void displayQuestion();
+ bool displayAnswers();
+ bool displayAnswer(uint16 i);
+
+ uint16 getAnswer();
+ int16 selectAnswer();
+ uint16 askPassword();
+ int16 getHoverAnswer(int16 x, int16 y);
+
+};
+
+uint16 DialogueManager::askPassword() {
debugC(1, kDebugDialogue, "checkDialoguePassword()");
char password[100];
uint16 passwordLen = 0;
while (true) {
+ clear();
+
strcpy(password, ".......");
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
Common::Rect r(_answerBalloonW[0], _answerBalloonH[0]);
r.moveTo(_answerBalloonX[0], _answerBalloonY[0]);
- _gfx->drawBalloon(r, 1);
- _gfx->displayWrappedString(q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], MAX_BALLOON_WIDTH, 3);
- _gfx->flatBlitCnv(face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
- _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0);
+ _vm->_gfx->drawBalloon(r, 1);
+ _vm->_gfx->displayWrappedString(_q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], 3, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, 0, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->displayString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0);
+ _vm->_gfx->updateScreen();
Common::Event e;
while (e.kbd.ascii != Common::KEYCODE_RETURN && passwordLen < MAX_PASSWORD_LENGTH) {
@@ -223,15 +266,15 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
passwordLen++;
password[passwordLen] = '\0';
- _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0);
- _gfx->updateScreen();
+ _vm->_gfx->displayString(_answerBalloonX[0] + 10, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0);
+ _vm->_gfx->updateScreen();
g_system->delayMillis(20);
}
- if ((!scumm_stricmp(_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
- (!scumm_stricmp(_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
- (!scumm_stricmp(_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) {
+ if ((!scumm_stricmp(_vm->_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
+ (!scumm_stricmp(_vm->_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
+ (!scumm_stricmp(_vm->_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) {
break;
@@ -243,165 +286,135 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
}
-bool _askPassword;
-bool Parallaction::displayAnswer(Dialogue *q, uint16 i) {
- uint32 v28 = _localFlags[_currentLocationIndex];
- if (q->_answers[i]->_yesFlags & kFlagsGlobal)
+bool DialogueManager::displayAnswer(uint16 i) {
+
+ uint32 v28 = _localFlags[_vm->_currentLocationIndex];
+ if (_q->_answers[i]->_yesFlags & kFlagsGlobal)
v28 = _commandFlags | kFlagsGlobal;
// display suitable answers
- if (((q->_answers[i]->_yesFlags & v28) == q->_answers[i]->_yesFlags) && ((q->_answers[i]->_noFlags & ~v28) == q->_answers[i]->_noFlags)) {
+ if (((_q->_answers[i]->_yesFlags & v28) == _q->_answers[i]->_yesFlags) && ((_q->_answers[i]->_noFlags & ~v28) == _q->_answers[i]->_noFlags)) {
- _gfx->getStringExtent(q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]);
+ _vm->_gfx->getStringExtent(_q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]);
Common::Rect r(_answerBalloonW[i], _answerBalloonH[i]);
r.moveTo(_answerBalloonX[i], _answerBalloonY[i]);
- _gfx->drawBalloon(r, 1);
+ _vm->_gfx->drawBalloon(r, 1);
_answerBalloonY[i+1] = 10 + _answerBalloonY[i] + _answerBalloonH[i];
- _askPassword = _gfx->displayWrappedString(q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], MAX_BALLOON_WIDTH, 3);
+ _askPassword = _vm->_gfx->displayWrappedString(_q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], 3, MAX_BALLOON_WIDTH);
return true;
}
+ _answerBalloonY[i+1] = _answerBalloonY[i];
+ _answerBalloonY[i] = SKIPPED_ANSWER;
+
return false;
}
-bool Parallaction::displayAnswers(Dialogue *q) {
+bool DialogueManager::displayAnswers() {
bool displayed = false;
uint16 i = 0;
- while (i < NUM_ANSWERS && q->_answers[i]) {
- if (displayAnswer(q, i)) {
+ while (i < NUM_ANSWERS && _q->_answers[i]) {
+ if (displayAnswer(i))
displayed = true;
- } else {
- _answerBalloonY[i+1] = _answerBalloonY[i];
- _answerBalloonY[i] = SKIPPED_ANSWER;
- }
+
i++;
}
- _gfx->updateScreen();
+ _vm->_gfx->updateScreen();
return displayed;
}
-void Parallaction::displayQuestion(Dialogue *q, Cnv *cnv) {
+void DialogueManager::displayQuestion() {
int16 w = 0, h = 0;
- if (!scumm_stricmp(q->_text, "NULL")) return;
-
- StaticCnv face;
- face._width = cnv->_width;
- face._height = cnv->_height;
- face._data0 = cnv->getFramePtr(q->_mood & 0xF);
- face._data1 = NULL; // cnv->field_8[v60->_mood & 0xF];
+ if (!scumm_stricmp(_q->_text, "NULL")) return;
- _gfx->flatBlitCnv(&face, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront);
- _gfx->getStringExtent(q->_text, MAX_BALLOON_WIDTH, &w, &h);
+ _vm->_gfx->flatBlitCnv(_questioner, _q->_mood & 0xF, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->getStringExtent(_q->_text, MAX_BALLOON_WIDTH, &w, &h);
Common::Rect r(w, h);
r.moveTo(QUESTION_BALLOON_X, QUESTION_BALLOON_Y);
- _gfx->drawBalloon(r, q->_mood & 0x10);
- _gfx->displayWrappedString(q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, MAX_BALLOON_WIDTH, 0);
- _gfx->updateScreen();
+ _vm->_gfx->drawBalloon(r, _q->_mood & 0x10);
+ _vm->_gfx->displayWrappedString(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->updateScreen();
waitUntilLeftClick();
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ clear();
return;
}
-uint16 Parallaction::getDialogueAnswer(Dialogue *q, Cnv *cnv) {
+uint16 DialogueManager::getAnswer() {
uint16 answer = 0;
- StaticCnv face;
- face._width = cnv->_width;
- face._height = cnv->_height;
- face._data0 = cnv->getFramePtr(0);
- face._data1 = NULL; // cnv->field_8[0];
-
- _gfx->flatBlitCnv(&face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
-
if (_askPassword == false) {
- answer = selectAnswer(q, &face);
+ answer = selectAnswer();
} else {
- answer = askDialoguePassword(q, &face);
+ answer = askPassword();
}
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); // erase answer screen
+ clear();
debugC(1, kDebugDialogue, "runDialogue: user selected answer #%i", answer);
return answer;
}
-void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name);
-
- enterDialogue();
-
- _gfx->setFont(kFontDialogue);
-
- bool isNpc = scumm_stricmp(data->_name, "yourself") && data->_name[0] != '\0';
- Cnv *face = isNpc ? _disk->loadTalk(data->_name) : _char._talk;
+void DialogueManager::run() {
_askPassword = false;
CommandList *cmdlist = NULL;
- uint16 answer;
- Dialogue *q = data->_dialogue;
- while (q) {
+ _q = _dialogue->_questions[0];
+ int16 answer;
+
+ while (_q) {
answer = 0;
- displayQuestion(q, face);
- if (q->_answers[0] == NULL) break;
+ displayQuestion();
+ if (_q->_answers[0] == NULL) break;
_answerBalloonY[0] = 10;
- if (scumm_stricmp(q->_answers[0]->_text, "NULL")) {
- if (!displayAnswers(q)) break;
- answer = getDialogueAnswer(q, _char._talk);
- cmdlist = &q->_answers[answer]->_commands;
+ if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
+ if (!displayAnswers()) break;
+ answer = getAnswer();
+ cmdlist = &_q->_answers[answer]->_commands;
}
- q = q->_answers[answer]->_following._question;
+ _q = _q->_answers[answer]->_following._question;
}
- debugC(1, kDebugDialogue, "runDialogue: out of dialogue loop");
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
- if (isNpc) {
- delete face;
- }
+ clear();
- exitDialogue();
if (cmdlist)
- runCommands(*cmdlist);
-
- return;
+ _vm->runCommands(*cmdlist);
}
-int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
+int16 DialogueManager::selectAnswer() {
int16 numAvailableAnswers = 0;
int16 _si = 0;
int16 _di = 0;
int16 i = 0;
- for (; q->_answers[i]; i++) {
+ for (; _q->_answers[i]; i++) {
if (_answerBalloonY[i] == SKIPPED_ANSWER) continue;
_di = i;
@@ -410,11 +423,9 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
_answerBalloonY[i] = 2000;
if (numAvailableAnswers == 1) {
- _gfx->displayWrappedString(q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], MAX_BALLOON_WIDTH, 0);
- cnv->_data0 = _char._talk->getFramePtr(q->_answers[_di]->_mood & 0xF);
-// cnv->_data1 = _char._talk->field_8[q->_answers[_di]->_mood & 0xF];
- _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
- _gfx->updateScreen();
+ _vm->_gfx->displayWrappedString(_q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_di]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->updateScreen();
waitUntilLeftClick();
return _di;
}
@@ -424,20 +435,18 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
_mouseButtons = kMouseNone;
while (_mouseButtons != kMouseLeftUp) {
- updateInput();
- _si = getHoverAnswer(_mousePos.x, _mousePos.y, q);
+ _vm->updateInput();
+ _si = getHoverAnswer(_vm->_mousePos.x, _vm->_mousePos.y);
if (_si != v2) {
if (v2 != -1)
- _gfx->displayWrappedString(q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], MAX_BALLOON_WIDTH, 3);
+ _vm->_gfx->displayWrappedString(_q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], 3, MAX_BALLOON_WIDTH);
- _gfx->displayWrappedString(q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], MAX_BALLOON_WIDTH, 0);
- cnv->_data0 = _char._talk->getFramePtr(q->_answers[_si]->_mood & 0xF);
-// cnv->_data1 = _char._talk->field_8[q->_answers[_si]->_mood & 0xF];
- _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->displayWrappedString(_q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_si]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
}
- _gfx->updateScreen();
+ _vm->_gfx->updateScreen();
g_system->delayMillis(30);
v2 = _si;
}
@@ -449,13 +458,13 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
//
// finds out which answer is currently selected
//
-int16 getHoverAnswer(int16 x, int16 y, Question *q) {
+int16 DialogueManager::getHoverAnswer(int16 x, int16 y) {
int16 top = 1000;
int16 bottom = 1000;
for (int16 _si = 0; _si < NUM_ANSWERS; _si++) {
- if (q->_answers[_si] == NULL) break;
+ if (_q->_answers[_si] == NULL) break;
if (_answerBalloonY[_si] != SKIPPED_ANSWER) {
top = _answerBalloonY[_si];
@@ -476,21 +485,21 @@ int16 getHoverAnswer(int16 x, int16 y, Question *q) {
}
-void Parallaction::enterDialogue() {
- showCursor(false);
-
- return;
-}
+void Parallaction::runDialogue(SpeakData *data) {
+ debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name);
-// rebuilds inventory
-//
-void Parallaction::exitDialogue() {
+ _gfx->setFont(kFontDialogue);
- refreshInventory(_characterName);
+ if (_vm->getPlatform() == Common::kPlatformPC)
+ showCursor(false);
+ DialogueManager man(this, data);
+ man.run();
+
+ refreshInventory(_characterName);
showCursor(true);
-
+
return;
}
@@ -503,12 +512,8 @@ Answer::Answer() {
}
Answer::~Answer() {
- if (_mood & 0x10)
- delete _following._question;
-
if (_text)
free(_text);
-
}
Question::Question() {
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
index 7b11fbbbed..2e6d9e4820 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk.cpp
@@ -26,6 +26,8 @@
#include "common/stdafx.h"
#include "graphics/iff.h"
+#include "graphics/surface.h"
+
#include "parallaction/parallaction.h"
@@ -90,8 +92,10 @@ void Disk::errorFileNotFound(const char *s) {
}
-void Disk::selectArchive(const char *name) {
- _resArchive.open(name);
+Common::String Disk::selectArchive(const Common::String& name) {
+ Common::String oldName = _resArchive.name();
+ _resArchive.open(name.c_str());
+ return oldName;
}
void Disk::setLanguage(uint16 language) {
@@ -691,33 +695,106 @@ AmigaDisk::~AmigaDisk() {
#define NUM_PLANES 5
-// FIXME: no mask is loaded
-void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize) {
+/*
+ unpackFrame transforms images from 5-bitplanes format to
+ 8-bit color-index mode
+*/
+void AmigaDisk::unpackFrame(byte *dst, byte *src, uint16 planeSize) {
byte s0, s1, s2, s3, s4, mask, t0, t1, t2, t3, t4;
- for (uint32 i = 0; i < numFrames; i++) {
- for (uint32 j = 0; j < planeSize; j++) {
- s0 = src[j];
- s1 = src[j+planeSize];
- s2 = src[j+planeSize*2];
- s3 = src[j+planeSize*3];
- s4 = src[j+planeSize*4];
-
- for (uint32 k = 0; k < 8; k++) {
- mask = 1 << (7 - k);
- t0 = (s0 & mask ? 1 << 0 : 0);
- t1 = (s1 & mask ? 1 << 1 : 0);
- t2 = (s2 & mask ? 1 << 2 : 0);
- t3 = (s3 & mask ? 1 << 3 : 0);
- t4 = (s4 & mask ? 1 << 4 : 0);
- *dst++ = t0 | t1 | t2 | t3 | t4;
+ for (uint32 j = 0; j < planeSize; j++) {
+ s0 = src[j];
+ s1 = src[j+planeSize];
+ s2 = src[j+planeSize*2];
+ s3 = src[j+planeSize*3];
+ s4 = src[j+planeSize*4];
+
+ for (uint32 k = 0; k < 8; k++) {
+ mask = 1 << (7 - k);
+ t0 = (s0 & mask ? 1 << 0 : 0);
+ t1 = (s1 & mask ? 1 << 1 : 0);
+ t2 = (s2 & mask ? 1 << 2 : 0);
+ t3 = (s3 & mask ? 1 << 3 : 0);
+ t4 = (s4 & mask ? 1 << 4 : 0);
+ *dst++ = t0 | t1 | t2 | t3 | t4;
+ }
+
+ }
+
+}
+
+/*
+ patchFrame applies DLTA data (dlta) to specified buffer (dst)
+*/
+void AmigaDisk::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height) {
+
+ uint32 *dataIndex = (uint32*)dlta;
+ uint32 *ofslenIndex = (uint32*)dlta + 8;
+
+ uint16 *base = (uint16*)dlta;
+ uint16 wordsPerLine = bytesPerPlane >> 1;
+
+ for (uint j = 0; j < NUM_PLANES; j++) {
+ uint16 *dst16 = (uint16*)(dst + j * bytesPerPlane * height);
+
+ uint16 *data = base + READ_BE_UINT32(dataIndex);
+ dataIndex++;
+ uint16 *ofslen = base + READ_BE_UINT32(ofslenIndex);
+ ofslenIndex++;
+
+ while (*ofslen != 0xFFFF) {
+
+ uint16 ofs = READ_BE_UINT16(ofslen);
+ ofslen++;
+ uint16 size = READ_BE_UINT16(ofslen);
+ ofslen++;
+
+ while (size > 0) {
+ dst16[ofs] ^= *data++;
+ ofs += wordsPerLine;
+ size--;
}
}
- src += planeSize * NUM_PLANES;
}
+
+}
+
+// FIXME: no mask is loaded
+void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) {
+
+ byte *baseFrame = src;
+ byte *tempBuffer = 0;
+
+ uint16 planeSize = bytesPerPlane * height;
+
+ for (uint32 i = 0; i < numFrames; i++) {
+ if (READ_BE_UINT32(src) == MKID_BE('DLTA')) {
+
+ uint size = READ_BE_UINT32(src + 4);
+
+ if (tempBuffer == 0)
+ tempBuffer = (byte*)malloc(planeSize * NUM_PLANES);
+
+ memcpy(tempBuffer, baseFrame, planeSize * NUM_PLANES);
+
+ patchFrame(tempBuffer, src + 8, bytesPerPlane, height);
+ unpackFrame(dst, tempBuffer, planeSize);
+
+ src += (size + 8);
+ dst += planeSize * 8;
+ } else {
+ unpackFrame(dst, src, planeSize);
+ src += planeSize * NUM_PLANES;
+ dst += planeSize * 8;
+ }
+ }
+
+ if (tempBuffer)
+ free(tempBuffer);
+
}
StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
@@ -737,7 +814,7 @@ StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
uint32 decsize = width * height;
byte *data = (byte*)calloc(decsize, 1);
- unpackBitmap(data, buf, 1, height * bytesPerPlane);
+ unpackBitmap(data, buf, 1, bytesPerPlane, height);
free(buf);
@@ -767,7 +844,7 @@ Cnv* AmigaDisk::makeCnv(Common::SeekableReadStream &stream) {
uint32 decsize = numFrames * width * height;
byte *data = (byte*)calloc(decsize, 1);
- unpackBitmap(data, buf, numFrames, height * bytesPerPlane);
+ unpackBitmap(data, buf, numFrames, bytesPerPlane, height);
free(buf);
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index bfef6d81df..14ea4f0e16 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -60,6 +60,7 @@ protected:
uint32 _fileCursor;
uint32 _fileEndOffset;
+ Common::String _archiveName;
char _archiveDir[MAX_ARCHIVE_ENTRIES][32];
uint32 _archiveLenghts[MAX_ARCHIVE_ENTRIES];
uint32 _archiveOffsets[MAX_ARCHIVE_ENTRIES];
@@ -74,9 +75,11 @@ protected:
public:
Archive();
- void open(const char *file);
+ void open(const char* file);
void close();
+ Common::String name() const;
+
bool openArchivedFile(const char *name);
void closeArchivedFile();
@@ -103,7 +106,7 @@ public:
Disk(Parallaction *vm);
virtual ~Disk();
- void selectArchive(const char *name);
+ Common::String selectArchive(const Common::String &name);
void setLanguage(uint16 language);
virtual Script* loadLocation(const char *name) = 0;
@@ -163,7 +166,9 @@ class AmigaDisk : public Disk {
protected:
Cnv* makeCnv(Common::SeekableReadStream &stream);
StaticCnv* makeStaticCnv(Common::SeekableReadStream &stream);
- void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize);
+ void patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height);
+ void unpackFrame(byte *dst, byte *src, uint16 planeSize);
+ void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height);
Common::SeekableReadStream *openArchivedFile(const char* name, bool errorOnFileNotFound = false);
Font *createFont(const char *name, Common::SeekableReadStream &stream);
void loadMask(const char *name);
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index aab35f8562..59645381b6 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -306,8 +306,6 @@ void Gfx::floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color) {
d += SCREEN_WIDTH;
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -350,8 +348,6 @@ void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) {
d += (SCREEN_WIDTH - q.width());
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -389,8 +385,6 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer)
d += (SCREEN_WIDTH - q.right + q.left);
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -480,6 +474,18 @@ void Gfx::setMousePointer(int16 index) {
//
// Cnv management
//
+void Gfx::flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) {
+
+ StaticCnv scnv;
+
+ scnv._width = cnv->_width;
+ scnv._height = cnv->_height;
+ scnv._data0 = cnv->getFramePtr(frame);
+ scnv._data1 = NULL; // _questioner->field_8[v60->_mood & 0xF];
+
+ flatBlitCnv(&scnv, x, y, buffer);
+}
+
void Gfx::flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer) {
Common::Rect r(cnv->_width, cnv->_height);
r.moveTo(x, y);
@@ -577,30 +583,19 @@ void Gfx::makeCnvFromString(StaticCnv *cnv, char *text) {
}
-void Gfx::displayString(uint16 x, uint16 y, const char *text) {
- assert(_font == _fonts[kFontMenu]);
-
+void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) {
byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
- _font->setColor(1);
+ _font->setColor(color);
_font->drawString(dst, SCREEN_WIDTH, text);
}
void Gfx::displayCenteredString(uint16 y, const char *text) {
uint16 x = (SCREEN_WIDTH - getStringWidth(text)) / 2;
- displayString(x, y, text);
-}
-
-void Gfx::displayBalloonString(uint16 x, uint16 y, const char *text, byte color) {
- assert(_font == _fonts[kFontDialogue]);
-
- byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
-
- _font->setColor(color);
- _font->drawString(dst, SCREEN_WIDTH, text);
+ displayString(x, y, text, 1);
}
-bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color) {
-// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, maxwidth, color);
+bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth) {
+// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, color, wrapwidth);
uint16 lines = 0;
bool rv = false;
@@ -613,10 +608,10 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth,
while (strlen(text) > 0) {
- text = parseNextToken(text, token, 40, " ");
+ text = parseNextToken(text, token, 40, " ", true);
linewidth += getStringWidth(token);
- if (linewidth > maxwidth) {
+ if (linewidth > wrapwidth) {
// wrap line
lines++;
rx = x + 10; // x
@@ -630,7 +625,7 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth,
if (!scumm_stricmp(token, "%p")) {
rv = true;
} else
- displayBalloonString(rx, ry, token, color);
+ displayString(rx, ry, token, color);
rx += getStringWidth(token) + getStringWidth(" ");
linewidth += getStringWidth(" ");
@@ -658,7 +653,7 @@ void Gfx::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* heig
while (strlen(text) != 0) {
- text = parseNextToken(text, token, 40, " ");
+ text = parseNextToken(text, token, 40, " ", true);
w += getStringWidth(token);
if (w > maxwidth) {
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 1f0c467293..d535d3cf05 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -67,7 +67,7 @@ struct PaletteFxRange {
byte _first;
byte _last;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
@@ -165,10 +165,9 @@ public:
// dialogue and text
void drawBalloon(const Common::Rect& r, uint16 arg_8);
- void displayBalloonString(uint16 x, uint16 y, const char *text, byte color);
- void displayString(uint16 x, uint16 y, const char *text);
+ void displayString(uint16 x, uint16 y, const char *text, byte color);
void displayCenteredString(uint16 y, const char *text);
- bool displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color);
+ bool displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth = SCREEN_WIDTH);
uint16 getStringWidth(const char *text);
void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height);
@@ -204,6 +203,8 @@ public:
// DOS version didn't make use of it, but it is probably needed for Amiga stuff.
void flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer);
void blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer);
+ void flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer);
+
// palette
void setPalette(Palette palette, uint32 first = FIRST_BASE_COLOR, uint32 num = BASE_PALETTE_COLORS);
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
index 4d8efa3255..3c54460692 100644
--- a/engines/parallaction/location.cpp
+++ b/engines/parallaction/location.cpp
@@ -38,6 +38,7 @@ void Parallaction::parseLocation(const char *filename) {
_gfx->setFont(kFontLabel);
Script *_locationScript = _disk->loadLocation(filename);
+ _hasLocationSound = false;
fillBuffers(*_locationScript, true);
while (scumm_stricmp(_tokens[0], "ENDLOCATION")) {
@@ -140,16 +141,15 @@ void Parallaction::parseLocation(const char *filename) {
parseAnimation(*_locationScript, _animations, _tokens[1]);
}
if (!scumm_stricmp(_tokens[0], "SOUND")) {
- strcpy(_soundFile, _tokens[1]);
+ if (getPlatform() == Common::kPlatformAmiga) {
+ strcpy(_locationSound, _tokens[1]);
+ _hasLocationSound = true;
+ }
}
if (!scumm_stricmp(_tokens[0], "MUSIC")) {
if (getPlatform() == Common::kPlatformAmiga)
_soundMan->setMusicFile(_tokens[1]);
}
- if (!scumm_stricmp(_tokens[0], "SOUND")) {
-// if (getPlatform() == Common::kPlatformAmiga)
-// _soundMan->loadSfx(_tokens[1], atoi(_tokens[2]));
- }
fillBuffers(*_locationScript, true);
}
@@ -182,14 +182,14 @@ void Parallaction::freeLocation() {
if (_localFlagNames)
delete _localFlagNames;
-
+
// HACK: prevents leakage. A routine like this
// should allocate memory at all, though.
if ((_engineFlags & kEngineQuit) == 0) {
_localFlagNames = new Table(120);
_localFlagNames->addData("visited");
}
-
+
_location._walkNodes.clear();
// TODO (LIST): helperNode should be rendered useless by the use of a Common::List<>
@@ -379,11 +379,11 @@ void Parallaction::changeLocation(char *location) {
runJobs();
_gfx->swapBuffers();
}
-
+
if (_location._comment) {
doLocationEnterTransition();
}
-
+
runJobs();
_gfx->swapBuffers();
@@ -392,7 +392,8 @@ void Parallaction::changeLocation(char *location) {
runCommands(_location._aCommands);
}
-// _soundMan->playSfx(0);
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
debugC(1, kDebugLocation, "changeLocation() done");
@@ -416,7 +417,7 @@ void Parallaction::doLocationEnterTransition() {
debugC(3, kDebugLocation, "skipping location transition");
return; // visited
}
-
+
byte pal[PALETTE_SIZE];
_gfx->buildBWPalette(pal);
_gfx->setPalette(pal);
@@ -437,7 +438,7 @@ void Parallaction::doLocationEnterTransition() {
_gfx->floodFill(Gfx::kBitFront, r, 0);
r.grow(-1);
_gfx->floodFill(Gfx::kBitFront, r, 1);
- _gfx->displayWrappedString(_location._comment, 3, 5, 130, 0);
+ _gfx->displayWrappedString(_location._comment, 3, 5, 0, 130);
_gfx->updateScreen();
waitUntilLeftClick();
diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp
index b1b6fb44c8..427f24a467 100644
--- a/engines/parallaction/menu.cpp
+++ b/engines/parallaction/menu.cpp
@@ -201,7 +201,7 @@ uint16 Menu::chooseLanguage() {
_vm->_gfx->setPalette(_vm->_gfx->_palette);
_vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE");
+ _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE", 1);
_vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
@@ -287,10 +287,10 @@ uint16 Menu::selectGame() {
if (_si != 0) {
// load a game
- _vm->_gfx->displayString(60, 30, loadGameMsg[_language]);
+ _vm->_gfx->displayString(60, 30, loadGameMsg[_language], 1);
} else {
// new game
- _vm->_gfx->displayString(60, 30, newGameMsg[_language]);
+ _vm->_gfx->displayString(60, 30, newGameMsg[_language], 1);
}
_vm->_gfx->updateScreen();
@@ -353,7 +353,7 @@ void Menu::selectCharacter() {
askPassword = false;
_di = 0;
- _vm->_gfx->displayString(60, 30, introMsg1[_language]); // displays message
+ _vm->_gfx->displayString(60, 30, introMsg1[_language], 1); // displays message
_vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_donna_points = 0;
@@ -415,7 +415,7 @@ void Menu::selectCharacter() {
if (askPassword == false) break;
_vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront);
- _vm->_gfx->displayString(60, 30, introMsg2[_language]);
+ _vm->_gfx->displayString(60, 30, introMsg2[_language], 1);
_vm->_gfx->updateScreen();
g_system->delayMillis(2000);
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index e0291c5a2a..c830b575a9 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -84,7 +84,6 @@ Command * _forwardedCommands[20] = {
char _forwardedAnimationNames[20][20];
uint16 _numForwards = 0;
-char _soundFile[20];
uint32 _commandFlags = 0;
uint16 _introSarcData3 = 200;
@@ -158,6 +157,8 @@ int Parallaction::init() {
_localFlagNames = NULL;
initResources();
+ _hasLocationSound = false;
+
_skipMenu = false;
_transCurrentHoverItem = 0;
@@ -369,6 +370,9 @@ void Parallaction::runGame() {
if (_location._comment)
doLocationEnterTransition();
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
+
changeCursor(kCursorArrow);
if (_location._aCommands.size() > 0)
@@ -759,10 +763,13 @@ void Parallaction::changeCharacter(const char *name) {
// character for sanity before memory is freed
freeCharacter();
- _disk->selectArchive((_vm->getPlatform() == Common::kPlatformAmiga) ? "disk0" : "disk1");
+ Common::String oldArchive = _disk->selectArchive((_vm->getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
_vm->_char._ani._cnv = _disk->loadFrames(fullName);
if (!IS_DUMMY_CHARACTER(name)) {
+ if (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT))
+ _disk->selectArchive("disk0");
+
_vm->_char._head = _disk->loadHead(baseName);
_vm->_char._talk = _disk->loadTalk(baseName);
_vm->_char._objs = _disk->loadObjects(baseName);
@@ -774,6 +781,9 @@ void Parallaction::changeCharacter(const char *name) {
if (!(getFeatures() & GF_DEMO))
parseLocation("common");
}
+
+ if (!oldArchive.empty())
+ _disk->selectArchive(oldArchive);
}
strcpy(_characterName1, fullName);
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 38db16ce99..561b15acc9 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -27,8 +27,7 @@
#define PARALLACTION_H
#include "common/str.h"
-#include "gui/dialog.h"
-#include "gui/widget.h"
+
#include "engines/engine.h"
@@ -62,7 +61,7 @@ enum {
enum {
GF_DEMO = 1 << 0,
GF_LANG_EN = 1 << 1,
- GF_LANG_FR = 1 << 2,
+ GF_LANG_FR = 1 << 2,
GF_LANG_DE = 1 << 3,
GF_LANG_IT = 1 << 4,
GF_LANG_MULT = 1 << 5
@@ -177,7 +176,6 @@ extern uint32 _localFlags[];
extern Command *_forwardedCommands[];
extern char _forwardedAnimationNames[][20];
extern uint16 _numForwards;
-extern char _soundFile[];
extern char _slideText[][40];
extern uint16 _introSarcData3; // sarcophagus stuff to be saved
extern uint16 _introSarcData2; // sarcophagus stuff to be saved
@@ -398,7 +396,7 @@ protected: // data
bool _skipMenu;
bool _mouseHidden;
-
+
// input-only
InputData _input;
bool _actionAfterWalk; // actived when the character needs to move before taking an action
@@ -417,6 +415,9 @@ protected: // data
Common::String _saveFileName;
+ bool _hasLocationSound;
+ char _locationSound[50];
+
protected: // members
bool detectGame(void);
@@ -461,15 +462,6 @@ protected: // members
void freeCharacter();
- uint16 askDialoguePassword(Dialogue *q, StaticCnv *face);
- bool displayAnswer(Dialogue *q, uint16 i);
- bool displayAnswers(Dialogue *q);
- void displayQuestion(Dialogue *q, Cnv *cnv);
- uint16 getDialogueAnswer(Dialogue *q, Cnv *cnv);
- int16 selectAnswer(Question *q, StaticCnv *cnv);
- void enterDialogue();
- void exitDialogue();
-
int addInventoryItem(uint16 item);
void dropItem(uint16 item);
int16 pickupItem(Zone *z);
@@ -480,33 +472,6 @@ protected: // members
// FIXME: remove global
extern Parallaction *_vm;
-class SaveLoadChooser : public GUI::Dialog {
- typedef Common::String String;
- typedef Common::StringList StringList;
-protected:
- GUI::ListWidget *_list;
- GUI::ButtonWidget *_chooseButton;
- GUI::GraphicsWidget *_gfxWidget;
- GUI::StaticTextWidget *_date;
- GUI::StaticTextWidget *_time;
- GUI::StaticTextWidget *_playtime;
- GUI::ContainerWidget *_container;
- Parallaction *_vm;
-
- uint8 _fillR, _fillG, _fillB;
-
-public:
- SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine);
- ~SaveLoadChooser();
-
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
- const String &getResultString() const;
- void setList(const StringList& list);
- int runModal();
-
- virtual void reflowLayout();
-};
-
} // namespace Parallaction
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index f044e6c3c7..44aae6c1cc 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -119,24 +119,72 @@ void clearTokens() {
}
-// looks for next token in a string
//
-// scans 's' until one of the stop-chars in 'brk' is found
-// builds a token and return the part of the string which hasn't been parsed
-
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk) {
-
- while (*s != '\0') {
+// Scans 's' until one of the stop-chars in 'brk' is found, building a token.
+// If the routine encounters quotes, it will extract the contained text and
+// make a proper token. When scanning inside quotes, 'brk' is ignored and
+// only newlines are considered stop-chars.
+//
+// The routine returns the unparsed portion of the input string 's'.
+//
+char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes) {
+
+ enum STATES { NORMAL, QUOTED };
+
+ STATES state = NORMAL;
+
+ char *t = s;
+
+ while (count > 0) {
+
+ switch (state) {
+ case NORMAL:
+ if (*s == '\0') {
+ *tok = '\0';
+ return s;
+ }
+
+ if (strchr(brk, *s)) {
+ *tok = '\0';
+ return ++s;
+ }
+
+ if (*s == '"') {
+ if (ignoreQuotes) {
+ *tok++ = *s++;
+ count--;
+ } else {
+ state = QUOTED;
+ s++;
+ }
+ } else {
+ *tok++ = *s++;
+ count--;
+ }
+ break;
- if (brk[0] == *s) break;
- if (brk[1] == *s) break;
- if (brk[2] == *s) break;
+ case QUOTED:
+ if (*s == '\0') {
+ *tok = '\0';
+ return s;
+ }
+ if (*s == '"' || *s == '\n' || *s == '\t') {
+ *tok = '\0';
+ return ++s;
+ }
+
+ *tok++ = *s++;
+ count--;
+ break;
+ }
- *tok++ = *s++;
}
*tok = '\0';
- return s;
+ warning("token was truncated from line '%s'", t);
+
+ return tok;
+
}
uint16 fillTokens(char* line) {
@@ -144,15 +192,6 @@ uint16 fillTokens(char* line) {
uint16 i = 0;
while (strlen(line) > 0 && i < 20) {
line = parseNextToken(line, _tokens[i], 40, " \t\n");
- if (_tokens[i][0] == '"' && _tokens[i][strlen(_tokens[i]) - 1] != '"') {
-
- line = parseNextToken(line, _tokens[i+1], 40, "\"");
- strcat(_tokens[i], _tokens[i+1]);
- _tokens[i][0] = ' ';
- line++;
-
- }
-
line = Common::ltrim(line);
i++;
}
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index e27095bd16..aa3929a52c 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -33,7 +33,7 @@
namespace Parallaction {
uint16 fillBuffers(Common::SeekableReadStream &stream, bool errorOnEOF = false);
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk);
+char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
extern char _tokens[][40];
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index f1dc53539d..2a9431ef94 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -26,6 +26,7 @@
#include "common/stdafx.h"
#include "common/savefile.h"
+#include "gui/dialog.h"
#include "gui/widget.h"
#include "gui/ListWidget.h"
#include "gui/message.h"
@@ -48,6 +49,37 @@ namespace Parallaction {
extern char _gameNames[][20];
+
+class SaveLoadChooser : public GUI::Dialog {
+ typedef Common::String String;
+ typedef Common::StringList StringList;
+protected:
+ GUI::ListWidget *_list;
+ GUI::ButtonWidget *_chooseButton;
+ GUI::GraphicsWidget *_gfxWidget;
+ GUI::StaticTextWidget *_date;
+ GUI::StaticTextWidget *_time;
+ GUI::StaticTextWidget *_playtime;
+ GUI::ContainerWidget *_container;
+ Parallaction *_vm;
+
+ uint8 _fillR, _fillG, _fillB;
+
+public:
+ SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine);
+ ~SaveLoadChooser();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ const String &getResultString() const;
+ void setList(const StringList& list);
+ int runModal();
+
+ virtual void reflowLayout();
+};
+
+
+
+
void Parallaction::doLoadGame(uint16 slot) {
_introSarcData3 = 200;
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
index 7d74a6a59f..d9bd36a1f5 100644
--- a/engines/parallaction/zone.cpp
+++ b/engines/parallaction/zone.cpp
@@ -216,22 +216,13 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
strcpy(vC8, _tokens[1]);
- StaticCnv vE0;
u->door->_cnv = _disk->loadFrames(vC8);
-
- vE0._width = u->door->_cnv->_width;
- vE0._height = u->door->_cnv->_height;
-
uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
- vE0._data0 = u->door->_cnv->getFramePtr(_ax);
-
-// _ax = (z->_flags & kFlagsClosed ? 0 : 1);
-// vE0._data1 = doorcnv->field_8[_ax];
- u->door->_background = (byte*)malloc(vE0._width*vE0._height);
+ u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height);
_gfx->backupDoorBackground(u->door, z->_left, z->_top);
- _gfx->flatBlitCnv(&vE0, z->_left, z->_top, Gfx::kBitBack);
+ _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
}
if (!scumm_stricmp(_tokens[0], "startpos")) {
@@ -304,21 +295,15 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
void Parallaction::displayCharacterComment(ExamineData *data) {
if (data->_description == NULL) return;
- StaticCnv v3C;
- v3C._width = _char._talk->_width;
- v3C._height = _char._talk->_height;
- v3C._data0 = _char._talk->getFramePtr(0);
- v3C._data1 = NULL; //_talk->field_8[0];
-
_gfx->setFont(kFontDialogue);
- _gfx->flatBlitCnv(&v3C, 190, 80, Gfx::kBitFront);
+ _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
int16 v26, v28;
_gfx->getStringExtent(data->_description, 130, &v28, &v26);
Common::Rect r(v28, v26);
r.moveTo(140, 10);
_gfx->drawBalloon(r, 0);
- _gfx->displayWrappedString(data->_description, 140, 10, 130, 0);
+ _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
_gfx->updateScreen();
@@ -359,7 +344,7 @@ void Parallaction::displayItemComment(ExamineData *data) {
r.moveTo(0, 90);
_gfx->drawBalloon(r, 0);
_gfx->flatBlitCnv(_vm->_char._head, 100, 152, Gfx::kBitFront);
- _gfx->displayWrappedString(data->_description, 0, 90, 130, 0);
+ _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
jobEraseAnimations((void*)1, NULL);
_gfx->updateScreen();
@@ -441,10 +426,8 @@ void jobToggleDoor(void *parm, Job *j) {
uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
- v14._data0 = z->u.door->_cnv->getFramePtr(_ax);
-
- _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBit2);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
}
count++;
diff --git a/engines/parallaction/zone.h b/engines/parallaction/zone.h
index 9cc0fd6767..634a1364aa 100644
--- a/engines/parallaction/zone.h
+++ b/engines/parallaction/zone.h
@@ -68,7 +68,8 @@ enum ZoneFlags {
};
-#define NUM_ANSWERS 5
+#define NUM_QUESTIONS 20
+#define NUM_ANSWERS 5
struct Command;
struct Question;
@@ -97,7 +98,9 @@ struct Question {
~Question();
};
-typedef Question Dialogue;
+struct Dialogue {
+ Question *_questions[NUM_QUESTIONS];
+};
struct GetData { // size = 24
uint32 _icon;
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index e0e9415cab..d7882a78fd 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -268,6 +268,8 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_pathRect.top = _vm->getDisplayInfo().pathStartY;
_pathRect.bottom = _vm->_scene->getHeight();
+ _showActors = true;
+
// Get actor resource file context
_actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
if (_actorContext == NULL) {
@@ -1130,7 +1132,7 @@ void Actor::handleSpeech(int msec) {
}
if (_activeSpeech.stringsCount == 0) {
- _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, ticksToMSec(kScriptTimeTicksPerSecond / 3));
+ _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, _vm->ticksToMSec(kScriptTimeTicksPerSecond / 3));
}
return;
@@ -1808,6 +1810,10 @@ void Actor::drawActors() {
return;
}
+ if (!_showActors) {
+ return;
+ }
+
CommonObjectOrderList::iterator drawOrderIterator;
CommonObjectDataPointer drawObject;
int frameNumber;
@@ -2349,6 +2355,11 @@ void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount,
}
void Actor::abortAllSpeeches() {
+ // WORKAROUND: Don't abort speeches in scene 31 (tree with beehive). This prevents the
+ // making fire animation from breaking
+ if (_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 31)
+ return;
+
abortSpeech();
if (_vm->_script->_abortEnabled)
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index 1557abffb9..b9ec62337c 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -612,6 +612,8 @@ public:
void freeObjList();
void loadObjList(int objectCount, int objectsResourceID);
+ void showActors(bool flag) { _showActors = flag; }
+
/*
uint16 _currentFrameIndex;
void frameTest() {
@@ -712,6 +714,7 @@ private:
int _xCellCount;
int _yCellCount;
Rect _pathRect;
+ bool _showActors;
PathDirectionData *_pathDirectionList;
int _pathDirectionListCount;
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 59c3339c9b..d29fc6ebe6 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -445,6 +445,18 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
if (anim->completed < anim->cycles) {
frame = anim->currentFrame;
+
+ // WORKAROUND for a buggy animation in IHNM. Animation 0 in scene 67 (the mob of angry prisoners) should
+ // start from frame 0, not frame 1. Frame 0 is the background of the animation (the mob of prisoners), whereas
+ // the rest of the frames are their animated arms. Therefore, in order for the prisoners to appear correctly,
+ // frame 0 should be displayed as the first frame, but anim->currentframe is set to 1, which means that the
+ // prisoners will never be shown. In the original, the prisoners (first frame in the animation) are shown a
+ // bit after the animation is started (which is wrong again, but not that apparent), whereas in ScummVM the
+ // first frame is never shown. Therefore, make sure that for this animation, frame 0 is shown first
+ if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 4 &&
+ _vm->_scene->currentSceneNumber() == 67 && animId == 0 && anim->completed == 1)
+ frame = 0;
+
// FIXME: if start > 0, then this works incorrectly
decodeFrame(anim, anim->frameOffsets[frame], displayBuffer, _vm->getDisplayWidth() * _vm->getDisplayHeight());
_vm->_frameCount++;
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 631a1a4e83..da06255a82 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -481,6 +481,37 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEMacPatch_Files,
},
+ // Inherit the earth - MAC CD Wyrmkeep version (compressed sound)
+ {
+ {
+ "ite",
+ "Wyrmkeep CD",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"inherit the earth voices.cmp",GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_MACCD,
+ GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEWINDEMO_GameFonts),
+ ITEWINDEMO_GameFonts,
+ &ITEMACCD_GameSound,
+ &ITEMACCD_GameSound,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITEMacPatch_Files),
+ ITEMacPatch_Files,
+ },
+
// Inherit the earth - Linux Demo version
// Note: it should be before GID_ITE_WINDEMO2 version
{
@@ -640,6 +671,42 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD (compressed sound)
+
+ // version is different from the other Wyrmkeep re-releases in that it does
+ // not have any substitute files. Presumably the ite.rsc file has been
+ // modified to include the Wyrmkeep changes. The resource files are little-
+ // endian, except for the voice file which is big-endian.
+ {
+ {
+ "ite",
+ "Multi-OS CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "a6433e34b97b15e64fe8214651012db9", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"inherit the earth voices.cmp",GAME_VOICEFILE | GAME_SWAPENDIAN, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformUnknown,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_MULTICD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITEMACCD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Wyrmkeep Linux CD version
{
{
@@ -671,6 +738,37 @@ static const SAGAGameDescription gameDescriptions[] = {
ITELinPatch_Files,
},
+ // Inherit the earth - Wyrmkeep Linux CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformLinux,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_LINCD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITELinPatch_Files),
+ ITELinPatch_Files,
+ },
+
// Inherit the earth - Wyrmkeep Windows CD version
{
{
@@ -701,6 +799,36 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEWinPatch1_Files,
},
+ // Inherit the earth - Wyrmkeep Windows CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_WINCD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ ARRAYSIZE(ITEWinPatch1_Files),
+ ITEWinPatch1_Files,
+ },
+
// Inherit the earth - DOS CD version
{
{
@@ -731,6 +859,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_G,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD version with digital music
{
{
@@ -762,6 +920,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_G2,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD German version
// reported by mld. Bestsellergamers cover disk
{
@@ -793,6 +982,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD German version (compressed sound)
+ // reported by mld. Bestsellergamers cover disk
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_DE,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD German version with digital music
{
{
@@ -824,6 +1044,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD German version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_DE2,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - CD version
{
{
@@ -854,6 +1105,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - German Floppy version
{
{
@@ -883,6 +1164,35 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - German Floppy version (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_DE,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - German Floppy version with digital music
{
{
@@ -913,6 +1223,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - German Floppy version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_DE2,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Disk version
{
{
@@ -942,6 +1282,35 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Disk version (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_G,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Disk version with digital music
{
{
@@ -972,6 +1341,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Disk version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_G2,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// I Have No Mouth And I Must Scream - Demo version
{
{
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index 191ea4ed61..b93c6017c7 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -341,6 +341,7 @@ int Events::handleOneShot(Event *event) {
_vm->_gfx->setPalette(palPointer);
}
}
+ _vm->_actor->showActors(true);
}
break;
case kAnimEvent:
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index 8658e6d992..0fa7aab742 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -85,7 +85,7 @@ struct PalEntry {
byte red;
byte green;
byte blue;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 03fc0beb7a..55b2b0a996 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -1478,6 +1478,7 @@ void Interface::setOption(PanelButton *panelButton) {
case kTextLoad:
if (_vm->getSaveFilesCount() > 0) {
if (_vm->isSaveListFull() || (_optionSaveFileTitleNumber > 0)) {
+ debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
fileName = _vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
setMode(kPanelMain);
_vm->load(fileName);
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 27729247ef..71b6964530 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -354,7 +354,7 @@ bool Music::isPlaying() {
void Music::play(uint32 resourceId, MusicFlags flags) {
Audio::AudioStream *audioStream = NULL;
MidiParser *parser;
- ResourceContext *context;
+ ResourceContext *context = NULL;
byte *resourceData;
size_t resourceSize;
uint32 loopStart;
@@ -413,7 +413,61 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
loopStart = 4 * 18727;
}
- audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
+ // uncompressed digital music
+ audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
+ } else {
+ // compressed digital music
+ ResourceData * musicResourceData;
+ Common::File *_file;
+ byte compressedHeader[10];
+ GameSoundTypes soundType;
+
+ musicResourceData = _vm->_resource->getResourceData(_musicContext, resourceId - 9);
+ _file = _musicContext->getFile(musicResourceData);
+
+ if (_vm->getMusicInfo() == NULL) {
+ error("RAWInputStream() wrong musicInfo");
+ }
+
+ _file->seek((long)musicResourceData->offset, SEEK_SET);
+
+ _file->read(compressedHeader, 9);
+
+ if (compressedHeader[0] == char(0)) {
+ soundType = kSoundMP3;
+ } else if (compressedHeader[0] == char(1)) {
+ soundType = kSoundOGG;
+ } else if (compressedHeader[0] == char(2)) {
+ soundType = kSoundFLAC;
+ }
+
+ switch (soundType) {
+#ifdef USE_MAD
+ case kSoundMP3:
+ debug(1, "Playing MP3 compressed digital music");
+ audioStream = Audio::makeMP3Stream(_file, musicResourceData->size);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case kSoundOGG:
+ debug(1, "Playing OGG compressed digital music");
+ audioStream = Audio::makeVorbisStream(_file, musicResourceData->size);
+ break;
+#endif
+#ifdef USE_FLAC
+ case kSoundFLAC:
+ debug(1, "Playing FLAC compressed digital music");
+ audioStream = Audio::makeFlacStream(_file, musicResourceData->size);
+ break;
+#endif
+ default:
+ // Unknown compression
+ error("Trying to play a compressed digital music, but the compression is not known");
+ break;
+ }
+
+ }
}
}
}
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 125c85aa9b..96d8608bcd 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -31,6 +31,9 @@
#include "sound/audiocd.h"
#include "sound/mididrv.h"
#include "sound/midiparser.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
+#include "sound/flac.h"
namespace Saga {
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 4e5d98bbf9..16536f762e 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -77,7 +77,7 @@ void Render::drawScene() {
assert(_initialized);
- _frameCount++;
+ _renderedFrameCount++;
backBufferSurface = _vm->_gfx->getBackBuffer();
@@ -183,8 +183,8 @@ void Render::fpsTimerCallback(void *refCon) {
}
void Render::fpsTimer(void) {
- _fps = _frameCount;
- _frameCount = 0;
+ _fps = _renderedFrameCount;
+ _renderedFrameCount = 0;
}
} // End of namespace Saga
diff --git a/engines/saga/render.h b/engines/saga/render.h
index c97de8efc9..4c6e3ee5b1 100644
--- a/engines/saga/render.h
+++ b/engines/saga/render.h
@@ -85,7 +85,7 @@ private:
Surface _backGroundSurface;
unsigned int _fps;
- unsigned int _frameCount;
+ unsigned int _renderedFrameCount;
uint32 _flags;
};
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 9532d2fd56..844a738418 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -152,7 +152,8 @@ enum GameFeatures {
GF_BIG_ENDIAN_DATA = 1 << 0,
GF_WYRMKEEP = 1 << 1,
GF_CD_FX = 1 << 2,
- GF_SCENE_SUBSTITUTES = 1 << 3
+ GF_SCENE_SUBSTITUTES = 1 << 3,
+ GF_COMPRESSED_SOUNDS = 1 << 4
};
enum VerbTypeIds {
@@ -224,7 +225,10 @@ enum GameSoundTypes {
kSoundVOX = 1,
kSoundVOC = 2,
kSoundWAV = 3,
- kSoundMacPCM = 4
+ kSoundMacPCM = 4,
+ kSoundMP3 = 5,
+ kSoundOGG = 6,
+ kSoundFLAC = 7
};
enum TextStringIds {
@@ -335,6 +339,7 @@ enum GameObjectTypes {
enum ScriptTimings {
kScriptTimeTicksPerSecond = (728L/10L),
+ kScriptTimeTicksPerSecondIHNM = 72,
kRepeatSpeedTicks = (728L/10L)/3,
kNormalFadeDuration = 320, // 64 steps, 5 msec each
kQuickFadeDuration = 64, // 64 steps, 1 msec each
@@ -455,10 +460,6 @@ struct SaveGameHeader {
char name[SAVE_TITLE_SIZE];
};
-inline int ticksToMSec(int tick) {
- return tick * 1000 / kScriptTimeTicksPerSecond;
-}
-
inline int clamp(int minValue, int value, int maxValue) {
if (value <= minValue) {
return minValue;
@@ -591,6 +592,13 @@ public:
return _leftMouseButtonPressed || _rightMouseButtonPressed;
}
+ inline int ticksToMSec(int tick) {
+ if (getGameType() == GType_ITE)
+ return tick * 1000 / kScriptTimeTicksPerSecond;
+ else
+ return tick * 1000 / kScriptTimeTicksPerSecondIHNM;
+ }
+
private:
uint _saveFilesMaxCount;
uint _saveFilesCount;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 84d1b45114..362b212b14 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -570,6 +570,8 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_chapterPointsChanged = false;
+ _vm->_actor->showActors(false);
+
if ((_vm->getGameType() == GType_IHNM) && (loadSceneParams->chapter != NO_CHAPTER_CHANGE)) {
if (loadSceneParams->loadFlag != kLoadBySceneNumber) {
error("loadScene wrong usage");
diff --git a/engines/saga/script.h b/engines/saga/script.h
index ec3a7e1cf4..5adfb6181a 100644
--- a/engines/saga/script.h
+++ b/engines/saga/script.h
@@ -598,7 +598,7 @@ private:
void sfClearGlobalFlag(SCRIPTFUNC_PARAMS);
void sfTestGlobalFlag(SCRIPTFUNC_PARAMS);
void sfSetPoints(SCRIPTFUNC_PARAMS);
- void sf103(SCRIPTFUNC_PARAMS);
+ void sfQueueMusic(SCRIPTFUNC_PARAMS);
void sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS);
void SF_stub(const char *name, ScriptThread *thread, int nArgs);
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index e713326661..4954188a6e 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -240,7 +240,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
OPCODE(sfSetSpeechBox),
OPCODE(sfDebugShowData),
OPCODE(sfWaitFramesEsc),
- OPCODE(sf103),
+ OPCODE(sfQueueMusic),
OPCODE(sfDisableAbortSpeeches)
};
if (_vm->getGameType() == GType_IHNM)
@@ -266,7 +266,7 @@ void Script::sfWait(SCRIPTFUNC_PARAMS) {
time = thread->pop();
if (!_skipSpeeches) {
- thread->waitDelay(ticksToMSec(time)); // put thread to sleep
+ thread->waitDelay(_vm->ticksToMSec(time)); // put thread to sleep
}
}
@@ -437,7 +437,7 @@ void Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
int16 cycles = thread->pop();
_vm->_anim->setCycles(animId, cycles);
- _vm->_anim->setFrameTime(animId, ticksToMSec(kRepeatSpeedTicks));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(kRepeatSpeedTicks));
_vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnim(%d, %d)", animId, cycles);
@@ -548,23 +548,30 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
sceneNumber = thread->pop();
entrance = thread->pop();
- if (_vm->getGameType() == GType_IHNM)
+ if (_vm->getGameType() == GType_IHNM) {
transition = thread->pop();
- if (sceneNumber < 0) {
- if (_vm->getGameType() == GType_ITE) {
- _vm->shutDown();
- return;
- }
+ _vm->_gfx->setCursor(kCursorBusy);
}
- if (_vm->getGameType() == GType_IHNM) {
- warning("FIXME: implement sfScriptGotoScene differences for IHNM");
+ if ((_vm->getGameType() == GType_ITE && sceneNumber < 0) ||
+ (_vm->getGameType() == GType_IHNM && sceneNumber == 0)) {
+ // TODO: set creditsFlag to true for IHNM
+ _vm->shutDown();
+ return;
+ }
+ if (_vm->getGameType() == GType_IHNM) {
// Since it doesn't look like the IHNM scripts remove the
// cutaway after the intro, this is probably the best place to
// to it.
- _vm->_anim->clearCutaway();
+ Event event;
+ event.type = kEvTImmediate;
+ event.code = kCutawayEvent;
+ event.op = kEventClear;
+ event.time = 0;
+ event.duration = 0;
+ _vm->_events->queue(&event);
}
// It is possible to leave scene when converse panel is on,
@@ -574,6 +581,7 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
_vm->_interface->setMode(kPanelMain);
}
+ // changeScene calls loadScene which calls setVerb. setVerb resets all pending objects and object flags
if (sceneNumber == -1 && _vm->getGameType() == GType_IHNM) {
// TODO: This is used to return back to the character selection screen in IHNM.
// However, it seems more than this is needed, AM's speech is wrong and no actors
@@ -583,10 +591,19 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
_vm->_scene->changeScene(sceneNumber, entrance, (sceneNumber == ITE_SCENE_ENDCREDIT1) ? kTransitionFade : kTransitionNoFade);
}
- //TODO: placard stuff
+ if (_vm->_interface->getMode() == kPanelPlacard ||
+ _vm->_interface->getMode() == kPanelCutaway ||
+ _vm->_interface->getMode() == kPanelVideo) {
+ _vm->_gfx->showCursor(true);
+ _vm->_interface->setMode(kPanelMain);
+ }
+
_pendingVerb = _vm->_script->getVerbType(kVerbNone);
_currentObject[0] = _currentObject[1] = ID_NOTHING;
- showVerb();
+ showVerb(); // calls setStatusText("")
+
+ if (_vm->getGameType() == GType_IHNM)
+ _vm->_gfx->setCursor(kCursorNormal);
}
// Script function #17 (0x11)
@@ -684,7 +701,7 @@ void Script::sfSetBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
int16 animId = thread->pop();
int16 speed = thread->pop();
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
debug(1, "sfSetBgdAnimSpeed(%d, %d)", animId, speed);
}
@@ -712,7 +729,7 @@ void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
int16 speed = thread->pop();
_vm->_anim->setCycles(animId, cycles);
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
_vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnimSpeed(%d, %d, %d)", animId, cycles, speed);
@@ -1008,7 +1025,13 @@ void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
actor->_actorFlags |= kActorRandom;
}
if (flags & kCycleReverse) {
- actor->_actorFlags |= kActorBackwards;
+ if (_vm->getGameType() == GType_IHNM &&
+ _vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 41) {
+ // Prevent Benny from walking backwards after talking to the child via the monitor. This occurs in the
+ // original as well, and is fixed by not setting the kActorBackwards flag at this point
+ } else {
+ actor->_actorFlags |= kActorBackwards;
+ }
}
actor->_cycleFrameSequence = cycleFrameSequence;
@@ -1075,7 +1098,7 @@ void Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
if (speed >= 0) {
_vm->_anim->setCycles(animId, cycles);
_vm->_anim->stop(animId);
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
}
_vm->_anim->link(animId1, animId);
@@ -2108,8 +2131,41 @@ void Script::sfWaitFramesEsc(SCRIPTFUNC_PARAMS) {
thread->_returnValue = _vm->_framesEsc;
}
-void Script::sf103(SCRIPTFUNC_PARAMS) {
- SF_stub("sf103", thread, nArgs);
+void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
+ int16 param1 = thread->pop();
+ int16 param2 = thread->pop();
+ Event event;
+
+ if (param1 < 0) {
+ _vm->_music->stop();
+ return;
+ }
+
+ if (param1 >= _vm->_music->_songTableLen) {
+ warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
+ } else {
+ _vm->_music->setVolume(-1, 1);
+ event.type = kEvTOneshot;
+ event.code = kMusicEvent;
+ event.param = _vm->_music->_songTable[param1];
+ event.param2 = param2 ? MUSIC_LOOP : MUSIC_NORMAL;
+ event.op = kEventPlay;
+ event.time = _vm->ticksToMSec(500); // I find the delay in the original to be too long, so I've set it to
+ // wait for half the time, which sounds better when chapter points
+ // change
+ // FIXME: If this is too short for other cases apart from chapter
+ // point change, set it back to 1000
+
+ _vm->_events->queue(&event);
+
+ if (!_vm->_scene->haveChapterPointsChanged()) {
+ _vm->_scene->setCurrentMusicTrack(param1);
+ _vm->_scene->setCurrentMusicRepeat(param2);
+ } else {
+ // Don't save this music track when saving in IHNM
+ _vm->_scene->setChapterPointsChanged(false);
+ }
+ }
}
void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) {
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index c0442c75de..ceb1ebf630 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -156,7 +156,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
return false;
}
-
_vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength);
if ((context->fileType & GAME_VOICEFILE) != 0) {
@@ -175,9 +174,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
if (soundResourceLength >= 8) {
if (!memcmp(soundResource, "Creative", 8)) {
resourceType = kSoundVOC;
- } else if (!memcmp(soundResource, "RIFF", 4) != 0) {
+ } else if (!memcmp(soundResource, "RIFF", 4) != 0) {
resourceType = kSoundWAV;
+ }
+
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS) {
+ if (soundResource[0] == char(0)) {
+ resourceType = kSoundMP3;
+ } else if (soundResource[0] == char(1)) {
+ resourceType = kSoundOGG;
+ } else if (soundResource[0] == char(2)) {
+ resourceType = kSoundFLAC;
+ }
}
+
}
@@ -266,6 +276,29 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
free(soundResource);
break;
+ case kSoundMP3:
+ case kSoundOGG:
+ case kSoundFLAC:
+ ResourceData *resourceData;
+ resourceData = _vm->_resource->getResourceData(context, resourceId);
+
+ // Read compressed sfx header
+ readS.seek(1); // Skip compression identifier byte
+ buffer.frequency = readS.readUint16LE();
+ buffer.originalSize = readS.readUint32LE();
+ buffer.sampleBits = readS.readByte();
+ buffer.stereo = (readS.readByte() == char(0)) ? false : true;
+
+ buffer.size = soundResourceLength;
+ buffer.soundType = resourceType;
+ buffer.soundFile = context->getFile(resourceData);
+ buffer.fileOffset = resourceData->offset + 9; // skip compressed sfx header: byte + uint16 + uint32 + byte + byte
+
+ buffer.buffer = NULL;
+
+ result = true;
+ free(soundResource);
+ break;
default:
error("SndRes::load Unknown sound type");
}
@@ -286,7 +319,10 @@ int SndRes::getVoiceLength(uint32 resourceId) {
return -1;
}
- msDouble = (double)buffer.size;
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS))
+ msDouble = (double)buffer.size;
+ else
+ msDouble = (double)buffer.originalSize;
if (buffer.sampleBits == 16) {
msDouble /= 2.0;
}
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index a4ce79b9c4..6c2516c8a3 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -80,7 +80,40 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int
if (!buffer.isSigned)
flags |= Audio::Mixer::FLAG_UNSIGNED;
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ } else {
+ buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
+ Audio::AudioStream *stream = NULL;
+
+ switch (buffer.soundType) {
+#ifdef USE_MAD
+ case kSoundMP3:
+ debug(1, "Playing MP3 compressed sound");
+ stream = Audio::makeMP3Stream(buffer.soundFile, buffer.size);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case kSoundOGG:
+ debug(1, "Playing OGG compressed sound");
+ stream = Audio::makeVorbisStream(buffer.soundFile, buffer.size);
+ break;
+#endif
+#ifdef USE_FLAC
+ case kSoundFLAC:
+ debug(1, "Playing FLAC compressed sound");
+ stream = Audio::makeFlacStream(buffer.soundFile, buffer.size);
+ break;
+#endif
+ default:
+ // Unknown compression
+ error("Trying to play a compressed sound, but the compression is not known");
+ break;
+ }
+
+ if (stream != NULL)
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1, volume, 0, true, false);
+ }
}
void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) {
diff --git a/engines/saga/sound.h b/engines/saga/sound.h
index 3abea583ba..961f8eba56 100644
--- a/engines/saga/sound.h
+++ b/engines/saga/sound.h
@@ -28,7 +28,11 @@
#ifndef SAGA_SOUND_H
#define SAGA_SOUND_H
+#include "common/file.h"
#include "sound/mixer.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
+#include "sound/flac.h"
namespace Saga {
@@ -46,7 +50,11 @@ struct SoundBuffer {
byte *buffer;
size_t size;
+ size_t originalSize;
bool isBigEndian;
+ GameSoundTypes soundType;
+ Common::File *soundFile;
+ size_t fileOffset;
};
enum sndHandleType {
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 2a51464341..c8667d7ab2 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -47,12 +47,12 @@ struct AkosHeader {
uint16 num_anims;
uint16 unk_3;
uint16 codec;
-};
+} PACKED_STRUCT;
struct AkosOffset {
uint32 akcd; // offset into the akcd data
uint16 akci; // offset into the akci data
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index e6ef618a3e..155bbff97f 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -37,7 +37,7 @@ struct CostumeInfo {
uint16 width, height;
int16 rel_x, rel_y;
int16 move_x, move_y;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp
index 424e5d891e..e79cea4359 100644
--- a/engines/scumm/boxes.cpp
+++ b/engines/scumm/boxes.cpp
@@ -80,7 +80,7 @@ struct Box { /* Internal walkbox file format */
uint32 unk3;
} v8;
};
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 8624f80fe7..e9430337ff 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -765,19 +765,22 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
// narrow down the list a bit more.
if (results.size() > 1 && ConfMan.hasKey("platform")) {
Common::Platform platform = Common::parsePlatform(ConfMan.get("platform"));
+ Common::List<DetectorResult> tmp;
+
+ // Copy only those candidates which match the platform setting
for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ) {
- if (x->game.platform != platform) {
- x = results.erase(x);
- } else {
- ++x;
+ if (x->game.platform == platform) {
+ tmp.push_back(*x);
}
}
- }
- // If we narrowed it down too much, abort
- if (results.empty()) {
- warning("Engine_SCUMM_create: Game data inconsistent with platform override");
- return kNoGameDataFoundError;
+ // If we narrowed it down too much, print a warning, else use the list
+ // we just computed as new candidates list.
+ if (tmp.empty()) {
+ warning("Engine_SCUMM_create: Game data inconsistent with platform override");
+ } else {
+ results = tmp;
+ }
}
// Still no unique match found -> print a warning
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 85a7a4b675..16fe72531b 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -825,26 +825,26 @@ PauseDialog::PauseDialog(ScummEngine *scumm, int res)
: InfoDialog(scumm, res) {
}
-void PauseDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == ' ') // Close pause dialog if space key is pressed
+void PauseDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == ' ') // Close pause dialog if space key is pressed
close();
else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
ConfirmDialog::ConfirmDialog(ScummEngine *scumm, int res)
: InfoDialog(scumm, res) {
}
-void ConfirmDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (tolower(ascii) == 'n') {
+void ConfirmDialog::handleKeyDown(Common::KeyState state) {
+ if (state.keycode == Common::KEYCODE_n) {
setResult(0);
close();
- } else if (tolower(ascii) == 'y') {
+ } else if (state.keycode == Common::KEYCODE_y) {
setResult(1);
close();
} else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
#pragma mark -
@@ -892,11 +892,11 @@ void ValueDisplayDialog::reflowLayout() {
_h = height;
}
-void ValueDisplayDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == _incKey || ascii == _decKey) {
- if (ascii == _incKey && _value < _max)
+void ValueDisplayDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == _incKey || state.ascii == _decKey) {
+ if (state.ascii == _incKey && _value < _max)
_value++;
- else if (ascii == _decKey && _value > _min)
+ else if (state.ascii == _decKey && _value > _min)
_value--;
setResult(_value);
@@ -924,8 +924,8 @@ void SubtitleSettingsDialog::handleTickle() {
close();
}
-void SubtitleSettingsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (keycode == 't' && modifiers == Common::KBD_CTRL) {
+void SubtitleSettingsDialog::handleKeyDown(Common::KeyState state) {
+ if (state.keycode == 't' && state.flags == Common::KBD_CTRL) {
cycleValue();
reflowLayout();
@@ -959,11 +959,11 @@ Indy3IQPointsDialog::Indy3IQPointsDialog(ScummEngine *scumm, char* text)
: InfoDialog(scumm, text) {
}
-void Indy3IQPointsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == 'i')
+void Indy3IQPointsDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == 'i')
close();
else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
} // End of namespace Scumm
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index b69e989f8a..23c63d8992 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -169,8 +169,8 @@ public:
setResult(0);
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- setResult(ascii);
+ virtual void handleKeyDown(Common::KeyState state) {
+ setResult(state.ascii);
close();
}
@@ -189,7 +189,7 @@ protected:
class PauseDialog : public InfoDialog {
public:
PauseDialog(ScummEngine *scumm, int res);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
/**
@@ -199,7 +199,7 @@ public:
class ConfirmDialog : public InfoDialog {
public:
ConfirmDialog(ScummEngine *scumm, int res);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
/**
@@ -216,7 +216,7 @@ public:
virtual void handleMouseDown(int x, int y, int button, int clickCount) {
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
virtual void reflowLayout();
@@ -247,7 +247,7 @@ public:
virtual void handleMouseDown(int x, int y, int button, int clickCount) {
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
protected:
int _value;
uint32 _timer;
@@ -259,7 +259,7 @@ protected:
class Indy3IQPointsDialog : public InfoDialog {
public:
Indy3IQPointsDialog(ScummEngine *scumm, char* text);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
} // End of namespace Scumm
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 3ab3e1a2e0..2c7f9ead5b 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -1257,10 +1257,11 @@ struct _lfl_index {
uint16 script_addr[200];
byte sound_lfl[100];
uint16 sound_addr[100];
-} lfl_index;
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
+_lfl_index lfl_index;
bool ScummNESFile::generateResource(int res) {
const LFL *lfl = &lfls[res - 1];
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 54eb470c26..84ad8adb3b 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -250,7 +250,7 @@ protected:
int32 dim2start; //0C
int32 dim2end; //10
byte data[1]; //14
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index 757cf13b7c..d7f4d99754 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -172,7 +172,7 @@ class Win32ResExtractor : public ResExtractor {
byte *memory;
byte *first_resource;
int total_size;
- };
+ } PACKED_STRUCT;
struct WinResource {
char id[256];
@@ -183,7 +183,7 @@ class Win32ResExtractor : public ResExtractor {
bool is_directory;
char *get_resource_id_quoted();
- };
+ } PACKED_STRUCT;
struct Win32IconResDir {
@@ -191,12 +191,12 @@ class Win32ResExtractor : public ResExtractor {
byte height;
byte color_count;
byte reserved;
- };
+ } PACKED_STRUCT;
struct Win32CursorDir {
uint16 width;
uint16 height;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconDirEntry {
union {
@@ -207,14 +207,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 bit_count;
uint32 bytes_in_res;
uint16 res_id;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconDir {
uint16 reserved;
uint16 type;
uint16 count;
Win32CursorIconDirEntry entries[1];
- };
+ } PACKED_STRUCT;
struct Win32CursorIconFileDirEntry {
byte width;
@@ -225,14 +225,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 hotspot_y;
uint32 dib_size;
uint32 dib_offset;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconFileDir {
uint16 reserved;
uint16 type;
uint16 count;
Win32CursorIconFileDirEntry entries[1];
- };
+ } PACKED_STRUCT;
struct Win32BitmapInfoHeader {
uint32 size;
@@ -246,25 +246,25 @@ class Win32ResExtractor : public ResExtractor {
int32 y_pels_per_meter;
uint32 clr_used;
uint32 clr_important;
- };
+ } PACKED_STRUCT;
struct Win32RGBQuad {
byte blue;
byte green;
byte red;
byte reserved;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDirectoryEntry {
uint32 name;
uint32 offset_to_data;
- };
+ } PACKED_STRUCT;
struct Win16NETypeInfo {
uint16 type_id;
uint16 count;
uint32 resloader; // FARPROC16 - smaller? uint16?
- };
+ } PACKED_STRUCT;
struct DOSImageHeader {
uint16 magic;
@@ -286,7 +286,7 @@ class Win32ResExtractor : public ResExtractor {
uint16 oeminfo;
uint16 res2[10];
uint32 lfanew;
- };
+ } PACKED_STRUCT;
struct Win32ImageFileHeader {
uint16 machine;
@@ -296,12 +296,12 @@ class Win32ResExtractor : public ResExtractor {
uint32 number_of_symbols;
uint16 size_of_optional_header;
uint16 characteristics;
- };
+ } PACKED_STRUCT;
struct Win32ImageDataDirectory {
uint32 virtual_address;
uint32 size;
- };
+ } PACKED_STRUCT;
struct Win32ImageOptionalHeader {
uint16 magic;
@@ -335,13 +335,13 @@ class Win32ResExtractor : public ResExtractor {
uint32 loader_flags;
uint32 number_of_rva_and_sizes;
Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- };
+ } PACKED_STRUCT;
struct Win32ImageNTHeaders {
uint32 signature;
Win32ImageFileHeader file_header;
Win32ImageOptionalHeader optional_header;
- };
+ } PACKED_STRUCT;
struct Win32ImageSectionHeader {
byte name[IMAGE_SIZEOF_SHORT_NAME];
@@ -357,14 +357,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 number_of_relocations;
uint16 number_of_linenumbers;
uint32 characteristics;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDataEntry {
uint32 offset_to_data;
uint32 size;
uint32 code_page;
uint32 resource_handle;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDirectory {
uint32 characteristics;
@@ -373,7 +373,7 @@ class Win32ResExtractor : public ResExtractor {
uint16 minor_version;
uint16 number_of_named_entries;
uint16 number_of_id_entries;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp
index 23b325c20b..b6ed064bc9 100644
--- a/engines/scumm/imuse/instrument.cpp
+++ b/engines/scumm/imuse/instrument.cpp
@@ -149,7 +149,7 @@ private:
#include "common/pack-start.h" // START STRUCT PACKING
- struct {
+ struct AdlibInstrument {
byte flags_1;
byte oplvl_1;
byte atdec_1;
@@ -166,10 +166,12 @@ private:
byte flags_b;
struct { byte a,b,c,d,e,f,g,h; } extra_b;
byte duration;
- } _instrument;
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
+ AdlibInstrument _instrument;
+
public:
Instrument_Adlib(const byte *data);
Instrument_Adlib(Serializer *s);
@@ -241,7 +243,7 @@ private:
byte tva_env_sustain_level;
} partial[4];
byte checksum;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 2d7401fe57..ffcb7d03f2 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -75,83 +75,53 @@ void ScummEngine::parseEvents() {
sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot);
_saveLoadFlag = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2;
_saveTemporaryState = false;
- } else if (event.kbd.flags == Common::KBD_CTRL) {
- if (event.kbd.keycode == 'f')
- _fastMode ^= 1;
- else if (event.kbd.keycode == 'g')
- _fastMode ^= 2;
- else if (event.kbd.keycode == 'd')
- _debugger->attach();
- else if (event.kbd.keycode == 's')
- _res->resourceStats();
- else
- _keyPressed = event.kbd; // Normal key press, pass on to the game.
- } else if (event.kbd.flags & Common::KBD_ALT) {
- // Handle KBD_ALT combos. We know that the result must be 273 for Alt-W
- // because that's what MI2 looks for in its "instant win" cheat.
-
- // FIXME: Handle this specific property of MI2 inside processKeyboard ?
- _keyPressed = event.kbd;
- _keyPressed.ascii = event.kbd.keycode + 154;
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'f') {
+ _fastMode ^= 1;
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'g') {
+ _fastMode ^= 2;
+ } else if ((event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'd') ||
+ event.kbd.ascii == '~' || event.kbd.ascii == '#') {
+ _debugger->attach();
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 's') {
+ _res->resourceStats();
} else {
// Normal key press, pass on to the game.
_keyPressed = event.kbd;
}
- if (event.kbd.keycode >= Common::KEYCODE_UP && event.kbd.keycode <= Common::KEYCODE_LEFT) {
- if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) {
- _keyPressed = event.kbd;
- _keyPressed.ascii = event.kbd.ascii - Common::KEYCODE_UP + 54;
- } else if (_game.version < 7) {
- // FIXME: Handle this specific property inside processKeyboard ?
-
- // Don't let game see arrow keys. This fixes bug with up arrow (273)
- // corresponding to the "instant win" cheat in MI2 mentioned above.
- //
- // This is not applicable to V7+ games, which need to see the arrow keys,
- // too, else certain things (derby scene, asterorid lander) won't work.
- _keyPressed.reset();
- }
- }
-
if (_game.heversion >= 80) {
// Keyboard is controlled via variable
- int _keyState = 0;
+ int keyState = 0;
if (event.kbd.keycode == Common::KEYCODE_LEFT) // Left
- _keyState = 1;
+ keyState = 1;
if (event.kbd.keycode == Common::KEYCODE_RIGHT) // Right
- _keyState |= 2;
+ keyState |= 2;
if (event.kbd.keycode == Common::KEYCODE_UP) // Up
- _keyState |= 4;
+ keyState |= 4;
if (event.kbd.keycode == Common::KEYCODE_DOWN) // Down
- _keyState |= 8;
+ keyState |= 8;
if (event.kbd.flags == Common::KBD_SHIFT)
- _keyState |= 16;
+ keyState |= 16;
if (event.kbd.flags == Common::KBD_CTRL)
- _keyState |= 32;
+ keyState |= 32;
- VAR(VAR_KEY_STATE) = _keyState;
+ VAR(VAR_KEY_STATE) = keyState;
}
- // FIXME: There is a discrepancy between EVENT_KEYDOWN and EVENT_KEYUP here:
- // For EVENT_KEYDOWN, we use _keyPressed.keycode, which has potentially been
- // modified, while for EVENT_KEYUP we use the unfiltered event.kbd.keycode.
- // This could lead problems (like a key becoming 'stuck').
-
- // FIXME #2: We are mixing ascii and keycode values here. We probably should
- // be using keycodes, but at least INSANE checks for "Shift-V" by looking for
- // the 'V' key being pressed. It would be easy to solve that by also storing the
- // the modifier flags. However, since getKeyState() is also called by scripts,
- // we have to be very careful with semantic changes.
- // Nevertheless, it's bad to rely on "ascii" holdoing keycode values for special
- // keys (like the function keys), so this should be fixed.
-
+ // FIXME: We are using ASCII values to index the _keyDownMap here,
+ // yet later one code which checks _keyDownMap will use KEYCODEs
+ // to do so. That is, we are mixing ascii and keycode values here,
+ // which is bad. We probably should be only using keycodes, but at
+ // least INSANE checks for "Shift-V" by looking for the 'V' key
+ // being pressed. It would be easy to solve that by also storing
+ // the modifier flags. However, since getKeyState() is also called
+ // by scripts, we have to be careful with semantic changes.
if (_keyPressed.ascii >= 512)
debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii);
else
@@ -159,11 +129,9 @@ void ScummEngine::parseEvents() {
break;
case Common::EVENT_KEYUP:
- // FIXME: for some reason Common::KBD_ALT is set sometimes
- // possible to a bug in sdl-common.cpp
- if (event.kbd.ascii >= 512)
+ if (event.kbd.ascii >= 512) {
debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii);
- else {
+ } else {
_keyDownMap[event.kbd.ascii] = false;
// Due to some weird bug with capslock key pressed
@@ -173,6 +141,8 @@ void ScummEngine::parseEvents() {
// both upper and lower letters are unpressed on keyup event
//
// Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights"
+ //
+ // Fingolfin remarks: This wouldn't be a problem if we used keycodes.
_keyDownMap[toupper(event.kbd.ascii)] = false;
}
break;
@@ -204,24 +174,21 @@ void ScummEngine::parseEvents() {
_rightBtnPressed &= ~msDown;
break;
- // The following two cases enable dialog choices to be
- // scrolled through in the SegaCD version of MI
- // as nothing else uses the wheel don't bother
- // checking the gameid. Values are taken from script-14.
-
+ // The following two cases enable dialog choices to be scrolled
+ // through in the SegaCD version of MI. Values are taken from script-14.
+ // See bug report #1193185 for details.
case Common::EVENT_WHEELDOWN:
- _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7'
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD)
+ _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7'
break;
case Common::EVENT_WHEELUP:
- _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6'
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD)
+ _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6'
break;
case Common::EVENT_QUIT:
- if (ConfMan.getBool("confirm_exit"))
- confirmExitDialog();
- else
- _quit = true;
+ _quit = true;
break;
default:
@@ -446,11 +413,6 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
// Fall back to default behavior
ScummEngine::processKeyboard(lastKeyHit);
- // Store the input type. So far we can't distinguish
- // between 1, 3 and 5.
- // 1) Verb 2) Scene 3) Inv. 4) Key
- // 5) Sentence Bar
-
if (VAR_KEYPRESS != 0xFF && _mouseAndKeyboardStat) { // Key Input
if (315 <= _mouseAndKeyboardStat && _mouseAndKeyboardStat <= 323) {
// Convert F-Keys for V1/V2 games (they start at 1)
@@ -503,12 +465,6 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (_game.id == GID_CMI)
mainmenuKeyEnabled = true;
-/*
- FIXME: We also used to force-enable F5 in Sam&Max and HE >= 72 games -- why?
- if ((_game.version <= 3) || (_game.id == GID_SAMNMAX) || (_game.id == GID_CMI) || (_game.heversion >= 72))
- mainmenuKeyEnabled = true;
-*/
-
if (mainmenuKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == 0)) {
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0);
@@ -569,15 +525,35 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_CHARINC != 0xFF)
VAR(VAR_CHARINC) = _defaultTalkDelay;
- } else if (lastKeyHit.ascii == '~' || lastKeyHit.ascii == '#') { // Debug console
- _debugger->attach();
-
} else {
- // FIXME: Possibly convert even more keycode/ascii pairs to their SCUMM counterparts?
- if (lastKeyHit.keycode >= Common::KEYCODE_F1 && lastKeyHit.keycode <= Common::KEYCODE_F9)
+
+ if (lastKeyHit.keycode >= Common::KEYCODE_F1 &&
+ lastKeyHit.keycode <= Common::KEYCODE_F9) {
_mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_F1 + 315;
- else
+
+ } else if (_game.id == GID_MONKEY2 && (lastKeyHit.flags & Common::KBD_ALT)) {
+ // Handle KBD_ALT combos in MI2. We know that the result must be 273 for Alt-W
+ // because that's what MI2 looks for in its "instant win" cheat.
+ _mouseAndKeyboardStat = lastKeyHit.keycode + 154;
+
+ } else if (lastKeyHit.keycode >= Common::KEYCODE_UP &&
+ lastKeyHit.keycode <= Common::KEYCODE_LEFT) {
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) {
+ // Map arrow keys to number keys in the SEGA version of MI to support
+ // scrolling to conversation choices. See bug report #1193185 for details.
+ _mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_UP + 54;
+ } else if (_game.version >= 7) {
+ // Don't let pre-V7 game see arrow keys. This fixes bug with up arrow (273)
+ // corresponding to the "instant win" cheat in MI2 mentioned above.
+ //
+ // This is not applicable to V7+ games, which need to see the arrow keys,
+ // too, else certain things (derby scene, asterorid lander) won't work.
+ _mouseAndKeyboardStat = lastKeyHit.ascii;
+ }
+
+ } else {
_mouseAndKeyboardStat = lastKeyHit.ascii;
+ }
}
}
diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h
index 008c2995e5..6723081dfe 100644
--- a/engines/scumm/intern.h
+++ b/engines/scumm/intern.h
@@ -313,7 +313,7 @@ protected:
virtual void readGlobalObjects();
virtual void loadCharset(int no);
- virtual void runInputScript(int a, int cmd, int mode);
+ virtual void runInputScript(int clickArea, int val, int mode);
virtual void runInventoryScript(int i);
virtual int getVar();
@@ -554,7 +554,7 @@ protected:
int16 type;
int16 dim2;
byte data[1];
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index d7b858a312..d8ef669410 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -82,6 +82,12 @@ MODULE_OBJS += \
smush/saud_channel.o \
smush/smush_mixer.o \
smush/smush_font.o
+
+ifdef USE_ARM_SMUSH_ASM
+MODULE_OBJS += \
+ smush/codec47ARM.o
+endif
+
endif
ifndef DISABLE_HE
diff --git a/engines/scumm/object.h b/engines/scumm/object.h
index bf38d42289..f27e6a501e 100644
--- a/engines/scumm/object.h
+++ b/engines/scumm/object.h
@@ -91,7 +91,7 @@ struct RoomHeader {
uint32 transparency;
} v8;
};
-};
+} PACKED_STRUCT;
struct CodeHeader {
union {
@@ -123,7 +123,7 @@ struct CodeHeader {
} v7;
};
-};
+} PACKED_STRUCT;
struct ImageHeader { /* file format */
union {
@@ -172,7 +172,7 @@ struct ImageHeader { /* file format */
} hotspot[15];
} v8;
};
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h
index 43771d295f..cd88d57602 100644
--- a/engines/scumm/player_v2.h
+++ b/engines/scumm/player_v2.h
@@ -61,7 +61,7 @@ struct channel_data {
uint16 unknown[4]; // 38 - 44
uint16 music_timer; // 46
uint16 music_script_nr; // 48
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 9578b05c1f..9d0d0ad654 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -200,8 +200,6 @@ bool ScummEngine::loadState(int slot, bool compat) {
_engineStartTime = _system->getMillis() / 1000;
}
- _dialogStartTime = _system->getMillis() / 1000;
-
// Due to a bug in scummvm up to and including 0.3.0, save games could be saved
// in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here
if (hdr.ver == VER(7))
@@ -213,7 +211,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
// state for temporary state saves - such as certain cutscenes in DOTT,
// FOA, Sam and Max, etc.
//
- // Thusly, we should probably not stop music when restoring from one of
+ // Thus, we should probably not stop music when restoring from one of
// these saves. This change stops the Mole Man theme from going quiet in
// Sam & Max when Doug tells you about the Ball of Twine, as mentioned in
// patch #886058.
@@ -378,9 +376,6 @@ bool ScummEngine::loadState(int slot, bool compat) {
_sound->pauseSounds(false);
- _engineStartTime += _system->getMillis() / 1000 - _dialogStartTime;
- _dialogStartTime = 0;
-
return true;
}
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 46e4e64347..cc56adf622 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -1156,39 +1156,39 @@ void ScummEngine::checkAndRunSentenceScript() {
runScript(sentenceScript, 0, 0, localParamList);
}
-void ScummEngine_v2::runInputScript(int a, int cmd, int mode) {
+void ScummEngine_v2::runInputScript(int clickArea, int val, int mode) {
int args[24];
int verbScript;
verbScript = 4;
- VAR(VAR_CLICK_AREA) = a;
- switch (a) {
- case 1: // Verb clicked
- VAR(VAR_CLICK_VERB) = cmd;
+ VAR(VAR_CLICK_AREA) = clickArea;
+ switch (clickArea) {
+ case kVerbClickArea: // Verb clicked
+ VAR(VAR_CLICK_VERB) = val;
break;
- case 3: // Inventory clicked
- VAR(VAR_CLICK_OBJECT) = cmd;
+ case kInventoryClickArea: // Inventory clicked
+ VAR(VAR_CLICK_OBJECT) = val;
break;
}
memset(args, 0, sizeof(args));
- args[0] = a;
- args[1] = cmd;
+ args[0] = clickArea;
+ args[1] = val;
args[2] = mode;
if (verbScript)
runScript(verbScript, 0, 0, args);
}
-void ScummEngine::runInputScript(int a, int cmd, int mode) {
+void ScummEngine::runInputScript(int clickArea, int val, int mode) {
int args[24];
int verbScript;
verbScript = VAR(VAR_VERB_SCRIPT);
memset(args, 0, sizeof(args));
- args[0] = a;
- args[1] = cmd;
+ args[0] = clickArea;
+ args[1] = val;
args[2] = mode;
// All HE 72+ games but only some HE 71 games.
if (_game.heversion >= 71) {
@@ -1198,18 +1198,18 @@ void ScummEngine::runInputScript(int a, int cmd, int mode) {
// Macintosh verison of indy3ega used different interface, so adjust values.
if (_game.id == GID_INDY3 && _game.platform == Common::kPlatformMacintosh) {
- if (a == 1 && (cmd >= 101 && cmd <= 108)) {
- if (cmd == 107) {
+ if (clickArea == kVerbClickArea && (val >= 101 && val <= 108)) {
+ if (val == 107) {
VAR(67) -= 2;
inventoryScript();
return;
- } else if (cmd == 108) {
+ } else if (val == 108) {
VAR(67) += 2;
inventoryScript();
return;
} else {
args[0] = 3;
- args[1] = VAR(83 + (cmd - 101));
+ args[1] = VAR(83 + (val - 101));
}
}
}
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 840940caa3..cd48ef4d02 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Fri Jun 08 10:51:50 2007
+ This file was generated by the md5table tool on Mon Jul 2 22:44:41 2007
DO NOT EDIT MANUALLY!
*/
@@ -254,6 +254,7 @@ static const MD5Table md5table[] = {
{ "6886e5d08cee329b1f2e743ae2e3ceed", "monkey2", "", "", 11135, Common::DE_DEU, Common::kPlatformPC },
{ "695fe0b3963333b7e15b37514db3c745", "thinkerk", "", "Demo", 29789, Common::EN_USA, Common::kPlatformUnknown },
{ "697c9b7c55a05d8199c48b48e379d2c8", "puttmoon", "", "", -1, Common::HB_ISR, Common::kPlatformPC },
+ { "69d70269fafc4445adbb0d223e4f9a3f", "indy3", "EGA", "EGA", 5361, Common::EN_ANY, Common::kPlatformPC },
{ "69ea626f1f87eecb78ea0d6c6b983a1d", "monkey2", "", "", -1, Common::IT_ITA, Common::kPlatformPC },
{ "69ffe29185b8d71f09f6199f8b2a87cb", "lost", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "6a30a07f353a75cdc602db27d73e1b42", "puttputt", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -486,7 +487,7 @@ static const MD5Table md5table[] = {
{ "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", -1, Common::EN_USA, Common::kPlatformNES },
{ "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown },
{ "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC },
- { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns },
+ { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns },
{ "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", 8955, Common::IT_ITA, Common::kPlatformPC },
{ "da669b20271b85182e9c17a2a37ea02e", "monkey2", "", "", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "db21a6e338fe3b70c2723b6530865bf2", "PuttTime", "HE 85", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 4b3a365394..2140b15544 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -120,7 +120,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_gdi = new Gdi(this);
}
_res = new ResourceManager(this);
-
+
// Convert MD5 checksum back into a digest
for (int i = 0; i < 16; ++i) {
char tmpStr[3] = "00";
@@ -2236,31 +2236,39 @@ void ScummEngine::startManiac() {
#pragma mark --- GUI ---
#pragma mark -
-int ScummEngine::runDialog(Dialog &dialog) {
- _dialogStartTime = _system->getMillis() / 1000;
-
- // Pause sound & video
- bool old_soundsPaused = _sound->_soundsPaused;
- _sound->pauseSounds(true);
+void ScummEngine::pauseEngineIntern(bool pause) {
+ if (pause) {
+ // Record start of the pause, so that we can later
+ // adjust _engineStartTime accordingly.
+ _pauseStartTime = _system->getMillis();
- bool visible = CursorMan.isVisible();
+ // Pause sound & video
+ _oldSoundsPaused = _sound->_soundsPaused;
+ _sound->pauseSounds(true);
+
+ } else {
+ // Update the screen to make it less likely that the player will see a
+ // brief cursor palette glitch when the GUI is disabled.
+ _system->updateScreen();
- // Open & run the dialog
- int result = dialog.runModal();
+ // Resume sound & video
+ _sound->pauseSounds(_oldSoundsPaused);
- // Restore old cursor
- updateCursor();
- CursorMan.showMouse(visible);
+ // Adjust engine start time
+ _engineStartTime += (_system->getMillis() - _pauseStartTime) / 1000;
+ _pauseStartTime = 0;
+ }
+}
- // Update the screen to make it less likely that the player will see a
- // brief cursor palette glitch when the GUI is disabled.
- _system->updateScreen();
+int ScummEngine::runDialog(Dialog &dialog) {
+ // Pause engine
+ pauseEngine(true);
- // Resume sound & video
- _sound->pauseSounds(old_soundsPaused);
+ // Open & run the dialog
+ int result = dialog.runModal();
- _engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime;
- _dialogStartTime = 0;
+ // Resume engine
+ pauseEngine(false);
// Return the result
return result;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 8c8124714d..4146846856 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -406,9 +406,6 @@ class ScummEngine : public Engine {
friend class CharsetRenderer;
friend class ResourceManager;
- GUI::Debugger *getDebugger();
- void errorString(const char *buf_input, char *buf_output);
-
public:
/* Put often used variables at the top.
* That results in a shorter form of the opcode
@@ -437,17 +434,20 @@ public:
protected:
VirtualMachineState vm;
+
+ bool _oldSoundsPaused;
public:
// Constructor / Destructor
ScummEngine(OSystem *syst, const DetectorResult &dr);
virtual ~ScummEngine();
- /** Startup function, main loop. */
- int go();
-
- // Init functions
- int init();
+ // Engine APIs
+ virtual int init();
+ virtual int go();
+ virtual void errorString(const char *buf_input, char *buf_output);
+ virtual GUI::Debugger *getDebugger();
+ virtual void pauseEngineIntern(bool pause);
protected:
virtual void setupScumm();
@@ -638,7 +638,7 @@ protected:
void saveInfos(Common::OutSaveFile* file);
int32 _engineStartTime;
- int32 _dialogStartTime;
+ int32 _pauseStartTime;
protected:
/* Script VM - should be in Script class */
@@ -863,7 +863,7 @@ protected:
void verbMouseOver(int verb);
int findVerbAtPos(int x, int y) const;
virtual void drawVerb(int verb, int mode);
- virtual void runInputScript(int a, int cmd, int mode);
+ virtual void runInputScript(int clickArea, int val, int mode);
void restoreVerbBG(int verb);
void drawVerbBitmap(int verb, int x, int y);
int getVerbSlot(int id, int mode) const;
diff --git a/engines/scumm/smush/codec47.cpp b/engines/scumm/smush/codec47.cpp
index 34d61d1c8a..6904e96c11 100644
--- a/engines/scumm/smush/codec47.cpp
+++ b/engines/scumm/smush/codec47.cpp
@@ -342,6 +342,24 @@ void Codec47Decoder::makeTables47(int width) {
} while (c < 32768);
}
+#ifdef USE_ARM_SMUSH_ASM
+
+extern "C" void ARM_Smush_decode2( byte *dst,
+ const byte *src,
+ int width,
+ int height,
+ const byte *param_ptr,
+ int16 *_table,
+ byte *_tableBig,
+ int32 offset1,
+ int32 offset2,
+ byte *_tableSmall);
+
+#define decode2(SRC,DST,WIDTH,HEIGHT,PARAM) \
+ ARM_Smush_decode2(SRC,DST,WIDTH,HEIGHT,PARAM,_table,_tableBig, \
+ _offset1,_offset2,_tableSmall)
+
+#else
void Codec47Decoder::level3(byte *d_dst) {
int32 tmp;
byte code = *_d_src++;
@@ -503,6 +521,7 @@ void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height,
dst += next_line;
} while (--bh);
}
+#endif
Codec47Decoder::Codec47Decoder(int width, int height) {
_width = width;
diff --git a/engines/scumm/smush/codec47ARM.s b/engines/scumm/smush/codec47ARM.s
new file mode 100644
index 0000000000..d96049a32c
--- /dev/null
+++ b/engines/scumm/smush/codec47ARM.s
@@ -0,0 +1,372 @@
+@ ScummVM - Graphic Adventure Engine
+@
+@ ScummVM is the legal property of its developers, whose names
+@ are too numerous to list here. Please refer to the COPYRIGHT
+@ file distributed with this source distribution.
+@
+@ This program is free software@ you can redistribute it and/or
+@ modify it under the terms of the GNU General Public License
+@ as published by the Free Software Foundation@ either version 2
+@ of the License, or (at your option) any later version.
+@
+@ This program is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY@ without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@ GNU General Public License for more details.
+@
+@ You should have received a copy of the GNU General Public License
+@ along with this program@ if not, write to the Free Software
+@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+@
+@ $URL:$
+@ $Id:$
+@
+@ @author Robin Watts (robin@wss.co.uk)
+@
+@ This file, provides an ARM optimised version of sections of codec47.cpp.
+@ The algorithm is essentially the same as that within codec47.cpp
+@ so to understand this file you should understand codec47.cpp first.
+
+ .text
+
+ .global ARM_Smush_decode2
+
+ARM_Smush_decode2:
+ @ r0 = dst
+ @ r1 = src
+ @ r2 = width
+ @ r3 = height
+ @ r4 = param
+ @ <> = _table
+ @ <> = _tableBig
+ @ <> = _offset1
+ @ <> = _offset2
+ @ <> = _tableSmall
+ STMFD r13!,{r2,r4-r11,R14}
+
+ LDR r4,[r13,#(9+1)*4] @ r4 = param
+ @ stall
+ @ stall
+ SUB r4,r4,#0xF8
+
+ @ r0 = dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = height
+ @ r4 = param
+ ADD r7,r2,#7 @ r14 = bw
+ MOV r7,r7,LSR #3
+y_loop:
+x_loop:
+ @ LEVEL 1
+ LDRB r6,[r1],#1 @ r6 = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level1codeSMALL
+ CMP r6,#0xFC
+ BLT level1codeMID
+ BEQ level1codeFC
+ CMP r6,#0xFE
+ BGT level1codeFF
+ BEQ level1codeFE
+level1codeFD:
+ LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
+ LDR r8,[r13,#(9+1+2)*4] @ r8 = _tableBig
+ @ stall
+ ADD r12,r6,r6,LSL #1 @ r12= tmp*3
+ ADD r6,r6,r12,LSL #5 @ r6 = tmp*97
+ ADD r8,r8,r6,LSL #2 @ r8 = _tableBig + tmp*388
+ LDRB r9,[r8,#384] @ r9 = l = tmp_ptr[384]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ ADD r12,r8,#384 @ r12= &tmp_ptr[384]
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level1codeFD_over1
+level1codeFD_loop1:
+ LDRB r10,[r8],#1
+ LDRB r11,[r8],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level1codeFD_loop1
+level1codeFD_over1:
+ LDRB r9,[r12,#1] @ r9 = l = tmp_ptr[385]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ SUB r12,r12,#384-128 @ r12= &tmp_ptr[128]
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level1codeFD_over2
+level1codeFD_loop2:
+ LDRB r10,[r12],#1
+ LDRB r11,[r12],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level1codeFD_loop2
+level1codeFD_over2:
+level1_end:
+
+ ADD r0,r0,#8
+ SUBS r7,r7,#1
+ BGT x_loop
+
+ ADD r7,r2,#7
+ MOV r7,r7,LSR #3
+ ADD r0,r0,r2,LSL #3
+ SUB r0,r0,r7,LSL #3 @ r0 = dst += next_line
+ SUBS r3,r3,#8 @ if (--bh > 0)
+ BGT y_loop @ loop back
+
+ LDMFD r13!,{r2,r4-r11,PC}
+
+level1codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level1codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ SUB r11,r2,#7 @ r11 = _d_pitch-7
+ ADD r9,r9,r0 @ tmp2 = _d_dst+_offset
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
+ @ r8 = &_dst[tmp2]
+ MOV r12,#8
+level1codeSMALL_loop:
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],#1 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[0] = r5
+ STRB r6, [r0],#1 @ d_dst[1] = r6
+ STRB r9, [r0],#1 @ d_dst[2] = r9
+ STRB r10,[r0],#1 @ d_dst[3] = r10
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[4] = r5
+ STRB r6, [r0],#1 @ d_dst[5] = r6
+ STRB r9, [r0],#1 @ d_dst[6] = r9
+ STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
+ SUBS r12,r12,#1
+ BGT level1codeSMALL_loop
+ SUB r0,r0,r2,LSL #3 @ revert d_dst
+ B level1_end
+
+level1codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+level1codeFE:
+ LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
+ MOV r12,#8
+ SUB r11,r2,#7 @ r11 = _d_pitch-7
+level1codeMID_loop:
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],r11
+ SUBS r12,r12,#1
+ BGT level1codeMID_loop
+ SUB r0,r0,r2,LSL #3 @ revert d_dst
+ B level1_end
+
+level1codeFF:
+ BL level2
+ ADD r0,r0,#4
+ BL level2
+ ADD r0,r0,r2,LSL #2
+ SUB r0,r0,#4
+ BL level2
+ ADD r0,r0,#4
+ BL level2
+ SUB r0,r0,#4
+ SUB r0,r0,r2,LSL #2
+ B level1_end
+
+level2:
+ @ r0 = _d_dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = PRESERVE
+ @ r4 = param
+ @ r7 = PRESERVE
+ @ r14= return address
+ LDRB r6,[r1],#1 @ r6 = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level2codeSMALL
+ CMP r6,#0xFC
+ BLT level2codeMID
+ BEQ level2codeFC
+ CMP r6,#0xFE
+ BGT level2codeFF
+ BEQ level2codeFE
+level2codeFD:
+ LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
+ LDR r8,[r13,#(9+1+5)*4] @ r8 = _tableSmall
+ @ stall
+ @ stall
+ ADD r8,r8,r6,LSL #7 @ r8 = _tableSmall + tmp*128
+ LDRB r9,[r8,#96] @ r9 = l = tmp_ptr[96]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ ADD r12,r8,#32 @ r12 = tmp_ptr + 32
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level2codeFD_over1
+level2codeFD_loop1:
+ LDRB r10,[r8],#1
+ LDRB r11,[r8],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level2codeFD_loop1
+level2codeFD_over1:
+ LDRB r9,[r12,#97-32] @ r9 = l = tmp_ptr[97]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ MOVEQ PC,R14
+level2codeFD_loop2:
+ LDRB r10,[r12],#1
+ LDRB r11,[r12],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level2codeFD_loop2
+
+ MOV PC,R14
+
+level2codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level2codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ SUB r11,r2,#3 @ r11 = _d_pitch-3
+ ADD r9,r9,r0 @ tmp2 = _d_dst + _table[code]
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset1
+ @ r8 = &_dst[tmp2]
+ MOV r12,#4
+level2codeSMALL_loop:
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[4] = r5
+ STRB r6, [r0],#1 @ d_dst[5] = r6
+ STRB r9, [r0],#1 @ d_dst[6] = r9
+ STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
+ SUBS r12,r12,#1
+ BGT level2codeSMALL_loop
+ SUB r0,r0,r2,LSL #2 @ revert d_dst
+ MOV PC,R14
+
+level2codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+level2codeFE:
+ LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
+ MOV r12,#4
+ SUB r11,r2,#3 @ r11 = _d_pitch-7
+level2codeMID_loop:
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],r11
+ SUBS r12,r12,#1
+ BGT level2codeMID_loop
+ SUB r0,r0,r2,LSL #2 @ revert d_dst
+ MOV PC,R14
+
+level2codeFF:
+ MOV r5,r14
+ BL level3
+ ADD r0,r0,#2
+ BL level3
+ ADD r0,r0,r2,LSL #1
+ SUB r0,r0,#2
+ BL level3
+ ADD r0,r0,#2
+ BL level3
+ SUB r0,r0,#2
+ SUB r0,r0,r2,LSL #1
+ MOV PC,R5
+
+level3:
+ @ r0 = _d_dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = PRESERVE
+ @ r4 = param
+ @ r5 = preserve
+ @ r7 = PRESERVE
+ @ r14= return address
+ LDRB r6,[r1],#1 @ r6 = code = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level3codeSMALL
+ CMP r6,#0xFC
+ BLT level3codeMID
+ BEQ level3codeFC
+ CMP r6,#0xFE
+ BGT level3codeFF
+level3codeFE:
+ LDRB r6,[r1],#1 @ r6 = t = *_d_src++
+level3codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRLTB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+ @ stall
+ @ stall
+ STRB r6,[r0,#1]
+ STRB r6,[r0],r2
+ STRB r6,[r0,#1]
+ STRB r6,[r0],-r2
+ MOV PC,R14
+
+level3codeFF:
+ LDRB r6,[r1],#1
+ LDRB r9,[r1],#1
+ LDRB r10,[r1],#1
+ LDRB r11,[r1],#1
+ STRB r9, [r0,#1]
+ STRB r6, [r0],r2
+ STRB r11,[r0,#1]
+ STRB r10,[r0],-r2
+ MOV PC,R14
+
+level3codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level3codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ ADD r9,r9,r0 @ tmp2 = _d_dst+offset
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
+ @ r8 = &_dst[tmp2]
+ LDRB r6, [r8,#1] @ r6 = d_dst[tmp2+1]
+ LDRB r9, [r8],r2 @ r9 = d_dst[tmp2+0]
+ LDRB r10,[r8,#1] @ r10= d_dst[tmp2+dst+1]
+ LDRB r11,[r8],-r2 @ r11= d_dst[tmp2+dst]
+ STRB r6, [r0,#1] @ d_dst[1 ] = r6
+ STRB r9, [r0],r2 @ d_dst[0 ] = r9
+ STRB r10,[r0,#1] @ d_dst[dst+1] = r10
+ STRB r11,[r0],-r2 @ d_dst[dst ] = r11
+ MOV PC,R14
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index edd8004d30..56ee454240 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -385,7 +385,7 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) {
runObject(_activeInventory, _activeVerb);
}
} else {
- runInputScript(3, object, 0);
+ runInputScript(kInventoryClickArea, object, 0);
}
}
}
@@ -537,7 +537,7 @@ void ScummEngine::checkExecVerbs() {
if (vs->verbid && vs->saveid == 0 && vs->curmode == 1) {
if (_mouseAndKeyboardStat == vs->key) {
// Trigger verb as if the user clicked it
- runInputScript(1, vs->verbid, 1);
+ runInputScript(kVerbClickArea, vs->verbid, 1);
return;
}
}
@@ -580,14 +580,14 @@ void ScummEngine::checkExecVerbs() {
// Check if person is available (see script 23 from ZAK_FM-TOWNS and script 4 from ZAK_PC).
// Zak: Var[144 Bit 15], Annie: Var[145 Bit 0], Melissa: Var[145 Bit 1], Leslie: Var[145 Bit 2]
if (!readVar(0x890E + fKey)) {
- runInputScript(1, 36 + fKey, 0);
+ runInputScript(kVerbClickArea, 36 + fKey, 0);
}
}
return;
}
// Generic keyboard input
- runInputScript(4, _mouseAndKeyboardStat, 1);
+ runInputScript(kKeyClickArea, _mouseAndKeyboardStat, 1);
} else if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
VirtScreen *zone = findVirtScreen(_mouse.y);
byte code = _mouseAndKeyboardStat & MBS_LEFT_CLICK ? 1 : 2;
@@ -600,7 +600,7 @@ void ScummEngine::checkExecVerbs() {
if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
// Click into V2 sentence line
- runInputScript(5, 0, 0);
+ runInputScript(kSentenceClickArea, 0, 0);
} else if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y > zone->topline + inventoryArea) {
// Click into V2 inventory
((ScummEngine_v2 *)this)->checkV2Inventory(_mouse.x, _mouse.y);
@@ -608,10 +608,10 @@ void ScummEngine::checkExecVerbs() {
over = findVerbAtPos(_mouse.x, _mouse.y);
if (over != 0) {
// Verb was clicked
- runInputScript(1, _verbs[over].verbid, code);
+ runInputScript(kVerbClickArea, _verbs[over].verbid, code);
} else {
// Scene was clicked
- runInputScript((zone->number == kMainVirtScreen) ? 2 : 1, 0, code);
+ runInputScript((zone->number == kMainVirtScreen) ? kSceneClickArea : kVerbClickArea, 0, code);
}
}
}
diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h
index 47fa98a9de..96a49a7ced 100644
--- a/engines/scumm/verbs.h
+++ b/engines/scumm/verbs.h
@@ -30,6 +30,18 @@
namespace Scumm {
+/**
+ * The area in which some click (or key press) occured and which is passed
+ * to the input script.
+ */
+enum ClickArea {
+ kVerbClickArea = 1,
+ kSceneClickArea = 2,
+ kInventoryClickArea = 3,
+ kKeyClickArea = 4,
+ kSentenceClickArea = 5
+};
+
enum {
kTextVerbType = 0,
kImageVerbType = 1
diff --git a/engines/sky/music/mt32music.cpp b/engines/sky/music/mt32music.cpp
index 4f816c6856..2be19a0651 100644
--- a/engines/sky/music/mt32music.cpp
+++ b/engines/sky/music/mt32music.cpp
@@ -120,7 +120,7 @@ bool MT32Music::processPatchSysEx(uint8 *sysExData) {
crc -= sysExBuf[cnt];
sysExBuf[14] = crc & 0x7F; // crc
_midiDrv->sysEx(sysExBuf, 15);
- g_system->delayMillis(5);
+ g_system->delayMillis(40);
return true;
}
@@ -170,7 +170,7 @@ void MT32Music::startDriver(void) {
sendBuf[len] = crc & 0x7F;
len++;
_midiDrv->sysEx(sendBuf, len);
- g_system->delayMillis (5);
+ g_system->delayMillis(40);
}
while (processPatchSysEx(sysExData))
diff --git a/engines/sky/sound.cpp b/engines/sky/sound.cpp
index cf769cb3e9..c0dc227718 100644
--- a/engines/sky/sound.cpp
+++ b/engines/sky/sound.cpp
@@ -46,13 +46,13 @@ struct RoomList {
uint8 room;
uint8 adlibVolume;
uint8 rolandVolume;
-};
+} PACKED_STRUCT;
struct Sfx {
uint8 soundNo;
uint8 flags;
RoomList roomList[10];
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sky/struc.h b/engines/sky/struc.h
index 25f0b3d772..cd7155f282 100644
--- a/engines/sky/struc.h
+++ b/engines/sky/struc.h
@@ -55,7 +55,7 @@ struct dataFileHeader {
int16 s_offset_x;
int16 s_offset_y;
uint16 s_compressed_size;
-};
+} PACKED_STRUCT;
struct TurnTable {
uint16 turnTableUp[5];
@@ -63,7 +63,7 @@ struct TurnTable {
uint16 turnTableLeft[5];
uint16 turnTableRight[5];
uint16 turnTableTalk[5];
-};
+} PACKED_STRUCT;
struct MegaSet {
uint16 gridWidth; // 0
@@ -82,7 +82,7 @@ struct MegaSet {
uint16 standRightId; // 11
uint16 standTalkId; // 12
uint16 turnTableId; // 13
-};
+} PACKED_STRUCT;
struct Compact {
uint16 logic; // 0: Entry in logic table to run (byte as <256entries in logic table
@@ -165,7 +165,7 @@ struct Compact {
MegaSet megaSet1; //
MegaSet megaSet2; //
MegaSet megaSet3; //
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 1ebfaedb2e..c5b968aabe 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -650,14 +650,7 @@ bool Control::getConfirm(const uint8 *title) {
}
bool Control::keyAccepted(uint16 ascii) {
- // this routine needs changes for Czech keys... No idea how to do that, though.
- // FIXME: It is not a good idea to put non-ASCII chars into a C source file,
- // since there is no way to specify which encoding you are using.
- // It is better to encode them as hex/octal. Although in this particular
- // case, it seems questionable to do this at all, since we currently
- // do not at all specify which encoding keyboard events use, so this
- // check here is probably not portable anyway...
- static const char allowedSpecials[] = "éèáàúùäöüÄÖÜß,.:-()?! \"\'";
+ static const char allowedSpecials[] = ",.:-()?! \"\'";
if (((ascii >= 'A') && (ascii <= 'Z')) ||
((ascii >= 'a') && (ascii <= 'z')) ||
((ascii >= '0') && (ascii <= '9')) ||
diff --git a/engines/sword1/mouse.h b/engines/sword1/mouse.h
index 92b26c3573..f2c800d63b 100644
--- a/engines/sword1/mouse.h
+++ b/engines/sword1/mouse.h
@@ -60,7 +60,7 @@ struct MousePtr {
uint16 hotSpotX;
uint16 hotSpotY;
uint8 dummyData[0x30];
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/object.h b/engines/sword1/object.h
index ba65002918..87cbce7b84 100644
--- a/engines/sword1/object.h
+++ b/engines/sword1/object.h
@@ -40,7 +40,7 @@ namespace Sword1 {
struct OEventSlot { //receiving event list in the compact -
int32 o_event; //array of these with O_TOTAL_EVENTS elements
int32 o_event_script;
-}; // size = 2*int32 = 8 bytes
+} PACKED_STRUCT; // size = 2*int32 = 8 bytes
#define TOTAL_script_levels 5
@@ -48,12 +48,12 @@ struct ScriptTree { //this is a logic tree, used by OBJECTs
int32 o_script_level; //logic level
int32 o_script_id[TOTAL_script_levels]; //script id's (are unique to each level)
int32 o_script_pc[TOTAL_script_levels]; //pc of script for each (if script_manager)
-}; // size = 11*int32 = 44 bytes
+} PACKED_STRUCT; // size = 11*int32 = 44 bytes
struct TalkOffset {
int32 x;
int32 y;
-}; // size = 2*int32 = 8 bytes
+} PACKED_STRUCT; // size = 2*int32 = 8 bytes
struct WalkData {
int32 frame;
@@ -61,7 +61,7 @@ struct WalkData {
int32 y;
int32 step;
int32 dir;
-}; // size = 5*int32 = 20 bytes
+} PACKED_STRUCT; // size = 5*int32 = 20 bytes
struct Object {
int32 o_type; // 0 broad description of type - object, floor, etc.
@@ -119,7 +119,7 @@ struct Object {
WalkData o_route[O_WALKANIM_SIZE]; // 340 size = 600*20 bytes = 12000
// mega size = 12340 bytes (+ 8 byte offset table + 20 byte header = 12368)
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/router.h b/engines/sword1/router.h
index 67be8d0593..60456cc5c8 100644
--- a/engines/sword1/router.h
+++ b/engines/sword1/router.h
@@ -44,7 +44,7 @@ struct BarData {
int16 dx; // x2 - x1
int16 dy; // y2 - y1
int32 co; // co = (y1*dx) - (x1*dy) from an equation for a line y*dx = x*dy + co
-};
+} PACKED_STRUCT;
struct NodeData {
int16 x;
@@ -52,7 +52,7 @@ struct NodeData {
int16 level;
int16 prev;
int16 dist;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 4d8601a0d8..492672fad8 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -33,6 +33,7 @@
#include "sword1/logic.h"
#include "sword1/sword1.h"
+#include "sound/flac.h"
#include "sound/mp3.h"
#include "sound/vorbis.h"
#include "sound/wave.h"
@@ -197,10 +198,10 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (data)
_mixer->playRaw(Audio::Mixer::kSpeechSoundType, &_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
}
-#ifdef USE_MAD
- else if (_cowMode == CowMp3) {
+#ifdef USE_FLAC
+ else if (_cowMode == CowFlac) {
_cowFile.seek(index);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeFlacStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
@@ -212,6 +213,19 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
else if (_cowMode == CowVorbis) {
_cowFile.seek(index);
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeVorbisStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ // with compressed audio, we can't calculate the wave volume.
+ // so default to talking.
+ for (int cnt = 0; cnt < 480; cnt++)
+ _waveVolume[cnt] = true;
+ _waveVolPos = 0;
+ }
+#endif
+#ifdef USE_MAD
+ else if (_cowMode == CowMp3) {
+ _cowFile.seek(index);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ // with compressed audio, we can't calculate the wave volume.
+ // so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
_waveVolume[cnt] = true;
_waveVolPos = 0;
@@ -332,6 +346,16 @@ void Sound::initCowSystem(void) {
/* look for speech1/2.clu in the data dir
and speech/speech.clu (running from cd or using cd layout)
*/
+#ifdef USE_FLAC
+ if (!_cowFile.isOpen()) {
+ sprintf(cowName, "SPEECH%d.CLF", SwordEngine::_systemVars.currentCD);
+ _cowFile.open(cowName);
+ if (_cowFile.isOpen()) {
+ debug(1, "Using Flac compressed Speech Cluster");
+ _cowMode = CowFlac;
+ }
+ }
+#endif
#ifdef USE_VORBIS
if (!_cowFile.isOpen()) {
sprintf(cowName, "SPEECH%d.CLV", SwordEngine::_systemVars.currentCD);
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index fb608a9631..fafc9c2d06 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -66,8 +66,9 @@ class ResMan;
enum CowMode {
CowWave = 0,
- CowMp3,
+ CowFlac,
CowVorbis,
+ CowMp3,
CowDemo
};
diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp
index 366e2c7608..08e6a108c4 100644
--- a/engines/sword1/staticres.cpp
+++ b/engines/sword1/staticres.cpp
@@ -5158,7 +5158,7 @@ const FxDef Sound::_fxList[312] = {
},
},
//------------------------
- // 198 Ambient sound for Montfauçon Square
+ // 198 Ambient sound for Montfaucon Square
{
FX_MONTAMB, // sampleId
FX_LOOP, // type
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index d899d25df5..b5152f33bc 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -355,14 +355,18 @@ const CdFile SwordEngine::_pcCdFileList[] = {
{ "cows.mad", FLAG_DEMO },
{ "speech1.clu", FLAG_SPEECH1 },
{ "speech2.clu", FLAG_SPEECH2 }
-#ifdef USE_MAD
- ,{ "speech1.cl3", FLAG_SPEECH1 },
- { "speech2.cl3", FLAG_SPEECH2 }
+#ifdef USE_FLAC
+ ,{ "speech1.clf", FLAG_SPEECH1 },
+ { "speech2.clf", FLAG_SPEECH2 }
#endif
#ifdef USE_VORBIS
,{ "speech1.clv", FLAG_SPEECH1 },
{ "speech2.clv", FLAG_SPEECH2 }
#endif
+#ifdef USE_MAD
+ ,{ "speech1.cl3", FLAG_SPEECH1 },
+ { "speech2.cl3", FLAG_SPEECH2 }
+#endif
};
const CdFile SwordEngine::_macCdFileList[] = {
@@ -383,14 +387,18 @@ const CdFile SwordEngine::_macCdFileList[] = {
{ "text.clm", FLAG_CD1 | FLAG_DEMO },
{ "speech1.clu", FLAG_SPEECH1 },
{ "speech2.clu", FLAG_SPEECH2 }
-#ifdef USE_MAD
- ,{ "speech1.cl3", FLAG_SPEECH1 },
- { "speech2.cl3", FLAG_SPEECH2 }
+#ifdef USE_FLAC
+ ,{ "speech1.clf", FLAG_SPEECH1 },
+ { "speech2.clf", FLAG_SPEECH2 }
#endif
#ifdef USE_VORBIS
,{ "speech1.clv", FLAG_SPEECH1 },
{ "speech2.clv", FLAG_SPEECH2 }
#endif
+#ifdef USE_MAD
+ ,{ "speech1.cl3", FLAG_SPEECH1 },
+ { "speech2.cl3", FLAG_SPEECH2 }
+#endif
};
diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h
index aedc38ef7e..e90eafe825 100644
--- a/engines/sword1/sworddefs.h
+++ b/engines/sword1/sworddefs.h
@@ -100,7 +100,7 @@ struct Header {
uint32 comp_length;
char compression[4];
uint32 decomp_length;
-};
+} PACKED_STRUCT;
struct FrameHeader {
uint8 runTimeComp[4];
@@ -115,25 +115,25 @@ struct ParallaxHeader {
char type[16];
uint16 sizeX;
uint16 sizeY;
-};
+} PACKED_STRUCT;
struct AnimUnit {
uint32 animX;
uint32 animY;
uint32 animFrame;
-};
+} PACKED_STRUCT;
struct AnimSet {
uint32 cdt;
uint32 spr;
-};
+} PACKED_STRUCT;
struct WalkGridHeader {
int32 scaleA;
int32 scaleB;
int32 numBars;
int32 numNodes;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/touche/ui.cpp b/engines/touche/ui.cpp
index ef8f5a0d7d..15dc64aaf2 100644
--- a/engines/touche/ui.cpp
+++ b/engines/touche/ui.cpp
@@ -381,6 +381,11 @@ void ToucheEngine::handleOptions(int forceDisplay) {
}
}
}
+ if (doRedraw) {
+ redrawMenu(&menuData);
+ updateScreenArea(90, 102, 460, 196);
+ doRedraw = false;
+ }
Common::Event event;
while (_eventMan->pollEvent(event)) {
const Button *button = 0;
@@ -419,11 +424,6 @@ void ToucheEngine::handleOptions(int forceDisplay) {
break;
}
}
- if (doRedraw) {
- redrawMenu(&menuData);
- updateScreenArea(90, 102, 460, 196);
- doRedraw = false;
- }
_system->updateScreen();
_system->delayMillis(10);
}
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index e0c6b2a4a8..2f139e8d57 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -34,7 +34,10 @@ namespace Graphics {
class CursorManager : public Common::Singleton<CursorManager> {
public:
+ /** Query whether the mouse cursor is visible. */
bool isVisible();
+
+ /** Show or hide the mouse cursor. */
bool showMouse(bool visible);
/**
diff --git a/graphics/dxa_player.cpp b/graphics/dxa_player.cpp
index 6f2bca111e..c4c9aaed55 100644
--- a/graphics/dxa_player.cpp
+++ b/graphics/dxa_player.cpp
@@ -152,6 +152,8 @@ void DXAPlayer::closeFile() {
return;
delete _fd;
+ _fd = 0;
+
free(_frameBuffer1);
free(_frameBuffer2);
free(_scaledBuffer);
diff --git a/gui/KeysDialog.cpp b/gui/KeysDialog.cpp
index 33d09e4e69..666f03bbc9 100644
--- a/gui/KeysDialog.cpp
+++ b/gui/KeysDialog.cpp
@@ -126,23 +126,23 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
}
}
-void KeysDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers){
+void KeysDialog::handleKeyDown(Common::KeyState state){
if (!Actions::Instance()->mappingActive())
- Dialog::handleKeyDown(ascii,keycode,modifiers);
+ Dialog::handleKeyDown(state);
}
-void KeysDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
+void KeysDialog::handleKeyUp(Common::KeyState state) {
#ifdef __SYMBIAN32__
if (Actions::Instance()->mappingActive()) {
#else
- if (modifiers == 0xff && Actions::Instance()->mappingActive()) { // GAPI key was selected
+ if (state.flags == 0xff && Actions::Instance()->mappingActive()) { // GAPI key was selected
#endif
char selection[100];
- Actions::Instance()->setMapping((ActionType)_actionSelected, ascii);
+ Actions::Instance()->setMapping((ActionType)_actionSelected, state.ascii);
- if (ascii != 0)
- sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) keycode));
+ if (state.ascii != 0)
+ sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) state.keycode));
else
sprintf(selection, "Associated key : none");
@@ -154,7 +154,7 @@ void KeysDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
_actionsList->setEnabled(true);
Actions::Instance()->beginMapping(false);
} else
- Dialog::handleKeyUp(ascii,keycode,modifiers);
+ Dialog::handleKeyUp(state);
}
} // namespace GUI
diff --git a/gui/KeysDialog.h b/gui/KeysDialog.h
index f4fa4d9419..6d780e665a 100644
--- a/gui/KeysDialog.h
+++ b/gui/KeysDialog.h
@@ -38,8 +38,8 @@ public:
KeysDialog(const Common::String &title = "Choose an action to map");
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
- virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyUp(Common::KeyState state);
+ virtual void handleKeyDown(Common::KeyState state);
protected:
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp
index 271cbccd94..3d5c3dee62 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -186,12 +186,12 @@ static int matchingCharsIgnoringCase(const char *x, const char *y, bool &stop) {
return match;
}
-bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+bool ListWidget::handleKeyDown(Common::KeyState state) {
bool handled = true;
bool dirty = false;
int oldSelectedItem = _selectedItem;
- if (!_editMode && isprint((char)ascii)) {
+ if (!_editMode && isprint((char)state.ascii)) {
// Quick selection mode: Go to first list item starting with this key
// (or a substring accumulated from the last couple key presses).
// Only works in a useful fashion if the list entries are sorted.
@@ -199,9 +199,9 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
// method "enableQuickSelect()" or so ?
uint32 time = getMillis();
if (_quickSelectTime < time) {
- _quickSelectStr = (char)ascii;
+ _quickSelectStr = (char)state.ascii;
} else {
- _quickSelectStr += (char)ascii;
+ _quickSelectStr += (char)state.ascii;
}
_quickSelectTime = time + 300; // TODO: Turn this into a proper constant (kQuickSelectDelay ?)
@@ -227,11 +227,11 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
scrollToCurrent();
} else if (_editMode) {
// Class EditableWidget handles all text editing related key presses for us
- handled = EditableWidget::handleKeyDown(ascii, keycode, modifiers);
+ handled = EditableWidget::handleKeyDown(state);
} else {
// not editmode
- switch (keycode) {
+ switch (state.keycode) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
if (_selectedItem >= 0) {
@@ -285,14 +285,14 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
#if !defined(PALMOS_MODE)
// not done on PalmOS because keyboard is emulated and keyup is not generated
- _currentKeyDown = keycode;
+ _currentKeyDown = state.keycode;
#endif
return handled;
}
-bool ListWidget::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
- if (keycode == _currentKeyDown)
+bool ListWidget::handleKeyUp(Common::KeyState state) {
+ if (state.keycode == _currentKeyDown)
_currentKeyDown = 0;
return true;
}
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index a8656061d3..fe3dd4cd7e 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -92,8 +92,8 @@ public:
virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseWheel(int x, int y, int direction);
- virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers);
- virtual bool handleKeyUp(uint16 ascii, int keycode, int modifiers);
+ virtual bool handleKeyDown(Common::KeyState state);
+ virtual bool handleKeyUp(Common::KeyState state);
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
virtual void reflowLayout();
diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp
index d40a01c981..ac91376269 100644
--- a/gui/PopUpWidget.cpp
+++ b/gui/PopUpWidget.cpp
@@ -58,7 +58,7 @@ public:
void handleMouseUp(int x, int y, int button, int clickCount);
void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel
void handleMouseMoved(int x, int y, int button); // Redraw selections depending on mouse position
- void handleKeyDown(uint16 ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc.
+ void handleKeyDown(Common::KeyState state); // Scroll through entries with arrow keys etc.
protected:
void drawMenuEntry(int entry, bool hilite);
@@ -210,8 +210,8 @@ void PopUpDialog::handleMouseMoved(int x, int y, int button) {
setSelection(item);
}
-void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (keycode == Common::KEYCODE_ESCAPE) {
+void PopUpDialog::handleKeyDown(Common::KeyState state) {
+ if (state.keycode == Common::KEYCODE_ESCAPE) {
// Don't change the previous selection
setResult(-1);
close();
@@ -221,7 +221,7 @@ void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
if (isMouseDown())
return;
- switch (keycode) {
+ switch (state.keycode) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
setResult(_selection);
@@ -239,6 +239,8 @@ void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
case Common::KEYCODE_END:
setSelection(_popUpBoss->_entries.size()-1);
break;
+ default:
+ break;
}
}
diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp
index 38ea6229ec..c414f6bf3b 100644
--- a/gui/TabWidget.cpp
+++ b/gui/TabWidget.cpp
@@ -198,11 +198,11 @@ void TabWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
}
-bool TabWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+bool TabWidget::handleKeyDown(Common::KeyState state) {
// TODO: maybe there should be a way to switch between tabs
// using the keyboard? E.g. Alt-Shift-Left/Right-Arrow or something
// like that.
- return Widget::handleKeyDown(ascii, keycode, modifiers);
+ return Widget::handleKeyDown(state);
}
void TabWidget::reflowLayout() {
diff --git a/gui/TabWidget.h b/gui/TabWidget.h
index 928f7916b6..a8c5e07525 100644
--- a/gui/TabWidget.h
+++ b/gui/TabWidget.h
@@ -87,7 +87,7 @@ public:
void setActiveTab(int tabID);
virtual void handleMouseDown(int x, int y, int button, int clickCount);
- virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual bool handleKeyDown(Common::KeyState state);
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
virtual void reflowLayout();
diff --git a/gui/about.cpp b/gui/about.cpp
index 31381cadd5..780091f35d 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -302,13 +302,13 @@ void AboutDialog::handleMouseUp(int x, int y, int button, int clickCount) {
close();
}
-void AboutDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii)
+void AboutDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii)
_willClose = true;
}
-void AboutDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
- if (ascii && _willClose)
+void AboutDialog::handleKeyUp(Common::KeyState state) {
+ if (state.ascii && _willClose)
close();
}
diff --git a/gui/about.h b/gui/about.h
index a1ee96b090..d62510b1a6 100644
--- a/gui/about.h
+++ b/gui/about.h
@@ -52,8 +52,8 @@ public:
void drawDialog();
void handleTickle();
void handleMouseUp(int x, int y, int button, int clickCount);
- void handleKeyDown(uint16 ascii, int keycode, int modifiers);
- void handleKeyUp(uint16 ascii, int keycode, int modifiers);
+ void handleKeyDown(Common::KeyState state);
+ void handleKeyUp(Common::KeyState state);
void reflowLayout();
};
diff --git a/gui/console.cpp b/gui/console.cpp
index b7c257d3ce..04a1103628 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -258,13 +258,13 @@ void ConsoleDialog::handleMouseWheel(int x, int y, int direction) {
_scrollBar->handleMouseWheel(x, y, direction);
}
-void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+void ConsoleDialog::handleKeyDown(Common::KeyState state) {
int i;
if (_slideMode != kNoSlideMode)
return;
- switch (keycode) {
+ switch (state.keycode) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER: {
if (_caretVisible)
@@ -351,7 +351,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
drawLine(pos2line(_currentPos));
break;
case Common::KEYCODE_PAGEUP:
- if (modifiers == Common::KBD_SHIFT) {
+ if (state.flags == Common::KBD_SHIFT) {
_scrollLine -= _linesPerPage - 1;
if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
@@ -360,7 +360,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
}
break;
case Common::KEYCODE_PAGEDOWN:
- if (modifiers == Common::KBD_SHIFT) {
+ if (state.flags == Common::KBD_SHIFT) {
_scrollLine += _linesPerPage - 1;
if (_scrollLine > _promptEndPos / kCharsPerLine) {
_scrollLine = _promptEndPos / kCharsPerLine;
@@ -372,7 +372,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
}
break;
case Common::KEYCODE_HOME:
- if (modifiers == Common::KBD_SHIFT) {
+ if (state.flags == Common::KBD_SHIFT) {
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer();
} else {
@@ -381,7 +381,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
draw();
break;
case Common::KEYCODE_END:
- if (modifiers == Common::KBD_SHIFT) {
+ if (state.flags == Common::KBD_SHIFT) {
_scrollLine = _promptEndPos / kCharsPerLine;
if (_scrollLine < _linesPerPage - 1)
_scrollLine = _linesPerPage - 1;
@@ -408,15 +408,15 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
drawLine(pos2line(_currentPos));
break;
default:
- if (ascii == '~' || ascii == '#') {
+ if (state.ascii == '~' || state.ascii == '#') {
slideUpAndClose();
- } else if (modifiers == Common::KBD_CTRL) {
- specialKeys(keycode);
- } else if ((ascii >= 32 && ascii <= 127) || (ascii >= 160 && ascii <= 255)) {
+ } else if (state.flags == Common::KBD_CTRL) {
+ specialKeys(state.keycode);
+ } else if ((state.ascii >= 32 && state.ascii <= 127) || (state.ascii >= 160 && state.ascii <= 255)) {
for (i = _promptEndPos - 1; i >= _currentPos; i--)
buffer(i + 1) = buffer(i);
_promptEndPos++;
- putchar((byte)ascii);
+ putchar((byte)state.ascii);
scrollToCurrent();
}
}
diff --git a/gui/console.h b/gui/console.h
index ea28e5b449..c683a1f619 100644
--- a/gui/console.h
+++ b/gui/console.h
@@ -140,7 +140,7 @@ public:
void handleTickle();
void reflowLayout();
void handleMouseWheel(int x, int y, int direction);
- void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ void handleKeyDown(Common::KeyState state);
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
int printf(const char *format, ...);
diff --git a/gui/credits.h b/gui/credits.h
index 5babeb1faa..fba9350bca 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -144,6 +144,8 @@ static const char *credits[] = {
"\\C\\c2""MT-32 emulator",
"\\C\\c0""Jochen Hoenicke",
"\\C\\c2""Speaker & PCjr sound support, Adlib work",
+"\\C\\c0""Robin Watts",
+"\\C\\c2""ARM assembly routines for nice speedups on several ports; improvements to the sound mixer",
"\\C\\c0""",
"\\C\\c0""",
"\\C\\c1""Website (content)",
@@ -286,8 +288,6 @@ static const char *credits[] = {
"\\C\\c2""Final MI1 CD music support, initial Ogg Vorbis support",
"\\C\\c0""Andr\351 Souza",
"\\C\\c2""SDL-based OpenGL renderer",
-"\\C\\c0""Robin Watts",
-"\\C\\c2""ARM assembly routines for the Windows CE port",
"\\C\\c0""",
"\\C\\c0""And to all the contributors, users, and beta testers we've missed. Thanks!",
"\\C\\c0""",
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 1afd18ec52..f643e6f988 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -211,18 +211,18 @@ void Dialog::handleMouseWheel(int x, int y, int direction) {
w->handleMouseWheel(x, y, direction);
}
-void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+void Dialog::handleKeyDown(Common::KeyState state) {
if (_focusedWidget) {
- if (_focusedWidget->handleKeyDown(ascii, keycode, modifiers))
+ if (_focusedWidget->handleKeyDown(state))
return;
}
// Hotkey handling
- if (ascii != 0) {
+ if (state.ascii != 0) {
Widget *w = _firstWidget;
- ascii = toupper(ascii);
+ state.ascii = toupper(state.ascii);
while (w) {
- if (w->_type == kButtonWidget && ascii == toupper(((ButtonWidget *)w)->_hotkey)) {
+ if (w->_type == kButtonWidget && state.ascii == toupper(((ButtonWidget *)w)->_hotkey)) {
// The hotkey for widget w was pressed. We fake a mouse click into the
// button by invoking the appropriate methods.
w->handleMouseDown(0, 0, 1, 1);
@@ -234,7 +234,7 @@ void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
}
// ESC closes all dialogs by default
- if (keycode == Common::KEYCODE_ESCAPE) {
+ if (state.keycode == Common::KEYCODE_ESCAPE) {
setResult(-1);
close();
}
@@ -242,10 +242,10 @@ void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
// TODO: tab/shift-tab should focus the next/previous focusable widget
}
-void Dialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
+void Dialog::handleKeyUp(Common::KeyState state) {
// Focused widget receives keyup events
if (_focusedWidget)
- _focusedWidget->handleKeyUp(ascii, keycode, modifiers);
+ _focusedWidget->handleKeyUp(state);
}
void Dialog::handleMouseMoved(int x, int y, int button) {
diff --git a/gui/dialog.h b/gui/dialog.h
index 1c97b4b185..418e3b8e63 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -77,8 +77,8 @@ protected:
virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseWheel(int x, int y, int direction);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
- virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
+ virtual void handleKeyUp(Common::KeyState state);
virtual void handleMouseMoved(int x, int y, int button);
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
diff --git a/gui/editable.cpp b/gui/editable.cpp
index a8638b8b48..1333bf0a9d 100644
--- a/gui/editable.cpp
+++ b/gui/editable.cpp
@@ -85,7 +85,7 @@ void EditableWidget::handleTickle() {
}
}
-bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
+bool EditableWidget::handleKeyDown(Common::KeyState state) {
bool handled = true;
bool dirty = false;
bool forcecaret = false;
@@ -94,7 +94,7 @@ bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
if (_caretVisible)
drawCaret(true);
- switch (keycode) {
+ switch (state.keycode) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
// confirm edit and exit editmode
@@ -143,7 +143,7 @@ bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
forcecaret = true;
break;
default:
- if (tryInsertChar((byte)ascii, _caretPos)) {
+ if (tryInsertChar((byte)state.ascii, _caretPos)) {
_caretPos++;
dirty = true;
forcecaret = true;
diff --git a/gui/editable.h b/gui/editable.h
index a56b079662..c8ef8a80cb 100644
--- a/gui/editable.h
+++ b/gui/editable.h
@@ -63,7 +63,7 @@ public:
virtual const String &getEditString() const { return _editString; }
virtual void handleTickle();
- virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual bool handleKeyDown(Common::KeyState state);
virtual void reflowLayout();
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 995a0cf78a..215f389f6d 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -148,7 +148,7 @@ protected:
EditGameDialog::EditGameDialog(const String &domain, const String &desc)
: OptionsDialog(domain, "gameoptions") {
- int labelWidth = g_gui.evaluator()->getVar("gameOptionsLabelWidth");
+ int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
// GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
String gamePath(ConfMan.get("path", _domain));
@@ -171,15 +171,15 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
tab->addTab("Game");
// GUI: Label & edit widget for the game ID
- new StaticTextWidget(tab, "gameoptions_id", "ID: ");
+ new StaticTextWidget(tab, "gameoptions_id", "ID:");
_domainWidget = new DomainEditTextWidget(tab, "gameoptions_domain", _domain);
// GUI: Label & edit widget for the description
- new StaticTextWidget(tab, "gameoptions_name", "Name: ");
+ new StaticTextWidget(tab, "gameoptions_name", "Name:");
_descriptionWidget = new EditTextWidget(tab, "gameoptions_desc", description);
// Language popup
- _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language: ", labelWidth);
+ _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language:", labelWidth);
_langPopUp->appendEntry("<default>");
_langPopUp->appendEntry("");
const Common::LanguageDescription *l = Common::g_languages;
@@ -188,7 +188,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
}
// Platform popup
- _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform: ", labelWidth);
+ _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform:", labelWidth);
_platformPopUp->appendEntry("<default>");
_platformPopUp->appendEntry("");
const Common::PlatformDescription *p = Common::g_platforms;
@@ -242,7 +242,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
// in the small version of the GUI.
// GUI: Button + Label for the game path
- new ButtonWidget(tab, "gameoptions_gamepath", "Game Path: ", kCmdGameBrowser, 0);
+ new ButtonWidget(tab, "gameoptions_gamepath", "Game Path:", kCmdGameBrowser, 0);
_gamePathWidget = new StaticTextWidget(tab, "gameoptions_gamepathText", gamePath);
// GUI: Button + Label for the additional path
@@ -253,7 +253,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
}
// GUI: Button + Label for the save path
- new ButtonWidget(tab, "gameoptions_savepath", "Save Path: ", kCmdSaveBrowser, 0);
+ new ButtonWidget(tab, "gameoptions_savepath", "Save Path:", kCmdSaveBrowser, 0);
_savePathWidget = new StaticTextWidget(tab, "gameoptions_savepathText", savePath);
if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
_savePathWidget->setLabel("Default");
@@ -270,7 +270,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
void EditGameDialog::reflowLayout() {
OptionsDialog::reflowLayout();
- int labelWidth = g_gui.evaluator()->getVar("gameOptionsLabelWidth");
+ int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
if (_langPopUp)
_langPopUp->changeLabelWidth(labelWidth);
@@ -588,6 +588,15 @@ void LauncherDialog::updateListing() {
if (g.contains("description"))
description = g.description();
}
+
+#ifdef __DS__
+ // DS port uses an extra section called 'ds'. This prevents the section from being
+ // detected as a game.
+ if (gameid == "ds") {
+ continue;
+ }
+#endif
+
if (description.empty())
description = "Unknown (target " + iter->_key + ", gameid " + gameid + ")";
@@ -789,13 +798,13 @@ void LauncherDialog::editGame(int item) {
}
}
-void LauncherDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- Dialog::handleKeyDown(ascii, keycode, modifiers);
+void LauncherDialog::handleKeyDown(Common::KeyState state) {
+ Dialog::handleKeyDown(state);
updateButtons();
}
-void LauncherDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) {
- Dialog::handleKeyUp(ascii, keycode, modifiers);
+void LauncherDialog::handleKeyUp(Common::KeyState state) {
+ Dialog::handleKeyUp(state);
updateButtons();
}
diff --git a/gui/launcher.h b/gui/launcher.h
index 5ccf9cb422..164a7e0707 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -47,8 +47,8 @@ public:
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
- virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
+ virtual void handleKeyUp(Common::KeyState state);
protected:
ListWidget *_list;
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index ad1933863a..51d67b8769 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -272,10 +272,10 @@ void NewGui::runLoop() {
switch (event.type) {
case Common::EVENT_KEYDOWN:
- activeDialog->handleKeyDown(event.kbd.ascii, event.kbd.keycode, event.kbd.flags);
+ activeDialog->handleKeyDown(event.kbd);
break;
case Common::EVENT_KEYUP:
- activeDialog->handleKeyUp(event.kbd.ascii, event.kbd.keycode, event.kbd.flags);
+ activeDialog->handleKeyUp(event.kbd);
break;
case Common::EVENT_MOUSEMOVE:
activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
diff --git a/gui/options.cpp b/gui/options.cpp
index 6d588b6b44..c233c892b9 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -67,7 +67,7 @@ enum {
static const char *savePeriodLabels[] = { "Never", "every 5 mins", "every 10 mins", "every 15 mins", "every 30 mins", 0 };
static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 };
-static const char *outputRateLabels[] = { "Default", "22 kHz", "8 kHz", "11kHz", "44 kHz", "48 kHz", 0 };
+static const char *outputRateLabels[] = { "<default>", "22 kHz", "8 kHz", "11kHz", "44 kHz", "48 kHz", 0 };
static const int outputRateValues[] = { 0, 22050, 8000, 11025, 44100, 48000, -1 };
@@ -503,7 +503,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) {
int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
// The GFX mode popup
- _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode: ", labelWidth);
+ _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:", labelWidth);
_gfxPopUp->appendEntry("<default>");
_gfxPopUp->appendEntry("");
@@ -513,7 +513,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) {
}
// RenderMode popup
- _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode: ", labelWidth);
+ _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode:", labelWidth);
_renderModePopUp->appendEntry("<default>", Common::kRenderDefault);
_renderModePopUp->appendEntry("");
const Common::RenderModeDescription *rm = Common::g_renderModes;
@@ -540,7 +540,7 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) {
int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
// The MIDI mode popup & a label
- _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver: ", labelWidth);
+ _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:", labelWidth);
// Populate it
const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
@@ -550,7 +550,7 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) {
}
// Sample rate settings
- _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate: ", labelWidth);
+ _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate:", labelWidth);
for (int i = 0; outputRateLabels[i]; i++) {
_outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]);
@@ -720,7 +720,7 @@ GlobalOptionsDialog::GlobalOptionsDialog()
int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
- _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave: ", labelWidth);
+ _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave:", labelWidth);
for (int i = 0; savePeriodLabels[i]; i++) {
_autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]);
diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp
index c12ca009da..8da2be99e1 100644
--- a/gui/theme-config.cpp
+++ b/gui/theme-config.cpp
@@ -73,14 +73,14 @@ const char *Theme::_defaultConfigINI =
"\n"
"# audio tab\n"
"opYoffset=vBorder\n"
-"gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight\n"
+"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + 6)\n"
"useWithPrefix=audioControls gameoptions_\n"
"useWithPrefix=subtitleControls gameoptions_\n"
"\n"
"# volume tab\n"
"opYoffset=vBorder\n"
-"gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight\n"
+"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + 6)\n"
"useWithPrefix=volumeControls gameoptions_\n"
"\n"
@@ -268,26 +268,26 @@ const char *Theme::_defaultConfigINI =
"# graphics tab\n"
"opYoffset=vBorder\n"
"opXoffset=gox\n"
-"gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight\n"
+"gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight)\n"
"useWithPrefix=graphicsControls gameoptions_\n"
"\n"
"# audio tab\n"
"opYoffset=vBorder\n"
-"gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight\n"
+"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight)\n"
"useWithPrefix=audioControls gameoptions_\n"
"useWithPrefix=subtitleControls gameoptions_\n"
"\n"
"# volume tab\n"
"opYoffset=vBorder\n"
-"gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight\n"
+"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight)\n"
"useWithPrefix=volumeControls gameoptions_\n"
"\n"
"# midi tab\n"
"opYoffset=vBorder\n"
-"gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight\n"
+"gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight)\n"
"useWithPrefix=midiControls gameoptions_\n"
"\n"
@@ -387,9 +387,9 @@ const char *Theme::_defaultConfigINI =
"opYoffset=(opYoffset + kLineHeight + 4)\n"
"grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h\n"
"opYoffset=(opYoffset + kLineHeight + 4)\n"
-"grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight\n"
+"grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight)\n"
-"grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 180) prev.h\n"
+"grAspectCheckbox=prev.x opYoffset prev.w prev.h\n"
"opYoffset=(opYoffset + buttonHeight)\n"
"\n"
"[audioControls]\n"
@@ -426,11 +426,11 @@ const char *Theme::_defaultConfigINI =
"mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - 15 - kLineHeight - 10) kLineHeight\n"
"mcFontClearButton=(prev.x2 + 10) (opYoffset + 2) kLineHeight kLineHeight\n"
"opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)\n"
-"mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight\n"
+"mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
-"mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight\n"
+"mcMt32Checkbox=mcx opYoffset prev.w buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
-"mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight\n"
+"mcGSCheckbox=mcx opYoffset prev.w buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
"mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight\n"
"mcMidiGainText.align=kTextAlignRight\n"
@@ -445,6 +445,7 @@ const char *Theme::_defaultConfigINI =
"sbtextw=(100 + vcAudioTabIndent)\n"
"opYoffset=(opYoffset + sbYoff)\n"
"subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight\n"
+"subToggleDesc.align=kTextAlignRight\n"
"subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight\n"
"opYoffset=(opYoffset + buttonHeight + 6)\n"
"subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight\n"
@@ -549,7 +550,7 @@ void Theme::processSingleLine(const String &section, const String &prefix, const
const char **postfixes = (ntmppostfix == 2) ? postfixesRGB : postfixesXYWH;
- // Now do it for real, only this time we already know the parantheses
+ // Now do it for real, only this time we already know the parentheses
// are balanced.
for (i = 0; i < str.size(); i++) {
@@ -570,10 +571,15 @@ void Theme::processSingleLine(const String &section, const String &prefix, const
_evaluator->setStringVar(prefixedname, _evaluator->lastToken());
// process VAR=VALUE construct
- if (npostfix == 0)
+ if (npostfix == 0) {
_evaluator->setVar(name, value);
- else
+
+ // Fix bug #1742561: "GUI: Missaligned text"
+ // "blah.align=foo" should be prefixed too
+ _evaluator->setVar(prefixedname, value);
+ } else {
_evaluator->setVar(prefixedname + postfixes[npostfix], value);
+ }
// If we have all 4 parameters, set .x2 and .y2
if (npostfix == 3) {
@@ -611,16 +617,16 @@ void Theme::processResSection(Common::ConfigFile &config, const String &name, bo
if (iterk->key == "use") {
if (iterk->value == name)
error("Theme section [%s]: cannot use itself", name.c_str());
- if (!config.hasSection(name))
- error("Undefined use of section [%s]", name.c_str());
+ if (!config.hasSection(iterk->value))
+ error("Undefined use of section [%s]", iterk->value.c_str());
processResSection(config, iterk->value, true);
continue;
}
if (iterk->key == "useAsIs") {
if (iterk->value == name)
error("Theme section [%s]: cannot use itself", name.c_str());
- if (!config.hasSection(name))
- error("Undefined use of section [%s]", name.c_str());
+ if (!config.hasSection(iterk->value))
+ error("Undefined use of section [%s]", iterk->value.c_str());
processResSection(config, iterk->value);
continue;
}
diff --git a/gui/themes/classic080.ini b/gui/themes/classic080.ini
index 481d00c27a..3a58ec60f7 100644
--- a/gui/themes/classic080.ini
+++ b/gui/themes/classic080.ini
@@ -187,26 +187,26 @@ opYoffset=(opYoffset + buttonHeight + 4)
# graphics tab
opYoffset=vBorder
opXoffset=gox
-gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight
+gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight)
useWithPrefix=graphicsControls gameoptions_
# audio tab
opYoffset=vBorder
-gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight
+gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight)
useWithPrefix=audioControls gameoptions_
useWithPrefix=subtitleControls gameoptions_
# volume tab
opYoffset=vBorder
-gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight
+gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight)
useWithPrefix=volumeControls gameoptions_
# midi tab
opYoffset=vBorder
-gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight
+gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight)
useWithPrefix=midiControls gameoptions_
@@ -305,9 +305,9 @@ grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2)
opYoffset=(opYoffset + kLineHeight + 4)
grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h
opYoffset=(opYoffset + kLineHeight + 4)
-grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight
+grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight)
-grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 180) prev.h
+grAspectCheckbox=prev.x opYoffset prev.w prev.h
opYoffset=(opYoffset + buttonHeight)
[audioControls]
@@ -344,11 +344,11 @@ mcFontButton=mcx opYoffset buttonWidth buttonHeight
mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight
mcFontClearButton=(prev.x2 + 10) (opYoffset + 3) kLineHeight kLineHeight
opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)
-mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight
+mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight
opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
-mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight
+mcMt32Checkbox=mcx opYoffset prev.w buttonHeight
opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
-mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight
+mcGSCheckbox=mcx opYoffset prev.w buttonHeight
opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight
mcMidiGainText.align=kTextAlignRight
@@ -363,6 +363,7 @@ sbOff=((sliderHeight - kLineHeight) / 2 + 2)
sbtextw=(100 + vcAudioTabIndent)
opYoffset=(opYoffset + sbYoff)
subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight
+subToggleDesc.align=kTextAlignRight
subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight
opYoffset=(opYoffset + buttonHeight + 6)
subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight
diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini
index 25fd8da01d..541c2fb00a 100644
--- a/gui/themes/modern.ini
+++ b/gui/themes/modern.ini
@@ -185,9 +185,9 @@ def_insetY=94
def_insetW=(w - buttonWidth - 17 * 2 - insetX)
def_insetH=(h - 23 - insetY)
def_optionsVPad=20
-def_gameOptionsLabelWidth=90
+def_optionsLabelWidth=110
def_gameOptionsOverrideVPad=20
-def_tabPopupsLabelW=110
+def_tabPopupsLabelW=optionsLabelWidth
def_aboutXOff=8
def_aboutYOff=5
def_aboutOuterBorder=80
@@ -196,10 +196,13 @@ def_scummmainVSpace=15
def_scummmainVAddOff=5
def_scummhelpW=370
def_scummhelpX=((w - scummhelpW) / 2)
-def_midiControlsSpacing=4
def_launcherVersionX=(w / 2 - 283 / 2 - 90)
def_launcherVersionY=21
+def_xSeparation=10
+def_ySeparation=10
+def_xBorder=15
+
use=pixmaps
use=colors
use=gradients
@@ -214,7 +217,7 @@ ListWidget.hlLeftPadding=0
ListWidget.hlRightPadding=0
PopUpWidget.leftPadding=7
PopUpWidget.rightPadding=5
-PopUpWidget.labelSpacing=3
+PopUpWidget.labelSpacing=xSeparation
EditTextWidget.font=kFontStyleNormal
EditTextWidget.leftPadding=7
EditTextWidget.rightPadding=5
@@ -245,7 +248,7 @@ launcher_logo=(w / 2 - 283 / 2) 5 283 80
launcher_logo.visible=true
space1=20
space2=5
-launcher_list=insetX insetY (w - buttonWidth - 17 * 2 - self.x) (h - 23 - self.y)
+launcher_list=insetX insetY insetW insetH
launcher_start_button=(prev.x2 + 17) prev.y buttonWidth buttonHeight
launcher_addGame_button=prev.x (prev.y2 + space1) prev.w prev.h
launcher_editGame_button=prev.x (prev.y2 + space2) prev.w prev.h
@@ -260,7 +263,7 @@ use=scummmain
globaloptions=insetX insetY insetW insetH
set_parent=globaloptions
vBorder=optionsVPad
-globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 16)
+globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation)
# graphics tab
opYoffset=vBorder
@@ -283,93 +286,94 @@ useWithPrefix=midiControls globaloptions_
# paths tab
yoffset=vBorder
glOff=((buttonHeight - kLineHeight) / 2 + 2)
-globaloptions_savebutton=10 yoffset buttonWidth buttonHeight
-globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
-yoffset=(yoffset + buttonHeight + 8)
-globaloptions_extrabutton=10 yoffset buttonWidth buttonHeight
-globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
-yoffset=(yoffset + buttonHeight + 8)
-globaloptions_themebutton=10 yoffset buttonWidth buttonHeight
-globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
-yoffset=(yoffset + buttonHeight + 12)
-globaloptions_keysbutton=5 yoffset buttonWidth buttonHeight
+globaloptions_savebutton=xBorder yoffset buttonWidth buttonHeight
+globaloptions_savepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight
+yoffset=(yoffset + buttonHeight + ySeparation)
+globaloptions_extrabutton=xBorder yoffset buttonWidth buttonHeight
+globaloptions_extrapath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight
+yoffset=(yoffset + buttonHeight + ySeparation)
+globaloptions_themebutton=xBorder yoffset buttonWidth buttonHeight
+globaloptions_themepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight
+yoffset=(yoffset + buttonHeight + ySeparation)
+globaloptions_keysbutton=xBorder yoffset buttonWidth buttonHeight
# Misc options
yoffset=vBorder
glOff=((buttonHeight - kLineHeight) / 2 + 2)
-globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight
-globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
-yoffset=(yoffset + buttonHeight + 12)
-globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) kPopUpHeight
+globaloptions_themebutton2=xBorder yoffset buttonWidth buttonHeight
+globaloptions_curtheme=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight
+yoffset=(yoffset + buttonHeight + ySeparation)
+globaloptions_autosaveperiod=xBorder yoffset (parent.w - self.x - xBorder) kPopUpHeight
-globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
-globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h
+globaloptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
+globaloptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h
### game options
gameoptions=insetX insetY insetW insetH
set_parent=gameoptions
vBorder=gameOptionsOverrideVPad
-gox=10
-gow=(parent.w - gox - 25)
+gox=xBorder
+gow=(parent.w - gox - xBorder)
-gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 16)
+gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation)
# game tab
opYoffset=optionsVPad
-gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight
+glOff=((kPopUpHeight - kLineHeight) / 2 + 2)
+gameoptions_id=gox (opYoffset + glOff) optionsLabelWidth kLineHeight
gameoptions_id.align=kTextAlignRight
-gameoptions_domain=prev.x2 (prev.y - 1) (gow - prev.w) kPopUpHeight
-opYoffset=(opYoffset + kLineHeight + 12)
-gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight
+gameoptions_domain=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+gameoptions_name=gox (opYoffset + glOff) optionsLabelWidth kLineHeight
gameoptions_name.align=kTextAlignRight
-gameoptions_desc=prev.x2 (prev.y - 1) (gow - prev.w) kPopUpHeight
-opYoffset=(opYoffset + kLineHeight + 15)
-gameoptions_lang=gox (opYoffset - 1) gow kPopUpHeight
-opYoffset=(opYoffset + kLineHeight + 12)
+gameoptions_desc=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+gameoptions_lang=gox opYoffset (parent.w - self.x - xBorder) kPopUpHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
gameoptions_platform=prev.x opYoffset prev.w prev.h
-opYoffset=(opYoffset + kLineHeight + 8)
+opYoffset=(opYoffset + prev.h + ySeparation)
# paths tab
opYoffset=optionsVPad
goOff=((buttonHeight - kLineHeight) / 2 + 2)
gameoptions_savepath=gox opYoffset buttonWidth buttonHeight
-gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight
-opYoffset=(opYoffset + buttonHeight + 8)
+gameoptions_savepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight
+opYoffset=(opYoffset + buttonHeight + ySeparation)
gameoptions_extrapath=gox opYoffset buttonWidth buttonHeight
-gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight
-opYoffset=(opYoffset + buttonHeight + 8)
+gameoptions_extrapathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight
+opYoffset=(opYoffset + buttonHeight + ySeparation)
gameoptions_gamepath=gox opYoffset buttonWidth buttonHeight
-gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight
-opYoffset=(opYoffset + buttonHeight + 8)
+gameoptions_gamepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight
+opYoffset=(opYoffset + buttonHeight + ySeparation)
# graphics tab
opYoffset=vBorder
opXoffset=gox
-gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight
-opYoffset=(opYoffset + buttonHeight + 6)
+gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight
+opYoffset=(prev.y2 + ySeparation)
useWithPrefix=graphicsControls gameoptions_
# audio tab
opYoffset=vBorder
-gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight
-opYoffset=(opYoffset + buttonHeight + 6)
+gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight
+opYoffset=(prev.y2 + ySeparation)
useWithPrefix=audioControls gameoptions_
useWithPrefix=subtitleControls gameoptions_
# volume tab
opYoffset=vBorder
-gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight
-opYoffset=(opYoffset + buttonHeight + 6)
+gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight
+opYoffset=(prev.y2 + ySeparation)
useWithPrefix=volumeControls gameoptions_
# midi tab
opYoffset=vBorder
-gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight
-opYoffset=(opYoffset + buttonHeight + 6)
+gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight
+opYoffset=(prev.y2 + ySeparation)
useWithPrefix=midiControls gameoptions_
-gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
-gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h
+gameoptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
+gameoptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h
### keys dialog
keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5)
@@ -386,14 +390,14 @@ keysdialog_mapping.align=kTextAlignCenter
### mass add dialog
massadddialog=10 20 300 174
set_parent=massadddialog
-massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight
+massadddialog_caption=xBorder (10 + 1 * kLineHeight) (parent.w - 2 * xBorder) kLineHeight
massadddialog_caption.align=kTextAlignCenter
-massadddialog_dirprogress=10 (10 + 3 * kLineHeight) prev.w prev.h
+massadddialog_dirprogress=xBorder (10 + 3 * kLineHeight) prev.w prev.h
massadddialog_dirprogress.align=kTextAlignCenter
-massadddialog_gameprogress=10 (10 + 4 * kLineHeight) prev.w prev.h
+massadddialog_gameprogress=xBorder (10 + 4 * kLineHeight) prev.w prev.h
massadddialog_gameprogress.align=kTextAlignCenter
-massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
-massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h
+massadddialog_ok=((parent.w - (buttonWidth * 2) - xSeparation) / 2) (parent.h - buttonHeight - ySeparation) buttonWidth buttonHeight
+massadddialog_cancel=(prev.x2 + xSeparation) prev.y prev.w prev.h
##### SCUMM dialogs
@@ -455,95 +459,93 @@ scummsaveload_extinfo.visible=true
[chooser]
chooserW=insetW
chooser=insetX insetY chooserW opHeight
-chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight)
-chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12)
-chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight
-chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h
+chooser_headline=xBorder 6 (chooserW - 2 * xBorder) kLineHeight
+chooser_list=prev.x (prev.y2 + 2) prev.w (opHeight - self.y - buttonHeight - 12)
+#JVPRAT: next Y doesn't seem right
+chooser_cancel=(chooserW - 2 * buttonWidth - xSeparation - xBorder) (opHeight - buttonHeight - 8) buttonWidth buttonHeight
+chooser_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h
[browser]
browser=insetX insetY insetW insetH
set_parent=browser
-browser_headline=10 5 (parent.w - 2 * 10) kLineHeight
+browser_headline=xBorder 5 (parent.w - 2 * xBorder) kLineHeight
browser_headline.align=kTextAlignCenter
-browser_path=10 (prev.y2 + 5) prev.w prev.h
-browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14)
-browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight
-browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
-browser_choose=(prev.x2 + 10) prev.y prev.w prev.h
+browser_path=prev.x (prev.y2 + 5) prev.w prev.h
+browser_list=prev.x prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14)
+browser_up=prev.x (parent.h - buttonHeight - 8) buttonWidth buttonHeight
+#JVPRAT: doesn't it lack insetx?:
+browser_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
+browser_choose=(prev.x2 + xSeparation) prev.y prev.w prev.h
[graphicsControls]
-gcx=(opXoffset + 10)
-gcw=(parent.w - gcx - 25)
-grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) kPopUpHeight
-opYoffset=(opYoffset + kLineHeight + 12)
+gcx=(opXoffset + xBorder)
+grModePopup=gcx opYoffset (parent.w - self.x - xBorder) kPopUpHeight
+opYoffset=(prev.y2 + ySeparation)
grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h
-opYoffset=(opYoffset + kLineHeight + 16)
-grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight
-opYoffset=(opYoffset + buttonHeight + 4)
-grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 136) prev.h
-opYoffset=(opYoffset + buttonHeight + 4)
+opYoffset=(prev.y2 + ySeparation)
+grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - xBorder) kLineHeight
+opYoffset=(prev.y2 + ySeparation)
+grAspectCheckbox=prev.x opYoffset prev.w prev.h
+opYoffset=(prev.y2 + ySeparation)
[audioControls]
-aux=(opXoffset + 10)
-auw=(parent.w - aux - 30)
-auMidiPopup=(aux) (opYoffset - 1) (auw + 5) kPopUpHeight
-opYoffset=(opYoffset + buttonHeight + 4)
-auSampleRatePopup=(aux) (opYoffset - 1) (auw + 5) kPopUpHeight
-opYoffset=(opYoffset + buttonHeight + 4)
+aux=(opXoffset + xBorder)
+auMidiPopup=aux opYoffset (parent.w - self.x - xBorder) kPopUpHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+auSampleRatePopup=aux (opYoffset - 1) prev.w kPopUpHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
[volumeControls]
-vctextw=110
-vcxoff=(opXoffset + vctextw + 10)
-vcx=(opXoffset + 10)
-vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight
+vcx=(opXoffset + xBorder)
+vcOff=((sliderHeight - kLineHeight) / 2 + 2)
+vcMusicText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight
vcMusicText.align=kTextAlignRight
-vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight
-vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight
-opYoffset=(opYoffset + sliderHeight + 8)
-vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight
+vcMusicSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight
+vcMusicLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight
+opYoffset=(opYoffset + sliderHeight + ySeparation)
+vcSfxText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight
vcSfxText.align=kTextAlignRight
-vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight
-vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight
-opYoffset=(opYoffset + sliderHeight + 8)
-vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight
+vcSfxSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight
+vcSfxLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight
+opYoffset=(opYoffset + sliderHeight + ySeparation)
+vcSpeechText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight
vcSpeechText.align=kTextAlignRight
-vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight
-vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight
-opYoffset=(opYoffset + sliderHeight + 12)
+vcSpeechSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight
+vcSpeechLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight
+opYoffset=(opYoffset + sliderHeight + ySeparation)
[midiControls]
-mcx=(opXoffset + 10)
+mcx=(opXoffset + xBorder)
mcOff=((buttonHeight - kLineHeight) / 2 + 2)
mcFontButton=mcx opYoffset buttonWidth buttonHeight
-mcFontPath=(prev.x2 + 20) (opYoffset + mcOff) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight
-mcFontClearButton=(prev.x2 + 10) (opYoffset + mcOff) kLineHeight kLineHeight
-opYoffset=(opYoffset + buttonHeight + 6 * midiControlsSpacing)
-mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight
-opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
-mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight
-opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
-mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight
-opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)
-mcMidiGainText=mcx (opYoffset + 2) 80 kLineHeight
+mcFontPath=(prev.x2 + xSeparation) (opYoffset + mcOff) (parent.w - self.x - xSeparation - kLineHeight - xBorder) kLineHeight
+mcFontClearButton=(prev.x2 + xSeparation) prev.y kLineHeight kLineHeight
+opYoffset=(opYoffset + buttonHeight + ySeparation)
+mcMixedCheckbox=mcx opYoffset (parent.w - self.x - xBorder) kLineHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+mcMt32Checkbox=mcx opYoffset prev.w kLineHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+mcGSCheckbox=mcx opYoffset prev.w kLineHeight
+opYoffset=(opYoffset + prev.h + ySeparation)
+mcOff=((sliderHeight - kLineHeight) / 2 + 2)
+mcMidiGainText=mcx (opYoffset + mcOff) optionsLabelWidth kLineHeight
mcMidiGainText.align=kTextAlignRight
-mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight
-mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight
-opYoffset=(opYoffset + sliderHeight + midiControlsSpacing)
+mcMidiGainSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight
+mcMidiGainLabel=(prev.x2 + xSeparation) (opYoffset + mcOff) 40 kLineHeight
+opYoffset=(opYoffset + sliderHeight + ySeparation)
[subtitleControls]
-sbx=(opXoffset + 10)
-sbtextw=110
-sbYoff=(buttonHeight / 8)
-sbOff=((sliderHeight - kLineHeight) / 2)
-opYoffset=(opYoffset + sbYoff)
-subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight
-subToggleButton=prev.x2 opYoffset (buttonWidth + 34) sliderHeight
-opYoffset=(opYoffset + buttonHeight + 6)
-subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight
+sbx=(opXoffset + xBorder)
+sbOff=((sliderHeight - kLineHeight) / 2 + 2)
+subToggleDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight
+subToggleDesc.align=kTextAlignRight
+subToggleButton=(prev.x2 + xSeparation) opYoffset (buttonWidth + 34) sliderHeight
+opYoffset=(prev.y2 + ySeparation)
+subSubtitleSpeedDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight
subSubtitleSpeedDesc.align=kTextAlignRight
-subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight
-subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight
-opYoffset=(opYoffset + sliderHeight + 8)
+subSubtitleSpeedSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight
+subSubtitleSpeedLabel=(prev.x2 + xSeparation) (opYoffset + sbOff) 24 kLineHeight
+opYoffset=(opYoffset + sliderHeight + ySeparation)
[scummmain]
## Main dialog
@@ -592,7 +594,6 @@ def_insetW=(w - buttonWidth - 17 * 2 - insetX)
def_insetH=(h - 13 - insetY)
def_launcherVersionX=50
def_launcherVersionY=5
-def_midiControlsSpacing=2
def_gameOptionsOverrideVPad=10
def_aboutXOff=3
def_aboutYOff=2
diff --git a/gui/widget.h b/gui/widget.h
index bf15081f79..c19059d32c 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -27,6 +27,7 @@
#include "common/scummsys.h"
#include "common/str.h"
+#include "common/keyboard.h"
#include "graphics/font.h"
#include "graphics/surface.h"
#include "gui/object.h"
@@ -127,8 +128,8 @@ public:
virtual void handleMouseLeft(int button) {}
virtual void handleMouseMoved(int x, int y, int button) {}
virtual void handleMouseWheel(int x, int y, int direction) {}
- virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers) { return false; } // Return true if the event was handled
- virtual bool handleKeyUp(uint16 ascii, int keycode, int modifiers) { return false; } // Return true if the event was handled
+ virtual bool handleKeyDown(Common::KeyState state) { return false; } // Return true if the event was handled
+ virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled
virtual void handleTickle() {}
virtual void reflowLayout() { GuiObject::reflowLayout(); }
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index eba02c74f3..6a04da5f43 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -156,21 +156,21 @@ public:
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
- int samples = 0;
- while (samples < numSamples && _ptr < _end) {
- const int len = MIN(numSamples, samples + (int)(_end - _ptr) / (is16Bit ? 2 : 1));
- while (samples < len) {
+ int samples = numSamples;
+ while (samples > 0 && _ptr < _end) {
+ int len = MIN(samples, (int)(_end - _ptr) / (is16Bit ? 2 : 1));
+ samples -= len;
+ do {
*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE);
_ptr += (is16Bit ? 2 : 1);
- samples++;
- }
+ } while (--len);
// Loop, if looping was specified
if (_loopPtr && _ptr >= _end) {
_ptr = _loopPtr;
_end = _loopEnd;
}
}
- return samples;
+ return numSamples-samples;
}
@@ -209,7 +209,7 @@ AudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, byte f
loopEnd = len;
assert(loopStart <= loopEnd);
assert(loopEnd <= len);
-
+
loopOffset = loopStart;
loopLen = loopEnd - loopStart;
}
@@ -250,7 +250,7 @@ protected:
// the linked list) in thread aware environments.
Common::Mutex _mutex;
- // List of all queueud buffers
+ // List of all queued buffers
Common::List<Buffer> _bufferQueue;
// Position in the front buffer, if any
@@ -292,8 +292,8 @@ template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock lock(_mutex);
- int samples = 0;
- while (samples < numSamples && !eosIntern()) {
+ int samples = numSamples;
+ while (samples > 0 && !eosIntern()) {
Buffer buf = *_bufferQueue.begin();
if (_pos == 0)
_pos = buf.start;
@@ -307,15 +307,15 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16
continue;
}
- const int len = MIN(numSamples, samples + samplesLeftInCurBuffer / (is16Bit ? 2 : 1));
- while (samples < len) {
+ int len = MIN(samples, samplesLeftInCurBuffer / (is16Bit ? 2 : 1));
+ samples -= len;
+ do {
*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _pos, isLE);
_pos += (is16Bit ? 2 : 1);
- samples++;
- }
+ } while (--len);
}
- return samples;
+ return numSamples-samples;
}
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index a23e277f81..658ebfa457 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -37,7 +37,7 @@ static const MidiDriverDescription s_musicDrivers[] = {
// The flags for the "auto" & "null" drivers indicate that they are anything
// you want it to be.
- {"auto", "Default", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS},
+ {"auto", "<default>", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS},
{"null", "No music", MD_NULL, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS},
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index cc353d58b4..4ca7b4c897 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -54,7 +54,7 @@ private:
bool _permanent;
byte _volume;
int8 _balance;
- bool _paused;
+ int _pauseLevel;
int _id;
uint32 _samplesConsumed;
uint32 _samplesDecoded;
@@ -77,10 +77,15 @@ public:
return _input->endOfStream();
}
void pause(bool paused) {
- _paused = paused;
+ assert((paused && _pauseLevel >= 0) || (!paused && _pauseLevel));
+
+ if (paused)
+ _pauseLevel++;
+ else
+ _pauseLevel--;
}
bool isPaused() {
- return _paused;
+ return _pauseLevel != 0;
}
void setVolume(const byte volume) {
_volume = volume;
@@ -375,7 +380,7 @@ int Mixer::getVolumeForSoundType(SoundType type) const {
Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *input,
bool autofreeStream, bool reverseStereo, int id, bool permanent)
: _type(type), _mixer(mixer), _autofreeStream(autofreeStream),
- _volume(Mixer::kMaxChannelVolume), _balance(0), _paused(false), _id(id), _samplesConsumed(0),
+ _volume(Mixer::kMaxChannelVolume), _balance(0), _pauseLevel(0), _id(id), _samplesConsumed(0),
_samplesDecoded(0), _mixerTimeStamp(0), _converter(0), _input(input), _permanent(permanent) {
assert(mixer);
assert(input);
diff --git a/sound/mods/infogrames.cpp b/sound/mods/infogrames.cpp
index b577049657..3f607d213e 100644
--- a/sound/mods/infogrames.cpp
+++ b/sound/mods/infogrames.cpp
@@ -171,7 +171,7 @@ void Infogrames::init() {
_chn[i].periodMod = 0;
}
- _end = _data == 0;
+ _end = (_data == 0);
}
void Infogrames::reset() {
@@ -231,8 +231,7 @@ bool Infogrames::load(Common::SeekableReadStream &dum) {
(_cmdBlocks > (_data + size)))
return false;
- _end = false;
- _playing = true;
+ startPaula();
return true;
}
@@ -244,8 +243,6 @@ void Infogrames::unload(void) {
clearVoices();
reset();
-
- _end = true;
}
void Infogrames::getNextSample(Channel &chn) {
@@ -427,15 +424,14 @@ void Infogrames::interrupt() {
_volume = 0;
_period = 0;
getNextSample(_chn[chn]);
- _voice[chn].volume = _volume;
- _voice[chn].period = _period;
+ setChannelVolume(chn, _volume);
+ setChannelPeriod(chn, _period);
if ((_sample != 0xFF) && (_sample < _instruments->_count)) {
- _voice[chn].data = _instruments->_samples[_sample].data;
- _voice[chn].length = _instruments->_samples[_sample].length;
- _voice[chn].dataRepeat = _instruments->_samples[_sample].dataRepeat;
- _voice[chn].lengthRepeat =
- _instruments->_samples[_sample].lengthRepeat;
- _voice[chn].offset = 0;
+ setChannelData(chn,
+ _instruments->_samples[_sample].data,
+ _instruments->_samples[_sample].dataRepeat,
+ _instruments->_samples[_sample].length,
+ _instruments->_samples[_sample].lengthRepeat);
_sample = 0xFF;
}
}
@@ -449,8 +445,7 @@ void Infogrames::interrupt() {
_repCount--;
init();
} else if (_repCount != -1) {
- _end = true;
- _playing = false;
+ stopPaula();
} else {
init();
}
diff --git a/sound/mods/infogrames.h b/sound/mods/infogrames.h
index 7220c2bf9a..572c5a6426 100644
--- a/sound/mods/infogrames.h
+++ b/sound/mods/infogrames.h
@@ -80,14 +80,6 @@ public:
Instruments *getInstruments(void) const { return _instruments; }
bool getRepeating(void) const { return _repCount != 0; }
void setRepeating (int32 repCount) { _repCount = repCount; }
- virtual void startPlay(void) { _playing = true;}
- virtual void stopPlay(void)
- {
- _mutex.lock();
- _playing = false;
- _mutex.unlock();
- }
- virtual void pausePlay(bool pause) { _playing = !pause; }
bool load(Common::SeekableReadStream &dum);
bool load(const char *dum) {
@@ -98,7 +90,16 @@ public:
return false;
}
void unload(void);
- void restart(void) { if (_data) { stopPlay(); init(); startPlay(); } }
+ void restart(void) {
+ if (_data) {
+ // Use the mutex here to ensure we do not call init()
+ // while data is being read by the mixer thread.
+ _mutex.lock();
+ init();
+ startPlay();
+ _mutex.unlock();
+ }
+ }
protected:
Instruments *_instruments;
diff --git a/sound/mods/module.h b/sound/mods/module.h
index b25fe87b41..041eebc269 100644
--- a/sound/mods/module.h
+++ b/sound/mods/module.h
@@ -37,7 +37,7 @@ struct note_t {
byte note;
uint16 period;
uint16 effect;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/sound/mods/paula.cpp b/sound/mods/paula.cpp
index 53b8f867ea..cfd9ebff11 100644
--- a/sound/mods/paula.cpp
+++ b/sound/mods/paula.cpp
@@ -29,7 +29,6 @@ namespace Audio {
Paula::Paula(bool stereo, int rate, int interruptFreq) :
_stereo(stereo), _rate(rate), _intFreq(interruptFreq) {
- _playing = false;
clearVoices();
_voice[0].panning = 63;
@@ -41,6 +40,7 @@ Paula::Paula(bool stereo, int rate, int interruptFreq) :
_intFreq = _rate;
_curInt = _intFreq;
+ _playing = false;
_end = true;
}
@@ -60,16 +60,6 @@ void Paula::clearVoice(byte voice) {
}
int Paula::readBuffer(int16 *buffer, const int numSamples) {
- int voice;
- int samples;
- int nSamples;
- int sLen;
- double frequency;
- double rate;
- double offset;
- int16 *p;
- const int8 *data;
-
Common::StackLock lock(_mutex);
memset(buffer, 0, numSamples * 2);
@@ -77,87 +67,106 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
return numSamples;
}
- samples = _stereo ? numSamples / 2 : numSamples;
+ if (_stereo)
+ return readBufferIntern<true>(buffer, numSamples);
+ else
+ return readBufferIntern<false>(buffer, numSamples);
+}
+
+
+template<bool stereo>
+inline void mixBuffer(int16 *&buf, const int8 *data, frac_t &offset, frac_t rate, int end, byte volume, byte panning) {
+ for (int i = 0; i < end; i++) {
+ const int32 tmp = ((int32) data[fracToInt(offset)]) * volume;
+ if (stereo) {
+ *buf++ += (tmp * (255 - panning)) >> 7;
+ *buf++ += (tmp * (panning)) >> 7;
+ } else
+ *buf++ += tmp;
+
+ offset += rate;
+ }
+}
+
+template<bool stereo>
+int Paula::readBufferIntern(int16 *buffer, const int numSamples) {
+ int samples = _stereo ? numSamples / 2 : numSamples;
while (samples > 0) {
+
+ // Handle 'interrupts'. This gives subclasses the chance to adjust the channel data
+ // (e.g. insert new samples, do pitch bending, whatever).
if (_curInt == _intFreq) {
interrupt();
_curInt = 0;
}
- nSamples = MIN(samples, _intFreq - _curInt);
- for (voice = 0; voice < NUM_VOICES; voice++) {
+
+ // Compute how many samples to generate: at most the requested number of samples,
+ // of course, but we may stop earlier when an 'interrupt' is expected.
+ const int nSamples = MIN(samples, _intFreq - _curInt);
+
+ // Loop over the four channels of the emulated Paula chip
+ for (int voice = 0; voice < NUM_VOICES; voice++) {
+
+ // No data, or paused -> skip channel
if (!_voice[voice].data || (_voice[voice].period <= 0))
continue;
- frequency = (7093789.2 / 2.0) / _voice[voice].period;
- rate = frequency / _rate;
- offset = _voice[voice].offset;
- sLen = _voice[voice].length;
- data = _voice[voice].data;
- p = buffer;
+ // The Paula chip apparently run at 7.0937892 MHz. We combine this with
+ // the requested output sampling rate (typicall 44.1 kHz or 22.05 kHz)
+ // as well as the "period" of the channel we are processing right now,
+ // to compute the correct output 'rate'.
+ const double frequency = (7093789.2 / 2.0) / _voice[voice].period;
+ frac_t rate = doubleToFrac(frequency / _rate);
+ // Cap the volume
_voice[voice].volume = MIN((byte) 0x40, _voice[voice].volume);
- if ((_voice[voice].lengthRepeat > 2) &&
- ((int)(offset + nSamples * rate) >= sLen)) {
- int neededSamples = nSamples;
-
- int end = (int)((sLen - offset) / rate);
- for (int i = 0; i < end; i++)
- mix(p, data[(int)(offset + rate * i)], voice);
-
- _voice[voice].length = sLen = _voice[voice].lengthRepeat;
+ // Cache some data (helps the compiler to optimize the code, by
+ // indirectly telling it that no data aliasing can occur).
+ frac_t offset = _voice[voice].offset;
+ frac_t sLen = intToFrac(_voice[voice].length);
+ const int8 *data = _voice[voice].data;
+ int16 *p = buffer;
+ int end = 0;
+ int neededSamples = nSamples;
+
+ // Compute the number of samples to generate; that is, either generate
+ // just as many as were requested, or until the buffer is used up.
+ // Note that dividing two frac_t yields an integer (as the denominators
+ // cancel out each other).
+ // Note that 'end' could be 0 here. No harm in that :-).
+ end = MIN(neededSamples, (int)((sLen - offset + rate - 1) / rate));
+ mixBuffer<stereo>(p, data, offset, rate, end, _voice[voice].volume, _voice[voice].panning);
+ neededSamples -= end;
+
+ // If we have not yet generated enough samples, and looping is active: loop!
+ if (neededSamples > 0 && _voice[voice].lengthRepeat > 2) {
+
+ // At this point we know that we have used up all samples in the buffer, so reset it.
_voice[voice].data = data = _voice[voice].dataRepeat;
- _voice[voice].offset = offset = 0;
- neededSamples -= end;
+ _voice[voice].length = _voice[voice].lengthRepeat;
+ sLen = intToFrac(_voice[voice].length);
+
+ // If the "rate" exceeds the sample rate, we would have to perform constant
+ // wrap arounds. So, apply the first step of the euclidean algorithm to
+ // achieve the same more efficiently: Take rate modulo sLen
+ if (sLen < rate)
+ rate %= sLen;
+ // Repeat as long as necessary.
while (neededSamples > 0) {
- if (neededSamples >= (int) ((sLen - offset) / rate)) {
- while (rate > (sLen - offset))
- rate -= (sLen - offset);
-
- end = (int)((sLen - offset) / rate);
-
- for (int i = 0; i < end; i++)
- mix(p, data[(int)(offset + rate * i)], voice);
-
- _voice[voice].data = data = _voice[voice].dataRepeat;
- _voice[voice].length = sLen =
- _voice[voice].lengthRepeat;
- _voice[voice].offset = offset = 0;
-
- neededSamples -= end;
- } else {
- for (int i = 0; i < neededSamples; i++)
- mix(p, data[(int)(offset + rate * i)], voice);
- _voice[voice].offset += rate * neededSamples;
- if (ceil(_voice[voice].offset) >= sLen) {
- _voice[voice].data = data = _voice[voice].dataRepeat;
- _voice[voice].length = sLen =
- _voice[voice].lengthRepeat;
- _voice[voice].offset = offset = 0;
- }
- neededSamples = 0;
- }
- }
- } else {
- if (offset < sLen) {
- if ((int)(offset + nSamples * rate) >= sLen) {
- // The end of the sample is the limiting factor
-
- int end = (int)((sLen - offset) / rate);
- for (int i = 0; i < end; i++)
- mix(p, data[(int)(offset + rate * i)], voice);
- _voice[voice].offset = sLen;
- } else {
- // The requested number of samples is the limiting
- // factor, not the sample
-
- for (int i = 0; i < nSamples; i++)
- mix(p, data[(int)(offset + rate * i)], voice);
- _voice[voice].offset += rate * nSamples;
- }
+ offset = 0;
+
+ // Compute the number of samples to generate (see above) and mix 'em.
+ end = MIN(neededSamples, (int)((sLen - offset + rate - 1) / rate));
+ mixBuffer<stereo>(p, data, offset, rate, end, _voice[voice].volume, _voice[voice].panning);
+ neededSamples -= end;
}
}
+
+ // Write back the cached data
+ _voice[voice].offset = offset;
+
}
buffer += _stereo ? nSamples * 2 : nSamples;
_curInt += nSamples;
diff --git a/sound/mods/paula.h b/sound/mods/paula.h
index 0e89b78db6..e86c05b7f8 100644
--- a/sound/mods/paula.h
+++ b/sound/mods/paula.h
@@ -27,6 +27,7 @@
#define SOUND_MODS_PAULA_H
#include "sound/audiostream.h"
+#include "common/frac.h"
#include "common/mutex.h"
namespace Audio {
@@ -45,15 +46,11 @@ public:
bool playing() const { return _playing; }
void setInterruptFreq(int freq) { _curInt = _intFreq = freq; }
- void setPanning(byte voice, byte panning) {
- assert(voice < NUM_VOICES);
- _voice[voice].panning = panning;
- }
void clearVoice(byte voice);
void clearVoices() { for (int i = 0; i < NUM_VOICES; ++i) clearVoice(i); }
- virtual void startPlay(void) {}
- virtual void stopPlay(void) {}
- virtual void pausePlay(bool pause) {}
+ void startPlay(void) { _playing = true; }
+ void stopPlay(void) { _playing = false; }
+ void pausePlay(bool pause) { _playing = !pause; }
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
@@ -69,27 +66,79 @@ protected:
uint32 lengthRepeat;
int16 period;
byte volume;
- double offset;
+ frac_t offset;
byte panning; // For stereo mixing: 0 = far left, 255 = far right
- } _voice[NUM_VOICES];
+ };
- int _rate;
- int _intFreq;
- int _curInt;
- bool _stereo;
bool _end;
- bool _playing;
Common::Mutex _mutex;
- void mix(int16 *&buf, int8 data, int voice) {
- const int32 tmp = ((int32) data) * _voice[voice].volume;
- if (_stereo) {
- *buf++ += (tmp * (255 - _voice[voice].panning)) >> 7;
- *buf++ += (tmp * (_voice[voice].panning)) >> 7;
- } else
- *buf++ += tmp;
+ virtual void interrupt(void) = 0;
+
+ void startPaula() {
+ _playing = true;
+ _end = false;
+ }
+
+ void stopPaula() {
+ _playing = false;
+ _end = true;
+ }
+
+ void setChannelPanning(byte channel, byte panning) {
+ assert(channel < NUM_VOICES);
+ _voice[channel].panning = panning;
}
- virtual void interrupt(void) {}
+
+ void setChannelPeriod(byte channel, int16 period) {
+ assert(channel < NUM_VOICES);
+ _voice[channel].period = period;
+ }
+
+ void setChannelVolume(byte channel, byte volume) {
+ assert(channel < NUM_VOICES);
+ _voice[channel].volume = volume;
+ }
+
+ void setChannelData(uint8 channel, const int8 *data, const int8 *dataRepeat, uint32 length, uint32 lengthRepeat, int32 offset = 0) {
+ assert(channel < NUM_VOICES);
+
+ // For now, we only support 32k samples, as we use 16bit fixed point arithmetics.
+ // If this ever turns out to be a problem, we can still enhance this code.
+ assert(0 <= offset && offset < 32768);
+ assert(length < 32768);
+ assert(lengthRepeat < 32768);
+
+ Channel &ch = _voice[channel];
+ ch.data = data;
+ ch.dataRepeat = dataRepeat;
+ ch.length = length;
+ ch.lengthRepeat = lengthRepeat;
+ ch.offset = intToFrac(offset);
+ }
+
+ void setChannelOffset(byte channel, frac_t offset) {
+ assert(channel < NUM_VOICES);
+ assert(0 <= offset);
+ _voice[channel].offset = offset;
+ }
+
+ frac_t getChannelOffset(byte channel) {
+ assert(channel < NUM_VOICES);
+ return _voice[channel].offset;
+ }
+
+private:
+ Channel _voice[NUM_VOICES];
+
+ const bool _stereo;
+ const int _rate;
+ int _intFreq;
+ int _curInt;
+ bool _playing;
+
+ template<bool stereo>
+ int readBufferIntern(int16 *buffer, const int numSamples);
};
} // End of namespace Audio
diff --git a/sound/mods/protracker.cpp b/sound/mods/protracker.cpp
index 806df85b2b..46ee3aabf7 100644
--- a/sound/mods/protracker.cpp
+++ b/sound/mods/protracker.cpp
@@ -37,8 +37,6 @@ class ProtrackerStream : public ::Audio::Paula {
private:
Module _module;
- int _rate;
-
int _tick;
int _row;
int _pos;
@@ -67,7 +65,7 @@ private:
struct {
byte sample;
uint16 period;
- double offset;
+ frac_t offset;
byte vol;
byte finetune;
@@ -95,7 +93,6 @@ public:
ProtrackerStream(Common::ReadStream *stream, int rate, bool stereo);
private:
- void startPlay() { _playing = true; _end = false; }
void interrupt();
void doPorta(int track) {
@@ -153,7 +150,6 @@ ProtrackerStream::ProtrackerStream(Common::ReadStream *stream, int rate, bool st
bool result = _module.load(*stream);
assert(result);
- _rate = rate;
_tick = _row = _pos = 0;
_speed = 6;
@@ -173,7 +169,7 @@ ProtrackerStream::ProtrackerStream(Common::ReadStream *stream, int rate, bool st
memset(_track, 0, sizeof(_track));
- startPlay();
+ startPaula();
}
void ProtrackerStream::updateRow() {
@@ -181,10 +177,10 @@ void ProtrackerStream::updateRow() {
_track[track].arpeggio = false;
_track[track].vibrato = 0;
_track[track].delaySampleTick = 0;
- note_t note =
+ const note_t note =
_module.pattern[_module.songpos[_pos]][_row][track];
- int effect = note.effect >> 8;
+ const int effect = note.effect >> 8;
if (note.sample) {
if (_track[track].sample != note.sample) {
@@ -201,19 +197,18 @@ void ProtrackerStream::updateRow() {
_track[track].period = _module.noteToPeriod(note.note, _track[track].finetune);
else
_track[track].period = note.period;
- _track[track].offset = 0.0;
+ _track[track].offset = 0;
}
}
- int exy = note.effect & 0xff;
- if (exy);
- int ex = (note.effect >> 4) & 0xf;
- int ey = note.effect & 0xf;
+ const byte exy = note.effect & 0xff;
+ const byte ex = (note.effect >> 4) & 0xf;
+ const byte ey = note.effect & 0xf;
int vol;
switch (effect) {
case 0x0:
- if (ex || ey) {
+ if (exy) {
_track[track].arpeggio = true;
if (note.period) {
_track[track].arpeggioNotes[0] = note.note;
@@ -233,7 +228,7 @@ void ProtrackerStream::updateRow() {
_track[track].portaToNoteSpeed = exy;
break;
case 0x4:
- if (ex || ey) {
+ if (exy) {
_track[track].vibratoSpeed = ex;
_track[track].vibratoDepth = ey;
}
@@ -248,8 +243,8 @@ void ProtrackerStream::updateRow() {
break;
case 0x9: // Set sample offset
if (exy) {
- _track[track].offset = exy * 256;
- _voice[track].offset = _track[track].offset;
+ _track[track].offset = intToFrac(exy * 256);
+ setChannelOffset(track, _track[track].offset);
}
break;
case 0xA:
@@ -342,26 +337,22 @@ void ProtrackerStream::updateEffects() {
for (int track = 0; track < 4; track++) {
_track[track].vibrato = 0;
- note_t note =
+ const note_t note =
_module.pattern[_module.songpos[_pos]][_row][track];
- int effect = note.effect >> 8;
+ const int effect = note.effect >> 8;
- int exy = note.effect & 0xff;
- int ex = (note.effect >> 4) & 0xf;
- int ey = (note.effect) & 0xf;
+ const int exy = note.effect & 0xff;
+ const int ex = (note.effect >> 4) & 0xf;
+ const int ey = (note.effect) & 0xf;
switch (effect) {
case 0x0:
- if (ex || ey) {
- if (_tick == 1)
- _track[track].period =
- _module.noteToPeriod(_track[track].arpeggioNotes[0],
- _track[track].finetune);
- else
- _track[track].period =
- _module.noteToPeriod(_track[track].arpeggioNotes[_tick % 3],
- _track[track].finetune);
+ if (exy) {
+ const int idx = (_tick == 1) ? 0 : (_tick % 3);
+ _track[track].period =
+ _module.noteToPeriod(_track[track].arpeggioNotes[idx],
+ _track[track].finetune);
}
break;
case 0x1:
@@ -392,13 +383,13 @@ void ProtrackerStream::updateEffects() {
case 0x6:
break; // Pattern loop
case 0x9: // Retrigger note
- if (ey && _tick % ey == 0)
- _track[track].offset = 0.0;
+ if (ey && (_tick % ey) == 0)
+ _track[track].offset = 0;
break;
case 0xD: // Delay sample
if (_tick == _track[track].delaySampleTick) {
_track[track].sample = _track[track].delaySample;
- _track[track].offset = 0.0;
+ _track[track].offset = 0;
if (_track[track].sample)
_track[track].vol = _module.sample[_track[track].sample - 1].vol;
}
@@ -412,14 +403,15 @@ void ProtrackerStream::updateEffects() {
void ProtrackerStream::interrupt(void) {
int track;
- for (track = 0; track < 4; track++)
- _track[track].offset = _voice[track].offset;
-
- if (_tick == 0) {
- if (_track[track].arpeggio) {
+ for (track = 0; track < 4; track++) {
+ _track[track].offset = getChannelOffset(track);
+ if (_tick == 0 && _track[track].arpeggio) {
_track[track].period = _module.noteToPeriod(_track[track].arpeggioNotes[0],
_track[track].finetune);
}
+ }
+
+ if (_tick == 0) {
if (_hasJumpToPattern) {
_hasJumpToPattern = false;
_pos = _jumpToPattern;
@@ -450,15 +442,16 @@ void ProtrackerStream::interrupt(void) {
}
for (track = 0; track < 4; track++) {
- _voice[track].period = _track[track].period + _track[track].vibrato;
- _voice[track].volume = _track[track].vol;
+ setChannelVolume(track, _track[track].vol);
+ setChannelPeriod(track, _track[track].period + _track[track].vibrato);
if (_track[track].sample) {
sample_t &sample = _module.sample[_track[track].sample - 1];
- _voice[track].data = sample.data;
- _voice[track].dataRepeat = sample.replen > 2 ? sample.data + sample.repeat : 0;
- _voice[track].length = sample.len;
- _voice[track].lengthRepeat = sample.replen;
- _voice[track].offset = _track[track].offset;
+ setChannelData(track,
+ sample.data,
+ sample.replen > 2 ? sample.data + sample.repeat : 0,
+ sample.len,
+ sample.replen,
+ _track[track].offset);
_track[track].sample = 0;
}
}
diff --git a/sound/mods/rjp1.cpp b/sound/mods/rjp1.cpp
index ab5d7430be..3f5582de51 100644
--- a/sound/mods/rjp1.cpp
+++ b/sound/mods/rjp1.cpp
@@ -113,8 +113,6 @@ protected:
void stopPaulaChannel(uint8 channel);
void setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen);
- void setupPaulaChannelPeriod(uint8 channel, int16 period);
- void setPaulaChannelVolume(uint8 channel, uint8 volume);
virtual void interrupt();
@@ -202,8 +200,7 @@ void Rjp1::startSong(int song) {
}
}
// "start" Paula audiostream
- _playing = true;
- _end = false;
+ startPaula();
}
void Rjp1::startSequence(uint8 channelNum, uint8 seqNum) {
@@ -351,7 +348,7 @@ void Rjp1::modulatePeriod(Rjp1Channel *channel) {
channel->freqInit += channel->freqInc;
--channel->freqStep;
}
- setupPaulaChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext);
+ setChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext);
}
void Rjp1::setupNote(Rjp1Channel *channel, int16 period) {
@@ -482,7 +479,7 @@ void Rjp1::modulateVolumeWaveform(Rjp1Channel *channel) {
void Rjp1::setVolume(Rjp1Channel *channel) {
channel->volume = (channel->volume * channel->volumeScale) / 64;
channel->volume = CLIP<int16>(channel->volume, 0, 64);
- setPaulaChannelVolume(channel - _channelsTable, channel->volume);
+ setChannelVolume(channel - _channelsTable, channel->volume);
}
void Rjp1::stopPaulaChannel(uint8 channel) {
@@ -491,23 +488,10 @@ void Rjp1::stopPaulaChannel(uint8 channel) {
void Rjp1::setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen) {
if (waveData) {
- Channel *ch = &_voice[channel];
- ch->data = waveData;
- ch->dataRepeat = waveData + repeatPos * 2;
- ch->length = len * 2;
- ch->lengthRepeat = repeatLen * 2;
- ch->offset = offset * 2;
+ setChannelData(channel, waveData, waveData + repeatPos * 2, len * 2, repeatLen * 2, offset * 2);
}
}
-void Rjp1::setupPaulaChannelPeriod(uint8 channel, int16 period) {
- _voice[channel].period = period;
-}
-
-void Rjp1::setPaulaChannelVolume(uint8 channel, uint8 volume) {
- _voice[channel].volume = volume;
-}
-
void Rjp1::interrupt() {
for (int i = 0; i < 4; ++i) {
_vars.currentChannel = i;
diff --git a/sound/mods/soundfx.cpp b/sound/mods/soundfx.cpp
index 06104f4838..e60fd8468a 100644
--- a/sound/mods/soundfx.cpp
+++ b/sound/mods/soundfx.cpp
@@ -63,10 +63,6 @@ protected:
void updateEffects(int ch);
void handleTick();
- void startPaula();
- void stopPaula();
- void setPaulaChannelPeriod(uint8 channel, int16 period);
- void setPaulaChannelVolume(uint8 channel, uint8 volume);
void enablePaulaChannel(uint8 channel);
void disablePaulaChannel(uint8 channel);
void setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen);
@@ -174,7 +170,7 @@ void SoundFx::play() {
_curOrder = 0;
_ticks = 0;
_eventsFreq = CIA_FREQ / _delay;
- setInterruptFreq(_rate / _eventsFreq);
+ setInterruptFreq(getRate() / _eventsFreq);
startPaula();
}
@@ -202,7 +198,7 @@ void SoundFx::handlePattern(int ch, uint32 pat) {
}
break;
}
- setPaulaChannelVolume(ch, volume);
+ setChannelVolume(ch, volume);
}
}
_effects[ch] = note2;
@@ -211,7 +207,7 @@ void SoundFx::handlePattern(int ch, uint32 pat) {
} else if (note1 == 0xFFFE) { // STP
disablePaulaChannel(ch);
} else if (note1 != 0) {
- setPaulaChannelPeriod(ch, note1);
+ setChannelPeriod(ch, note1);
enablePaulaChannel(ch);
}
}
@@ -256,39 +252,17 @@ void SoundFx::handleTick() {
}
}
-void SoundFx::startPaula() {
- _playing = true;
- _end = false;
-}
-
-void SoundFx::stopPaula() {
- _playing = false;
- _end = true;
-}
-
-void SoundFx::setPaulaChannelPeriod(uint8 channel, int16 period) {
- _voice[channel].period = period;
-}
-
-void SoundFx::setPaulaChannelVolume(uint8 channel, uint8 volume) {
- _voice[channel].volume = volume;
-}
-
void SoundFx::enablePaulaChannel(uint8 channel) {
+ // FIXME: Is this empty on purpose?!?
}
void SoundFx::disablePaulaChannel(uint8 channel) {
- _voice[channel].period = 0;
+ setChannelPeriod(channel, 0);
}
void SoundFx::setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen) {
if (data && len > 1) {
- Channel *ch = &_voice[channel];
- ch->data = data;
- ch->dataRepeat = data + repeatPos * 2;
- ch->length = len * 2;
- ch->lengthRepeat = repeatLen * 2;
- ch->offset = 0;
+ setChannelData(channel, data, data + repeatPos * 2, len * 2, repeatLen * 2);
}
}
diff --git a/sound/rate.cpp b/sound/rate.cpp
index 6a51f3d5d5..6e8e83f9a6 100644
--- a/sound/rate.cpp
+++ b/sound/rate.cpp
@@ -35,15 +35,11 @@
#include "sound/audiostream.h"
#include "sound/rate.h"
#include "sound/mixer.h"
+#include "common/frac.h"
#include "common/util.h"
namespace Audio {
-/**
- * The precision of the fractional computations used by the rate converter.
- * Normally you should never have to modify this value.
- */
-#define FRAC_BITS 16
/**
* The size of the intermediate input cache. Bigger values may increase
@@ -88,12 +84,8 @@ public:
*/
template<bool stereo, bool reverseStereo>
SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
- if (inrate == outrate) {
- error("Input and Output rates must be different to use rate effect");
- }
-
if ((inrate % outrate) != 0) {
- error("Input rate must be a multiple of Output rate to use rate effect");
+ error("Input rate must be a multiple of output rate to use rate effect");
}
if (inrate >= 65536 || outrate >= 65536) {
@@ -174,10 +166,10 @@ protected:
int inLen;
/** fractional position of the output stream in input stream unit */
- long opos, opos_frac;
+ frac_t opos;
/** fractional position increment in the output stream */
- long opos_inc, opos_inc_frac;
+ frac_t opos_inc;
/** last sample(s) in the input stream (left/right channel) */
st_sample_t ilast0, ilast1;
@@ -198,24 +190,18 @@ public:
*/
template<bool stereo, bool reverseStereo>
LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
- unsigned long incr;
-
- if (inrate == outrate) {
- error("Input and Output rates must be different to use rate effect");
- }
-
if (inrate >= 65536 || outrate >= 65536) {
error("rate effect can only handle rates < 65536");
}
- opos_frac = 0;
- opos = 1;
-
- /* increment */
- incr = (inrate << FRAC_BITS) / outrate;
+ opos = FRAC_ONE;
- opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1);
- opos_inc = incr >> FRAC_BITS;
+ // Compute the linear interpolation increment.
+ // This will overflow if inrate >= 2^16, and underflow if outrate >= 2^16.
+ // Also, if the quotient of the two rate becomes too small / too big, that
+ // would cause problems, but since we rarely scale from 1 to 65536 Hz or vice
+ // versa, I think we can live with that limiation ;-).
+ opos_inc = (inrate << FRAC_BITS) / outrate;
ilast0 = ilast1 = 0;
icur0 = icur1 = 0;
@@ -236,8 +222,8 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
while (obuf < oend) {
- // read enough input samples so that opos <= 0
- while (0 <= opos) {
+ // read enough input samples so that opos < 0
+ while (FRAC_ONE <= opos) {
// Check if we have to refill the buffer
if (inLen == 0) {
inPtr = inBuf;
@@ -252,17 +238,17 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
ilast1 = icur1;
icur1 = *inPtr++;
}
- opos--;
+ opos -= FRAC_ONE;
}
// Loop as long as the outpos trails behind, and as long as there is
// still space in the output buffer.
- while (0 > opos && obuf < oend) {
+ while (opos < FRAC_ONE && obuf < oend) {
// interpolate
st_sample_t out0, out1;
- out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
+ out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF) >> FRAC_BITS));
out1 = (stereo ?
- (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) :
+ (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF) >> FRAC_BITS)) :
out0);
// output left channel
@@ -274,9 +260,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
obuf += 2;
// Increment output position
- long tmp = opos_frac + opos_inc_frac;
- opos += opos_inc + (tmp >> FRAC_BITS);
- opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
+ opos += opos_inc;
}
}
return ST_SUCCESS;
@@ -344,38 +328,30 @@ public:
#pragma mark -
-
-/**
- * Create and return a RateConverter object for the specified input and output rates.
- */
-RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
+template<bool stereo, bool reverseStereo>
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) {
if (inrate != outrate) {
if ((inrate % outrate) == 0) {
- if (stereo) {
- if (reverseStereo)
- return new SimpleRateConverter<true, true>(inrate, outrate);
- else
- return new SimpleRateConverter<true, false>(inrate, outrate);
- } else
- return new SimpleRateConverter<false, false>(inrate, outrate);
+ return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate);
} else {
- if (stereo) {
- if (reverseStereo)
- return new LinearRateConverter<true, true>(inrate, outrate);
- else
- return new LinearRateConverter<true, false>(inrate, outrate);
- } else
- return new LinearRateConverter<false, false>(inrate, outrate);
- }
+ return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate);
+ }
} else {
- if (stereo) {
- if (reverseStereo)
- return new CopyRateConverter<true, true>();
- else
- return new CopyRateConverter<true, false>();
- } else
- return new CopyRateConverter<false, false>();
+ return new CopyRateConverter<stereo, reverseStereo>();
}
}
+/**
+ * Create and return a RateConverter object for the specified input and output rates.
+ */
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
+ if (stereo) {
+ if (reverseStereo)
+ return makeRateConverter<true, true>(inrate, outrate);
+ else
+ return makeRateConverter<true, false>(inrate, outrate);
+ } else
+ return makeRateConverter<false, false>(inrate, outrate);
+}
+
} // End of namespace Audio
diff --git a/sound/rate_arm.cpp b/sound/rate_arm.cpp
index 694e213dce..ad8f0519c6 100644
--- a/sound/rate_arm.cpp
+++ b/sound/rate_arm.cpp
@@ -50,13 +50,18 @@
#include "sound/mixer.h"
#include "common/util.h"
+//#define DEBUG_RATECONV
+
namespace Audio {
/**
* The precision of the fractional computations used by the rate converter.
* Normally you should never have to modify this value.
+ * This stuff is defined in common/frac.h, but we redefine it here as the
+ * ARM routine we call doesn't respect those definitions.
*/
#define FRAC_BITS 16
+#define FRAC_ONE (1<<FRAC_BITS)
/**
* The size of the intermediate input cache. Bigger values may increase
@@ -152,6 +157,10 @@ extern "C" void ARM_SimpleRate_R(AudioStream &input,
extern "C" int SimpleRate_readFudge(Audio::AudioStream &input,
int16 *a, int b)
{
+#ifdef DEBUG_RATECONV
+ fprintf(stderr, "Reading ptr=%x n%d\n", a, b);
+ fflush(stderr);
+#endif
return input.readBuffer(a, b);
}
@@ -197,7 +206,7 @@ typedef struct {
int inLen;
/** position of how far output is ahead of input */
- /** Holds what would have been opos-ipos */
+ /** Holds what would have been opos-ipos<<16 + opos_frac */
long opos;
/** integer position increment in the output stream */
@@ -206,13 +215,8 @@ typedef struct {
/** current sample(s) in the input stream (left/right channel) */
st_sample_t icur[2];
/** last sample(s) in the input stream (left/right channel) */
- st_sample_t ilast[2];
-
- /** fractional position in the output stream */
- long opos_frac;
-
- /** fractional position increment in the output stream */
- long opos_inc_frac;
+ /** Note, these are deliberately ints, not st_sample_t's */
+ int32 ilast[2];
st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
} LinearRateDetails;
@@ -270,16 +274,14 @@ LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate
error("rate effect can only handle rates < 65536");
}
- lr.opos_frac = 0;
- lr.opos = 1;
+ lr.opos = FRAC_ONE;
/* increment */
incr = (inrate << FRAC_BITS) / outrate;
- lr.opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1);
- lr.opos_inc = incr >> FRAC_BITS;
+ lr.opos_inc = incr;
- lr.ilast[0] = lr.ilast[1] = 0;
+ lr.ilast[0] = lr.ilast[1] = 32768;
lr.icur[0] = lr.icur[1] = 0;
lr.inLen = 0;
diff --git a/sound/rate_arm_asm.s b/sound/rate_arm_asm.s
index 709d343c6c..5a9cf5717f 100644
--- a/sound/rate_arm_asm.s
+++ b/sound/rate_arm_asm.s
@@ -396,6 +396,7 @@ ARM_LinearRate_M:
LDMIA r2,{r0,r1,r8} @ r0 = inPtr
@ r1 = inLen
@ r8 = opos
+ MOV r10,#0
CMP r11,#0 @ if (osamp <= 0)
BLE LinearRate_M_end @ bale
ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits
@@ -408,29 +409,23 @@ LinearRate_M_loop:
SUBS r1, r1, #1 @ r1 = inLen -= 1
BLT LinearRate_M_read
LinearRate_M_read_return:
- LDR r10,[r2, #16] @ r10= icur[0,1]
+ LDRH r4, [r2, #16] @ r4 = icur[0]
LDRSH r5, [r0],#2 @ r5 = tmp1 = *inPtr++
- SUBS r8, r8, #1 @ r8 = opos--
- STR r10,[r2,#20] @ ilast[0,1] = icur[0,1]
+ SUBS r8, r8, #65536 @ r8 = opos--
+ STRH r4, [r2,#22] @ ilast[0] = icur[0]
STRH r5, [r2,#16] @ icur[0] = tmp1
BGE LinearRate_M_loop
@ part2 - form output samples
LinearRate_M_part2:
@ We are guaranteed that opos < 0 here
- LDRSH r6, [r2,#20] @ r6 = ilast[0]
+ LDR r6, [r2,#20] @ r6 = ilast[0]<<16 + 32768
LDRSH r5, [r2,#16] @ r5 = icur[0]
- LDRH r4, [r2,#24] @ r4 = opos_frac
- LDR r10,[r2,#28] @ r10= opos_frac_inc
- MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16
+ MOV r4, r8, LSL #16
+ MOV r4, r4, LSR #16
SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0]
- ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1)
MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0]
- ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac
- STRH r4,[r2,#24] @ opos_frac &= 65535
- ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS)
-
LDRSH r4, [r3] @ r4 = obuf[0]
LDRSH r5, [r3,#2] @ r5 = obuf[1]
MOV r6, r6, ASR #16 @ r6 = tmp0 = tmp1 >>= 16
@@ -438,10 +433,9 @@ LinearRate_M_part2:
MUL r6, r14,r6 @ r6 = tmp1*vol_r
ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
- MOV r4, #0
- RSCVS r7, r4, #1<<31 @ Clamp r7
+ RSCVS r7, r10, #1<<31 @ Clamp r7
ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r
- RSCVS r6, r4, #1<<31 @ Clamp r6
+ RSCVS r6, r10, #1<<31 @ Clamp r6
MOV r7, r7, LSR #16 @ Shift back to halfword
MOV r6, r6, LSR #16 @ Shift back to halfword
@@ -449,7 +443,7 @@ LinearRate_M_part2:
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r7, [r3],#2 @ Store output value
STRH r6, [r3],#2 @ Store output value
- SUBS r11, r11,#1 @ opos--
+ SUBS r11, r11,#1 @ osamp--
BLE LinearRate_M_end @ end if needed
ADDS r8, r8, r5 @ r8 = opos += opos_inc
@@ -460,7 +454,7 @@ LinearRate_M_end:
STMIA r2,{r0,r1,r8}
LDMFD r13!,{r4-r11,PC}
LinearRate_M_read:
- ADD r0, r2, #32 @ r0 = inPtr = inBuf
+ ADD r0, r2, #28 @ r0 = inPtr = inBuf
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -508,43 +502,37 @@ LinearRate_S_read_return:
LDR r10,[r2, #16] @ r10= icur[0,1]
LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++
LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++
- SUBS r8, r8, #1 @ r8 = opos--
- STR r10,[r2,#20] @ ilast[0,1] = icur[0,1]
+ SUBS r8, r8, #65536 @ r8 = opos--
+ STRH r10,[r2,#22] @ ilast[0] = icur[0]
+ MOV r10,r10,LSR #16
+ STRH r10,[r2,#26] @ ilast[1] = icur[1]
STRH r5, [r2,#16] @ icur[0] = tmp0
- STRH r6, [r2,#16] @ icur[1] = tmp1
+ STRH r6, [r2,#18] @ icur[1] = tmp1
BGE LinearRate_S_loop
@ part2 - form output samples
LinearRate_S_part2:
@ We are guaranteed that opos < 0 here
- LDRSH r6, [r2,#20] @ r6 = ilast[0]
+ LDR r6, [r2,#20] @ r6 = ilast[0]<<16 + 32768
LDRSH r5, [r2,#16] @ r5 = icur[0]
- LDRH r4, [r2,#24] @ r4 = opos_frac
- MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16
+ MOV r4, r8, LSL #16
+ MOV r4, r4, LSR #16
SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0]
- ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1)
MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0]
- LDRSH r7, [r2,#22] @ r6 = ilast[1]
+ LDR r7, [r2,#24] @ r7 = ilast[1]<<16 + 32768
LDRSH r5, [r2,#18] @ r5 = icur[1]
- LDR r10,[r2,#28] @ r10= opos_frac_inc
- MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16
+ LDRSH r10,[r3] @ r10= obuf[0]
+ MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1]
- ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1)
- MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1]
-
- ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac
- STRH r4,[r2,#24] @ opos_frac &= 65535
- ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS)
+ MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1]
- LDRSH r4, [r3] @ r4 = obuf[0]
LDRSH r5, [r3,#2] @ r5 = obuf[1]
MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16
- MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
MUL r7, r12,r7 @ r7 = tmp0*vol_l
MUL r6, r14,r6 @ r6 = tmp1*vol_r
- ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
+ ADDS r7, r7, r10, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
MOV r4, #0
RSCVS r7, r4, #1<<31 @ Clamp r7
ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r
@@ -556,7 +544,7 @@ LinearRate_S_part2:
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r7, [r3],#2 @ Store output value
STRH r6, [r3],#2 @ Store output value
- SUBS r11, r11,#1 @ opos--
+ SUBS r11, r11,#1 @ osamp--
BLE LinearRate_S_end @ and loop
ADDS r8, r8, r5 @ r8 = opos += opos_inc
@@ -567,7 +555,7 @@ LinearRate_S_end:
STMIA r2,{r0,r1,r8}
LDMFD r13!,{r4-r11,PC}
LinearRate_S_read:
- ADD r0, r2, #32 @ r0 = inPtr = inBuf
+ ADD r0, r2, #28 @ r0 = inPtr = inBuf
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
@@ -615,43 +603,37 @@ LinearRate_R_read_return:
LDR r10,[r2, #16] @ r10= icur[0,1]
LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++
LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++
- SUBS r8, r8, #1 @ r8 = opos--
- STR r10,[r2,#20] @ ilast[0,1] = icur[0,1]
+ SUBS r8, r8, #65536 @ r8 = opos--
+ STRH r10,[r2,#22] @ ilast[0] = icur[0]
+ MOV r10,r10,LSR #16
+ STRH r10,[r2,#22] @ ilast[1] = icur[1]
STRH r5, [r2,#16] @ icur[0] = tmp0
- STRH r6, [r2,#16] @ icur[1] = tmp1
+ STRH r6, [r2,#18] @ icur[1] = tmp1
BGE LinearRate_R_loop
@ part2 - form output samples
LinearRate_R_part2:
@ We are guaranteed that opos < 0 here
- LDRSH r6, [r2,#20] @ r6 = ilast[0]
+ LDR r6, [r2,#20] @ r6 = ilast[0]
LDRSH r5, [r2,#16] @ r5 = icur[0]
- LDRH r4, [r2,#24] @ r4 = opos_frac
- MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16
+ MOV r4, r8, LSL #16
+ MOV r4, r4, LSR #16
SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0]
- ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1)
MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0]
- LDRSH r7, [r2,#22] @ r6 = ilast[1]
+ LDR r7, [r2,#24] @ r7 = ilast[1]
LDRSH r5, [r2,#18] @ r5 = icur[1]
- LDR r10,[r2,#28] @ r10= opos_frac_inc
- MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16
+ LDR r10,[r3] @ r10= obuf[0]
+ MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1]
- ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1)
- MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1]
+ MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1]
- ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac
- STRH r4,[r2,#24] @ opos_frac &= 65535
- ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS)
-
- LDRSH r4, [r3] @ r4 = obuf[0]
LDRSH r5, [r3,#2] @ r5 = obuf[1]
MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16
- MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16
MUL r7, r12,r7 @ r7 = tmp0*vol_l
MUL r6, r14,r6 @ r6 = tmp1*vol_r
- ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
+ ADDS r7, r7, r10, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l
MOV r4, #0
RSCVS r7, r4, #1<<31 @ Clamp r7
ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r
@@ -663,7 +645,7 @@ LinearRate_R_part2:
LDR r5, [r2,#12] @ r5 = opos_inc
STRH r6, [r3],#2 @ Store output value
STRH r7, [r3],#2 @ Store output value
- SUBS r11, r11,#1 @ opos--
+ SUBS r11, r11,#1 @ osamp--
BLE LinearRate_R_end @ and loop
ADDS r8, r8, r5 @ r8 = opos += opos_inc
@@ -674,7 +656,7 @@ LinearRate_R_end:
STMIA r2,{r0,r1,r8}
LDMFD r13!,{r4-r11,PC}
LinearRate_R_read:
- ADD r0, r2, #32 @ r0 = inPtr = inBuf
+ ADD r0, r2, #28 @ r0 = inPtr = inBuf
STMFD r13!,{r0,r2-r3,r12,r14}
MOV r1, r0 @ r1 = inBuf
diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp
index 5d36c9ec28..e3aa9d2528 100644
--- a/sound/softsynth/ym2612.cpp
+++ b/sound/softsynth/ym2612.cpp
@@ -129,7 +129,7 @@ void Operator2612::frequency(int freq) {
value *= 127 - _specifiedTotalLevel;
value /= 127;
}
- _attackTime = (int32) value; // 1 ÉÃ == (1 << 12)
+ _attackTime = (int32) value; // 1 ?? == (1 << 12)
if (_attackTime > 0)
_attackTime = (1 << (12+10)) / (_owner->_rate * _attackTime);
@@ -295,7 +295,7 @@ Voice2612::~Voice2612() {
void Voice2612::velocity(int velo) {
_velocity = velo;
#if 0
- int v = (velo * _control7) >> 7; // ¤³¤ì¤À¤ÈÀºÅÙÎɤ¯¤Ê¤¤¤Ç¤¹¤Í
+ int v = (velo * _control7) >> 7;
#else
int v = velo + (_control7 - 127) * 4;
#endif
diff --git a/sound/voc.h b/sound/voc.h
index ebd343f05d..fd19a29c5a 100644
--- a/sound/voc.h
+++ b/sound/voc.h
@@ -43,14 +43,14 @@ struct VocFileHeader {
uint16 datablock_offset;
uint16 version;
uint16 id;
-};
+} PACKED_STRUCT;
struct VocBlockHeader {
uint8 blocktype;
uint8 size[3];
uint8 sr;
uint8 pack;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/test/common/pack.h b/test/common/pack.h
index 68254db187..76086b05ca 100644
--- a/test/common/pack.h
+++ b/test/common/pack.h
@@ -12,7 +12,7 @@ struct TestStruct {
uint16 z;
uint32 a;
byte b;
-};
+} PACKED_STRUCT;
#include <common/pack-end.h> // END STRUCT PACKING
diff --git a/tools/credits.pl b/tools/credits.pl
index acdbe03797..7a1bebbed3 100755
--- a/tools/credits.pl
+++ b/tools/credits.pl
@@ -624,6 +624,7 @@ begin_credits("Credits");
begin_section("Miscellaneous");
add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator");
add_person("Jochen Hoenicke", "hoenicke", "Speaker &amp; PCjr sound support, Adlib work");
+ add_person("Robin Watts", "robinwatts", "ARM assembly routines for nice speedups on several ports; improvements to the sound mixer");
end_section();
end_section();
@@ -752,7 +753,6 @@ begin_credits("Credits");
add_person("Edward Rudd", "urkle", "Fixes for playing MP3 versions of MI1/Loom audio");
add_person("Daniel Schepler", "dschepler", "Final MI1 CD music support, initial Ogg Vorbis support");
add_person("Andr&eacute; Souza", "luke_br", "SDL-based OpenGL renderer");
- add_person("Robin Watts", "robinwatts", "ARM assembly routines for the Windows CE port");
end_persons();
end_section();
diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt
index 468bb6b6ce..f97785cbe0 100644
--- a/tools/scumm-md5.txt
+++ b/tools/scumm-md5.txt
@@ -122,22 +122,23 @@ indy3 Indiana Jones and the Last Crusade
157367c3c21e0d03a0cba44361b4cf65 -1 en Atari No Adlib EGA - Andreas Bylund
0f9c7a76657f0840b8f7ccb5bffeb9f4 -1 fr Atari No Adlib EGA - Andreas Bylund
5fbe557049892eb4b709d90916ec97ca 5361 en DOS EGA EGA v1.0, 7/09/89 Fingolfin
- 6b3ec67da214f558dc5ceaa2acd47453 -1 en DOS EGA EGA v1.3 from 14 Aug 89 tsuteiuQ, Andrea Petrucci, Peter Eckerlein
+ 6b3ec67da214f558dc5ceaa2acd47453 -1 en DOS EGA EGA v1.3, 14 Aug 89 tsuteiuQ, Andrea Petrucci, Peter Eckerlein
6508fd55530e6915507e1cc37f7f045d -1 en DOS EGA EGA v1.3, 8/14/89 (5.25\") Zer02
- 66236cd1aec24e1d4aff4c4cc93b7e18 -1 fr DOS EGA EGA v1.3 from 25 Aug 89 Andrea Petrucci, Peter Eckerlein
- 89cfc425566003ff74b7dc7b3e6fd469 -1 fr DOS EGA EGA v1.3, 25 Aug 89 Jorpho
+ 66236cd1aec24e1d4aff4c4cc93b7e18 -1 fr DOS EGA EGA ?? v1.3, 25 Aug 89 Andrea Petrucci, Peter Eckerlein
+ 89cfc425566003ff74b7dc7b3e6fd469 -1 fr DOS EGA EGA ?? v1.3, 25 Aug 89 Jorpho
+ 69d70269fafc4445adbb0d223e4f9a3f 5361 en DOS EGA EGA v1.4, 11/07/89 (5.25\") Petr Maruska
6f6ef668c608c7f534fea6e6d3878dde -1 de DOS EGA EGA v1.4 from 19 Oct 89 dhewg, Peter Eckerlein
d62d248c3df6ec177405e2cb23d923b2 -1 it DOS EGA EGA v1.4 from 25 Nov 89 Andrea Petrucci, Peter Eckerlein
86be8ada36371d4fdc35659d0e912a26 -1 es DOS EGA EGA ?? v1.4b from 7 May 90 Andrea Petrucci, Peter Eckerlein
ce7fd0c382389a6791fc3e199c117ef4 -1 es DOS EGA EGA ?? v1.4b from 7 May 90 abnog, Peter Eckerlein
- 1dd7aa088e09f96d06818aa9a9deabe0 5361 en Mac No Adlib EGA - Fingolfin
+ 1dd7aa088e09f96d06818aa9a9deabe0 5361 en Mac No Adlib EGA v1.7, 8/17/90 Fingolfin
1875b90fade138c9253a8e967007031a 6295 en DOS VGA VGA IBM 256 color v2.0 from 3 May 90 Peter Eckerlein, Fingolfin
399b217b0c8d65d0398076da486363a9 6295 de DOS VGA VGA VGA v1.02 from 7 Nov 91 Peter Eckerlein, Fingolfin
17b5d5e6af4ae89d62631641d66d5a05 -1 it DOS VGA VGA IBM 256 color v2.1 from 3 May 01 Andrea Petrucci, Peter Eckerlein
3cce1913a3bc586b51a75c3892ff18dd -1 ru DOS VGA VGA VGA
- 04687cdf7f975a89d2474929f7b80946 7552 en FM-TOWNS FM-TOWNS - - Fingolfin
+ 04687cdf7f975a89d2474929f7b80946 7552 en FM-TOWNS FM-TOWNS - v1.00 1/23/91 Fingolfin
3a0c35f3c147b98a2bdf8d400cfc4ab5 -1 jp FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci
b597e0403cc0002f69170e6caba7edd9 5361 en DOS EGA EGA Demo non-interactive Fingolfin
@@ -163,7 +164,7 @@ loom Loom
187d315f6b5168f68680dfe8c3d76a3e -1 hb DOS EGA EGA -
c3df37df9d3b481b45f75283a9907c47 -1 it DOS EGA EGA - Andrea Petrucci
2a208ffbcd0e83e86f4356e6f64aa6e1 -1 es DOS EGA EGA v1.2 Espanol from 31 Aug 90 abnog, Andrea Petrucci, Peter Eckerlein
- 6f0be328c64d689bb606d22a389e1b0f 5748 en Mac No Adlib EGA - Fingolfin
+ 6f0be328c64d689bb606d22a389e1b0f 5748 en Mac No Adlib EGA v1.2 25 Jan 91 Fingolfin
5d88b9d6a88e6f8e90cded9d01b7f082 8307 en DOS VGA VGA CD Version v1.0 from 10. Feb 92 (Talkie) Peter Eckerlein, Fingolfin
@@ -186,7 +187,7 @@ monkey The Secret of Monkey Island
910e31cffb28226bd68c569668a0d6b4 -1 es DOS EGA EGA 8 disk Andrea Petrucci
1d05cd189e4908f79b57e78a4402f292 -1 en DOS EGA EGA 4 disk Andrea Petrucci
ce6a4cef315b20fef58a95bc40a2d8d3 -1 fr DOS EGA EGA 4 disk Matthieu Milan
- aa7a07d94ae853f6460be4ce0a1bf530 -1 fr DOS EGA EGA 4 disk v1.0,9/7/90 II Parazythum
+ aa7a07d94ae853f6460be4ce0a1bf530 -1 fr DOS EGA EGA 4 disk v1.0, 9/7/90 II Parazythum
e98b982ceaf9d253d730bde8903233d6 -1 de DOS EGA EGA 4 disk Joachim Eberhard
477dbafbd66a53c98416dc01aef019ad -1 it DOS EGA EGA 4 disk Andrea Petrucci
@@ -199,16 +200,16 @@ monkey The Secret of Monkey Island
c7890e038806df2bb5c0c8c6f1986ea2 -1 en DOS VGA VGA 8 disk Andrea Petrucci
15e03ffbfeddb9c2aebc13dcb2a4a8f4 8357 en DOS VGA VGA 4 disk
08656dd9698ddf1023ba9bf8a195e37b -1 en DOS VGA VGA V1.1 crossbow777
- d0b531227a27c6662018d2bd05aac52a 8357 de DOS VGA VGA 4 disk Fingolfin
+ d0b531227a27c6662018d2bd05aac52a 8357 de DOS VGA VGA 4 disk v1.1, 14.Feb.91 Fingolfin
66fd5ff9a810dfeb6d6bdada18221140 -1 it DOS VGA VGA 4 disk Andrea Petrucci
45152f7cf2ba8f43cf8a8ea2e740ae09 8357 es DOS VGA VGA 4 disk Fingolfin
- 2d1e891fe52df707c30185e52c50cd92 8955 en DOS CD CD - Fingolfin
- aa8a0cb65f3afbbe2c14c3f9f92775a3 8955 fr DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci
- 305d3dd57c96c65b017bc70c8c7cfb5e 8955 de DOS CD CD - Fingolfin
- da6269b18fcb08189c0aa9c95533cce2 8955 it DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci
- f049e38c1f8302b5db6170f1872af89a 8955 es DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci
- 2ccd8891ce4d3f1a334d21bff6a88ca2 9455 en Mac CD - - Fingolfin, Lars N&aelig;sbye Christensen
+ 2d1e891fe52df707c30185e52c50cd92 8955 en DOS CD CD CD-ROM v2.3 Fingolfin
+ aa8a0cb65f3afbbe2c14c3f9f92775a3 8955 fr DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci
+ 305d3dd57c96c65b017bc70c8c7cfb5e 8955 de DOS CD CD CD-ROM v2.3 Fingolfin
+ da6269b18fcb08189c0aa9c95533cce2 8955 it DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci
+ f049e38c1f8302b5db6170f1872af89a 8955 es DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci
+ 2ccd8891ce4d3f1a334d21bff6a88ca2 9455 en Mac CD - Mac v2.4 Fingolfin, Lars N&aelig;sbye Christensen
b9ba19ce376efc69be78ef3baef8d2b9 -1 en Mac CD - alt? Grant Yeager
c13225cb1bbd3bc9fe578301696d8021 -1 en SEGA SEGA - -
@@ -220,7 +221,7 @@ monkey The Secret of Monkey Island
54a936ad06161ff7bfefcb96200f7bff -1 en Amiga VGA VGA Demo - khalek
pass Passport to Adventure
- e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - - Fingolfin
+ e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - v1.0 9/14/90 Fingolfin
zak Misc FM-TOWNS demos
2d388339d6050d8ccaa757b64633954e 7520 en FM-TOWNS FM-TOWNS Demo indy/loom (non-interactive) khalek
@@ -228,21 +229,21 @@ zak Misc FM-TOWNS demos
3938ee1aa4433fca9d9308c9891172b1 -1 en FM-TOWNS FM-TOWNS Demo indy/zak (non-interactive) khalek
monkey2 Monkey Island 2: LeChuck's Revenge
- 132bff65e6367c09cc69318ce1b59333 11155 en Amiga - - - Fingolfin
+ 132bff65e6367c09cc69318ce1b59333 11155 en Amiga - - v1.0 4/8/92 Fingolfin
c30ef068add4277104243c31ce46c12b -1 fr Amiga - - - Andreas Bylund
da669b20271b85182e9c17a2a37ea02e -1 de Amiga - - - Andreas Bylund, Norbert Lange
11ddf1fde76e3156eb3a38da213f484e -1 it Amiga - - - Andrea Petrucci
6ea966b4d660c870b9ee790d1fbfc535 -1 es Amiga - - - Andreas Bylund
3686cf8f89e102ececf4366e1d2c8126 11135 en DOS - - -
8e4ee4db46954bfe2912e259a16fad82 -1 fr DOS - - - Nicolas Sauz&egrave;de, Andrea Petrucci
- 6886e5d08cee329b1f2e743ae2e3ceed 11135 de DOS - - - Fingolfin
+ 6886e5d08cee329b1f2e743ae2e3ceed 11135 de DOS - - v1.0D 17Feb92 Fingolfin
69ea626f1f87eecb78ea0d6c6b983a1d -1 it DOS - - - Andrea Petrucci
bd126753de619a495f9f22adc951c8d5 -1 it DOS - - alt? Andrea Petrucci
7974365d3dc0f43a2748c975f91ff042 -1 es DOS - - - Andrea Petrucci
- 4cb9c3618f71668f8e4346c8f323fa82 10700 en Mac - - - Fingolfin
+ 4cb9c3618f71668f8e4346c8f323fa82 10700 en Mac - - v1.0 11/5/92 Fingolfin
e246e02db9630533a40d99c9f54a8e01 -1 en Mac - - alt? Lars N&aelig;sbye Christensen
- da09e666fc8f5b78d7b0ac65d1a3b56e -1 en FM-TOWNS - - - dhewg, Andrea Petrucci
+ da09e666fc8f5b78d7b0ac65d1a3b56e 11135 en FM-TOWNS - - - dhewg, Andrea Petrucci
430bc518017b6fac046f58bab6baad5d -1 jp FM-TOWNS - - - Antti Leimi, Andrea Petrucci
387a544b8b10b26912d8413bab63a853 -1 en DOS - Demo non-interactive khalek
diff --git a/tools/skycpt/AsciiCptCompile.cpp b/tools/skycpt/AsciiCptCompile.cpp
index 9df29f8b44..df5f1dfd30 100644
--- a/tools/skycpt/AsciiCptCompile.cpp
+++ b/tools/skycpt/AsciiCptCompile.cpp
@@ -1,4 +1,4 @@
-// AsciiCptCompile.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
+// AsciiCptCompile.cpp
//
#include "stdafx.h"
diff --git a/tools/skycpt/stdafx.cpp b/tools/skycpt/stdafx.cpp
index 22a7f25f57..fd4f341c7b 100644
--- a/tools/skycpt/stdafx.cpp
+++ b/tools/skycpt/stdafx.cpp
@@ -1,8 +1 @@
-// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet
-// AsciiCptCompile.pch ist der vorcompilierte Header
-// stdafx.obj enthält die vorcompilierte Typinformation
-
#include "stdafx.h"
-
-// TODO: Verweisen Sie auf zusätzliche Header, die in STDAFX.H
-// und nicht in dieser Datei erforderlich sind.