aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--NEWS18
-rw-r--r--backends/midi/quicktime.cpp6
-rw-r--r--backends/platform/dc/Makefile27
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp13
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h1
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp18
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h11
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.cpp2
-rw-r--r--backends/platform/ps2/Makefile.ps25
-rw-r--r--backends/platform/ps2/fileio.cpp67
-rw-r--r--backends/platform/ps2/iop/rpckbd/Makefile30
-rw-r--r--backends/platform/ps2/iop/rpckbd/include/ps2kbd.h90
-rw-r--r--backends/platform/ps2/iop/rpckbd/src/imports.lst58
-rw-r--r--backends/platform/ps2/iop/rpckbd/src/irx_imports.h35
-rw-r--r--backends/platform/ps2/iop/rpckbd/src/ps2kbd.c1199
-rw-r--r--backends/platform/ps2/iop/rpckbd/src/us_keymap.h1579
-rw-r--r--backends/platform/ps2/irxboot.cpp2
-rw-r--r--backends/platform/ps2/systemps2.cpp19
-rw-r--r--backends/platform/ps2/systemps2.h7
-rw-r--r--backends/platform/psp/Makefile28
-rw-r--r--backends/platform/psp/osys_psp.cpp50
-rw-r--r--backends/platform/psp/osys_psp.h8
-rw-r--r--backends/platform/sdl/sdl.cpp127
-rw-r--r--backends/platform/sdl/sdl.h30
-rw-r--r--backends/platform/symbian/BuildPackageUpload_LocalSettings.pl17
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp108
-rw-r--r--backends/platform/wii/osystem.cpp2
-rw-r--r--backends/platform/wii/osystem.h5
-rw-r--r--backends/platform/wii/osystem_sfx.cpp16
-rw-r--r--backends/platform/wince/missing/missing.cpp512
-rw-r--r--backends/saves/default/default-saves.cpp2
-rw-r--r--base/game.cpp4
-rw-r--r--base/game.h2
-rw-r--r--base/internal_version.h2
-rw-r--r--base/plugins.h10
-rw-r--r--common/config-manager.cpp68
-rw-r--r--common/file.cpp2
-rw-r--r--common/str.cpp58
-rw-r--r--common/str.h19
-rw-r--r--common/stream.cpp55
-rw-r--r--common/stream.h27
-rwxr-xr-xconfigure8
-rw-r--r--dists/msvc7/parallaction.vcproj6
-rw-r--r--dists/msvc71/parallaction.vcproj6
-rw-r--r--dists/msvc8/parallaction.vcproj8
-rw-r--r--dists/msvc9/parallaction.vcproj8
-rw-r--r--dists/redhat/scummvm.spec2
-rw-r--r--dists/scummvm.rc8
-rwxr-xr-xdists/slackware/scummvm.SlackBuild2
-rw-r--r--engines/agos/agos.h2
-rw-r--r--engines/agos/gfx.cpp129
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/gfx.cpp15
-rw-r--r--engines/cine/prc.cpp9
-rw-r--r--engines/cine/prc.h2
-rw-r--r--engines/cine/script_fw.cpp14
-rw-r--r--engines/cine/texte.cpp10
-rw-r--r--engines/cine/texte.h5
-rw-r--r--engines/cine/various.cpp55
-rw-r--r--engines/gob/detection.cpp13
-rw-r--r--engines/gob/driver_vga.cpp2
-rw-r--r--engines/gob/goblin.cpp330
-rw-r--r--engines/gob/goblin.h103
-rw-r--r--engines/gob/goblin_v2.cpp2
-rw-r--r--engines/gob/inter.cpp20
-rw-r--r--engines/gob/inter.h2
-rw-r--r--engines/gob/inter_v1.cpp173
-rw-r--r--engines/gob/inter_v2.cpp12
-rw-r--r--engines/gob/mult.cpp26
-rw-r--r--engines/gob/mult.h9
-rw-r--r--engines/gob/mult_v1.cpp33
-rw-r--r--engines/gob/mult_v2.cpp26
-rw-r--r--engines/gob/sound/sound.h2
-rw-r--r--engines/gob/sound/soundmixer.h2
-rw-r--r--engines/gob/variables.cpp58
-rw-r--r--engines/gob/variables.h26
-rw-r--r--engines/igor/igor.cpp2
-rw-r--r--engines/kyra/detection.cpp58
-rw-r--r--engines/kyra/kyra_mr.cpp8
-rw-r--r--engines/kyra/kyra_mr.h5
-rw-r--r--engines/kyra/kyra_v1.cpp12
-rw-r--r--engines/kyra/script.cpp6
-rw-r--r--engines/kyra/script.h2
-rw-r--r--engines/kyra/script_tim.cpp18
-rw-r--r--engines/kyra/script_tim.h10
-rw-r--r--engines/kyra/sequences_lok.cpp2
-rw-r--r--engines/kyra/sound.cpp19
-rw-r--r--engines/kyra/sound_lok.cpp15
-rw-r--r--engines/kyra/sound_towns.cpp13
-rw-r--r--engines/kyra/staticres.cpp30
-rw-r--r--engines/lure/luredefs.h2
-rw-r--r--engines/lure/res_struct.cpp6
-rw-r--r--engines/m4/converse.cpp2
-rw-r--r--engines/m4/globals.cpp10
-rw-r--r--engines/m4/globals.h2
-rw-r--r--engines/m4/resource.cpp2
-rw-r--r--engines/parallaction/balloons.cpp456
-rw-r--r--engines/parallaction/callables_ns.cpp3
-rw-r--r--engines/parallaction/dialogue.cpp390
-rw-r--r--engines/parallaction/disk.h10
-rw-r--r--engines/parallaction/disk_br.cpp19
-rw-r--r--engines/parallaction/disk_ns.cpp8
-rw-r--r--engines/parallaction/exec.h241
-rw-r--r--engines/parallaction/exec_br.cpp159
-rw-r--r--engines/parallaction/exec_ns.cpp290
-rw-r--r--engines/parallaction/gfxbase.cpp44
-rw-r--r--engines/parallaction/graphics.cpp185
-rw-r--r--engines/parallaction/graphics.h49
-rw-r--r--engines/parallaction/gui_br.cpp2
-rw-r--r--engines/parallaction/input.cpp59
-rw-r--r--engines/parallaction/input.h11
-rw-r--r--engines/parallaction/module.mk1
-rw-r--r--engines/parallaction/objects.cpp3
-rw-r--r--engines/parallaction/parallaction.cpp136
-rw-r--r--engines/parallaction/parallaction.h168
-rw-r--r--engines/parallaction/parallaction_br.cpp37
-rw-r--r--engines/parallaction/parallaction_ns.cpp21
-rw-r--r--engines/parallaction/parser_br.cpp2
-rw-r--r--engines/parallaction/parser_ns.cpp2
-rw-r--r--engines/parallaction/sound.cpp4
-rw-r--r--engines/parallaction/walk.cpp174
-rw-r--r--engines/queen/graphics.cpp11
-rw-r--r--engines/queen/graphics.h4
-rw-r--r--engines/queen/sound.cpp17
-rw-r--r--engines/queen/sound.h1
-rw-r--r--engines/scumm/detection.cpp4
-rw-r--r--engines/scumm/dialogs.cpp27
-rw-r--r--engines/scumm/dialogs.h2
-rw-r--r--engines/scumm/he/resource_he.cpp5
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp6
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.h4
-rw-r--r--engines/scumm/saveload.cpp6
-rw-r--r--engines/sword2/music.cpp21
-rw-r--r--engines/sword2/sound.h2
-rw-r--r--sound/midiparser_smf.cpp25
-rw-r--r--sound/midiparser_xmidi.cpp61
-rw-r--r--test/common/str.h53
-rwxr-xr-xtools/svnpropset.sh20
139 files changed, 6342 insertions, 2096 deletions
diff --git a/Makefile b/Makefile
index 506265032a..2395511ee3 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ CXXFLAGS:= -Wall $(CXXFLAGS)
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
# Enable even more warnings...
CXXFLAGS+= -pedantic -Wpointer-arith -Wcast-qual -Wcast-align
-CXXFLAGS+= -Wshadow -Wimplicit -Wundef -Wnon-virtual-dtor -Wwrite-strings
+CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
# Disable RTTI and exceptions, and enabled checking of pointers returned by "new"
CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new
diff --git a/NEWS b/NEWS
index 95ffaf251c..2814d47c56 100644
--- a/NEWS
+++ b/NEWS
@@ -3,19 +3,23 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
0.12.0 (????-??-??)
New Games:
- - Added support for The Legend of Kyrandia: Book Two: Hand of Fate
- - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge
- - Added support for Lost in Time
- - Added support for The Bizarre Adventures of Woodruff and the Schnibble
- - Added support for the PC version of Waxworks
+ - Added support for The Legend of Kyrandia: Book Two: Hand of Fate.
+ - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge.
+ - Added support for Lost in Time.
+ - Added support for The Bizarre Adventures of Woodruff and the Schnibble.
+ - Added support for the PC version of Waxworks.
- Added support for the Macintosh version of I Have no Mouth, and I
- must Scream
- - Added support for Drascula: The Vampire Strikes Back
+ must Scream.
+ - Added support for Drascula: The Vampire Strikes Back.
General:
- Added CAMD MIDI driver for AmigaOS4.
- Revived the PS2 port (was already in 0.11.1 but was forgotten in the
release notes).
+ - Plugged numerous memory leaks in all engines (part of GSoC'08 task),
+ - Added audio double buffering to the SDL backend, which fixes the
+ problems with the MT-32 emulator on Mac OS X (for now only enabled
+ on Mac OS X).
AGOS:
- Fixed palette issues in Amiga versions of Simon the Sorcerer 1.
diff --git a/backends/midi/quicktime.cpp b/backends/midi/quicktime.cpp
index 568adf022b..a18eadcb30 100644
--- a/backends/midi/quicktime.cpp
+++ b/backends/midi/quicktime.cpp
@@ -132,8 +132,7 @@ bail:
return MERR_DEVICE_NOT_AVAILABLE;
}
-void MidiDriver_QT::close()
-{
+void MidiDriver_QT::close() {
MidiDriver_MPU401::close();
dispose();
}
@@ -248,8 +247,7 @@ void MidiDriver_QT::setPitchBendRange (byte channel, uint range) {
NASetController(qtNoteAllocator, qtNoteChannel[channel], kControllerPitchBend, theBend);
}
-void MidiDriver_QT::dispose()
-{
+void MidiDriver_QT::dispose() {
for (int i = 0; i < 16; i++) {
if (qtNoteChannel[i] != 0)
NADisposeNoteChannel(qtNoteAllocator, qtNoteChannel[i]);
diff --git a/backends/platform/dc/Makefile b/backends/platform/dc/Makefile
index 5c01b20b27..db5861903b 100644
--- a/backends/platform/dc/Makefile
+++ b/backends/platform/dc/Makefile
@@ -33,8 +33,33 @@ ifdef DYNAMIC_MODULES
DEFINES += -DDYNAMIC_MODULES
PRE_OBJS_FLAGS = -Wl,--whole-archive
POST_OBJS_FLAGS = -Wl,--no-whole-archive
+ENABLED=DYNAMIC_PLUGIN
+else
+ENABLED=STATIC_PLUGIN
endif
+ENABLE_SCUMM = $(ENABLED)
+ENABLE_SCUMM_7_8 = $(ENABLED)
+ENABLE_HE = $(ENABLED)
+ENABLE_AGI = $(ENABLED)
+ENABLE_AGOS = $(ENABLED)
+ENABLE_CINE = $(ENABLED)
+ENABLE_CRUISE = $(ENABLED)
+ENABLE_DRASCULA = $(ENABLED)
+ENABLE_GOB = $(ENABLED)
+ENABLE_IGOR = $(ENABLED)
+ENABLE_KYRA = $(ENABLED)
+ENABLE_LURE = $(ENABLED)
+ENABLE_M4 = $(ENABLED)
+ENABLE_MADE = $(ENABLED)
+ENABLE_PARALLACTION = $(ENABLED)
+ENABLE_QUEEN = $(ENABLED)
+ENABLE_SAGA = $(ENABLED)
+ENABLE_SKY = $(ENABLED)
+ENABLE_SWORD1 = $(ENABLED)
+ENABLE_SWORD2 = $(ENABLED)
+ENABLE_TOUCHE = $(ENABLED)
+
OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o
@@ -50,7 +75,7 @@ SCUMMVM.BIN : scummvm.bin
plugin_dist :
for p in plugins/*.plg; do \
- sh-elf-strip -g -o "`basename \"$$p\" | tr '[:lower:]' '[:upper:]'`" "$$p"; \
+ sh-elf-strip -g -o "`basename \"$$p\" | LC_CTYPE=C tr '[:lower:]' '[:upper:]'`" "$$p"; \
done
dist : SCUMMVM.BIN plugins plugin_dist
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index a130509e36..f4706807f7 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -168,7 +168,7 @@ bool displayModeIs8Bit = false;
u8 gameID;
bool snapToBorder = false;
-bool consoleEnable = false;
+bool consoleEnable = true;
bool gameScreenSwap = false;
bool isCpuScalerEnabled();
//#define HEAVY_LOGGING
@@ -899,12 +899,6 @@ u16* get8BitBackBuffer() {
return BG_GFX + 0x10000; // 16bit qty!
}
-void setSoundProc(OSystem_DS::SoundProc proc, void* param) {
-// consolePrintf("Set sound callback");
- soundCallback = proc;
- soundParam = param;
-}
-
// The sound system in ScummVM seems to always return stereo interleaved samples.
// Here, I'm treating an 11Khz stereo stream as a 22Khz mono stream, which works sorta ok, but is
// a horrible bodge. Any advice on how to change the engine to output mono would be greatly
@@ -914,7 +908,8 @@ void doSoundCallback() {
consolePrintf("doSoundCallback...");
#endif
- if (soundCallback) {
+ if (OSystem_DS::instance())
+ if (OSystem_DS::instance()->getMixerImpl()) {
lastCallbackFrame = frameCount;
for (int r = IPC->playingSection; r < IPC->playingSection + 4; r++) {
@@ -923,7 +918,7 @@ void doSoundCallback() {
if (IPC->fillNeeded[chunk]) {
IPC->fillNeeded[chunk] = false;
DC_FlushAll();
- soundCallback(soundParam, (byte *) (soundBuffer + ((bufferSamples >> 2) * chunk)), bufferSamples >> 1);
+ OSystem_DS::instance()->getMixerImpl()->mixCallback((byte *) (soundBuffer + ((bufferSamples >> 2) * chunk)), bufferSamples >> 1);
IPC->fillNeeded[chunk] = false;
DC_FlushAll();
}
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index f20442b11e..43258b5c5d 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -88,7 +88,6 @@ int getMillis(); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
-void setSoundProc(OSystem_DS::SoundProc proc, void* param); // Setup a callback function for sound
void doSoundCallback(); // Call function if sound buffers need more data
void playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound
void stopSound(int channel);
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index d2c3b579bd..79b0c5390b 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -67,10 +67,12 @@ void OSystem_DS::initBackend() {
ConfMan.setInt("autosave_period", 0);
ConfMan.setBool("FM_medium_quality", true);
- _mixer = new DSAudioMixer;
- _timer = new DSTimerManager;
- DS::setSoundProc(Audio::Mixer::mixCallback, _mixer);
- DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
+ _mixer = new DSAudioMixer(this);
+ _timer = new DSTimerManager();
+ DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
+
+ _mixer->setOutputRate(11025 /*DS::getSoundFrequency()*/);
+ _mixer->setReady(true);
OSystem::initBackend();
}
@@ -139,7 +141,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
green >>= 3;
blue >>= 3;
-// if (r != 255)
+ if (r != 255)
{
BG_PALETTE[r] = red | (green << 5) | (blue << 10);
if (!DS::getKeyboardEnable()) {
@@ -158,13 +160,13 @@ bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
// Ensure we copy using 16 bit quantities due to limitation of VRAM addressing
- u16* image = (u16 *) DS::get8BitBackBuffer();
+ const u16* image = (const u16 *) DS::get8BitBackBuffer();
for (int y = 0; y < DS::getGameHeight(); y++)
{
DC_FlushRange(image + (y << 8), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++)
{
- *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x];
+ *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[(y << 8) + x];
}
}
@@ -277,7 +279,7 @@ void OSystem_DS::grabOverlay (OverlayColor *buf, int pitch) {
void OSystem_DS::copyRectToOverlay (const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
u16* bg = (u16 *) DS::get16BitBackBuffer();
- u16* src = (u16 *) buf;
+ const u16* src = (const u16 *) buf;
// if (x + w > 256) w = 256 - x;
//if (x + h > 256) h = 256 - y;
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index e53575a4a5..8c8d661ad8 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -30,10 +30,13 @@
#include "gbampsave.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
-#include "sound/mixer.h"
+#include "sound/mixer_intern.h"
#include "graphics/surface.h"
-class DSAudioMixer : public Audio::Mixer {
+class DSAudioMixer : public Audio::MixerImpl {
+
+public:
+ DSAudioMixer(OSystem* system) : Audio::MixerImpl(system) { }
};
class DSTimerManager : public DefaultTimerManager {
@@ -62,7 +65,7 @@ protected:
Graphics::Surface* createTempFrameBuffer();
public:
- typedef void (*SoundProc)(void *param, byte *buf, int len);
+ typedef void (*SoundProc)(byte *buf, int len);
typedef int (*TimerProc)(int interval);
OSystem_DS();
@@ -146,6 +149,8 @@ public:
virtual void unlockScreen();
virtual Audio::Mixer* getMixer() { return _mixer; }
+ Audio::MixerImpl* getMixerImpl() { return _mixer; }
+
virtual Common::TimerManager* getTimerManager() { return _timer; }
static int timerHandler(int t);
diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp
index 9eeeb62410..ff52572a40 100644
--- a/backends/platform/ds/arm9/source/wordcompletion.cpp
+++ b/backends/platform/ds/arm9/source/wordcompletion.cpp
@@ -1,6 +1,6 @@
#include "wordcompletion.h"
-#include "engines/agi/agi.h"
#include "osystem_ds.h"
+#include "engines/agi/agi.h" // Caution for #define for NUM_CHANNELS, causes problems in mixer_intern.h
#ifdef ENABLE_AGI
diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2
index 22cd4eaa1b..204f4f7a16 100644
--- a/backends/platform/ps2/Makefile.ps2
+++ b/backends/platform/ps2/Makefile.ps2
@@ -19,16 +19,17 @@ RM = rm -f
srcdir = ../../..
VPATH = $(srcdir)
INCDIR = ../../../
+DEPDIR = .deps
DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_MPEG2 -DUSE_ZLIB -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar
# PS2SDK-Ports from ps2dev.org's SVN repository for libmad, zlib and ucl
-PS2SDK_PORTS = /home/robby/libStuffNew/ps2sdk-ports
+PS2SDK_PORTS = /mnt/winxp/scummvm/ports
PS2SDK_PORTS_INCS = /ucl /zlib/include /libmad/ee/include
PS2SDK_PORTS_LIBS = /ucl /zlib/lib /libmad/ee/lib
# we also need SjPcm, Tremor and libmpeg2
-MORE_LIBS_DIR = /home/robby/libStuff
+MORE_LIBS_DIR = /mnt/winxp/scummvm/ports
MORE_LIBS_INCS = /SjPcm/ee/src /mpeg2dec/include /tremor
MORE_LIBS_LIBS = /SjPcm/ee/lib /mpeg2dec/libmpeg2 /tremor/tremor
diff --git a/backends/platform/ps2/fileio.cpp b/backends/platform/ps2/fileio.cpp
index bc310a43f4..b7fa8d03f1 100644
--- a/backends/platform/ps2/fileio.cpp
+++ b/backends/platform/ps2/fileio.cpp
@@ -340,8 +340,6 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
assert(cacheListSema >= 0);
}
- //printf("ps2_fopen: %s, %s\n", fname, mode);
-
if (((mode[0] != 'r') && (mode[0] != 'w')) || ((mode[1] != '\0') && (mode[1] != 'b'))) {
printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
return NULL;
@@ -363,6 +361,8 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
} else {
// Regular access to one of the devices
+ printf("ps2_fopen = %s\n", fname); // romeo : temp
+
if (!rdOnly)
return NULL; // we only provide readaccess for cd,dvd,hdd,usb
@@ -378,19 +378,22 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
}
int64 cacheId = -1;
- if (rdOnly && tocManager.haveEntries())
+ if (tocManager.haveEntries())
cacheId = tocManager.fileExists(fname);
if (cacheId != 0) {
Ps2File *file = findInCache(cacheId);
- if (file)
+ if (file) {
+ printf(" findInCache(%x)\n", cacheId); // romeo : temp
return (FILE*)file;
+ }
bool isAudioFile = strstr(fname, ".bun") || strstr(fname, ".BUN") || strstr(fname, ".Bun");
file = new Ps2ReadFile(cacheId, isAudioFile);
if (file->open(fname)) {
openFileCount++;
+ printf(" new cacheID = %x\n", cacheId); // romeo : temp
return (FILE*)file;
} else
delete file;
@@ -579,7 +582,7 @@ void TocManager::readEntries(const char *root) {
}
char readPath[256];
sprintf(readPath, "%s/", _root);
- printf("readDir: %s\n", readPath);
+ printf("readDir: %s (root: %s )\n", readPath, root);
readDir(readPath, &_rootNode, 0);
}
@@ -587,28 +590,62 @@ void TocManager::readDir(const char *path, TocNode **node, int level) {
if (level <= 2) { // we don't scan deeper than that
iox_dirent_t dirent;
int fd = fio.dopen(path);
+ TocNode *eNode = NULL; // = *node; // entry node
+ bool first = true;
+
+ printf("path=%s - level=%d fd=%d\n", path, level, fd); // romeo : temp
if (fd >= 0) {
- while (fio.dread(fd, &dirent) > 0)
- if (dirent.name[0] != '.') { // skip '.' and '..'
+ while (fio.dread(fd, &dirent) > 0) {
+ if (dirent.name[0] != '.') { // skip '.' & '..' - romeo : check
+ // --- do we have them on PS2?
*node = new TocNode;
+ if (first) {
+ eNode = *node;
+ first = false;
+ }
(*node)->sub = (*node)->next = NULL;
-
(*node)->nameLen = strlen(dirent.name);
memcpy((*node)->name, dirent.name, (*node)->nameLen + 1);
- if (dirent.stat.mode & FIO_S_IFDIR) { // directory
+ if (dirent.stat.mode & FIO_S_IFDIR) {
(*node)->isDir = true;
- char nextPath[256];
- sprintf(nextPath, "%s%s/", path, dirent.name);
- readDir(nextPath, &((*node)->sub), level + 1);
- } else
+ printf("dirent.name = %s [DIR]\n", dirent.name);
+ }
+ else {
(*node)->isDir = false;
+ printf("dirent.name = %s\n", dirent.name);
+ }
+
node = &((*node)->next);
}
+ }
+
fio.dclose(fd);
- } else
- printf("Can't open path: %s\n", path);
+ }
+
+ TocNode *iNode = eNode;
+ char nextPath[256];
+
+ while (iNode) {
+ if (iNode->isDir == true) {
+ sprintf(nextPath, "%s%s/", path, iNode->name);
+ readDir(nextPath, &(iNode->sub), level + 1);
+ }
+ iNode = iNode->next;
+ }
+
}
+
+ /*
+ ** Wizard of Oz' trick (to get all games running from USB on PS2):
+
+ 1. Make a list of files / dirs in level #0 (dclose before continuing)
+
+ 2. Go through the dirs : dopen / dread them / mark dirs / dclose
+
+ It's a safe recursion, cause it recurses on 'isDir' nodes
+ after dclosing the higher hierarchy
+ */
}
int64 TocManager::fileExists(const char *name) {
diff --git a/backends/platform/ps2/iop/rpckbd/Makefile b/backends/platform/ps2/iop/rpckbd/Makefile
new file mode 100644
index 0000000000..b25efa3660
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/Makefile
@@ -0,0 +1,30 @@
+# _____ ___ ____ ___ ____
+# ____| | ____| | | |____|
+# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
+#-----------------------------------------------------------------------
+# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
+# Licenced under Academic Free License version 2.0
+# Review ps2sdk README & LICENSE files for further details.
+#
+# $Id$
+
+
+IOP_OBJS_DIR = obj/
+IOP_BIN_DIR = bin/
+IOP_SRC_DIR = src/
+IOP_INC_DIR = include/
+
+IOP_BIN=bin/rpckbd.irx
+IOP_OBJS=obj/ps2kbd.o obj/imports.o
+
+IOP_CFLAGS=-Wall
+IOP_INCS += -I$(PS2SDKSRC)/iop/usb/usbd/include
+
+all: $(IOP_OBJS_DIR) $(IOP_BIN_DIR) $(IOP_BIN)
+
+clean:
+ rm -f -r $(IOP_OBJS_DIR) $(IOP_BIN_DIR)
+
+include $(PS2SDKSRC)/Defs.make
+include $(PS2SDKSRC)/iop/Rules.make
+include $(PS2SDKSRC)/iop/Rules.release
diff --git a/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h
new file mode 100644
index 0000000000..f16c7ca12b
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/include/ps2kbd.h
@@ -0,0 +1,90 @@
+/*
+# _____ ___ ____ ___ ____
+# ____| | ____| | | |____|
+# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
+#-----------------------------------------------------------------------
+# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
+# Licenced under Academic Free License version 2.0
+# Review ps2sdk README & LICENSE files for further details.
+#
+# $Id$
+# USB Keyboard Driver for PS2
+*/
+
+#ifndef __PS2KBD_H__
+#define __PS2KBD_H__
+
+#define PS2KBD_RPC_ID 0xb0b0b80
+
+#define PS2KBD_LED_NUMLOCK 1
+#define PS2KBD_LED_CAPSLOCK 2
+#define PS2KBD_LED_SCRLOCK 4
+#define PS2KBD_LED_COMPOSE 8
+#define PS2KBD_LED_KANA 16
+
+#define PS2KBD_LED_MASK 0x1F;
+
+#define PS2KBD_ESCAPE_KEY 0x1B
+
+#define PS2KBD_LEFT_CTRL (1 << 0)
+#define PS2KBD_LEFT_SHIFT (1 << 1)
+#define PS2KBD_LEFT_ALT (1 << 2)
+#define PS2KBD_LEFT_GUI (1 << 3)
+#define PS2KBD_RIGHT_CTRL (1 << 4)
+#define PS2KBD_RIGHT_SHIFT (1 << 5)
+#define PS2KBD_RIGHT_ALT (1 << 6)
+#define PS2KBD_RIGHT_GUI (1 << 7)
+
+#define PS2KBD_CTRL (PS2KBD_LEFT_CTRL | PS2KBD_RIGHT_CTRL)
+#define PS2KBD_SHIFT (PS2KBD_LEFT_SHIFT | PS2KBD_RIGHT_SHIFT)
+#define PS2KBD_ALT (PS2KBD_LEFT_ALT | PS2KBD_RIGHT_ALT)
+#define PS2KBD_GUI (PS2KBD_LEFT_GUI | PS2KBD_RIGHT_GUI)
+
+#define PS2KBD_RAWKEY_UP 0xF0
+#define PS2KBD_RAWKEY_DOWN 0xF1
+
+typedef struct _kbd_rawkey {
+ u8 state;
+ u8 key;
+} kbd_rawkey __attribute__ ((packed));
+
+#define PS2KBD_READMODE_NORMAL 1
+#define PS2KBD_READMODE_RAW 2
+
+/* Notes on read mode */
+/* In normal readmode (default) read multiples of 1 character off the keyboard file. These are
+ processed by the keymaps so that you get back ASCII data */
+/* In raw readmode must read multiples of 2. First byte indicates state (i.e. Up or Down)
+ Second byte is the USB key code for that key. This table is presented in the USB HID Usage Tables manaual
+ from usb.org */
+
+#define PS2KBD_KEYMAP_SIZE 256
+
+typedef struct _kbd_keymap
+
+{
+ u8 keymap[PS2KBD_KEYMAP_SIZE];
+ u8 shiftkeymap[PS2KBD_KEYMAP_SIZE];
+ u8 keycap[PS2KBD_KEYMAP_SIZE];
+} kbd_keymap;
+
+
+/* IRPC function numbers */
+#define KBD_RPC_SETREADMODE 1 /* Sets up keymapped or raw mode */
+#define KBD_RPC_SETLEDS 2 /* Sets the LED state for ALL keyboards connected */
+#define KBD_RPC_SETREPEATRATE 3 /* Sets the repeat rate of the keyboard */
+#define KBD_RPC_SETKEYMAP 4 /* Sets the keymap for the standard keys, non shifted and shifted */
+#define KBD_RPC_SETCTRLMAP 5 /* Sets the control key mapping */
+#define KBD_RPC_SETALTMAP 6 /* Sets the alt key mapping */
+#define KBD_RPC_SETSPECIALMAP 7 /* Sets the special key mapping */
+#define KBD_RPC_FLUSHBUFFER 9 /* Flush the internal buffer, probably best after a keymap change */
+#define KBD_RPC_RESETKEYMAP 10 /* Reset keymaps to default states */
+#define KBD_RPC_READKEY 11
+#define KBD_RPC_READRAW 12
+
+/* Note on keymaps. In normal keymap a 0 would indicate no key */
+/* Key maps are represented by 3 256*8bit tables. First table maps USB key to a char when not shifted */
+/* Second table maps USB key to a char when shifted */
+/* Third table contains boolean values. If 1 then the key is shifted/unshifted in capslock, else capslock is ignored */
+
+#endif
diff --git a/backends/platform/ps2/iop/rpckbd/src/imports.lst b/backends/platform/ps2/iop/rpckbd/src/imports.lst
new file mode 100644
index 0000000000..41e13e6e73
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/src/imports.lst
@@ -0,0 +1,58 @@
+
+sysclib_IMPORTS_start
+I_memset
+I_strcmp
+I_memcpy
+sysclib_IMPORTS_end
+
+loadcore_IMPORTS_start
+I_FlushDcache
+loadcore_IMPORTS_end
+
+sifcmd_IMPORTS_start
+I_sceSifInitRpc
+I_sceSifSetRpcQueue
+I_sceSifRegisterRpc
+I_sceSifRpcLoop
+sifcmd_IMPORTS_end
+
+stdio_IMPORTS_start
+I_printf
+stdio_IMPORTS_end
+
+thsemap_IMPORTS_start
+I_CreateSema
+I_SignalSema
+I_WaitSema
+I_PollSema
+I_DeleteSema
+thsemap_IMPORTS_end
+
+thbase_IMPORTS_start
+I_StartThread
+I_CreateThread
+I_USec2SysClock
+I_iSetAlarm
+I_SetAlarm
+I_CancelAlarm
+thbase_IMPORTS_end
+
+thevent_IMPORTS_start
+I_WaitEventFlag
+I_iSetEventFlag
+I_CreateEventFlag
+thevent_IMPORTS_end
+
+sysmem_IMPORTS_start
+I_AllocSysMemory
+I_FreeSysMemory
+sysmem_IMPORTS_end
+
+usbd_IMPORTS_start
+I_UsbGetDeviceStaticDescriptor
+I_UsbOpenEndpoint
+I_UsbSetDevicePrivateData
+I_UsbTransfer
+I_UsbRegisterDriver
+usbd_IMPORTS_end
+
diff --git a/backends/platform/ps2/iop/rpckbd/src/irx_imports.h b/backends/platform/ps2/iop/rpckbd/src/irx_imports.h
new file mode 100644
index 0000000000..6ecc8e5864
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/src/irx_imports.h
@@ -0,0 +1,35 @@
+/*
+# _____ ___ ____ ___ ____
+# ____| | ____| | | |____|
+# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
+#-----------------------------------------------------------------------
+# Copyright (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
+# Licenced under Academic Free License version 2.0
+# Review ps2sdk README & LICENSE files for further details.
+#
+# $Id$
+# Defines all IRX imports.
+*/
+
+#ifndef IOP_IRX_IMPORTS_H
+#define IOP_IRX_IMPORTS_H
+
+#include "irx.h"
+
+/* Please keep these in alphabetical order! */
+#include "dmacman.h"
+#include "intrman.h"
+#include "libsd.h"
+#include "loadcore.h"
+#include "sifcmd.h"
+#include "stdio.h"
+#include "sysclib.h"
+#include "sysmem.h"
+#include "thbase.h"
+#include "thevent.h"
+#include "thmsgbx.h"
+#include "thsemap.h"
+#include "usbd.h"
+#include "vblank.h"
+
+#endif /* IOP_IRX_IMPORTS_H */
diff --git a/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c
new file mode 100644
index 0000000000..f87a47f0cb
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/src/ps2kbd.c
@@ -0,0 +1,1199 @@
+/*
+# _____ ___ ____ ___ ____
+# ____| | ____| | | |____|
+# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
+#-----------------------------------------------------------------------
+# Copyright 2001-2005, ps2dev - http://www.ps2dev.org
+# Licenced under Academic Free License version 2.0
+# Review ps2sdk README & LICENSE files for further details.
+#
+# $Id$
+# USB Keyboard Driver for PS2
+*/
+
+#include "types.h"
+#include "ioman.h"
+#include "loadcore.h"
+#include "stdio.h"
+#include "sifcmd.h"
+#include "sifrpc.h"
+#include "sysclib.h"
+#include "sysmem.h"
+#include "usbd.h"
+#include "usbd_macro.h"
+#include "thbase.h"
+#include "thevent.h"
+#include "thsemap.h"
+
+#include "ps2kbd.h"
+#include "us_keymap.h"
+
+#define PS2KBD_VERSION 0x100
+
+#define USB_SUBCLASS_BOOT 1
+#define USB_HIDPROTO_KEYBOARD 1
+
+#define PS2KBD_MAXDEV 2
+#define PS2KBD_MAXKEYS 6
+
+#define PS2KBD_DEFLINELEN 4096
+#define PS2KBD_DEFREPEATRATE 100
+/* Default repeat rate in milliseconds */
+#define PS2KBD_REPEATWAIT 1000
+/* Number of milliseconds to wait before starting key repeat */
+#define USB_KEYB_NUMLOCK 0x53
+#define USB_KEYB_CAPSLOCK 0x39
+#define USB_KEYB_SCRLOCK 0x47
+
+#define USB_KEYB_NUMPAD_START 0x54
+#define USB_KEYB_NUMPAD_END 0x63
+
+#define SEMA_ZERO -419
+#define SEMA_DELETED -425
+
+int ps2kbd_init();
+void ps2kbd_config_set(int resultCode, int bytes, void *arg);
+void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg);
+void ps2kbd_data_recv(int resultCode, int bytes, void *arg);
+int ps2kbd_probe(int devId);
+int ps2kbd_connect(int devId);
+int ps2kbd_disconnect(int devId);
+void usb_getstring(int endp, int index, char *desc);
+
+typedef struct _kbd_data_recv
+
+{
+ u8 mod_keys;
+ u8 reserved;
+ u8 keycodes[PS2KBD_MAXKEYS];
+} kbd_data_recv;
+
+typedef struct _keyb_dev
+
+{
+ int configEndp;
+ int dataEndp;
+ int packetSize;
+ int devId;
+ int interfaceNo; /* Holds the interface number selected on this device */
+ char repeatkeys[2];
+ u32 eventmask;
+ u8 ledStatus; /* Maintains state on the led status */
+ kbd_data_recv oldData;
+ kbd_data_recv data; /* Holds the data for the transfers */
+} kbd_dev;
+
+/* Global Variables */
+
+int kbd_readmode;
+u32 kbd_repeatrate;
+kbd_dev *devices[PS2KBD_MAXDEV]; /* Holds a list of current devices */
+int dev_count;
+UsbDriver kbd_driver = { NULL, NULL, "PS2Kbd", ps2kbd_probe, ps2kbd_connect, ps2kbd_disconnect };
+u8 *lineBuffer;
+u32 lineStartP, lineEndP;
+int lineSema;
+int bufferSema;
+u32 lineSize;
+u8 keymap[PS2KBD_KEYMAP_SIZE]; /* Normal key map */
+u8 shiftkeymap[PS2KBD_KEYMAP_SIZE]; /* Shifted key map */
+u8 keycap[PS2KBD_KEYMAP_SIZE]; /* Does this key get shifted by capslock ? */
+u8 special_keys[PS2KBD_KEYMAP_SIZE];
+u8 control_map[PS2KBD_KEYMAP_SIZE];
+u8 alt_map[PS2KBD_KEYMAP_SIZE];
+//static struct fileio_driver kbd_fdriver;
+iop_device_t kbd_filedrv;
+u8 keyModValue[8] = { 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7 };
+int repeat_tid;
+int eventid; /* Id of the repeat event */
+
+int _start ()
+{
+ FlushDcache();
+
+ ps2kbd_init();
+
+ printf("PS2KBD - USB Keyboard Library\n");
+
+ return 0;
+
+}
+
+int ps2kbd_probe(int devId)
+
+{
+ UsbDeviceDescriptor *dev;
+ UsbConfigDescriptor *conf;
+ UsbInterfaceDescriptor *intf;
+ UsbEndpointDescriptor *endp;
+ //UsbStringDescriptor *str;
+
+ if(dev_count >= PS2KBD_MAXDEV)
+ {
+ printf("ERROR: Maximum keyboard devices reached\n");
+ return 0;
+ }
+
+ //printf("PS2Kbd_probe devId %d\n", devId);
+
+ dev = UsbGetDeviceStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */
+ if(!dev)
+ {
+ printf("ERROR: Couldn't get device descriptor\n");
+ return 0;
+ }
+
+ //printf("Device class %d, Size %d, Man %d, Product %d Cpnfigurations %d\n", dev->bDeviceClass, dev->bMaxPacketSize0, dev->iManufacturer, dev->iProduct, dev->bNumConfigurations);
+ /* Check that the device class is specified in the interfaces and it has at least one configuration */
+ if((dev->bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->bNumConfigurations < 1))
+ {
+ //printf("This is not the droid you're looking for\n");
+ return 0;
+ }
+
+ conf = UsbGetDeviceStaticDescriptor(devId, dev, USB_DT_CONFIG);
+ if(!conf)
+ {
+ printf("ERROR: Couldn't get configuration descriptor\n");
+ return 0;
+ }
+ //printf("Config Length %d Total %d Interfaces %d\n", conf->bLength, conf->wTotalLength, conf->bNumInterfaces);
+
+ if((conf->bNumInterfaces < 1) || (conf->wTotalLength < (sizeof(UsbConfigDescriptor) + sizeof(UsbInterfaceDescriptor))))
+ {
+ printf("ERROR: No interfaces available\n");
+ return 0;
+ }
+
+ intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */
+/* printf("Interface Length %d Endpoints %d Class %d Sub %d Proto %d\n", intf->bLength, */
+/* intf->bNumEndpoints, intf->bInterfaceClass, intf->bInterfaceSubClass, */
+/* intf->bInterfaceProtocol); */
+
+ if((intf->bInterfaceClass != USB_CLASS_HID) || (intf->bInterfaceSubClass != USB_SUBCLASS_BOOT) ||
+ (intf->bInterfaceProtocol != USB_HIDPROTO_KEYBOARD) || (intf->bNumEndpoints < 1))
+
+ {
+ //printf("We came, we saw, we told it to fuck off\n");
+ return 0;
+ }
+
+ endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength);
+ endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */
+
+ //printf("Endpoint 1 Addr %d, Attr %d, MaxPacket %d\n", endp->bEndpointAddress, endp->bmAttributes, endp->wMaxPacketSizeLB);
+
+ if(((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) ||
+ ((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN))
+ {
+ printf("ERROR: Endpoint not interrupt type and/or an input\n");
+ return 0;
+ }
+
+ printf("PS2KBD: Found a keyboard device\n");
+
+ return 1;
+}
+
+int ps2kbd_connect(int devId)
+
+{
+ /* Assume we can only get here if we have already checked the device is kosher */
+
+ UsbDeviceDescriptor *dev;
+ UsbConfigDescriptor *conf;
+ UsbInterfaceDescriptor *intf;
+ UsbEndpointDescriptor *endp;
+ kbd_dev *currDev;
+ int devLoop;
+
+ //printf("PS2Kbd_connect devId %d\n", devId);
+
+ dev = UsbGetDeviceStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */
+ if(!dev)
+ {
+ printf("ERROR: Couldn't get device descriptor\n");
+ return 1;
+ }
+
+ conf = UsbGetDeviceStaticDescriptor(devId, dev, USB_DT_CONFIG);
+ if(!conf)
+ {
+ printf("ERROR: Couldn't get configuration descriptor\n");
+ return 1;
+ }
+
+ intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */
+ endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength);
+ endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */
+
+ for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
+ {
+ if(devices[devLoop] == NULL)
+ {
+ break;
+ }
+ }
+
+ if(devLoop == PS2KBD_MAXDEV)
+ {
+ /* How the f*** did we end up here ??? */
+ printf("ERROR: Device Weirdness!!\n");
+ return 1;
+ }
+
+ currDev = (kbd_dev *) AllocSysMemory(0, sizeof(kbd_dev), NULL);
+ if(!currDev)
+ {
+ printf("ERROR: Couldn't allocate a device point for the kbd\n");
+ return 1;
+ }
+
+ devices[devLoop] = currDev;
+ memset(currDev, 0, sizeof(kbd_dev));
+ currDev->configEndp = UsbOpenEndpoint(devId, NULL);
+ currDev->dataEndp = UsbOpenEndpoint(devId, endp);
+ currDev->packetSize = endp->wMaxPacketSizeLB | ((int) endp->wMaxPacketSizeHB << 8);
+ currDev->eventmask = (1 << devLoop);
+ if(currDev->packetSize > sizeof(kbd_data_recv))
+ {
+ currDev->packetSize = sizeof(kbd_data_recv);
+ }
+
+ if(dev->iManufacturer != 0)
+ {
+ usb_getstring(currDev->configEndp, dev->iManufacturer, "Keyboard Manufacturer");
+ }
+
+ if(dev->iProduct != 0)
+ {
+ usb_getstring(currDev->configEndp, dev->iProduct, "Keyboard Product");
+ }
+
+ currDev->devId = devId;
+ currDev->interfaceNo = intf->bInterfaceNumber;
+ currDev->ledStatus = 0;
+
+ UsbSetDevicePrivateData(devId, currDev); /* Set the index for the device data */
+
+ //printf("Configuration value %d\n", conf->bConfigurationValue);
+ UsbSetDeviceConfiguration(currDev->configEndp, conf->bConfigurationValue, ps2kbd_config_set, currDev);
+
+ dev_count++; /* Increment device count */
+ printf("PS2KBD: Connected device\n");
+
+ return 0;
+}
+
+int ps2kbd_disconnect(int devId)
+
+{
+ int devLoop;
+ printf("PS2Kbd_disconnect devId %d\n", devId);
+
+ for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
+ {
+ if((devices[devLoop]) && (devices[devLoop]->devId == devId))
+ {
+ dev_count--;
+ FreeSysMemory(devices[devLoop]);
+ devices[devLoop] = NULL;
+ printf("PS2KBD: Disconnected device\n");
+ break;
+ }
+ }
+
+ return 0;
+}
+
+typedef struct _string_descriptor
+
+{
+ u8 buf[200];
+ char *desc;
+} string_descriptor;
+
+void ps2kbd_getstring_set(int resultCode, int bytes, void *arg)
+
+{
+ UsbStringDescriptor *str = (UsbStringDescriptor *) arg;
+ string_descriptor *strBuf = (string_descriptor *) arg;
+ char string[50];
+ int strLoop;
+
+/* printf("=========getstring=========\n"); */
+
+/* printf("PS2KEYBOARD: GET_DESCRIPTOR res %d, bytes %d, arg %p\n", resultCode, bytes, arg); */
+
+ if(resultCode == USB_RC_OK)
+ {
+ memset(string, 0, 50);
+ for(strLoop = 0; strLoop < ((bytes - 2) / 2); strLoop++)
+ {
+ string[strLoop] = str->wData[strLoop] & 0xFF;
+ }
+ printf("%s: %s\n", strBuf->desc, string);
+ }
+
+ FreeSysMemory(arg);
+}
+
+void usb_getstring(int endp, int index, char *desc)
+
+{
+ u8 *data;
+ string_descriptor *str;
+ int ret;
+
+ data = (u8 *) AllocSysMemory(0, sizeof(string_descriptor), NULL);
+ str = (string_descriptor *) data;
+
+ if(data != NULL)
+ {
+ str->desc = desc;
+ ret = UsbControlTransfer(endp, 0x80, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | index,
+ 0, sizeof(string_descriptor) - 4, data, ps2kbd_getstring_set, data);
+ if(ret != USB_RC_OK)
+ {
+ printf("PS2KBD: Error sending string descriptor request\n");
+ FreeSysMemory(data);
+ }
+ }
+}
+
+void ps2kbd_config_set(int resultCode, int bytes, void *arg)
+ /* Called when we have finished choosing our configuration */
+
+{
+ kbd_dev *dev;
+
+ if(resultCode != USB_RC_OK)
+ {
+ printf("PS2KEYBOARD: Configuration set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
+ return;
+ }
+
+ //printf("PS2KEYBOARD: Configuration set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
+ /* Do a interrupt data transfer */
+
+ dev = (kbd_dev *) arg;
+ if(dev != NULL)
+ {
+ int ret;
+
+ ret = UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_IDLE, 0, dev->interfaceNo, 0, NULL, ps2kbd_idlemode_set, arg);
+ }
+}
+
+void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg)
+
+{
+ kbd_dev *dev;
+
+
+
+ if(resultCode != USB_RC_OK)
+ {
+ printf("PS2KBD: Idlemode set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
+ return;
+ }
+
+ dev = (kbd_dev *) arg;
+ if(dev != NULL)
+ {
+ int ret;
+
+ ret = UsbInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg);
+ }
+}
+
+void ps2kbd_led_set(int resultCode, int bytes, void *arg)
+
+{
+ //printf("LED Set\n");
+}
+
+void ps2kbd_build_uniquekeys(u8 *res, const u8 *new, const u8 *old)
+
+ /* Builds a list of unique keys */
+
+{
+ int loopNew, loopOld;
+ int loopRes = 0;
+ int foundKey;
+
+ for(loopNew = 0; loopNew < PS2KBD_MAXKEYS; loopNew++)
+ {
+ if(new[loopNew] != 0)
+ {
+ foundKey = 0;
+ for(loopOld = 0; loopOld < PS2KBD_MAXKEYS; loopOld++)
+ {
+ if(new[loopNew] == old[loopOld])
+ {
+ foundKey = 1;
+ break;
+ }
+ }
+ if(!foundKey)
+ {
+ res[loopRes++] = new[loopNew];
+ }
+ }
+ }
+}
+
+u32 ps2kbd_repeathandler(void *arg)
+
+{
+ kbd_dev *dev = arg;
+ iop_sys_clock_t t;
+ //printf("Repeat handler\n");
+
+ iSetEventFlag(eventid, dev->eventmask);
+
+ USec2SysClock(kbd_repeatrate * 1000, &t);
+ iSetAlarm(&t, ps2kbd_repeathandler, arg);
+
+ return t.hi;
+}
+
+void ps2kbd_getkeys(u8 keyMods, u8 ledStatus, const u8 *keys, kbd_dev *dev)
+
+{
+ int loopKey;
+ int tempPos = 0;
+ int byteCount = 0;
+ u8 currChars[2];
+
+ if(lineStartP < lineEndP)
+ {
+ tempPos = lineStartP + lineSize;
+ }
+ else
+ {
+ tempPos = lineStartP;
+ }
+
+ for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
+ {
+ u8 currKey = keys[loopKey];
+
+ currChars[0] = 0;
+ currChars[1] = 0;
+
+ if(lineEndP == (tempPos - 1))
+ {
+ break;
+ }
+
+ if(currKey) /* If this is a valid key */
+ {
+ if((currKey >= USB_KEYB_NUMPAD_START) && (currKey <= USB_KEYB_NUMPAD_END))
+ /* Handle numpad specially */
+ {
+ if(ledStatus & PS2KBD_LED_NUMLOCK)
+ {
+ if(keymap[currKey])
+ {
+ currChars[0] = keymap[currKey];
+ }
+ }
+ else
+ {
+ if(special_keys[currKey])
+ {
+ currChars[0] = PS2KBD_ESCAPE_KEY;
+ currChars[1] = special_keys[currKey];
+ }
+ else if(keymap[currKey] != '5') /* Make sure this isnt a 5 key :) */
+ {
+ currChars[0] = keymap[currKey];
+ }
+ }
+ }
+ else if(special_keys[currKey]) /* This is a special key */
+ {
+ currChars[0] = PS2KBD_ESCAPE_KEY;
+ currChars[1] = special_keys[currKey];
+ }
+ else if(keyMods & PS2KBD_CTRL) /* CTRL */
+ {
+ if(control_map[currKey])
+ {
+ currChars[0] = control_map[currKey];
+ }
+ }
+ else if(keyMods & PS2KBD_ALT) /* ALT */
+ {
+ if(alt_map[currKey])
+ {
+ currChars[0] = alt_map[currKey];
+ }
+ }
+ else if(keyMods & PS2KBD_SHIFT) /* SHIFT */
+ {
+ if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey]))
+ {
+ currChars[0] = keymap[currKey];
+ }
+ else
+ {
+ currChars[0] = shiftkeymap[currKey];
+ }
+ }
+ else /* Normal key */
+ {
+ if(keymap[keys[loopKey]])
+ {
+ if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey]))
+ {
+ currChars[0] = shiftkeymap[currKey];
+ }
+ else
+ {
+ currChars[0] = keymap[currKey];
+ }
+ }
+ }
+ }
+
+ if((currChars[0] == PS2KBD_ESCAPE_KEY) && (currChars[1] != 0))
+ {
+ if(lineEndP != (tempPos - 2))
+ {
+ lineBuffer[lineEndP++] = currChars[0];
+ lineEndP %= lineSize;
+ lineBuffer[lineEndP++] = currChars[1];
+ lineEndP %= lineSize;
+ byteCount += 2;
+ }
+ dev->repeatkeys[0] = currChars[0];
+ dev->repeatkeys[1] = currChars[1];
+ }
+ else if(currChars[0] != 0)
+ {
+ lineBuffer[lineEndP++] = currChars[0];
+ lineEndP %= lineSize;
+ byteCount++;
+ dev->repeatkeys[0] = currChars[0];
+ dev->repeatkeys[1] = 0;
+ }
+ }
+
+ if(byteCount > 0)
+ {
+ iop_sys_clock_t t;
+ /* Set alarm to do repeat rate */
+ //printf("repeatkeys %d %d\n", kbd_repeatkeys[0], kbd_repeatkeys[1]);
+ USec2SysClock(PS2KBD_REPEATWAIT * 1000, &t);
+ SetAlarm(&t, ps2kbd_repeathandler, dev);
+ }
+
+ for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema to indicate data */
+ {
+ SignalSema(bufferSema);
+ }
+
+/* lineBuffer[PS2KBD_DEFLINELEN - 1] = 0; */
+/* printf(lineBuffer); */
+ //printf("lineStart %d, lineEnd %d\n", lineStartP, lineEndP);
+}
+
+
+void ps2kbd_getkeys_raw(u8 newKeyMods, u8 oldKeyMods, u8 *new, const u8 *old)
+
+{
+ int loopKey;
+ u8 currKey;
+ u8 keyMods = newKeyMods ^ oldKeyMods;
+ u8 keyModsMap = newKeyMods & keyMods;
+ int tempPos = 0;
+ int byteCount = 0;
+
+ if(lineStartP < lineEndP)
+ {
+ tempPos = lineStartP + lineSize;
+ }
+ else
+ {
+ tempPos = lineStartP;
+ }
+
+ for(loopKey = 0; loopKey < 8; loopKey++)
+ {
+ int currMod = (1 << loopKey);
+ if(keyMods & currMod)
+ {
+ if(lineEndP == (tempPos - 2))
+ {
+ return;
+ }
+
+ currKey = keyModValue[loopKey];
+
+ if(keyModsMap & currMod) /* If key pressed */
+ {
+ lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN;
+ //printf("Key down\n");
+ }
+ else
+ {
+ lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP;
+ //printf("Key up\n");
+ }
+
+ lineEndP %= lineSize;
+ lineBuffer[lineEndP++] = currKey;
+ lineEndP %= lineSize;
+ byteCount += 2;
+ //printf("Key %d\n", currKey);
+ }
+ }
+
+ for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
+ {
+ if(lineEndP == (tempPos - 2))
+ {
+ return;
+ }
+
+ if(new[loopKey] != 0)
+ {
+ lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN;
+ lineEndP %= lineSize;
+ lineBuffer[lineEndP++] = new[loopKey];
+ lineEndP %= lineSize;
+ byteCount += 2;
+ //printf("Key down\nKey %d\n", new[loopKey]);
+ }
+
+ }
+
+ for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
+ {
+ if(lineEndP == (tempPos - 2))
+ {
+ return;
+ }
+
+ if(old[loopKey] != 0)
+ {
+ lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP;
+ lineEndP %= lineSize;
+ lineBuffer[lineEndP++] = old[loopKey];
+ lineEndP %= lineSize;
+ byteCount += 2;
+ //printf("Key up\nKey %d\n", old[loopKey]);
+ }
+
+ }
+
+ for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema for the number of bytes read */
+ {
+ SignalSema(bufferSema);
+ }
+}
+
+void ps2kbd_data_recv(int resultCode, int bytes, void *arg)
+
+{
+ kbd_dev *dev;
+ int ret;
+ int phantom;
+ int loop;
+
+ if(resultCode != USB_RC_OK)
+ {
+ printf("PS2KEYBOARD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
+ return;
+ }
+
+ //printf("PS2KBD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
+
+ dev = (kbd_dev *) arg;
+ if(dev == NULL)
+ {
+ printf("PS2KBD: dev == NULL\n");
+ return;
+ }
+
+/* printf("PS2KBD Modifiers %02X, Keys ", dev->data.mod_keys); */
+/* for(loop = 0; loop < PS2KBD_MAXKEYS; loop++) */
+/* { */
+/* printf("%02X ", dev->data.keycodes[loop]); */
+/* } */
+/* printf("\n"); */
+
+ CancelAlarm(ps2kbd_repeathandler, dev); /* Make sure repeat alarm is cancelled */
+
+ /* Check for phantom states */
+ phantom = 1;
+ for(loop = 0; loop < PS2KBD_MAXKEYS; loop++)
+ {
+ if(dev->data.keycodes[loop] != 1)
+ {
+ phantom = 0;
+ break;
+ }
+ }
+
+ if(!phantom) /* If not in a phantom state */
+ {
+ u8 uniqueKeys[PS2KBD_MAXKEYS];
+ u8 missingKeys[PS2KBD_MAXKEYS];
+ int loopKey;
+
+ memset(uniqueKeys, 0, PS2KBD_MAXKEYS);
+ memset(missingKeys, 0, PS2KBD_MAXKEYS);
+ ps2kbd_build_uniquekeys(uniqueKeys, dev->data.keycodes, dev->oldData.keycodes);
+ ps2kbd_build_uniquekeys(missingKeys, dev->oldData.keycodes, dev->data.keycodes);
+ /* Build new and missing key lists */
+
+/* printf("Unique keys : "); */
+/* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */
+/* { */
+/* printf("%02X ", uniqueKeys[loopKey]); */
+/* } */
+/* printf("\n"); */
+
+/* printf("Missing keys : "); */
+/* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */
+/* { */
+/* printf("%02X ", missingKeys[loopKey]); */
+/* } */
+/* printf("\n"); */
+
+ if(kbd_readmode == PS2KBD_READMODE_NORMAL)
+ {
+ u8 ledStatus;
+
+ ledStatus = dev->ledStatus;
+ //printf("ledStatus %02X\n", ledStatus);
+
+ for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) /* Process key codes */
+ {
+ switch(uniqueKeys[loopKey])
+ {
+ case USB_KEYB_NUMLOCK :
+ ledStatus ^= PS2KBD_LED_NUMLOCK;
+ uniqueKeys[loopKey] = 0;
+ break;
+ case USB_KEYB_CAPSLOCK :
+ ledStatus ^= PS2KBD_LED_CAPSLOCK;
+ uniqueKeys[loopKey] = 0;
+ break;
+ case USB_KEYB_SCRLOCK :
+ ledStatus ^= PS2KBD_LED_SCRLOCK;
+ uniqueKeys[loopKey] = 0;
+ break;
+ }
+ }
+
+ if(ledStatus != dev->ledStatus)
+ {
+ dev->ledStatus = ledStatus & PS2KBD_LED_MASK;
+ //printf("LEDS %02X\n", dev->ledStatus);
+ /* Call Set LEDS */
+ UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200,
+ dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, arg);
+ }
+
+ WaitSema(lineSema); /* Make sure no other thread is going to manipulate the buffer */
+ ps2kbd_getkeys(dev->data.mod_keys, dev->ledStatus, uniqueKeys, dev); /* read in remaining keys */
+ SignalSema(lineSema);
+ }
+ else /* RAW Mode */
+ {
+ WaitSema(lineSema);
+ ps2kbd_getkeys_raw(dev->data.mod_keys, dev->oldData.mod_keys, uniqueKeys, missingKeys);
+ SignalSema(lineSema);
+ }
+
+ memcpy(&dev->oldData, &dev->data, sizeof(kbd_data_recv));
+ }
+
+ ret = UsbInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg);
+}
+
+void flushbuffer()
+
+{
+ iop_sema_t s;
+
+ lineStartP = 0;
+ lineEndP = 0;
+ memset(lineBuffer, 0, lineSize);
+
+ DeleteSema(bufferSema);
+ s.initial = 0;
+ s.max = lineSize;
+ s.option = 0;
+ s.attr = 0;
+ bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */
+
+ if(bufferSema <= 0)
+ {
+ printf("Error creating buffer sema\n");
+ }
+}
+
+void ps2kbd_rpc_setreadmode(u32 readmode)
+
+{
+ int devLoop;
+
+ if(readmode == kbd_readmode) return;
+
+ if((readmode == PS2KBD_READMODE_NORMAL) || (readmode == PS2KBD_READMODE_RAW))
+ {
+ /* Reset line buffer */
+ //printf("ioctl_setreadmode %d\n", readmode);
+ for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
+ {
+ CancelAlarm(ps2kbd_repeathandler, devices[devLoop]);
+ }
+
+ WaitSema(lineSema);
+ kbd_readmode = readmode;
+ flushbuffer();
+ SignalSema(lineSema);
+ }
+}
+
+void ps2kbd_rpc_setkeymap(kbd_keymap *keymaps)
+
+{
+ //printf("ioctl_setkeymap %p\n", keymaps);
+ WaitSema(lineSema); /* Lock the input so you dont end up with weird results */
+ memcpy(keymap, keymaps->keymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(shiftkeymap, keymaps->shiftkeymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(keycap, keymaps->keycap, PS2KBD_KEYMAP_SIZE);
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_setctrlmap(u8 *ctrlmap)
+
+{
+ //printf("ioctl_setctrlmap %p\n", ctrlmap);
+ WaitSema(lineSema);
+ memcpy(control_map, ctrlmap, PS2KBD_KEYMAP_SIZE);
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_setaltmap(u8 *altmap)
+
+{
+ //printf("ioctl_setaltmap %p\n", altmap);
+ WaitSema(lineSema);
+ memcpy(alt_map, altmap, PS2KBD_KEYMAP_SIZE);
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_setspecialmap(u8 *special)
+
+{
+ //printf("ioctl_setspecialmap %p\n", special);
+ WaitSema(lineSema);
+ memcpy(special_keys, special, PS2KBD_KEYMAP_SIZE);
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_resetkeymap()
+ /* Reset keymap to default US variety */
+
+{
+ //printf("ioctl_resetkeymap()\n");
+ WaitSema(lineSema);
+ memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE);
+ memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE);
+ memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE);
+ memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE);
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_flushbuffer()
+ /* Flush the internal buffer */
+
+{
+ //printf("ioctl_flushbuffer()\n");
+ WaitSema(lineSema);
+ flushbuffer();
+ SignalSema(lineSema);
+}
+
+void ps2kbd_rpc_setleds(u8 ledStatus)
+
+{
+ int devLoop;
+ kbd_dev *dev;
+
+ //printf("ioctl_setleds %d\n", ledStatus);
+ ledStatus &= PS2KBD_LED_MASK;
+ for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
+ {
+ dev = devices[devLoop];
+ if(dev)
+ {
+ if(ledStatus != dev->ledStatus)
+ {
+ dev->ledStatus = ledStatus & PS2KBD_LED_MASK;
+ UsbControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200,
+ dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, dev);
+ }
+ }
+ }
+}
+
+void ps2kbd_rpc_setrepeatrate(u32 rate)
+{
+ kbd_repeatrate = rate;
+}
+
+int kbd_read(void *buf, int size)
+{
+ int count = 0;
+ char *data = (char *) buf;
+
+ if(kbd_readmode == PS2KBD_READMODE_RAW)
+ size &= ~1; /* Ensure size of a multiple of 2 */
+
+ if (PollSema(bufferSema) >= 0) {
+ SignalSema(bufferSema);
+ if (WaitSema(lineSema) >= 0) {
+ while((count < size) && (lineStartP != lineEndP)) {
+ data[count] = lineBuffer[lineStartP++];
+ lineStartP %= lineSize;
+ count++;
+ PollSema(bufferSema); /* Take off one count from the sema */
+ }
+ SignalSema(lineSema);
+ }
+ }
+ return count;
+}
+
+void repeat_thread(void *arg)
+
+{
+ u32 eventmask;
+ int devLoop;
+
+ for(;;)
+ {
+ WaitEventFlag(eventid, 0xFFFFFFFF, 0x01 | 0x10, &eventmask);
+ //printf("Recieved event %08X\n", eventmask);
+ for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
+ {
+ if((eventmask & (1 << devLoop)) && (devices[devLoop]))
+ {
+ int tempPos = 0;
+
+ WaitSema(lineSema);
+ if(lineStartP < lineEndP)
+ {
+ tempPos = lineStartP + lineSize;
+ }
+ else
+ {
+ tempPos = lineStartP;
+ }
+
+ if((devices[devLoop]->repeatkeys[0]) && (devices[devLoop]->repeatkeys[1]))
+ {
+ if(lineEndP != (tempPos - 2))
+ {
+ lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0];
+ lineEndP %= lineSize;
+ lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[1];
+ lineEndP %= lineSize;
+ SignalSema(bufferSema);
+ SignalSema(bufferSema);
+ }
+ }
+ else if(devices[devLoop]->repeatkeys[0])
+ {
+ if(lineEndP != (tempPos - 1))
+ {
+ lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0];
+ lineEndP %= lineSize;
+ SignalSema(bufferSema);
+ }
+ }
+
+ SignalSema(lineSema);
+ }
+ }
+ }
+}
+
+int init_repeatthread()
+ /* Creates a thread to handle key repeats */
+{
+ iop_thread_t param;
+ iop_event_t event;
+
+ event.attr = 0;
+ event.option = 0;
+ event.bits = 0;
+ eventid = CreateEventFlag(&event);
+
+ param.attr = TH_C;
+ param.thread = repeat_thread;
+ param.priority = 40;
+ param.stacksize = 0x800;
+ param.option = 0;
+
+ repeat_tid = CreateThread(&param);
+ if (repeat_tid > 0) {
+ StartThread(repeat_tid, 0);
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static unsigned long retKey;
+
+void *ps2kbd_rpc_server(int fno, void *data, int size) {
+ retKey = 0;
+ switch (fno) {
+ case KBD_RPC_SETREADMODE:
+ ps2kbd_rpc_setreadmode(*(u32 *)data);
+ break;
+ case KBD_RPC_SETKEYMAP:
+ ps2kbd_rpc_setkeymap((kbd_keymap *) data);
+ break;
+ case KBD_RPC_SETALTMAP:
+ ps2kbd_rpc_setaltmap((u8 *) data);
+ break;
+ case KBD_RPC_SETCTRLMAP:
+ ps2kbd_rpc_setctrlmap((u8 *) data);
+ break;
+ case KBD_RPC_SETSPECIALMAP:
+ ps2kbd_rpc_setspecialmap((u8 *) data);
+ break;
+ case KBD_RPC_FLUSHBUFFER:
+ ps2kbd_rpc_flushbuffer();
+ break;
+ case KBD_RPC_SETLEDS:
+ ps2kbd_rpc_setleds(*(u8*) data);
+ break;
+ case KBD_RPC_RESETKEYMAP:
+ ps2kbd_rpc_resetkeymap();
+ break;
+ case KBD_RPC_SETREPEATRATE:
+ ps2kbd_rpc_setrepeatrate(*(u32 *) data);
+ break;
+ case KBD_RPC_READRAW:
+ kbd_read(&retKey, 2);
+ return &retKey;
+ case KBD_RPC_READKEY:
+ kbd_read(&retKey, 1);
+ return &retKey;
+ default:
+ printf("Ps2Kbd: Unknown RPC command %d\n", fno);
+ break;
+ }
+ return NULL;
+}
+
+struct t_SifRpcDataQueue qd;
+struct t_SifRpcServerData sd0;
+void *rpcRcvBuf;
+
+void ps2kbd_start_rpc(unsigned long tid) {
+ rpcRcvBuf = AllocSysMemory(0, 3 * PS2KBD_KEYMAP_SIZE, NULL);
+ printf("Ps2Kbd: starting RPC server\n");
+ SifInitRpc(0);
+
+ SifSetRpcQueue(&qd, tid);
+ SifRegisterRpc(&sd0, PS2KBD_RPC_ID, ps2kbd_rpc_server, rpcRcvBuf, 0, 0, &qd);
+ SifRpcLoop(&qd);
+}
+
+int ps2kbd_init_rpc(void) {
+ struct _iop_thread param;
+ int th;
+
+ param.attr = 0x02000000;
+ param.thread = (void*)ps2kbd_start_rpc;
+ param.priority = 40;
+ param.stacksize = 0x800;
+ param.option = 0;
+
+ th = CreateThread(&param);
+
+ if (th > 0) {
+ StartThread(th, (void *)th);
+ return 0;
+ } else
+ return -1;
+}
+
+int ps2kbd_init() {
+ int ret;
+ iop_sema_t s;
+
+ s.initial = 1;
+ s.max = 1;
+ s.option = 0;
+ s.attr = 0;
+ lineSema = CreateSema(&s);
+ if(lineSema <= 0)
+ {
+ printf("Error creating sema\n");
+ return 1;
+ }
+
+ s.initial = 0;
+ s.max = PS2KBD_DEFLINELEN;
+ s.option = 0;
+ s.attr = 0;
+ bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */
+ if(bufferSema <= 0)
+ {
+ printf("Error creating buffer sema\n");
+ return 1;
+ }
+
+ lineBuffer = (u8 *) AllocSysMemory(0, PS2KBD_DEFLINELEN, NULL);
+ if(lineBuffer == NULL)
+ {
+ printf("Error allocating line buffer\n");
+ return 1;
+ }
+ lineStartP = 0;
+ lineEndP = 0;
+ lineSize = PS2KBD_DEFLINELEN;
+ memset(lineBuffer, 0, PS2KBD_DEFLINELEN);
+
+ memset(devices, 0, sizeof(kbd_dev *) * PS2KBD_MAXDEV);
+ dev_count = 0;
+ kbd_readmode = PS2KBD_READMODE_NORMAL;
+ kbd_repeatrate = PS2KBD_DEFREPEATRATE;
+ memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE);
+ memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE);
+ memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE);
+ memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE);
+ memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE);
+
+ ps2kbd_init_rpc();
+ init_repeatthread();
+
+ ret = UsbRegisterDriver(&kbd_driver);
+ if(ret != USB_RC_OK)
+ {
+ printf("Error registering USB devices\n");
+ return 1;
+ }
+
+ printf("UsbRegisterDriver %d\n", ret);
+
+ return 0;
+}
diff --git a/backends/platform/ps2/iop/rpckbd/src/us_keymap.h b/backends/platform/ps2/iop/rpckbd/src/us_keymap.h
new file mode 100644
index 0000000000..57f0686cd3
--- /dev/null
+++ b/backends/platform/ps2/iop/rpckbd/src/us_keymap.h
@@ -0,0 +1,1579 @@
+/*
+# _____ ___ ____ ___ ____
+# ____| | ____| | | |____|
+# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
+#-----------------------------------------------------------------------
+# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
+# Licenced under Academic Free License version 2.0
+# Review ps2sdk README & LICENSE files for further details.
+#
+# $Id$
+# USB Keyboard Driver for PS2
+*/
+
+#ifndef __US_KEYMAP_H__
+#define __US_KEYMAP_H__
+
+/* Default US keymap */
+
+u8 us_keymap[PS2KBD_KEYMAP_SIZE] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 'a',
+ 'b',
+ 'c',
+ 'd',
+ 'e',
+ 'f',
+ 'g',
+ 'h',
+ 'i',
+ 'j',
+ 'k',
+ 'l',
+ 'm',
+ 'n',
+ 'o',
+ 'p',
+ 'q',
+ 'r',
+ 's',
+ 't',
+ 'u',
+ 'v',
+ 'w',
+ 'x',
+ 'y',
+ 'z',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ '0',
+ 10, /* line feed */
+ 0, /* Esc */
+ 0x7,/* BS */
+ 0x9, /* TAB */
+ 0x20,
+ '-',
+ '=',
+ '[',
+ ']',
+ '\\',
+ '#',
+ ';',
+ '\'',
+ '`',
+ ',',
+ '.',
+ '/',
+ 0, /* CL */
+ 0, // F1
+ 0, // F2
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0, // F7
+ 0, // F8
+ 0, // F9
+ 0, // F10
+ 0, // F11
+ 0, // F12
+ 0, // PrintScr
+ 0, // Scroll Lock
+ 0, // Pause
+ 0, // Insert
+ 0, // Home
+ 0, // Pg Up
+ 0, // Delete
+ 0, // End
+ 0, // Pg Down
+ 0, // Right
+ 0, // Left
+ 0, // Down
+ 0, // Up
+ 0, // Numlock
+ '/', // Keypad
+ '*',
+ '-',
+ '+',
+ 10,
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ '0',
+ '.',
+ '\\',
+ 0,
+ 0,
+ '=',
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+u8 us_shiftkeymap[PS2KBD_KEYMAP_SIZE] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ 'G',
+ 'H',
+ 'I',
+ 'J',
+ 'K',
+ 'L',
+ 'M',
+ 'N',
+ 'O',
+ 'P',
+ 'Q',
+ 'R',
+ 'S',
+ 'T',
+ 'U',
+ 'V',
+ 'W',
+ 'X',
+ 'Y',
+ 'Z',
+ '!',
+ '@',
+ '#',
+ '$',
+ '%',
+ '^',
+ '&',
+ '*',
+ '(',
+ ')',
+ 10, /* line feed */
+ 0, /* Esc */
+ 0x7,/* BS */
+ 0x9, /* TAB */
+ 0x20,
+ '_',
+ '+',
+ '{',
+ '}',
+ '|',
+ '~',
+ ':',
+ '"',
+ '~',
+ '<',
+ '>',
+ '?',
+ 0, /* CL */
+ 0, // F1
+ 0, // F2
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0, // F7
+ 0, // F8
+ 0, // F9
+ 0, // F10
+ 0, // F11
+ 0, // F12
+ 0, // PrintScr
+ 0, // Scroll Lock
+ 0, // Pause
+ 0, // Insert
+ 0, // Home
+ 0, // Pg Up
+ 0, // Delete
+ 0, // End
+ 0, // Pg Down
+ 0, // Right
+ 0, // Left
+ 0, // Down
+ 0, // Up
+ 0, // Numlock
+ '/', // Keypad
+ '*',
+ '-',
+ '+',
+ 10,
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ '0',
+ '.',
+ '\\',
+ 0,
+ 0,
+ '=',
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+u8 us_keycap[PS2KBD_KEYMAP_SIZE] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 1, //a
+ 1, //b
+ 1, //c
+ 1, //d
+ 1, //e
+ 1, //f
+ 1,//g
+ 1,//h
+ 1,//i
+ 1,//j
+ 1,//k
+ 1,//l
+ 1,//m
+ 1,//n
+ 1,//o
+ 1,//p
+ 1,//q
+ 1,//r
+ 1,//s
+ 1,//t
+ 1,//u
+ 1,//v
+ 1,//w
+ 1,//x
+ 1,//y
+ 1,//z
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* line feed */
+ 0, /* Esc */
+ 0,/* BS */
+ 0, /* TAB */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* CL */
+ 0, // F1
+ 0, // F2
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0, // F7
+ 0, // F8
+ 0, // F9
+ 0, // F10
+ 0, // F11
+ 0, // F12
+ 0, // PrintScr
+ 0, // Scroll Lock
+ 0, // Pause
+ 0, // Insert
+ 0, // Home
+ 0, // Pg Up
+ 0, // Delete
+ 0, // End
+ 0, // Pg Down
+ 0, // Right
+ 0, // Left
+ 0, // Down
+ 0, // Up
+ 0, // Numlock
+ 0, // Keypad
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+u8 us_special_keys[PS2KBD_KEYMAP_SIZE] = {
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, //a
+ 0, //b
+ 0, //c
+ 0, //d
+ 0, //e
+ 0, //f
+ 0,//g
+ 0,//h
+ 0,//i
+ 0,//j
+ 0,//k
+ 0,//l
+ 0,//m
+ 0,//n
+ 0,//o
+ 0,//p
+ 0,//q
+ 0,//r
+ 0,//s
+ 0,//t
+ 0,//u
+ 0,//v
+ 0,//w
+ 0,//x
+ 0,//y
+ 0,//z
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* line feed */
+ 0x1B, /* Esc */
+ 0,/* BS */
+ 0, /* TAB */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* CL */
+ 1, // F1
+ 2, // F2
+ 3, // F3
+ 4, // F4
+ 5, // F5
+ 6, // F6
+ 7, // F7
+ 8, // F8
+ 9, // F9
+ 10, // F10
+ 11, // F11
+ 12, // F12
+ 32, // PrintScr
+ 33, // Scroll Lock
+ 34, // Pause
+ 35, // Insert
+ 36, // Home
+ 37, // Pg Up
+ 38, // Delete
+ 39, // End
+ 40, // Pg Down
+ 41, // Right
+ 42, // Left
+ 43, // Down
+ 44, // Up
+ 0, // Numlock
+ 0, // Keypad /
+ 0, // Keypad *
+ 0, // Keypad -
+ 0, // Keypad +
+ 0, // Keypad Enter
+ 39, // Keypad 1/End
+ 43, // Keypad 2/Down
+ 40, // Keypad 3/PageDn
+ 42, // Keypad 4/Left
+ 0, // Keypad 5
+ 41, // Keypad 6/Right
+ 36, // Keypad 7/Home
+ 44, // Keypad 8/Up
+ 37, // Keypad 9/PageUp
+ 35, // Keypad 0/Insert
+ 38, // Keypad ./Delete
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+u8 us_control_map[PS2KBD_KEYMAP_SIZE] = {
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 1, //a
+ 2, //b
+ 3, //c
+ 4, //d
+ 5, //e
+ 6, //f
+ 7,//g
+ 8,//h
+ 9,//i
+ 10,//j
+ 11,//k
+ 12,//l
+ 13,//m
+ 14,//n
+ 15,//o
+ 16,//p
+ 17,//q
+ 18,//r
+ 19,//s
+ 20,//t
+ 21,//u
+ 22,//v
+ 23,//w
+ 24,//x
+ 25,//y
+ 26,//z
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* line feed */
+ 0, /* Esc */
+ 0,/* BS */
+ 0, /* TAB */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* CL */
+ 0, // F1
+ 0, // F2
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0, // F7
+ 0, // F8
+ 0, // F9
+ 0, // F10
+ 0, // F11
+ 0, // F12
+ 0, // PrintScr
+ 0, // Scroll Lock
+ 0, // Pause
+ 0, // Insert
+ 0, // Home
+ 0, // Pg Up
+ 0, // Delete
+ 0, // End
+ 0, // Pg Down
+ 0, // Right
+ 0, // Left
+ 0, // Down
+ 0, // Up
+ 0, // Numlock
+ 0, // Keypad
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+u8 us_alt_map[PS2KBD_KEYMAP_SIZE] = {
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 128, //a
+ 129, //b
+ 130, //c
+ 131, //d
+ 132, //e
+ 133, //f
+ 134,//g
+ 135,//h
+ 136,//i
+ 137,//j
+ 138,//k
+ 139,//l
+ 140,//m
+ 141,//n
+ 142,//o
+ 143,//p
+ 144,//q
+ 145,//r
+ 146,//s
+ 147,//t
+ 148,//u
+ 149,//v
+ 150,//w
+ 151,//x
+ 152,//y
+ 154,//z
+ 155,
+ 156,
+ 157,
+ 158,
+ 159,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165, /* line feed */
+ 0, /* Esc */
+ 0,/* BS */
+ 0, /* TAB */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* CL */
+ 0, // F1
+ 0, // F2
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0, // F7
+ 0, // F8
+ 0, // F9
+ 0, // F10
+ 0, // F11
+ 0, // F12
+ 0, // PrintScr
+ 0, // Scroll Lock
+ 0, // Pause
+ 0, // Insert
+ 0, // Home
+ 0, // Pg Up
+ 0, // Delete
+ 0, // End
+ 0, // Pg Down
+ 0, // Right
+ 0, // Left
+ 0, // Down
+ 0, // Up
+ 0, // Numlock
+ 0, // Keypad
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+#endif
diff --git a/backends/platform/ps2/irxboot.cpp b/backends/platform/ps2/irxboot.cpp
index 327e5bdc71..65d1e243eb 100644
--- a/backends/platform/ps2/irxboot.cpp
+++ b/backends/platform/ps2/irxboot.cpp
@@ -43,7 +43,7 @@ IrxFile irxFiles[] = {
{ "PADMAN", BIOS, NOTHING, NULL, 0 },
{ "LIBSD", BIOS, NOTHING, NULL, 0 },
- { "IOMANX.IRX", SYSTEM | NOT_HOST, NOTHING, NULL, 0 }, // already loaded by ps2link
+ { "IOMANX.IRX", SYSTEM /*| NOT_HOST*/, NOTHING, NULL, 0 }, // already loaded by ps2link
{ "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 },
{ "CODYVDFS.IRX", SYSTEM, NOTHING, NULL, 0 },
{ "SJPCM.IRX", SYSTEM, NOTHING, NULL, 0 },
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 28ced7b345..d4dd9aedcf 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -54,9 +54,11 @@
#include "graphics/surface.h"
#include "graphics/font.h"
#include "backends/timer/default/default-timer.h"
-#include "sound/mixer.h"
+#include "sound/mixer_intern.h"
#include "common/events.h"
#include "backends/platform/ps2/ps2debug.h"
+#include "backends/fs/ps2/ps2-fs-factory.h"
+
// asm("mfc0 %0, $9\n" : "=r"(tickStart));
extern void *_gp;
@@ -309,7 +311,9 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) {
void OSystem_PS2::init(void) {
sioprintf("Timer...\n");
_scummTimerManager = new DefaultTimerManager();
- _scummMixer = new Audio::Mixer();
+ _scummMixer = new Audio::MixerImpl(this);
+ _scummMixer->setOutputRate(44100);
+ _scummMixer->setReady(true);
initTimer();
sioprintf("Starting SavefileManager\n");
@@ -410,7 +414,8 @@ void OSystem_PS2::soundThread(void) {
// we have to produce more samples, call sound mixer
// the scratchpad at 0x70000000 is used as temporary soundbuffer
//_scummSoundProc(_scummSoundParam, (uint8*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
- Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
+ // Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
+ _scummMixer->mixCallback((byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
// demux data into 2 buffers, L and R
__asm__ (
@@ -534,10 +539,6 @@ Common::TimerManager *OSystem_PS2::getTimerManager() {
return _scummTimerManager;
}
-int OSystem_PS2::getOutputSampleRate(void) const {
- return 48000;
-}
-
Audio::Mixer *OSystem_PS2::getMixer() {
return _scummMixer;
}
@@ -546,6 +547,10 @@ Common::SaveFileManager *OSystem_PS2::getSavefileManager(void) {
return _saveManager;
}
+FilesystemFactory *OSystem_PS2::getFilesystemFactory() {
+ return &Ps2FilesystemFactory::instance();
+}
+
void OSystem_PS2::setShakePos(int shakeOffset) {
_screen->setShakePos(shakeOffset);
}
diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h
index 9dbe9be553..08975ab2c8 100644
--- a/backends/platform/ps2/systemps2.h
+++ b/backends/platform/ps2/systemps2.h
@@ -33,6 +33,7 @@ class DefaultTimerManager;
class Gs2dScreen;
class Ps2Input;
class Ps2SaveFileManager;
+// class Ps2FilesystemFactory;
struct IrxReference;
#define MAX_MUTEXES 16
@@ -48,7 +49,7 @@ namespace Common {
};
namespace Audio {
- class Mixer;
+ class MixerImpl;
};
class OSystem_PS2 : public OSystem {
@@ -87,7 +88,6 @@ public:
virtual bool pollEvent(Common::Event &event);
virtual Audio::Mixer *getMixer();
- virtual int getOutputSampleRate(void) const;
virtual bool openCD(int drive);
virtual bool pollCD();
@@ -112,6 +112,7 @@ public:
virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b);
virtual Common::SaveFileManager *getSavefileManager();
+ virtual FilesystemFactory *getFilesystemFactory();
virtual void getTimeAndDate(struct tm &t) const;
@@ -133,7 +134,7 @@ private:
void readRtcTime(void);
DefaultTimerManager *_scummTimerManager;
- Audio::Mixer *_scummMixer;
+ Audio::MixerImpl *_scummMixer;
bool _mouseVisible;
diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile
index aa27f388b9..ca09286c4d 100644
--- a/backends/platform/psp/Makefile
+++ b/backends/platform/psp/Makefile
@@ -2,10 +2,36 @@
# $URL$
# $Id$
+ENABLED=STATIC_PLUGIN
+
#control build
DISABLE_SCALERS = true
DISABLE_HQ_SCALERS = true
+ENABLE_SCUMM = $(ENABLED)
+ENABLE_SCUMM_7_8 = $(ENABLED)
+#ENABLE_HE = $(ENABLED)
+ENABLE_AGI = $(ENABLED)
+ENABLE_AGOS = $(ENABLED)
+#ENABLE_CINE = $(ENABLED)
+#ENABLE_CRUISE = $(ENABLED)
+ENABLE_DRASCULA = $(ENABLED)
+ENABLE_GOB = $(ENABLED)
+#ENABLE_IGOR = $(ENABLED)
+ENABLE_KYRA = $(ENABLED)
+ENABLE_LURE = $(ENABLED)
+#ENABLE_M4 = $(ENABLED)
+#ENABLE_MADE = $(ENABLED)
+#ENABLE_PARALLACTION = $(ENABLED)
+#ENABLE_QUEEN = $(ENABLED)
+#ENABLE_SAGA = $(ENABLED)
+ENABLE_SKY = $(ENABLED)
+ENABLE_SWORD1 = $(ENABLED)
+ENABLE_SWORD2 = $(ENABLED)
+#ENABLE_TINSEL = $(ENABLED)
+#ENABLE_TOUCHE = $(ENABLED)
+
+
srcdir = ../../..
VPATH = $(srcdir)
HAVE_GCC3 = false
@@ -63,6 +89,8 @@ OBJS := psp_main.o \
kbd_l_c.o \
trace.o
+DEPDIR = .deps
+
include $(srcdir)/Makefile.common
PSP_EBOOT_SFO = param.sfo
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index 2d18b4bfd6..6e9b5980d4 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -72,7 +72,7 @@ const OSystem::GraphicsMode OSystem_PSP::s_supportedGraphicsModes[] = {
};
-OSystem_PSP::OSystem_PSP() : _screenWidth(0), _screenHeight(0), _overlayWidth(0), _overlayHeight(0), _offscreen(0), _overlayBuffer(0), _overlayVisible(false), _shakePos(0), _mouseBuf(0), _prevButtons(0), _lastPadCheck(0), _padAccel(0) {
+OSystem_PSP::OSystem_PSP() : _screenWidth(0), _screenHeight(0), _overlayWidth(0), _overlayHeight(0), _offscreen(0), _overlayBuffer(0), _overlayVisible(false), _shakePos(0), _mouseBuf(0), _prevButtons(0), _lastPadCheck(0), _padAccel(0), _mixer(0) {
memset(_palette, 0, sizeof(_palette));
@@ -99,11 +99,11 @@ OSystem_PSP::~OSystem_PSP() {
void OSystem_PSP::initBackend() {
_savefile = new DefaultSaveFileManager();
- _mixer = new Audio::MixerImpl(this);
_timer = new DefaultTimerManager();
- setSoundCallback(Audio::Mixer::mixCallback, _mixer);
setTimerCallback(&timer_handler, 10);
+ setupMixer();
+
OSystem::initBackend();
}
@@ -586,7 +586,15 @@ void OSystem_PSP::deleteMutex(MutexRef mutex) {
SDL_DestroyMutex((SDL_mutex *)mutex);
}
-bool OSystem_PSP::setSoundCallback(SoundProc proc, void *param) {
+void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) {
+ OSystem_PSP *this_ = (OSystem_PSP *)sys;
+ assert(this_);
+
+ if (this_->_mixer)
+ this_->_mixer->mixCallback(samples, len);
+}
+
+void OSystem_PSP::setupMixer(void) {
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
@@ -613,21 +621,29 @@ bool OSystem_PSP::setSoundCallback(SoundProc proc, void *param) {
desired.format = AUDIO_S16SYS;
desired.channels = 2;
desired.samples = samples;
- desired.callback = proc;
- desired.userdata = param;
+ desired.callback = mixCallback;
+ desired.userdata = this;
+
+ assert(!_mixer);
+ _mixer = new Audio::MixerImpl(this);
+ assert(_mixer);
+
if (SDL_OpenAudio(&desired, &obtained) != 0) {
- return false;
+ warning("Could not open audio: %s", SDL_GetError());
+ _samplesPerSec = 0;
+ _mixer->setReady(false);
+ } else {
+ // Note: This should be the obtained output rate, but it seems that at
+ // least on some platforms SDL will lie and claim it did get the rate
+ // even if it didn't. Probably only happens for "weird" rates, though.
+ _samplesPerSec = obtained.freq;
+
+ // Tell the mixer that we are ready and start the sound processing
+ _mixer->setOutputRate(_samplesPerSec);
+ _mixer->setReady(true);
+
+ SDL_PauseAudio(0);
}
- // Note: This should be the obtained output rate, but it seems that at
- // least on some platforms SDL will lie and claim it did get the rate
- // even if it didn't. Probably only happens for "weird" rates, though.
- _samplesPerSec = obtained.freq;
- SDL_PauseAudio(0);
- return true;
-}
-
-int OSystem_PSP::getOutputSampleRate() const {
- return _samplesPerSec;
}
void OSystem_PSP::quit() {
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 64514f6872..dca6ccb036 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -26,6 +26,7 @@
#include "common/scummsys.h"
#include "common/system.h"
#include "graphics/surface.h"
+#include "sound/mixer_intern.h"
#include "backends/fs/psp/psp-fs-factory.h"
@@ -71,7 +72,7 @@ protected:
SceCtrlData pad;
Common::SaveFileManager *_savefile;
- Audio::Mixer *_mixer;
+ Audio::MixerImpl *_mixer;
Common::TimerManager *_timer;
public:
@@ -129,9 +130,8 @@ public:
virtual void unlockMutex(MutexRef mutex);
virtual void deleteMutex(MutexRef mutex);
- typedef void (*SoundProc)(void *param, byte *buf, int len);
- virtual bool setSoundCallback(SoundProc proc, void *param);
- virtual int getOutputSampleRate() const;
+ static void mixCallback(void *sys, byte *samples, int len);
+ virtual void setupMixer(void);
Common::SaveFileManager *getSavefileManager() { return _savefile; }
Audio::Mixer *getMixer() { return _mixer; }
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 290fe63663..76ac91c282 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -191,7 +191,7 @@ OSystem_SDL::OSystem_SDL()
OSystem_SDL::~OSystem_SDL() {
SDL_RemoveTimer(_timerID);
- SDL_CloseAudio();
+ closeMixer();
free(_dirtyChecksums);
free(_currentPalette);
@@ -199,7 +199,6 @@ OSystem_SDL::~OSystem_SDL() {
free(_mouseData);
delete _savefile;
- delete _mixer;
delete _timer;
}
@@ -306,7 +305,7 @@ void OSystem_SDL::quit() {
SDL_ShowCursor(SDL_ENABLE);
SDL_RemoveTimer(_timerID);
- SDL_CloseAudio();
+ closeMixer();
free(_dirtyChecksums);
free(_currentPalette);
@@ -314,7 +313,6 @@ void OSystem_SDL::quit() {
free(_mouseData);
delete _savefile;
- delete _mixer;
delete _timer;
SDL_Quit();
@@ -389,14 +387,110 @@ void OSystem_SDL::deleteMutex(MutexRef mutex) {
#pragma mark --- Audio ---
#pragma mark -
+#ifdef MIXER_DOUBLE_BUFFERING
+
+void OSystem_SDL::mixerProducerThread() {
+ byte nextSoundBuffer;
+
+ SDL_LockMutex(_soundMutex);
+ while (true) {
+ // Wait till we are allowed to produce data
+ SDL_CondWait(_soundCond, _soundMutex);
+
+ if (_soundThreadShouldQuit)
+ break;
+
+ // Generate samples and put them into the next buffer
+ nextSoundBuffer = _activeSoundBuf ^ 1;
+ _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
+
+ // Swap buffers
+ _activeSoundBuf = nextSoundBuffer;
+ }
+ SDL_UnlockMutex(_soundMutex);
+}
+
+int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) {
+ OSystem_SDL *this_ = (OSystem_SDL *)arg;
+ assert(this_);
+ this_->mixerProducerThread();
+ return 0;
+}
+
+
+void OSystem_SDL::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) {
+ _soundThreadIsRunning = false;
+ _soundThreadShouldQuit = false;
+
+ // Create mutex and condition variable
+ _soundMutex = SDL_CreateMutex();
+ _soundCond = SDL_CreateCond();
+
+ // Create two sound buffers
+ _activeSoundBuf = 0;
+ _soundBufSize = bufSize;
+ _soundBuffers[0] = (byte *)calloc(1, bufSize);
+ _soundBuffers[1] = (byte *)calloc(1, bufSize);
+
+ _soundThreadIsRunning = true;
+
+ // Finally start the thread
+ _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this);
+}
+
+void OSystem_SDL::deinitThreadedMixer() {
+ // Kill thread?? _soundThread
+
+ if (_soundThreadIsRunning) {
+ // Signal the producer thread to end, and wait for it to actually finish.
+ _soundThreadShouldQuit = true;
+ SDL_CondBroadcast(_soundCond);
+ SDL_WaitThread(_soundThread, NULL);
+
+ // Kill the mutex & cond variables.
+ // Attention: AT this point, the mixer callback must not be running
+ // anymore, else we will crash!
+ SDL_DestroyMutex(_soundMutex);
+ SDL_DestroyCond(_soundCond);
+
+ _soundThreadIsRunning = false;
+
+ free(_soundBuffers[0]);
+ free(_soundBuffers[1]);
+ }
+}
+
+
+void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
+ OSystem_SDL *this_ = (OSystem_SDL *)arg;
+ assert(this_);
+ assert(this_->_mixer);
+
+ assert((int)this_->_soundBufSize == len);
+
+ // Lock mutex, to ensure our data is not overwritten by the producer thread
+ SDL_LockMutex(this_->_soundMutex);
+
+ // Copy data from the current sound buffer
+ memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
+
+ // Unlock mutex and wake up the produced thread
+ SDL_UnlockMutex(this_->_soundMutex);
+ SDL_CondSignal(this_->_soundCond);
+}
+
+#else
+
void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
OSystem_SDL *this_ = (OSystem_SDL *)sys;
assert(this_);
+ assert(this_->_mixer);
- if (this_->_mixer)
- this_->_mixer->mixCallback(samples, len);
+ this_->_mixer->mixCallback(samples, len);
}
+#endif
+
void OSystem_SDL::setupMixer() {
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
@@ -443,10 +537,31 @@ void OSystem_SDL::setupMixer() {
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);
+
+#ifdef MIXER_DOUBLE_BUFFERING
+ initThreadedMixer(_mixer, obtained.samples * 4);
+#endif
+
+ // start the sound system
SDL_PauseAudio(0);
}
}
+void OSystem_SDL::closeMixer() {
+ if (_mixer)
+ _mixer->setReady(false);
+
+ SDL_CloseAudio();
+
+ delete _mixer;
+ _mixer = 0;
+
+#ifdef MIXER_DOUBLE_BUFFERING
+ deinitThreadedMixer();
+#endif
+
+}
+
Audio::Mixer *OSystem_SDL::getMixer() {
assert(_mixer);
return _mixer;
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 8a94a17b00..4ad588f5f5 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -51,6 +51,15 @@ namespace Common {
#define USE_OSD 1
#endif
+#if defined(MACOSX)
+// On Mac OS X, we need to double buffer the audio buffer, else anything
+// which produces sampled data with high latency (like the MT-32 emulator)
+// will sound terribly.
+// This could be enabled for more / most ports in the future, but needs some
+// testing.
+#define MIXER_DOUBLE_BUFFERING 1
+#endif
+
enum {
GFX_NORMAL = 0,
@@ -137,6 +146,8 @@ public:
virtual void setupMixer();
static void mixCallback(void *s, byte *samples, int len);
+ virtual void closeMixer();
+
virtual Audio::Mixer *getMixer();
// Poll CD status
@@ -369,6 +380,23 @@ protected:
*/
MutexRef _graphicsMutex;
+#ifdef MIXER_DOUBLE_BUFFERING
+ SDL_mutex *_soundMutex;
+ SDL_cond *_soundCond;
+ SDL_Thread *_soundThread;
+ bool _soundThreadIsRunning;
+ bool _soundThreadShouldQuit;
+
+ byte _activeSoundBuf;
+ uint _soundBufSize;
+ byte *_soundBuffers[2];
+
+ void mixerProducerThread();
+ static int SDLCALL mixerProducerThreadEntry(void *arg);
+ void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize);
+ void deinitThreadedMixer();
+#endif
+
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
@@ -377,7 +405,7 @@ protected:
Common::TimerManager *_timer;
-
+protected:
void addDirtyRgnAuto(const byte *buf);
void makeChecksums(const byte *buf);
diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
index 1e5e4dc0c8..5d85fc03a2 100644
--- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
+++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
@@ -226,28 +226,31 @@
$VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines";
# now one for each ready-for-release engine
-
+ if (0)
+ {
foreach (@WorkingEngines)
{
$VariationSets{'ALL'}{$_} = "$DefaultFeatures $_";
}
# for scumm, we need to add 2 features:
- $VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he";
-
+ #$VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he";
+ }
+
# now one for each not-ready-for-release-or-testing engine
-
+ if (0)
+ {
foreach (@TestingEngines)
{
$VariationSets{'ALL'}{"test_$_"} = "$DefaultFeatures $_";
}
-
+ }
# below here you could specify weird & experimental combinations, non-ready engines
# a small version of the saga engine, because it is so big (no tremor,mad,zlib)
- $VariationSets{'ALL'}{'saga_mini'} = "saga";
+ #$VariationSets{'ALL'}{'saga_mini'} = "saga";
# a smaller version of scumm without support for v7, v8 and HE games
- $VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
+ #$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
# maybe you feel lucky and want to test the sword engines? :P
#$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index dfeb24d825..660b0c69ed 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -33,7 +33,7 @@
#include "gui/Actions.h"
#include "gui/Key.h"
#include "gui/message.h"
-
+#include "sound/mixer_intern.h"
#include "..\..\sdl\main.cpp"
#ifdef SAMPLES_PER_SEC_8000 // the GreanSymbianMMP format cannot handle values for defines :(
@@ -42,10 +42,22 @@
#define SAMPLES_PER_SEC 16000
#endif
+#define KInputBufferLength 128
+// Symbian libc file functionality in order to provide shared file handles
+struct TSymbianFileEntry {
+ RFile iFileHandle;
+ char iInputBuffer[KInputBufferLength];
+ TInt iInputBufferLen;
+ TInt iInputPos;
+};
+
+#define FILE void
////////// extern "C" ///////////////////////////////////////////////////
namespace Symbian {
+
+
// Show a simple Symbian Info win with Msg & exit
void FatalError(const char *msg) {
TPtrC8 msgPtr((const TUint8 *)msg);
@@ -246,9 +258,9 @@ void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len)
if (!this_->_mixer)
return;
-#ifdef S60
+#if defined (S60) && !defined(S60V3)
// If not stereo then we need to downmix
- if (_channels != 2) {
+ if (this_->_mixer->_channels != 2) {
this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2);
int16 *bitmixDst = (int16 *)samples;
@@ -443,15 +455,9 @@ void OSystem_SDL_Symbian::initZones() {
}
}
-// Symbian libc file functionality in order to provide shared file handles
-struct TSymbianFileEntry {
- RFile iFileHandle;
-};
-
-#define FILE void
-
FILE* symbian_fopen(const char* name, const char* mode) {
TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
+ fileEntry->iInputPos = KErrNotFound;
if (fileEntry != NULL) {
TInt modeLen = strlen(mode);
@@ -509,9 +515,71 @@ void symbian_fclose(FILE* handle) {
}
size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- TPtr8 pointer( (unsigned char*) ptr, size*numItems);
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
+ TUint32 totsize = size*numItems;
+ TPtr8 pointer ( (unsigned char*) ptr, totsize);
+
+ // Nothing cached and we want to load at least KInputBufferLength bytes
+ if(totsize >= KInputBufferLength) {
+ TUint32 totLength = 0;
+ if(entry->iInputPos != KErrNotFound)
+ {
+ TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength);
+ pointer.Append(cacheBuffer);
+ entry->iInputPos = KErrNotFound;
+ totLength+=pointer.Length();
+ pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
+ }
- ((TSymbianFileEntry*)(handle))->iFileHandle.Read(pointer);
+ entry->iFileHandle.Read(pointer);
+ totLength+=pointer.Length();
+
+ pointer.Set((unsigned char*) ptr, totLength, totsize);
+
+ }
+ else {
+ // Nothing in buffer
+ if(entry->iInputPos == KErrNotFound) {
+ TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength);
+ entry->iFileHandle.Read(cacheBuffer);
+
+ if(cacheBuffer.Length() >= totsize) {
+ pointer.Copy(cacheBuffer.Left(totsize));
+ entry->iInputPos = totsize;
+ entry->iInputBufferLen = cacheBuffer.Length();
+ }
+ else {
+ pointer.Copy(cacheBuffer);
+ entry->iInputPos = KErrNotFound;
+ }
+
+ }
+ else {
+ TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength);
+
+ if(entry->iInputPos+totsize < entry->iInputBufferLen) {
+ pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize));
+ entry->iInputPos+=totsize;
+ }
+ else {
+
+ pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos));
+ cacheBuffer.SetLength(0);
+ entry->iFileHandle.Read(cacheBuffer);
+
+ if(cacheBuffer.Length() >= totsize-pointer.Length()) {
+ TUint32 restSize = totsize-pointer.Length();
+ pointer.Append(cacheBuffer.Left(restSize));
+ entry->iInputPos = restSize;
+ entry->iInputBufferLen = cacheBuffer.Length();
+ }
+ else {
+ pointer.Append(cacheBuffer);
+ entry->iInputPos = KErrNotFound;
+ }
+ }
+ }
+ }
return pointer.Length()/size;
}
@@ -519,6 +587,7 @@ size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle
size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
TPtrC8 pointer( (unsigned char*) ptr, size*numItems);
+ ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) {
return numItems;
}
@@ -528,12 +597,18 @@ size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handl
bool symbian_feof(FILE* handle) {
TInt pos = 0;
- if (((TSymbianFileEntry*)(handle))->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
+
+ if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
TInt size = 0;
- if (((TSymbianFileEntry*)(handle))->iFileHandle.Size(size) == KErrNone) {
- if (pos == size)
+ if (entry->iFileHandle.Size(size) == KErrNone) {
+ if(entry->iInputPos == KErrNotFound && pos == size)
return true;
+
+ if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen)
+ return true;
+
return false;
}
}
@@ -549,6 +624,7 @@ long int symbian_ftell(FILE* handle) {
}
int symbian_fseek(FILE* handle, long int offset, int whence) {
+
TSeek seekMode = ESeekStart;
TInt pos = offset;
@@ -564,6 +640,8 @@ int symbian_fseek(FILE* handle, long int offset, int whence) {
break;
}
+
+ ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
return ((TSymbianFileEntry*)(handle))->iFileHandle.Seek(seekMode, pos);
}
diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
index 2667ecb69d..9e708345c5 100644
--- a/backends/platform/wii/osystem.cpp
+++ b/backends/platform/wii/osystem.cpp
@@ -91,7 +91,7 @@ void OSystem_Wii::initBackend() {
_startup_time = gettime();
_savefile = new DefaultSaveFileManager();
- _mixer = new Audio::Mixer();
+ _mixer = new Audio::MixerImpl(this);
_timer = new DefaultTimerManager();
initGfx();
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
index 2a168fd0b7..7fbc560b1a 100644
--- a/backends/platform/wii/osystem.h
+++ b/backends/platform/wii/osystem.h
@@ -31,7 +31,7 @@
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
#include "graphics/surface.h"
-#include "sound/mixer.h"
+#include "sound/mixer_intern.h"
#include <gctypes.h>
#include <gccore.h>
@@ -96,7 +96,7 @@ private:
protected:
Common::SaveFileManager *_savefile;
- Audio::Mixer *_mixer;
+ Audio::MixerImpl *_mixer;
DefaultTimerManager *_timer;
public:
@@ -159,7 +159,6 @@ public:
virtual void deleteMutex(MutexRef mutex);
typedef void (*SoundProc)(void *param, byte *buf, int len);
- virtual int getOutputSampleRate() const;
virtual void quit();
diff --git a/backends/platform/wii/osystem_sfx.cpp b/backends/platform/wii/osystem_sfx.cpp
index 16b2f3b055..0a225e80c7 100644
--- a/backends/platform/wii/osystem_sfx.cpp
+++ b/backends/platform/wii/osystem_sfx.cpp
@@ -36,9 +36,6 @@ static bool sfx_thread_quit = false;
static u8 sb = 0;
static u8 *sound_buffer[2];
-static OSystem_Wii::SoundProc sound_proc = NULL;
-static void *proc_param = NULL;
-
static void audio_switch_buffers() {
AUDIO_StopDMA();
AUDIO_InitDMA((u32) sound_buffer[sb], SFX_THREAD_FRAG_SIZE);
@@ -48,6 +45,7 @@ static void audio_switch_buffers() {
}
static void * sfx_thread_func(void *arg) {
+ Audio::MixerImpl *mixer = (Audio::MixerImpl *) arg;
u8 next_sb;
while (true) {
@@ -57,7 +55,7 @@ static void * sfx_thread_func(void *arg) {
break;
next_sb = sb ^ 1;
- sound_proc(proc_param, sound_buffer[next_sb], SFX_THREAD_FRAG_SIZE);
+ mixer->mixCallback(sound_buffer[next_sb], SFX_THREAD_FRAG_SIZE);
DCFlushRange(sound_buffer[next_sb], SFX_THREAD_FRAG_SIZE);
sb = next_sb;
@@ -75,7 +73,7 @@ void OSystem_Wii::initSfx() {
LWP_InitQueue(&sfx_queue);
- s32 res = LWP_CreateThread(&sfx_thread, sfx_thread_func, NULL, sfx_stack,
+ s32 res = LWP_CreateThread(&sfx_thread, sfx_thread_func, _mixer, sfx_stack,
SFX_THREAD_STACKSIZE, SFX_THREAD_PRIO);
if (res) {
@@ -95,9 +93,7 @@ void OSystem_Wii::initSfx() {
DCFlushRange(sound_buffer[0], SFX_THREAD_FRAG_SIZE);
DCFlushRange(sound_buffer[1], SFX_THREAD_FRAG_SIZE);
- sound_proc = Audio::Mixer::mixCallback;
- proc_param = _mixer;
-
+ _mixer->setOutputRate(48000);
_mixer->setReady(true);
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
@@ -127,7 +123,3 @@ void OSystem_Wii::deinitSfx() {
}
}
-int OSystem_Wii::getOutputSampleRate() const {
- return 48000;
-}
-
diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp
index 86d93dcb88..c760b1f7df 100644
--- a/backends/platform/wince/missing/missing.cpp
+++ b/backends/platform/wince/missing/missing.cpp
@@ -1,8 +1,34 @@
-/* MISSING.C
- Implementation for standard and semi-standard C library calls missing in WinCE
- environment.
- by Vasyl Tsvirkunov
-*/
+/* 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$
+ *
+ */
+
+/* Original code:
+ * Implementation for standard and semi-standard C library calls missing in WinCE
+ * environment.
+ * by Vasyl Tsvirkunov
+ */
+
#include <windows.h>
#include <tchar.h>
@@ -17,19 +43,8 @@
#include "time.h"
#include "dirent.h"
-/* forward declaration */
-
-#if _WIN32_WCE < 300
-
-#define _STDAFX_H
-#include "portdefs.h"
-
-#else
-
char *strdup(const char *strSource);
-#endif
-
#ifdef __GNUC__
#define EXT_C extern "C"
#else
@@ -40,19 +55,27 @@ char *strdup(const char *strSource);
void *bsearch(const void *key, const void *base, size_t nmemb,
size_t size, int (*compar)(const void *, const void *)) {
- size_t i;
+ // Perform binary search
+ size_t lo = 0;
+ size_t hi = nmemb;
+ while (lo < hi) {
+ size_t mid = (lo + hi) / 2;
+ const void *p = ((const char *)base) + mid * size;
+ int tmp = (*compar)(key, p);
+ if (tmp < 0)
+ hi = mid;
+ else if (tmp > 0)
+ lo = mid + 1;
+ else
+ return (void *)p;
+ }
- for (i=0; i<nmemb; i++)
- if (compar(key, (void*)((size_t)base + size * i)) == 0)
- return (void*)((size_t)base + size * i);
return NULL;
}
static WIN32_FIND_DATA wfd;
-/* Very limited implementation of stat. Used by UI.C, MEMORY-P.C (latter is not critical) */
-int stat(const char *fname, struct stat *ss)
-{
+int stat(const char *fname, struct stat *ss) {
TCHAR fnameUnc[MAX_PATH+1];
HANDLE handle;
int len;
@@ -63,8 +86,7 @@ int stat(const char *fname, struct stat *ss)
/* Special case (dummy on WinCE) */
len = strlen(fname);
if (len >= 2 && fname[len-1] == '.' && fname[len-2] == '.' &&
- (len == 2 || fname[len-3] == '\\'))
- {
+ (len == 2 || fname[len-3] == '\\')) {
/* That's everything implemented so far */
memset(ss, 0, sizeof(struct stat));
ss->st_size = 1024;
@@ -74,6 +96,7 @@ int stat(const char *fname, struct stat *ss)
MultiByteToWideChar(CP_ACP, 0, fname, -1, fnameUnc, MAX_PATH);
handle = FindFirstFile(fnameUnc, &wfd);
+ FindClose(handle);
if (handle == INVALID_HANDLE_VALUE)
return -1;
else
@@ -83,20 +106,16 @@ int stat(const char *fname, struct stat *ss)
ss->st_size = wfd.nFileSizeLow;
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
ss->st_mode |= S_IFDIR;
-
- FindClose(handle);
}
return 0;
}
char cwd[MAX_PATH+1] = "";
-EXT_C char *getcwd(char *buffer, int maxlen)
-{
+EXT_C char *getcwd(char *buffer, int maxlen) {
TCHAR fileUnc[MAX_PATH+1];
char* plast;
- if (cwd[0] == 0)
- {
+ if (cwd[0] == 0) {
GetModuleFileName(NULL, fileUnc, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, fileUnc, -1, cwd, MAX_PATH, NULL, NULL);
plast = strrchr(cwd, '\\');
@@ -114,8 +133,7 @@ EXT_C char *getcwd(char *buffer, int maxlen)
#ifdef __GNUC__
#undef GetCurrentDirectory
#endif
-EXT_C void GetCurrentDirectory(int len, char *buf)
-{
+EXT_C void GetCurrentDirectory(int len, char *buf) {
getcwd(buf,len);
};
@@ -125,26 +143,22 @@ fully qualified paths refer to root folder rather
than current folder (concept not implemented in CE).
*/
#undef fopen
-EXT_C FILE *wce_fopen(const char* fname, const char* fmode)
-{
+EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
char fullname[MAX_PATH+1];
if (!fname || fname[0] == '\0')
return NULL;
- if (fname[0] != '\\' && fname[0] != '/')
- {
+ if (fname[0] != '\\' && fname[0] != '/') {
getcwd(fullname, MAX_PATH);
strncat(fullname, "\\", MAX_PATH-strlen(fullname)-1);
strncat(fullname, fname, MAX_PATH-strlen(fullname)-strlen(fname));
return fopen(fullname, fmode);
- }
- else
+ } else
return fopen(fname, fmode);
}
/* Remove file by name */
-int remove(const char* path)
-{
+int remove(const char* path) {
TCHAR pathUnc[MAX_PATH+1];
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
return !DeleteFile(pathUnc);
@@ -158,14 +172,22 @@ int _access(const char *path, int mode) {
WIN32_FIND_DATA ffd;
HANDLE h=FindFirstFile(fname, &ffd);
+ FindClose(h);
if (h == INVALID_HANDLE_VALUE)
return -1; //Can't find file
- FindClose(h);
- if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- return 0; //Always return success if target is directory and exists
+ if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) {
+ // WORKAROUND: WinCE (or the emulator) sometimes returns bogus direcotry
+ // hits for files that don't exist. Checking for the same fname twice
+ // seems to weed out those false positives.
+ HANDLE h=FindFirstFile(fname, &ffd);
+ FindClose(h);
+ if (h == INVALID_HANDLE_VALUE)
+ return -1; //Can't find file
+ return 0; //Always return success if target is directory and exists
+ }
switch (mode) {
case 00: //Check existence
return 0;
@@ -183,8 +205,7 @@ int _access(const char *path, int mode) {
#ifndef __GNUC__
/* Limited dirent implementation. Used by UI.C and DEVICES.C */
-DIR* opendir(const char* fname)
-{
+DIR* opendir(const char* fname) {
DIR* pdir;
char fnameMask[MAX_PATH+1];
TCHAR fnameUnc[MAX_PATH+1];
@@ -209,13 +230,10 @@ DIR* opendir(const char* fname)
strcpy(pdir->dd_name, fname); /* it has exactly enough space for fname and nul char */
MultiByteToWideChar(CP_ACP, 0, fnameMask, -1, fnameUnc, MAX_PATH);
- if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE)
- {
+ if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) {
free(pdir);
return NULL;
- }
- else
- {
+ } else {
WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL);
pdir->dd_dir.d_name = strdup(nameFound);
@@ -224,34 +242,25 @@ DIR* opendir(const char* fname)
return pdir;
}
-struct dirent* readdir(DIR* dir)
-{
+struct dirent* readdir(DIR* dir) {
char nameFound[MAX_PATH+1];
static struct dirent dummy;
- if (dir->dd_stat == 0)
- {
+ if (dir->dd_stat == 0) {
dummy.d_name = ".";
dummy.d_namlen = 1;
dir->dd_stat ++;
return &dummy;
- }
- else if (dir->dd_stat == 1)
- {
+ } else if (dir->dd_stat == 1) {
dummy.d_name = "..";
dummy.d_namlen = 2;
dir->dd_stat ++;
return &dummy;
- }
- else if (dir->dd_stat == 2)
- {
+ } else if (dir->dd_stat == 2) {
dir->dd_stat++;
return &dir->dd_dir;
- }
- else
- {
- if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0)
- {
+ } else {
+ if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) {
dir->dd_stat = -1;
return NULL;
}
@@ -283,12 +292,6 @@ int closedir(DIR* dir)
return 1;
}
-/* in our case unlink is the same as remove */
-int unlink(const char* path)
-{
- return remove(path);
-}
-
/* Make directory, Unix style */
void mkdir(char* dirname, int mode)
{
@@ -299,10 +302,8 @@ void mkdir(char* dirname, int mode)
if (*path == '/')
*path = '\\';
/* Run through the string and attempt creating all subdirs on the path */
- for (ptr = path+1; *ptr; ptr ++)
- {
- if (*ptr == '\\' || *ptr == '/')
- {
+ for (ptr = path+1; *ptr; ptr ++) {
+ if (*ptr == '\\' || *ptr == '/') {
*ptr = 0;
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
CreateDirectory(pathUnc, 0);
@@ -313,373 +314,40 @@ void mkdir(char* dirname, int mode)
CreateDirectory(pathUnc, 0);
}
-/* Used in DEVICES.C and UI.C for some purpose. Not critical in this port */
-int system(const char* path) { return 0; }
-
-#if 0
-
-char *tmpnam(char *string)
-{
- TCHAR pTemp[MAX_PATH+1];
- static char buffer[MAX_PATH+1];
- GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp);
- WideCharToMultiByte(CP_ACP, 0, pTemp, -1, buffer, MAX_PATH, NULL, NULL);
-
- if (string)
- {
- strcpy(string, buffer);
- return string;
- }
- else
- return buffer;
-}
-
-FILE *tmpfile()
-{
- TCHAR pTemp[MAX_PATH+1];
- if (!GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp))
- return _wfopen(pTemp, TEXT("w+b"));
- else
- return 0;
-}
-
-#endif
-
-void rewind(FILE *stream)
-{
- fseek(stream, 0, SEEK_SET);
-}
-
-
-#if _WIN32_WCE < 300
-
-int isalnum(int c) {
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9'));
-}
-
-char *_strdup(const char *strSource)
-#else
char *strdup(const char *strSource)
-#endif
{
char* buffer;
- buffer = (char*)malloc(strlen(strSource)+1);
+ size_z len = strlen(strSource)+1;
+ buffer = (char*)malloc(len);
if (buffer)
- strcpy(buffer, strSource);
+ memcpy(buffer, strSource, len);
return buffer;
}
-/* Very limited implementation of sys/time.h */
-void usleep(long usec)
-{
- long msec = usec/1000;
- if (msec <= 0)
- Sleep(0);
- else
- Sleep(msec);
-}
-
-/* This may provide for better sync mechanism */
-unsigned int clock()
-{
- return GetTickCount();
-}
-
-/* And why do people use this? */
-#if _WIN32_WCE >= 300
-void abort()
-{
- exit(1);
-}
-#endif
-
-/*
-IMHO, no project should use this one, it is not portable at all. This implementation
-at least allows some projects to work.
-*/
-char* getenv(char* name)
-{
- static char buffer[MAX_PATH+1];
- if (strcmp(name, "HOME") == 0 || strcmp(name, "HOMEDIR") == 0)
- {
- getcwd(buffer, MAX_PATH);
- return buffer;
- }
- else
- return "";
-}
-
-#if _WIN32_WCE < 300 || defined(_TEST_HPC_STDIO)
-
-void *calloc(size_t n, size_t s) {
- void *result = malloc(n * s);
- if (result)
- memset(result, 0, n * s);
-
- return result;
-}
-
-char *strpbrk(const char *s, const char *accept) {
- int i;
-
- if (!s || !accept)
- return NULL;
-
- for (i=0; i<strlen(s); i++) {
- int j;
- for (j=0; j<strlen(accept); j++)
- if (s[i] == accept[j])
- return (char*)&s[i];
- }
-
- return NULL;
-}
-
-#ifndef _TEST_HPC_STDIO
-
-int isdigit(int c) {
- return (c >='0' && c <= '9');
-}
-
-int isprint(int c) {
- return (c >= ' ' && c <= '~');
-}
-
-int isspace(int c) {
- return (c == ' ');
-}
-
-#endif
-
-#ifndef WIN32_PLATFORM_HPCPRO
-
-
-int printf(const char *format, ...) {
- // useless anyway :)
- return 0;
-}
-
-FILE *fopen(const char *path, const char *mode) {
- TCHAR tempo[MAX_PATH];
- HANDLE result;
- bool writeAccess = (mode[0] == 'W' || mode[0] == 'w');
-
- MultiByteToWideChar(CP_ACP, 0, path, strlen(path) + 1, tempo, sizeof(tempo));
-
- result = CreateFile(tempo, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL);
- if (result == INVALID_HANDLE_VALUE)
- return NULL;
- else
- return (FILE*)result;
-}
-
-FILE * _wfopen(const TCHAR *path, const TCHAR *mode) {
- HANDLE result;
- bool writeAccess = (mode[0] == 'W' || mode[0] == 'w');
- result = CreateFile(path, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL);
- if (result == INVALID_HANDLE_VALUE)
- return NULL;
- else
- return (FILE*)result;
-}
-
-FILE *_wfreopen(const TCHAR *path, const TCHAR *mode, FILE *stream) {
- fclose(stream);
- stream = _wfopen(path, mode);
- return stream;
-}
-
-int fclose(FILE *stream) {
- CloseHandle((HANDLE)stream);
- return 1;
-}
-
-int fseek(FILE *stream, long offset, int whence) {
- SetFilePointer((HANDLE)stream, offset, NULL, (whence == SEEK_CUR ? FILE_CURRENT : whence == SEEK_END ? FILE_END : FILE_BEGIN));
- return 0;
-}
-
-long ftell(FILE *stream) {
- return (SetFilePointer((HANDLE)stream, 0, NULL, FILE_CURRENT));
-}
-
-size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
- DWORD sizeWritten;
-
- WriteFile((HANDLE)stream, ptr, size * nmemb, &sizeWritten, NULL);
-
- if (size != 0)
- return sizeWritten / size;
- else
- return 0;
-}
-
-size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
- DWORD sizeRead;
-
- ReadFile((HANDLE)stream, ptr, size * nmemb, &sizeRead, NULL);
-
- if (size != 0)
- return sizeRead / size;
- else
- return 0;
-}
-
-int fgetc(FILE *stream) {
- unsigned char c;
- if (fread(&c, 1, 1, stream) != 1)
- return -1;
- else
- return c;
-}
-
-char *fgets(char *s, int size, FILE *stream) {
- int i = 0;
- char tempo[1];
-
- memset(s, 0, size);
- while (fread(tempo, 1, 1, stream)) {
- //if (tempo[0] == '\r')
- // break;
- if (tempo[0] == '\r')
- continue;
- s[i++] = tempo[0];
- if (tempo[0] == '\n')
- break;
- if (i == size)
- break;
- }
- if (!i)
- return NULL;
- else
- return s;
-}
-
-int feof(FILE *stream) {
- DWORD fileSize;
- DWORD filePos;
- fileSize = GetFileSize((HANDLE)stream, NULL);
- filePos = SetFilePointer((HANDLE)stream, 0, 0, FILE_CURRENT);
- return (filePos == 0xFFFFFFFF || filePos > (fileSize - 1));
-}
-
-int ferror(FILE *stream) {
- return 0; // FIXME !
-}
-
-int fprintf(FILE *stream, const char *format, ...) {
- char buf[1024];
- va_list va;
-
- va_start(va, format);
- vsnprintf(buf, 1024, format, va);
- va_end(va);
-
- if (buf[strlen(buf) - 1] == '\n') {
- int i = strlen(buf) - 1;
- buf[i] = '\r';
- buf[i + 1] = '\n';
- buf[i + 2] = 0;
- }
-
- return fwrite(buf, 1, strlen(buf), stream);
-}
-
-FILE* _getstdfilex(int) {
- return NULL;
-}
-
-void clearerr(FILE *stream) {
-}
-
-int fflush(FILE *stream) {
- return 0;
-}
-
-#endif
-
-int stricmp( const char *string1, const char *string2 ) {
- char src[4096];
- char dest[4096];
- int i;
-
- for (i=0; i<strlen(string1); i++)
- if (string1[i] >= 'A' && string1[i] <= 'Z')
- src[i] = string1[i] + 32;
- else
- src[i] = string1[i];
- src[i] = 0;
-
- for (i=0; i<strlen(string2); i++)
- if (string2[i] >= 'A' && string2[i] <= 'Z')
- dest[i] = string2[i] + 32;
- else
- dest[i] = string2[i];
- dest[i] = 0;
-
- return strcmp(src, dest);
-}
-
-char *strrchr(const char *s, int c) {
- int i;
-
- for (i = strlen(s) - 1; i > 0; i--)
- if (s[i] == c)
- return (char*)(s + i);
-
- return NULL;
-}
-
-long int strtol(const char *nptr, char **endptr, int base) {
- // not correct but that's all we are using
-
- long int result;
- sscanf(nptr, "%ld", &result);
- return result;
-}
-
-
-#endif
-
-
// gcc build only functions follow
#else // defined(__GNUC__)
#ifndef __MINGW32CE__
-int islower(int c)
-{
+int islower(int c) {
return (c>='a' && c<='z');
}
-int isspace(int c)
-{
+int isspace(int c) {
return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v');
}
-int isalpha(int c)
-{
- return (islower(c) || (c>='A' && c<='Z'));
+int isalpha(int c) {
+ return ((c>='a' && c<='z') || (c>='A' && c<='Z'));
}
-int isalnum(int c)
-{
- return (isalpha(c) || (c>='0' && c<='9'));
-}
-
-int isprint(int c)
-{
- static char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
- int i = 0, flag = 0;
- while ((punct[i] != 0) && (flag = (punct[i] != c)))
- i++;
- return (isalnum(c) || flag);
+int isalnum(int c) {
+ return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'));
}
-extern "C" int atexit(void (*function)(void))
-{
- return 0;
+int isprint(int c) {
+ //static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
+ //return (isalnum(c) || strchr(punct, c));
+ return (32 <= c && c <= 126); // based on BSD manpage
}
#endif
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index ec6d6842c0..21bc56e441 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -120,7 +120,7 @@ Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
Common::StringList results;
Common::String search(pattern);
- if (savePath.lookupFile(savefiles, search, false, true)) {
+ if (savePath.lookupFile(savefiles, search, false, true, 0)) {
for (FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
results.push_back(file->getName());
}
diff --git a/base/game.cpp b/base/game.cpp
index 9628543672..e65c891dc7 100644
--- a/base/game.cpp
+++ b/base/game.cpp
@@ -32,10 +32,10 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
const PlainGameDescriptor *g = list;
while (g->gameid) {
if (0 == scumm_stricmp(gameid, g->gameid))
- break;
+ return g;
g++;
}
- return g;
+ return 0;
}
void GameDescriptor::updateDesc(const char *extra) {
diff --git a/base/game.h b/base/game.h
index 18d7967388..b068c300ce 100644
--- a/base/game.h
+++ b/base/game.h
@@ -48,7 +48,7 @@ struct PlainGameDescriptor {
/**
* Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor
* matching the given gameid. If not match is found return 0.
- * The end of the list marked by a PlainGameDescriptor with gameid equal to 0.
+ * The end of the list must marked by a PlainGameDescriptor with gameid equal to 0.
*/
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list);
diff --git a/base/internal_version.h b/base/internal_version.h
index 069c20b4c9..c867532dd9 100644
--- a/base/internal_version.h
+++ b/base/internal_version.h
@@ -1 +1 @@
-#define SCUMMVM_VERSION "0.12.0svn"
+#define SCUMMVM_VERSION "0.13.0svn"
diff --git a/base/plugins.h b/base/plugins.h
index 9d3ce97c3b..02116f6433 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -81,17 +81,11 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
#define STATIC_PLUGIN 1
#define DYNAMIC_PLUGIN 2
-// Note: The spaces around ENABLE_##ID have been added on purpose for
-// MSVC. For some reason, MSVC tries to add the parenthesis after
-// ENABLE_##ID to the check, thus making it false all the time.
-// Please do NOT remove them, otherwise no engine plugins will be
-// registered under MSVC
-
#define PLUGIN_ENABLED_STATIC(ID) \
- (defined( ENABLE_##ID ) && !PLUGIN_ENABLED_DYNAMIC(ID))
+ (ENABLE_##ID && !PLUGIN_ENABLED_DYNAMIC(ID))
#define PLUGIN_ENABLED_DYNAMIC(ID) \
- (defined( ENABLE_##ID ) && (ENABLE_##ID == DYNAMIC_PLUGIN) && defined(DYNAMIC_MODULES))
+ (ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES)
/**
* REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 5afbbad4ae..59855cf6c9 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -176,7 +176,6 @@ void ConfigManager::loadFile(const String &filename) {
if (!cfg_file.open(filename)) {
printf("Creating configuration file: %s\n", filename.c_str());
} else {
- char buf[MAXLINELEN];
String domain;
String comment;
int lineno = 0;
@@ -184,20 +183,28 @@ void ConfigManager::loadFile(const String &filename) {
// TODO: Detect if a domain occurs multiple times (or likewise, if
// a key occurs multiple times inside one domain).
- while (!cfg_file.eof()) {
+ while (!cfg_file.eof() && !cfg_file.ioFailed()) {
lineno++;
- if (!cfg_file.readLine(buf, MAXLINELEN))
- break;
- if (buf[0] == '#') {
+ // Read a line
+ String line;
+ while (line.lastChar() != '\n') {
+ char buf[MAXLINELEN];
+ if (!cfg_file.readLine_NEW(buf, MAXLINELEN))
+ break;
+ line += buf;
+ }
+
+ if (line.size() == 0) {
+ // Do nothing
+ } else if (line[0] == '#') {
// Accumulate comments here. Once we encounter either the start
// of a new domain, or a key-value-pair, we associate the value
// of the 'comment' variable with that entity.
- comment += buf;
- comment += '\n';
- } else if (buf[0] == '[') {
+ comment += line;
+ } else if (line[0] == '[') {
// It's a new domain which begins here.
- char *p = buf + 1;
+ const char *p = line.c_str() + 1;
// Get the domain name, and check whether it's valid (that
// is, verify that it only consists of alphanumerics,
// dashes and underscores).
@@ -209,8 +216,8 @@ void ConfigManager::loadFile(const String &filename) {
error("Config file buggy: missing ] in line %d", lineno);
break;
case ']':
- *p = 0;
- domain = buf + 1;
+ domain = String(line.c_str() + 1, p - (line.c_str() + 1));
+ //domain = String(line.c_str() + 1, p); // TODO: Pending Common::String changes
break;
default:
error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);
@@ -226,10 +233,14 @@ void ConfigManager::loadFile(const String &filename) {
_domainSaveOrder.push_back(domain);
} else {
- // Skip leading & trailing whitespaces
- char *t = rtrim(ltrim(buf));
-
- // Skip empty lines
+ // This line should be a line with a 'key=value' pair, or an empty one.
+
+ // Skip leading whitespaces
+ const char *t = line.c_str();
+ while (isspace(*t))
+ t++;
+
+ // Skip empty lines / lines with only whitespace
if (*t == 0)
continue;
@@ -238,13 +249,30 @@ void ConfigManager::loadFile(const String &filename) {
error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);
}
- // Split string at '=' into 'key' and 'value'.
- char *p = strchr(t, '=');
+ // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
+ const char *p = strchr(t, '=');
if (!p)
error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
- *p = 0;
- String key = rtrim(t);
- String value = ltrim(p + 1);
+
+ // Trim spaces before the '=' to obtain the key
+ const char *p2 = p;
+ while (p2 > t && isspace(*(p2-1)))
+ p2--;
+ String key(t, p2 - t);
+
+ // Skip spaces after the '='
+ t = p + 1;
+ while (isspace(*t))
+ t++;
+
+ // Trim trailing spaces
+ p2 = t + strlen(t);
+ while (p2 > t && isspace(*(p2-1)))
+ p2--;
+
+ String value(t, p2 - t);
+
+ // Finally, store the key/value pair in the active domain
set(key, value, domain);
// Store comment
diff --git a/common/file.cpp b/common/file.cpp
index 386777e2c5..a1ea1aff77 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -452,10 +452,12 @@ bool File::isOpen() const {
}
bool File::ioFailed() const {
+ // TODO/FIXME: Just use ferror() here?
return _ioFailed != 0;
}
void File::clearIOFailed() {
+ // TODO/FIXME: Just use clearerr() here?
_ioFailed = false;
}
diff --git a/common/str.cpp b/common/str.cpp
index ad48ef6087..a2e6e0c66d 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -43,32 +43,43 @@ static int computeCapacity(int len) {
return ((len + 32 - 1) & ~0x1F) - 1;
}
-String::String(const char *str, uint32 len)
-: _len(0), _str(_storage) {
+String::String(const char *str) : _len(0), _str(_storage) {
+ if (str == 0) {
+ _storage[0] = 0;
+ _len = 0;
+ } else
+ initWithCStr(str, strlen(str));
+}
+
+String::String(const char *str, uint32 len) : _len(0), _str(_storage) {
+ initWithCStr(str, len);
+}
+
+String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) {
+ assert(endP >= beginP);
+ initWithCStr(beginP, endP - beginP);
+}
+
+void String::initWithCStr(const char *str, uint32 len) {
+ assert(str);
// Init _storage member explicitly (ie. without calling its constructor)
// for GCC 2.95.x compatibility (see also tracker item #1602879).
_storage[0] = 0;
- if (str && *str) {
- const uint32 tmp = strlen(str);
- assert(len <= tmp);
- if (len <= 0)
- len = tmp;
- _len = len;
-
- if (len >= _builtinCapacity) {
- // Not enough internal storage, so allocate more
- _extern._capacity = computeCapacity(len);
- _extern._refCount = 0;
- _str = (char *)malloc(_extern._capacity+1);
- assert(_str != 0);
- }
-
- // Copy the string into the storage area
- memcpy(_str, str, len);
- _str[len] = 0;
+ _len = len;
+
+ if (len >= _builtinCapacity) {
+ // Not enough internal storage, so allocate more
+ _extern._capacity = computeCapacity(len);
+ _extern._refCount = 0;
+ _str = (char *)malloc(_extern._capacity+1);
+ assert(_str != 0);
}
+
+ // Copy the string into the storage area
+ memmove(_str, str, len);
+ _str[len] = 0;
}
String::String(const String &str)
@@ -91,6 +102,8 @@ String::String(char c)
_storage[0] = c;
_storage[1] = 0;
+ // TODO/FIXME: There is no reason for the following check -- we *do*
+ // allow strings to contain 0 bytes!
_len = (c == 0) ? 0 : 1;
}
@@ -130,11 +143,14 @@ String& String::operator =(const char *str) {
uint32 len = strlen(str);
ensureCapacity(len, false);
_len = len;
- memcpy(_str, str, len + 1);
+ memmove(_str, str, len + 1);
return *this;
}
String &String::operator =(const String &str) {
+ if (&str == this)
+ return *this;
+
if (str.isStorageIntern()) {
decRefCount(_extern._refCount);
_len = str._len;
diff --git a/common/str.h b/common/str.h
index a92ec34fff..ae9cb992b6 100644
--- a/common/str.h
+++ b/common/str.h
@@ -96,10 +96,24 @@ public:
static const char *emptyString;
#endif
+ /** Construct a new empty string. */
String() : _len(0), _str(_storage) { _storage[0] = 0; }
- String(const char *str, uint32 len = 0);
+
+ /** Construct a new string from the given NULL-terminated C string. */
+ String(const char *str);
+
+ /** Construct a new string containing exactly len characters read from address str. */
+ String(const char *str, uint32 len);
+
+ /** Construct a new string containing the characters between beginP (including) and endP (excluding). */
+ String(const char *beginP, const char *endP);
+
+ /** Construct a copy of the given string. */
String(const String &str);
+
+ /** Construct a string consisting of the given character. */
String(char c);
+
~String();
String &operator =(const char *str);
@@ -162,7 +176,7 @@ public:
void toLowercase();
void toUppercase();
-
+
uint hash() const;
public:
@@ -189,6 +203,7 @@ protected:
void ensureCapacity(uint32 new_len, bool keep_old);
void incRefCount() const;
void decRefCount(int *oldRefCount);
+ void initWithCStr(const char *str, uint32 len);
};
// Append two strings to form a new (temp) string
diff --git a/common/stream.cpp b/common/stream.cpp
index ab9804d7b6..61166fd451 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -148,6 +148,61 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
return buf;
}
+char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
+ assert(buf != 0 && bufSize > 1);
+ char *p = buf;
+ size_t len = 0;
+ char c = 0;
+
+ // If end-of-file occurs before any characters are read, return NULL
+ // and the buffer contents remain unchanged.
+ if (eos() || ioFailed()) {
+ return 0;
+ }
+
+ // Loop as long as the stream has not ended, there is still free
+ // space in the buffer, and the line has not ended
+ while (!eos() && len + 1 < bufSize && c != LF) {
+ c = readByte();
+
+ // If end-of-file occurs before any characters are read, return
+ // NULL and the buffer contents remain unchanged. If an error
+ /// occurs, return NULL and the buffer contents are indeterminate.
+ if (ioFailed() || (len == 0 && eos()))
+ return 0;
+
+ // Check for CR or CR/LF
+ // * DOS and Windows use CRLF line breaks
+ // * Unix and OS X use LF line breaks
+ // * Macintosh before OS X used CR line breaks
+ if (c == CR) {
+ // Look at the next char -- is it LF? If not, seek back
+ c = readByte();
+ if (c != LF && !eos())
+ seek(-1, SEEK_CUR);
+ // Treat CR & CR/LF as plain LF
+ c = LF;
+ }
+
+ *p++ = c;
+ len++;
+ }
+
+ // FIXME:
+ // This should fix a bug while using readLine with Common::File
+ // it seems that it sets the eos flag after an invalid read
+ // and at the same time the ioFailed flag
+ // the config file parser fails out of that reason for the new themes
+ if (eos()) {
+ clearIOFailed();
+ }
+
+ // We always terminate the buffer if no error occured
+ *p = 0;
+ return buf;
+}
+
+
uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
dataSize = MIN(dataSize, _end - _pos);
diff --git a/common/stream.h b/common/stream.h
index 313a695e82..4cf5fae114 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -304,13 +304,40 @@ public:
* Read one line of text from a CR or CR/LF terminated plain text file.
* This method is a rough analog of the (f)gets function.
*
+ * @bug A main difference (and flaw) in this function is that there is no
+ * way to detect that a line exceeeds the length of the buffer.
+ * Code which needs this should use the new readLine_NEW() method instead.
+ *
* @param buf the buffer to store into
* @param bufSize the size of the buffer
* @return a pointer to the read string, or NULL if an error occurred
+ *
* @note The line terminator (CR or CR/LF) is stripped and not inserted
* into the buffer.
*/
virtual char *readLine(char *buf, size_t bufSize);
+
+ /**
+ * Reads at most one less than the number of characters specified
+ * by bufSize from the and stores them in the string buf. Reading
+ * stops when the end of a line is reached (CR, CR/LF or LF), at
+ * end-of-file or error. The newline, if any, is retained (CR and
+ * CR/LF are translated to LF = 0xA = '\n'). If any characters are
+ * read and there is no error, a `\0' character is appended to end
+ * the string.
+ *
+ * Upon successful completion, return a pointer to the string. If
+ * end-of-file occurs before any characters are read, returns NULL
+ * and the buffer contents remain unchanged. If an error occurs,
+ * returns NULL and the buffer contents are indeterminate.
+ * This method does not distinguish between end-of-file and error;
+ * callers muse use ioFailed() or eos() to determine which occurred.
+ *
+ * @param buf the buffer to store into
+ * @param bufSize the size of the buffer
+ * @return a pointer to the read string, or NULL if an error occurred
+ */
+ virtual char *readLine_NEW(char *s, size_t bufSize);
};
/**
diff --git a/configure b/configure
index 3ce53e9d17..8c3b45a0dc 100755
--- a/configure
+++ b/configure
@@ -129,10 +129,10 @@ _srcdir=`dirname $0`
if type mktemp > /dev/null 2>&1 ; then
TMPO=`mktemp /tmp/scummvm-conf.XXXXXXXXXX`
else
- TMPO=${_srcdir}/scummvm-conf
+ TMPO=scummvm-conf
fi
TMPC=${TMPO}.cpp
-TMPLOG=${_srcdir}/config.log
+TMPLOG=config.log
# For cross compiling
_host=""
@@ -741,6 +741,10 @@ for ac_option in $@; do
--enable-release)
DEBFLAGS="-O2 -Wuninitialized"
;;
+ --enable-profiling)
+ CXXFLAGS="$CXXFLAGS -pg"
+ LDFLAGS="$LDFLAGS -pg"
+ ;;
--with-sdl-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
_sdlpath="$arg:$arg/bin"
diff --git a/dists/msvc7/parallaction.vcproj b/dists/msvc7/parallaction.vcproj
index 79ac169995..9dfb575c6b 100644
--- a/dists/msvc7/parallaction.vcproj
+++ b/dists/msvc7/parallaction.vcproj
@@ -97,6 +97,9 @@
</Configurations>
<Files>
<File
+ RelativePath="..\..\engines\parallaction\balloons.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\callables_br.cpp">
</File>
<File
@@ -124,6 +127,9 @@
RelativePath="..\..\engines\parallaction\disk_ns.cpp">
</File>
<File
+ RelativePath="..\..\engines\parallaction\exec.h">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\exec_br.cpp">
</File>
<File
diff --git a/dists/msvc71/parallaction.vcproj b/dists/msvc71/parallaction.vcproj
index 440e7123e8..6030b030a8 100644
--- a/dists/msvc71/parallaction.vcproj
+++ b/dists/msvc71/parallaction.vcproj
@@ -111,6 +111,9 @@
</References>
<Files>
<File
+ RelativePath="..\..\engines\parallaction\balloons.cpp">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\callables_br.cpp">
</File>
<File
@@ -138,6 +141,9 @@
RelativePath="..\..\engines\parallaction\disk_ns.cpp">
</File>
<File
+ RelativePath="..\..\engines\parallaction\exec.h">
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\exec_br.cpp">
</File>
<File
diff --git a/dists/msvc8/parallaction.vcproj b/dists/msvc8/parallaction.vcproj
index 21a6d3bab3..c5721bd30f 100644
--- a/dists/msvc8/parallaction.vcproj
+++ b/dists/msvc8/parallaction.vcproj
@@ -161,6 +161,10 @@
</References>
<Files>
<File
+ RelativePath="..\..\engines\parallaction\balloons.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\callables_br.cpp"
>
</File>
@@ -197,6 +201,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\parallaction\exec.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\exec_br.cpp"
>
</File>
diff --git a/dists/msvc9/parallaction.vcproj b/dists/msvc9/parallaction.vcproj
index bdc93860f9..d3117b6b0c 100644
--- a/dists/msvc9/parallaction.vcproj
+++ b/dists/msvc9/parallaction.vcproj
@@ -162,6 +162,10 @@
</References>
<Files>
<File
+ RelativePath="..\..\engines\parallaction\balloons.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\callables_br.cpp"
>
</File>
@@ -198,6 +202,10 @@
>
</File>
<File
+ RelativePath="..\..\engines\parallaction\exec.h"
+ >
+ </File>
+ <File
RelativePath="..\..\engines\parallaction\exec_br.cpp"
>
</File>
diff --git a/dists/redhat/scummvm.spec b/dists/redhat/scummvm.spec
index efde789ce3..1d3b2bce64 100644
--- a/dists/redhat/scummvm.spec
+++ b/dists/redhat/scummvm.spec
@@ -7,7 +7,7 @@
# Prologue information
#------------------------------------------------------------------------------
Name : scummvm
-Version : 0.12.0svn
+Version : 0.13.0svn
Release : 1
Summary : Graphic adventure game interpreter
Group : Interpreters
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 73763a1216..0fb2b87071 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -7,8 +7,8 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico"
#endif
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,12,0,0
- PRODUCTVERSION 0,12,0,0
+ FILEVERSION 0,13,0,0
+ PRODUCTVERSION 0,13,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -25,13 +25,13 @@ BEGIN
BEGIN
VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0"
VALUE "FileDescription", "http://www.scummvm.org/\0"
- VALUE "FileVersion", "0.12.0svn\0"
+ VALUE "FileVersion", "0.13.0svn\0"
VALUE "InternalName", "scummvm\0"
VALUE "LegalCopyright", "Copyright © 2001-2007 The ScummVM Team\0"
VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0"
VALUE "OriginalFilename", "scummvm.exe\0"
VALUE "ProductName", "ScummVM\0"
- VALUE "ProductVersion", "0.12.0svn\0"
+ VALUE "ProductVersion", "0.13.0svn\0"
END
END
BLOCK "VarFileInfo"
diff --git a/dists/slackware/scummvm.SlackBuild b/dists/slackware/scummvm.SlackBuild
index 415ee4c867..6ed0ed6e57 100755
--- a/dists/slackware/scummvm.SlackBuild
+++ b/dists/slackware/scummvm.SlackBuild
@@ -8,7 +8,7 @@ if [ "$TMP" = "" ]; then
fi
PKG=$TMP/package-scummvm
-VERSION=0.12.0svn
+VERSION=0.13.0svn
ARCH=i486
BUILD=1
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index 74a0b026e9..8ad5487b35 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -1075,6 +1075,8 @@ protected:
virtual void drawImage(VC10_state *state);
void drawBackGroundImage(VC10_state *state);
void drawVertImage(VC10_state *state);
+ void drawVertImageCompressed(VC10_state *state);
+ void drawVertImageUncompressed(VC10_state *state);
void setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height);
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index c014413bdc..9a3962ea21 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -744,10 +744,6 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
}
void AGOSEngine::drawBackGroundImage(VC10_state *state) {
- const byte *src;
- byte *dst;
- uint h, i;
-
state->width = _screenWidth;
if (_window3Flag == 1) {
state->width = 0;
@@ -755,15 +751,19 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
state->y_skip = 0;
}
- src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
- dst = state->surf_addr;
+ const byte* src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
+ byte* dst = state->surf_addr;
state->draw_width *= 2;
- h = state->draw_height;
+ uint h = state->draw_height;
+ const uint w = state->draw_width;
+ const byte paletteMod = state->paletteMod;
do {
- for (i = 0; i != state->draw_width; i++)
- dst[i] = src[i] + state->paletteMod;
+ for (uint i = 0; i != w; i+=2) {
+ dst[i] = src[i] + paletteMod;
+ dst[i+1] = src[i+1] + paletteMod;
+ }
dst += state->surf_pitch;
src += state->width;
} while (--h);
@@ -771,63 +771,86 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
void AGOSEngine::drawVertImage(VC10_state *state) {
if (state->flags & kDFCompressed) {
- uint w, h;
- byte *src, *dst, *dstPtr;
+ drawVertImageCompressed(state);
+ } else {
+ drawVertImageUncompressed(state);
+ }
+}
- state->x_skip *= 4; /* reached */
+void AGOSEngine::drawVertImageUncompressed(VC10_state *state) {
+ assert ((state->flags & kDFCompressed) == 0) ;
- state->dl = state->width;
- state->dh = state->height;
+ const byte *src;
+ byte *dst;
+ uint count;
- vc10_skip_cols(state);
+ src = state->srcPtr + (state->width * state->y_skip) * 8;
+ dst = state->surf_addr;
+ state->x_skip *= 4;
- dstPtr = state->surf_addr;
- if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
- dstPtr += vcReadVar(252);
- }
- w = 0;
- do {
+ do {
+ for (count = 0; count != state->draw_width; count++) {
byte color;
+ color = (src[count + state->x_skip] / 16) + state->paletteMod;
+ if ((state->flags & kDFNonTrans) || color)
+ dst[count * 2] = color | state->palette;
+ color = (src[count + state->x_skip] & 15) + state->paletteMod;
+ if ((state->flags & kDFNonTrans) || color)
+ dst[count * 2 + 1] = color | state->palette;
+ }
+ dst += state->surf_pitch;
+ src += state->width * 8;
+ } while (--state->draw_height);
+}
- src = vc10_depackColumn(state);
- dst = dstPtr;
+void AGOSEngine::drawVertImageCompressed(VC10_state *state) {
+ assert (state->flags & kDFCompressed) ;
+ uint w, h;
+
+ state->x_skip *= 4; /* reached */
- h = 0;
+ state->dl = state->width;
+ state->dh = state->height;
+
+ vc10_skip_cols(state);
+
+ byte *dstPtr = state->surf_addr;
+ if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
+ dstPtr += vcReadVar(252);
+ }
+ w = 0;
+ do {
+ byte color;
+
+ const byte *src = vc10_depackColumn(state);
+ byte *dst = dstPtr;
+
+ h = 0;
+ if (state->flags & kDFNonTrans) {
+ do {
+ byte colors = *src;
+ color = (colors / 16);
+ dst[0] = color | state->palette;
+ color = (colors & 15);
+ dst[1] = color | state->palette;
+ dst += state->surf_pitch;
+ src++;
+ } while (++h != state->draw_height);
+ } else {
do {
- color = (*src / 16);
- if ((state->flags & kDFNonTrans) || color != 0)
+ byte colors = *src;
+ color = (colors / 16);
+ if (color != 0)
dst[0] = color | state->palette;
- color = (*src & 15);
- if ((state->flags & kDFNonTrans) || color != 0)
+ color = (colors & 15);
+ if (color != 0)
dst[1] = color | state->palette;
dst += state->surf_pitch;
src++;
} while (++h != state->draw_height);
- dstPtr += 2;
- } while (++w != state->draw_width);
- } else {
- const byte *src;
- byte *dst;
- uint count;
-
- src = state->srcPtr + (state->width * state->y_skip) * 8;
- dst = state->surf_addr;
- state->x_skip *= 4;
-
- do {
- for (count = 0; count != state->draw_width; count++) {
- byte color;
- color = (src[count + state->x_skip] / 16) + state->paletteMod;
- if ((state->flags & kDFNonTrans) || color)
- dst[count * 2] = color | state->palette;
- color = (src[count + state->x_skip] & 15) + state->paletteMod;
- if ((state->flags & kDFNonTrans) || color)
- dst[count * 2 + 1] = color | state->palette;
- }
- dst += state->surf_pitch;
- src += state->width * 8;
- } while (--state->draw_height);
- }
+ }
+ dstPtr += 2;
+ } while (++w != state->draw_width);
}
void AGOSEngine::drawImage(VC10_state *state) {
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 710840c17e..06f2dfd982 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -94,6 +94,7 @@ public:
Common::StringList _volumeResourceFiles;
StringPtrHashMap _volumeEntriesMap;
+ TextHandler _textHandler;
private:
void initialize(void);
@@ -107,6 +108,7 @@ private:
extern CineEngine *g_cine;
#define BOOT_PRC_NAME "AUTO00.PRC"
+#define COPY_PROT_FAIL_PRC_NAME "L201.ANI"
enum {
VAR_MOUSE_X_MODE = 253,
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 47446f2410..1f868ccb75 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -337,7 +337,7 @@ int FWRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
idx = fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y);
+ drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y);
x += width + 1;
}
@@ -938,7 +938,7 @@ int OSRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
idx = fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
+ drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
x += width + 1;
}
@@ -969,6 +969,7 @@ void OSRenderer::drawBackground() {
/*! \brief Draw one overlay
* \param it Overlay info
+ * \todo Add handling of type 22 overlays
*/
void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
int len;
@@ -979,6 +980,9 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
switch (it->type) {
// color sprite
case 0:
+ if (objectTable[it->objIdx].frame < 0) {
+ break;
+ }
sprite = animDataTable + objectTable[it->objIdx].frame;
len = sprite->_realWidth * sprite->_height;
mask = new byte[len];
@@ -988,6 +992,13 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
delete[] mask;
break;
+ // bitmap
+ case 4:
+ if (objectTable[it->objIdx].frame >= 0) {
+ FWRenderer::renderOverlay(it);
+ }
+ break;
+
// masked background
case 20:
assert(it->objIdx < NUM_MAX_OBJECT);
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index 402c97b1a6..27b1044620 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -40,8 +40,9 @@ ScriptList objectScripts;
/*! \todo Is script size of 0 valid?
* \todo Fix script dump code
+ * @return Was the loading successful?
*/
-void loadPrc(const char *pPrcName) {
+bool loadPrc(const char *pPrcName) {
byte i;
uint16 numScripts;
byte *scriptPtr, *dataPtr;
@@ -52,9 +53,9 @@ void loadPrc(const char *pPrcName) {
scriptTable.clear();
// This is copy protection. Used to hang the machine
- if (!scumm_stricmp(pPrcName, "L201.ANI")) {
+ if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
exitEngine = 1;
- return;
+ return false;
}
checkDataDisk(-1);
@@ -107,6 +108,8 @@ void loadPrc(const char *pPrcName) {
}
}
#endif
+
+ return true;
}
} // End of namespace Cine
diff --git a/engines/cine/prc.h b/engines/cine/prc.h
index f5129d28b1..05bb240372 100644
--- a/engines/cine/prc.h
+++ b/engines/cine/prc.h
@@ -31,7 +31,7 @@ namespace Cine {
extern ScriptList globalScripts;
extern ScriptList objectScripts;
-void loadPrc(const char *pPrcName);
+bool loadPrc(const char *pPrcName);
} // End of namespace Cine
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 148e673095..54a4976000 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -1019,6 +1019,20 @@ int FWScript::o1_divVar() {
}
int FWScript::o1_compareVar() {
+ // WORKAROUND: A workaround for a script bug in script file CODE2.PRC
+ // in at least some of the Amiga and Atari ST versions of Future Wars.
+ // Fixes bug #2016647 (FW: crash with italian amiga version). A local
+ // variable 251 is compared against value 0 although it's quite apparent
+ // from the context in the script that instead global variable 251 should
+ // be compared against value 0. So looks like someone made a typo when
+ // making the scripts. Therefore we change that particular comparison
+ // from using the local variable 251 to using the global variable 251.
+ if (g_cine->getGameType() == Cine::GType_FW && scumm_stricmp(currentPrcName, "CODE2.PRC") == 0 &&
+ (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) &&
+ _script.getByte(_pos) == 251 && _script.getByte(_pos + 1) == 0 && _script.getWord(_pos + 2) == 0) {
+ return o1_compareGlobalVar();
+ }
+
byte varIdx = getNextByte();
byte varType = getNextByte();
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 9b4b83f420..e4fd334926 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -31,8 +31,6 @@ namespace Cine {
byte *textDataPtr;
-byte textTable[256][2][16 * 8];
-
const char **failureMessages;
const CommandeType *defaultActionCommand;
const CommandeType *systemMenu;
@@ -77,14 +75,14 @@ void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
loadRelatedPalette(pFileName);
for (i = 0; i < numCharacters; i++) {
- gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 16, 8);
- generateMask(textTable[i][0], textTable[i][1], 16 * 8, 0);
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 16, 8);
+ generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 16 * 8, 0);
tempBuffer += dataSize;
}
} else {
for (i = 0; i < 90; i++) {
- gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 8, 8);
- generateMask(textTable[i][0], textTable[i][1], 8 * 8, 0);
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 8, 8);
+ generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 8 * 8, 0);
tempBuffer += 0x40;
}
}
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index ae82832aea..f471c3c49e 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -34,7 +34,10 @@ namespace Cine {
typedef char CommandeType[20];
extern byte *textDataPtr;
-extern byte textTable[256][2][16 * 8];
+
+struct TextHandler {
+ byte textTable[256][2][16 * 8];
+};
extern const char **failureMessages;
extern const CommandeType *defaultActionCommand;
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 4b5d4efe13..ab2fa645c7 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -466,17 +466,26 @@ bool CineEngine::makeLoad(char *saveName) {
broken = brokenSave(*fHandle);
+ // At savefile position 0x0000:
currentDisk = fHandle->readUint16BE();
+ // At 0x0002:
fHandle->read(currentPartName, 13);
+ // At 0x000F:
fHandle->read(currentDatName, 13);
+ // At 0x001C:
saveVar2 = fHandle->readSint16BE();
+ // At 0x001E:
fHandle->read(currentPrcName, 13);
+ // At 0x002B:
fHandle->read(currentRelName, 13);
+ // At 0x0038:
fHandle->read(currentMsgName, 13);
+ // At 0x0045:
fHandle->read(bgName, 13);
+ // At 0x0052:
fHandle->read(currentCtName, 13);
checkDataDisk(currentDisk);
@@ -501,52 +510,84 @@ bool CineEngine::makeLoad(char *saveName) {
loadCtFW(currentCtName);
}
+ // At 0x005F:
fHandle->readUint16BE();
+ // At 0x0061:
fHandle->readUint16BE();
+ // At 0x0063:
for (i = 0; i < 255; i++) {
+ // At 0x0063 + i * 32 + 0:
objectTable[i].x = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 2:
objectTable[i].y = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 4:
objectTable[i].mask = fHandle->readUint16BE();
+ // At 0x0063 + i * 32 + 6:
objectTable[i].frame = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 8:
objectTable[i].costume = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 10:
fHandle->read(objectTable[i].name, 20);
+ // At 0x0063 + i * 32 + 30:
objectTable[i].part = fHandle->readUint16BE();
}
+ // At 0x2043 (i.e. 0x0063 + 255 * 32):
renderer->restorePalette(*fHandle);
+ // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2):
globalVars.load(*fHandle, NUM_MAX_VAR - 1);
+ // At 0x2281 (i.e. 0x2083 + 255 * 2):
for (i = 0; i < 16; i++) {
+ // At 0x2281 + i * 2:
zoneData[i] = fHandle->readUint16BE();
}
+ // At 0x22A1 (i.e. 0x2281 + 16 * 2):
for (i = 0; i < 4; i++) {
+ // At 0x22A1 + i * 2:
commandVar3[i] = fHandle->readUint16BE();
}
+ // At 0x22A9 (i.e. 0x22A1 + 4 * 2):
fHandle->read(commandBuffer, 0x50);
renderer->setCommand(commandBuffer);
+ // At 0x22F9 (i.e. 0x22A9 + 0x50):
renderer->_cmdY = fHandle->readUint16BE();
+ // At 0x22FB:
bgVar0 = fHandle->readUint16BE();
+ // At 0x22FD:
allowPlayerInput = fHandle->readUint16BE();
+ // At 0x22FF:
playerCommand = fHandle->readSint16BE();
+ // At 0x2301:
commandVar1 = fHandle->readSint16BE();
+ // At 0x2303:
isDrawCommandEnabled = fHandle->readUint16BE();
+ // At 0x2305:
var5 = fHandle->readUint16BE();
+ // At 0x2307:
var4 = fHandle->readUint16BE();
+ // At 0x2309:
var3 = fHandle->readUint16BE();
+ // At 0x230B:
var2 = fHandle->readUint16BE();
+ // At 0x230D:
commandVar2 = fHandle->readSint16BE();
+ // At 0x230F:
renderer->_messageBg = fHandle->readUint16BE();
+ // At 0x2311:
fHandle->readUint16BE();
+ // At 0x2313:
fHandle->readUint16BE();
+ // At 0x2315:
loadResourcesFromSave(*fHandle, broken);
// TODO: handle screen params (really required ?)
@@ -1518,12 +1559,22 @@ void mainLoopSub6(void) {
void checkForPendingDataLoad(void) {
if (newPrcName[0] != 0) {
- loadPrc(newPrcName);
+ bool loadPrcOk = loadPrc(newPrcName);
strcpy(currentPrcName, newPrcName);
strcpy(newPrcName, "");
- addScriptToList0(1);
+ // Check that the loading of the script file was successful before
+ // trying to add script 1 from it to the global scripts list. This
+ // fixes a crash when failing copy protection in Amiga or Atari ST
+ // versions of Future Wars.
+ if (loadPrcOk) {
+ addScriptToList0(1);
+ } else if (scumm_stricmp(currentPrcName, COPY_PROT_FAIL_PRC_NAME)) {
+ // We only show an error here for other files than the file that
+ // is loaded if copy protection fails (i.e. L201.ANI).
+ warning("checkForPendingDataLoad: loadPrc(%s) failed", currentPrcName);
+ }
}
if (newRelName[0] != 0) {
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 8351f2ecfb..63a0f8f45b 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -277,6 +277,19 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesNone,
"intro"
},
+ { // Supplied by raina in the forums
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712),
+ EN_ANY,
+ kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ "intro"
+ },
{ // Supplied by paul66 in bug report #1652352
{
"gob1",
diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp
index f68ce47783..2d3a10b570 100644
--- a/engines/gob/driver_vga.cpp
+++ b/engines/gob/driver_vga.cpp
@@ -112,7 +112,7 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
if ((width < 1) || (height < 1))
return;
- byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left;
+ const byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left;
byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x;
uint32 size = width * height;
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index e7aed0790e..5add0b9cea 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -78,58 +78,6 @@ Goblin::Goblin(GobEngine *vm) : _vm(vm) {
_pressedMapY = 0;
_pathExistence = 0;
- _some0ValPtr = 0;
-
- _gobRetVarPtr = 0;
- _curGobVarPtr = 0;
- _curGobXPosVarPtr = 0;
- _curGobYPosVarPtr = 0;
- _itemInPocketVarPtr = 0;
-
- _curGobStateVarPtr = 0;
- _curGobFrameVarPtr = 0;
- _curGobMultStateVarPtr = 0;
- _curGobNextStateVarPtr = 0;
- _curGobScrXVarPtr = 0;
- _curGobScrYVarPtr = 0;
- _curGobLeftVarPtr = 0;
- _curGobTopVarPtr = 0;
- _curGobRightVarPtr = 0;
- _curGobBottomVarPtr = 0;
- _curGobDoAnimVarPtr = 0;
- _curGobOrderVarPtr = 0;
- _curGobNoTickVarPtr = 0;
- _curGobTypeVarPtr = 0;
- _curGobMaxTickVarPtr = 0;
- _curGobTickVarPtr = 0;
- _curGobActStartStateVarPtr = 0;
- _curGobLookDirVarPtr = 0;
- _curGobPickableVarPtr = 0;
- _curGobRelaxVarPtr = 0;
- _curGobMaxFrameVarPtr = 0;
-
- _destItemStateVarPtr = 0;
- _destItemFrameVarPtr = 0;
- _destItemMultStateVarPtr = 0;
- _destItemNextStateVarPtr = 0;
- _destItemScrXVarPtr = 0;
- _destItemScrYVarPtr = 0;
- _destItemLeftVarPtr = 0;
- _destItemTopVarPtr = 0;
- _destItemRightVarPtr = 0;
- _destItemBottomVarPtr = 0;
- _destItemDoAnimVarPtr = 0;
- _destItemOrderVarPtr = 0;
- _destItemNoTickVarPtr = 0;
- _destItemTypeVarPtr = 0;
- _destItemMaxTickVarPtr = 0;
- _destItemTickVarPtr = 0;
- _destItemActStartStVarPtr = 0;
- _destItemLookDirVarPtr = 0;
- _destItemPickableVarPtr = 0;
- _destItemRelaxVarPtr = 0;
- _destItemMaxFrameVarPtr = 0;
-
_destItemType = 0;
_destItemState = 0;
for (int i = 0; i < 20; i++) {
@@ -690,7 +638,7 @@ void Goblin::switchGoblin(int16 index) {
_gobDestY = tmp;
_vm->_map->_curGoblinY = tmp;
- *_curGobVarPtr = _currentGoblin;
+ _curGobVarPtr = (uint32) _currentGoblin;
_pathExistence = 0;
_readyToAct = 0;
}
@@ -1250,172 +1198,172 @@ void Goblin::loadObjects(const char *source) {
void Goblin::saveGobDataToVars(int16 xPos, int16 yPos, int16 someVal) {
Gob_Object *obj;
- *_some0ValPtr = someVal;
- *_curGobXPosVarPtr = xPos;
- *_curGobYPosVarPtr = yPos;
- *_itemInPocketVarPtr = _itemIndInPocket;
+ _some0ValPtr = (uint32) someVal;
+ _curGobXPosVarPtr = (uint32) xPos;
+ _curGobYPosVarPtr = (uint32) yPos;
+ _itemInPocketVarPtr = (uint32) _itemIndInPocket;
obj = _goblins[_currentGoblin];
- *_curGobStateVarPtr = obj->state;
- *_curGobFrameVarPtr = obj->curFrame;
- *_curGobMultStateVarPtr = obj->multState;
- *_curGobNextStateVarPtr = obj->nextState;
- *_curGobScrXVarPtr = obj->xPos;
- *_curGobScrYVarPtr = obj->yPos;
- *_curGobLeftVarPtr = obj->left;
- *_curGobTopVarPtr = obj->top;
- *_curGobRightVarPtr = obj->right;
- *_curGobBottomVarPtr = obj->bottom;
- *_curGobDoAnimVarPtr = obj->doAnim;
- *_curGobOrderVarPtr = obj->order;
- *_curGobNoTickVarPtr = obj->noTick;
- *_curGobTypeVarPtr = obj->type;
- *_curGobMaxTickVarPtr = obj->maxTick;
- *_curGobTickVarPtr = obj->tick;
- *_curGobActStartStateVarPtr = obj->actionStartState;
- *_curGobLookDirVarPtr = obj->curLookDir;
- *_curGobPickableVarPtr = obj->pickable;
- *_curGobRelaxVarPtr = obj->relaxTime;
- *_curGobMaxFrameVarPtr = getObjMaxFrame(obj);
+ _curGobStateVarPtr = (uint32) obj->state;
+ _curGobFrameVarPtr = (uint32) obj->curFrame;
+ _curGobMultStateVarPtr = (uint32) obj->multState;
+ _curGobNextStateVarPtr = (uint32) obj->nextState;
+ _curGobScrXVarPtr = (uint32) obj->xPos;
+ _curGobScrYVarPtr = (uint32) obj->yPos;
+ _curGobLeftVarPtr = (uint32) obj->left;
+ _curGobTopVarPtr = (uint32) obj->top;
+ _curGobRightVarPtr = (uint32) obj->right;
+ _curGobBottomVarPtr = (uint32) obj->bottom;
+ _curGobDoAnimVarPtr = (uint32) obj->doAnim;
+ _curGobOrderVarPtr = (uint32) obj->order;
+ _curGobNoTickVarPtr = (uint32) obj->noTick;
+ _curGobTypeVarPtr = (uint32) obj->type;
+ _curGobMaxTickVarPtr = (uint32) obj->maxTick;
+ _curGobTickVarPtr = (uint32) obj->tick;
+ _curGobActStartStateVarPtr = (uint32) obj->actionStartState;
+ _curGobLookDirVarPtr = (uint32) obj->curLookDir;
+ _curGobPickableVarPtr = (uint32) obj->pickable;
+ _curGobRelaxVarPtr = (uint32) obj->relaxTime;
+ _curGobMaxFrameVarPtr = (uint32) getObjMaxFrame(obj);
if (_actDestItemDesc == 0)
return;
obj = _actDestItemDesc;
- *_destItemStateVarPtr = obj->state;
- *_destItemFrameVarPtr = obj->curFrame;
- *_destItemMultStateVarPtr = obj->multState;
- *_destItemNextStateVarPtr = obj->nextState;
- *_destItemScrXVarPtr = obj->xPos;
- *_destItemScrYVarPtr = obj->yPos;
- *_destItemLeftVarPtr = obj->left;
- *_destItemTopVarPtr = obj->top;
- *_destItemRightVarPtr = obj->right;
- *_destItemBottomVarPtr = obj->bottom;
- *_destItemDoAnimVarPtr = obj->doAnim;
- *_destItemOrderVarPtr = obj->order;
- *_destItemNoTickVarPtr = obj->noTick;
- *_destItemTypeVarPtr = obj->type;
- *_destItemMaxTickVarPtr = obj->maxTick;
- *_destItemTickVarPtr = obj->tick;
- *_destItemActStartStVarPtr = obj->actionStartState;
- *_destItemLookDirVarPtr = obj->curLookDir;
- *_destItemPickableVarPtr = obj->pickable;
- *_destItemRelaxVarPtr = obj->relaxTime;
- *_destItemMaxFrameVarPtr = getObjMaxFrame(obj);
+ _destItemStateVarPtr = (uint32) obj->state;
+ _destItemFrameVarPtr = (uint32) obj->curFrame;
+ _destItemMultStateVarPtr = (uint32) obj->multState;
+ _destItemNextStateVarPtr = (uint32) obj->nextState;
+ _destItemScrXVarPtr = (uint32) obj->xPos;
+ _destItemScrYVarPtr = (uint32) obj->yPos;
+ _destItemLeftVarPtr = (uint32) obj->left;
+ _destItemTopVarPtr = (uint32) obj->top;
+ _destItemRightVarPtr = (uint32) obj->right;
+ _destItemBottomVarPtr = (uint32) obj->bottom;
+ _destItemDoAnimVarPtr = (uint32) obj->doAnim;
+ _destItemOrderVarPtr = (uint32) obj->order;
+ _destItemNoTickVarPtr = (uint32) obj->noTick;
+ _destItemTypeVarPtr = (uint32) obj->type;
+ _destItemMaxTickVarPtr = (uint32) obj->maxTick;
+ _destItemTickVarPtr = (uint32) obj->tick;
+ _destItemActStartStVarPtr = (uint32) obj->actionStartState;
+ _destItemLookDirVarPtr = (uint32) obj->curLookDir;
+ _destItemPickableVarPtr = (uint32) obj->pickable;
+ _destItemRelaxVarPtr = (uint32) obj->relaxTime;
+ _destItemMaxFrameVarPtr = (uint32) getObjMaxFrame(obj);
_destItemState = obj->state;
_destItemType = obj->type;
}
void Goblin::initVarPointers(void) {
- _gobRetVarPtr = (int32 *)VAR_ADDRESS(59);
- _curGobStateVarPtr = (int32 *)VAR_ADDRESS(60);
- _curGobFrameVarPtr = (int32 *)VAR_ADDRESS(61);
- _curGobMultStateVarPtr = (int32 *)VAR_ADDRESS(62);
- _curGobNextStateVarPtr = (int32 *)VAR_ADDRESS(63);
- _curGobScrXVarPtr = (int32 *)VAR_ADDRESS(64);
- _curGobScrYVarPtr = (int32 *)VAR_ADDRESS(65);
- _curGobLeftVarPtr = (int32 *)VAR_ADDRESS(66);
- _curGobTopVarPtr = (int32 *)VAR_ADDRESS(67);
- _curGobRightVarPtr = (int32 *)VAR_ADDRESS(68);
- _curGobBottomVarPtr = (int32 *)VAR_ADDRESS(69);
- _curGobDoAnimVarPtr = (int32 *)VAR_ADDRESS(70);
- _curGobOrderVarPtr = (int32 *)VAR_ADDRESS(71);
- _curGobNoTickVarPtr = (int32 *)VAR_ADDRESS(72);
- _curGobTypeVarPtr = (int32 *)VAR_ADDRESS(73);
- _curGobMaxTickVarPtr = (int32 *)VAR_ADDRESS(74);
- _curGobTickVarPtr = (int32 *)VAR_ADDRESS(75);
- _curGobActStartStateVarPtr = (int32 *)VAR_ADDRESS(76);
- _curGobLookDirVarPtr = (int32 *)VAR_ADDRESS(77);
- _curGobPickableVarPtr = (int32 *)VAR_ADDRESS(80);
- _curGobRelaxVarPtr = (int32 *)VAR_ADDRESS(81);
- _destItemStateVarPtr = (int32 *)VAR_ADDRESS(82);
- _destItemFrameVarPtr = (int32 *)VAR_ADDRESS(83);
- _destItemMultStateVarPtr = (int32 *)VAR_ADDRESS(84);
- _destItemNextStateVarPtr = (int32 *)VAR_ADDRESS(85);
- _destItemScrXVarPtr = (int32 *)VAR_ADDRESS(86);
- _destItemScrYVarPtr = (int32 *)VAR_ADDRESS(87);
- _destItemLeftVarPtr = (int32 *)VAR_ADDRESS(88);
- _destItemTopVarPtr = (int32 *)VAR_ADDRESS(89);
- _destItemRightVarPtr = (int32 *)VAR_ADDRESS(90);
- _destItemBottomVarPtr = (int32 *)VAR_ADDRESS(91);
- _destItemDoAnimVarPtr = (int32 *)VAR_ADDRESS(92);
- _destItemOrderVarPtr = (int32 *)VAR_ADDRESS(93);
- _destItemNoTickVarPtr = (int32 *)VAR_ADDRESS(94);
- _destItemTypeVarPtr = (int32 *)VAR_ADDRESS(95);
- _destItemMaxTickVarPtr = (int32 *)VAR_ADDRESS(96);
- _destItemTickVarPtr = (int32 *)VAR_ADDRESS(97);
- _destItemActStartStVarPtr = (int32 *)VAR_ADDRESS(98);
- _destItemLookDirVarPtr = (int32 *)VAR_ADDRESS(99);
- _destItemPickableVarPtr = (int32 *)VAR_ADDRESS(102);
- _destItemRelaxVarPtr = (int32 *)VAR_ADDRESS(103);
- _destItemMaxFrameVarPtr = (int32 *)VAR_ADDRESS(105);
- _curGobVarPtr = (int32 *)VAR_ADDRESS(106);
- _some0ValPtr = (int32 *)VAR_ADDRESS(107);
- _curGobXPosVarPtr = (int32 *)VAR_ADDRESS(108);
- _curGobYPosVarPtr = (int32 *)VAR_ADDRESS(109);
- _curGobMaxFrameVarPtr = (int32 *)VAR_ADDRESS(110);
-
- _itemInPocketVarPtr = (int32 *)VAR_ADDRESS(114);
-
- *_itemInPocketVarPtr = -2;
+ _gobRetVarPtr.set(*_vm->_inter->_variables, 236);
+ _curGobStateVarPtr.set(*_vm->_inter->_variables, 240);
+ _curGobFrameVarPtr.set(*_vm->_inter->_variables, 244);
+ _curGobMultStateVarPtr.set(*_vm->_inter->_variables, 248);
+ _curGobNextStateVarPtr.set(*_vm->_inter->_variables, 252);
+ _curGobScrXVarPtr.set(*_vm->_inter->_variables, 256);
+ _curGobScrYVarPtr.set(*_vm->_inter->_variables, 260);
+ _curGobLeftVarPtr.set(*_vm->_inter->_variables, 264);
+ _curGobTopVarPtr.set(*_vm->_inter->_variables, 268);
+ _curGobRightVarPtr.set(*_vm->_inter->_variables, 272);
+ _curGobBottomVarPtr.set(*_vm->_inter->_variables, 276);
+ _curGobDoAnimVarPtr.set(*_vm->_inter->_variables, 280);
+ _curGobOrderVarPtr.set(*_vm->_inter->_variables, 284);
+ _curGobNoTickVarPtr.set(*_vm->_inter->_variables, 288);
+ _curGobTypeVarPtr.set(*_vm->_inter->_variables, 292);
+ _curGobMaxTickVarPtr.set(*_vm->_inter->_variables, 296);
+ _curGobTickVarPtr.set(*_vm->_inter->_variables, 300);
+ _curGobActStartStateVarPtr.set(*_vm->_inter->_variables, 304);
+ _curGobLookDirVarPtr.set(*_vm->_inter->_variables, 308);
+ _curGobPickableVarPtr.set(*_vm->_inter->_variables, 320);
+ _curGobRelaxVarPtr.set(*_vm->_inter->_variables, 324);
+ _destItemStateVarPtr.set(*_vm->_inter->_variables, 328);
+ _destItemFrameVarPtr.set(*_vm->_inter->_variables, 332);
+ _destItemMultStateVarPtr.set(*_vm->_inter->_variables, 336);
+ _destItemNextStateVarPtr.set(*_vm->_inter->_variables, 340);
+ _destItemScrXVarPtr.set(*_vm->_inter->_variables, 344);
+ _destItemScrYVarPtr.set(*_vm->_inter->_variables, 348);
+ _destItemLeftVarPtr.set(*_vm->_inter->_variables, 352);
+ _destItemTopVarPtr.set(*_vm->_inter->_variables, 356);
+ _destItemRightVarPtr.set(*_vm->_inter->_variables, 360);
+ _destItemBottomVarPtr.set(*_vm->_inter->_variables, 364);
+ _destItemDoAnimVarPtr.set(*_vm->_inter->_variables, 368);
+ _destItemOrderVarPtr.set(*_vm->_inter->_variables, 372);
+ _destItemNoTickVarPtr.set(*_vm->_inter->_variables, 376);
+ _destItemTypeVarPtr.set(*_vm->_inter->_variables, 380);
+ _destItemMaxTickVarPtr.set(*_vm->_inter->_variables, 384);
+ _destItemTickVarPtr.set(*_vm->_inter->_variables, 388);
+ _destItemActStartStVarPtr.set(*_vm->_inter->_variables, 392);
+ _destItemLookDirVarPtr.set(*_vm->_inter->_variables, 396);
+ _destItemPickableVarPtr.set(*_vm->_inter->_variables, 408);
+ _destItemRelaxVarPtr.set(*_vm->_inter->_variables, 412);
+ _destItemMaxFrameVarPtr.set(*_vm->_inter->_variables, 420);
+ _curGobVarPtr.set(*_vm->_inter->_variables, 424);
+ _some0ValPtr.set(*_vm->_inter->_variables, 428);
+ _curGobXPosVarPtr.set(*_vm->_inter->_variables, 432);
+ _curGobYPosVarPtr.set(*_vm->_inter->_variables, 436);
+ _curGobMaxFrameVarPtr.set(*_vm->_inter->_variables, 440);
+
+ _itemInPocketVarPtr.set(*_vm->_inter->_variables, 456);
+
+ _itemInPocketVarPtr = (uint32) -2;
}
void Goblin::loadGobDataFromVars(void) {
Gob_Object *obj;
- _itemIndInPocket = *_itemInPocketVarPtr;
+ _itemIndInPocket = (int32) _itemInPocketVarPtr;
obj = _goblins[_currentGoblin];
- obj->state = *_curGobStateVarPtr;
- obj->curFrame = *_curGobFrameVarPtr;
- obj->multState = *_curGobMultStateVarPtr;
- obj->nextState = *_curGobNextStateVarPtr;
- obj->xPos = *_curGobScrXVarPtr;
- obj->yPos = *_curGobScrYVarPtr;
- obj->left = *_curGobLeftVarPtr;
- obj->top = *_curGobTopVarPtr;
- obj->right = *_curGobRightVarPtr;
- obj->bottom = *_curGobBottomVarPtr;
- obj->doAnim = *_curGobDoAnimVarPtr;
- obj->order = *_curGobOrderVarPtr;
- obj->noTick = *_curGobNoTickVarPtr;
- obj->type = *_curGobTypeVarPtr;
- obj->maxTick = *_curGobMaxTickVarPtr;
- obj->tick = *_curGobTickVarPtr;
- obj->actionStartState = *_curGobActStartStateVarPtr;
- obj->curLookDir = *_curGobLookDirVarPtr;
- obj->pickable = *_curGobPickableVarPtr;
- obj->relaxTime = *_curGobRelaxVarPtr;
+ obj->state = (int32) _curGobStateVarPtr;
+ obj->curFrame = (int32) _curGobFrameVarPtr;
+ obj->multState = (int32) _curGobMultStateVarPtr;
+ obj->nextState = (int32) _curGobNextStateVarPtr;
+ obj->xPos = (int32) _curGobScrXVarPtr;
+ obj->yPos = (int32) _curGobScrYVarPtr;
+ obj->left = (int32) _curGobLeftVarPtr;
+ obj->top = (int32) _curGobTopVarPtr;
+ obj->right = (int32) _curGobRightVarPtr;
+ obj->bottom = (int32) _curGobBottomVarPtr;
+ obj->doAnim = (int32) _curGobDoAnimVarPtr;
+ obj->order = (int32) _curGobOrderVarPtr;
+ obj->noTick = (int32) _curGobNoTickVarPtr;
+ obj->type = (int32) _curGobTypeVarPtr;
+ obj->maxTick = (int32) _curGobMaxTickVarPtr;
+ obj->tick = (int32) _curGobTickVarPtr;
+ obj->actionStartState = (int32) _curGobActStartStateVarPtr;
+ obj->curLookDir = (int32) _curGobLookDirVarPtr;
+ obj->pickable = (int32) _curGobPickableVarPtr;
+ obj->relaxTime = (int32) _curGobRelaxVarPtr;
if (_actDestItemDesc == 0)
return;
obj = _actDestItemDesc;
- obj->state = *_destItemStateVarPtr;
- obj->curFrame = *_destItemFrameVarPtr;
- obj->multState = *_destItemMultStateVarPtr;
- obj->nextState = *_destItemNextStateVarPtr;
- obj->xPos = *_destItemScrXVarPtr;
- obj->yPos = *_destItemScrYVarPtr;
- obj->left = *_destItemLeftVarPtr;
- obj->top = *_destItemTopVarPtr;
- obj->right = *_destItemRightVarPtr;
- obj->bottom = *_destItemBottomVarPtr;
- obj->doAnim = *_destItemDoAnimVarPtr;
- obj->order = *_destItemOrderVarPtr;
- obj->noTick = *_destItemNoTickVarPtr;
- obj->type = *_destItemTypeVarPtr;
- obj->maxTick = *_destItemMaxTickVarPtr;
- obj->tick = *_destItemTickVarPtr;
- obj->actionStartState = *_destItemActStartStVarPtr;
- obj->curLookDir = *_destItemLookDirVarPtr;
- obj->pickable = *_destItemPickableVarPtr;
- obj->relaxTime = *_destItemRelaxVarPtr;
+ obj->state = (int32) _destItemStateVarPtr;
+ obj->curFrame = (int32) _destItemFrameVarPtr;
+ obj->multState = (int32) _destItemMultStateVarPtr;
+ obj->nextState = (int32) _destItemNextStateVarPtr;
+ obj->xPos = (int32) _destItemScrXVarPtr;
+ obj->yPos = (int32) _destItemScrYVarPtr;
+ obj->left = (int32) _destItemLeftVarPtr;
+ obj->top = (int32) _destItemTopVarPtr;
+ obj->right = (int32) _destItemRightVarPtr;
+ obj->bottom = (int32) _destItemBottomVarPtr;
+ obj->doAnim = (int32) _destItemDoAnimVarPtr;
+ obj->order = (int32) _destItemOrderVarPtr;
+ obj->noTick = (int32) _destItemNoTickVarPtr;
+ obj->type = (int32) _destItemTypeVarPtr;
+ obj->maxTick = (int32) _destItemMaxTickVarPtr;
+ obj->tick = (int32) _destItemTickVarPtr;
+ obj->actionStartState = (int32) _destItemActStartStVarPtr;
+ obj->curLookDir = (int32) _destItemLookDirVarPtr;
+ obj->pickable = (int32) _destItemPickableVarPtr;
+ obj->relaxTime = (int32) _destItemRelaxVarPtr;
if (obj->type != _destItemType)
obj->toRedraw = 1;
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index 3fd8a9f93b..2100bcbdac 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -28,6 +28,7 @@
#include "gob/util.h"
#include "gob/mult.h"
+#include "gob/variables.h"
#include "gob/sound/sounddesc.h"
namespace Gob {
@@ -115,57 +116,57 @@ public:
char _pathExistence;
// Pointers to interpreter variables
- int32 *_some0ValPtr;
-
- int32 *_gobRetVarPtr;
- int32 *_curGobVarPtr;
- int32 *_curGobXPosVarPtr;
- int32 *_curGobYPosVarPtr;
- int32 *_itemInPocketVarPtr;
-
- int32 *_curGobStateVarPtr;
- int32 *_curGobFrameVarPtr;
- int32 *_curGobMultStateVarPtr;
- int32 *_curGobNextStateVarPtr;
- int32 *_curGobScrXVarPtr;
- int32 *_curGobScrYVarPtr;
- int32 *_curGobLeftVarPtr;
- int32 *_curGobTopVarPtr;
- int32 *_curGobRightVarPtr;
- int32 *_curGobBottomVarPtr;
- int32 *_curGobDoAnimVarPtr;
- int32 *_curGobOrderVarPtr;
- int32 *_curGobNoTickVarPtr;
- int32 *_curGobTypeVarPtr;
- int32 *_curGobMaxTickVarPtr;
- int32 *_curGobTickVarPtr;
- int32 *_curGobActStartStateVarPtr;
- int32 *_curGobLookDirVarPtr;
- int32 *_curGobPickableVarPtr;
- int32 *_curGobRelaxVarPtr;
- int32 *_curGobMaxFrameVarPtr;
-
- int32 *_destItemStateVarPtr;
- int32 *_destItemFrameVarPtr;
- int32 *_destItemMultStateVarPtr;
- int32 *_destItemNextStateVarPtr;
- int32 *_destItemScrXVarPtr;
- int32 *_destItemScrYVarPtr;
- int32 *_destItemLeftVarPtr;
- int32 *_destItemTopVarPtr;
- int32 *_destItemRightVarPtr;
- int32 *_destItemBottomVarPtr;
- int32 *_destItemDoAnimVarPtr;
- int32 *_destItemOrderVarPtr;
- int32 *_destItemNoTickVarPtr;
- int32 *_destItemTypeVarPtr;
- int32 *_destItemMaxTickVarPtr;
- int32 *_destItemTickVarPtr;
- int32 *_destItemActStartStVarPtr;
- int32 *_destItemLookDirVarPtr;
- int32 *_destItemPickableVarPtr;
- int32 *_destItemRelaxVarPtr;
- int32 *_destItemMaxFrameVarPtr;
+ VariableReference _some0ValPtr;
+
+ VariableReference _gobRetVarPtr;
+ VariableReference _curGobVarPtr;
+ VariableReference _curGobXPosVarPtr;
+ VariableReference _curGobYPosVarPtr;
+ VariableReference _itemInPocketVarPtr;
+
+ VariableReference _curGobStateVarPtr;
+ VariableReference _curGobFrameVarPtr;
+ VariableReference _curGobMultStateVarPtr;
+ VariableReference _curGobNextStateVarPtr;
+ VariableReference _curGobScrXVarPtr;
+ VariableReference _curGobScrYVarPtr;
+ VariableReference _curGobLeftVarPtr;
+ VariableReference _curGobTopVarPtr;
+ VariableReference _curGobRightVarPtr;
+ VariableReference _curGobBottomVarPtr;
+ VariableReference _curGobDoAnimVarPtr;
+ VariableReference _curGobOrderVarPtr;
+ VariableReference _curGobNoTickVarPtr;
+ VariableReference _curGobTypeVarPtr;
+ VariableReference _curGobMaxTickVarPtr;
+ VariableReference _curGobTickVarPtr;
+ VariableReference _curGobActStartStateVarPtr;
+ VariableReference _curGobLookDirVarPtr;
+ VariableReference _curGobPickableVarPtr;
+ VariableReference _curGobRelaxVarPtr;
+ VariableReference _curGobMaxFrameVarPtr;
+
+ VariableReference _destItemStateVarPtr;
+ VariableReference _destItemFrameVarPtr;
+ VariableReference _destItemMultStateVarPtr;
+ VariableReference _destItemNextStateVarPtr;
+ VariableReference _destItemScrXVarPtr;
+ VariableReference _destItemScrYVarPtr;
+ VariableReference _destItemLeftVarPtr;
+ VariableReference _destItemTopVarPtr;
+ VariableReference _destItemRightVarPtr;
+ VariableReference _destItemBottomVarPtr;
+ VariableReference _destItemDoAnimVarPtr;
+ VariableReference _destItemOrderVarPtr;
+ VariableReference _destItemNoTickVarPtr;
+ VariableReference _destItemTypeVarPtr;
+ VariableReference _destItemMaxTickVarPtr;
+ VariableReference _destItemTickVarPtr;
+ VariableReference _destItemActStartStVarPtr;
+ VariableReference _destItemLookDirVarPtr;
+ VariableReference _destItemPickableVarPtr;
+ VariableReference _destItemRelaxVarPtr;
+ VariableReference _destItemMaxFrameVarPtr;
int16 _destItemType;
int16 _destItemState;
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index 9144e35070..d763aeb01c 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -88,7 +88,7 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated,
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (y + 1) / 2;
*obj->pPosX = x * _vm->_map->_tilesWidth;
} else {
- if (obj->goblinStates[state] != 0) {
+ if ((obj->goblinStates != 0) && (obj->goblinStates[state] != 0)) {
layer = obj->goblinStates[state][0].layer;
animation = obj->goblinStates[state][0].animation;
objAnim->state = state;
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 9c39653a1d..df9c1353a0 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -212,25 +212,35 @@ void Inter::funcBlock(int16 retFlag) {
break;
// WORKAROUND:
- // The EGA version of gob1 doesn't add a delay after showing
+ // The EGA and Mac versions of gob1 doesn't add a delay after showing
// images between levels. We manually add it here.
- if ((_vm->getGameType() == kGameTypeGob1) && _vm->isEGA()) {
+ if ((_vm->getGameType() == kGameTypeGob1) &&
+ (_vm->isEGA() || (_vm->getPlatform() == Common::kPlatformMacintosh))) {
+
int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;
- if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie
+
+ if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA
+ !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
+ (startaddr == 0x188D && addr == 0x1A58 && // Zombie, Mac
!strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
(startaddr == 0x1299 && addr == 0x139A && // Dungeon
!strncmp(_vm->_game->_curTotFile, "avt006.tot", 10)) ||
- (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron
+ (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron, EGA
+ !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) ||
+ (startaddr == 0x11C8 && addr == 0x1341 && // Cauldron, Mac
!strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) ||
(startaddr == 0x09F2 && addr == 0x0AF3 && // Statue
!strncmp(_vm->_game->_curTotFile, "avt016.tot", 10)) ||
(startaddr == 0x0B92 && addr == 0x0C93 && // Castle
!strncmp(_vm->_game->_curTotFile, "avt019.tot", 10)) ||
- (startaddr == 0x17D9 && addr == 0x18DA && // Finale
+ (startaddr == 0x17D9 && addr == 0x18DA && // Finale, EGA
+ !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10)) ||
+ (startaddr == 0x17E9 && addr == 0x19A8 && // Finale, Mac
!strncmp(_vm->_game->_curTotFile, "avt022.tot", 10))) {
_vm->_util->longDelay(5000);
}
+
} // End of workaround
cmd = *_vm->_global->_inter_execPtr;
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 60b3974d6d..b684be6c07 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -79,7 +79,7 @@ protected:
};
struct OpGobParams {
int16 extraData;
- int32 *retVarPtr;
+ VariableReference retVarPtr;
Goblin::Gob_Object *objDesc;
};
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index e2b8d65112..865d188a2e 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -912,12 +912,21 @@ void Inter_v1::o1_initMult() {
animDataVar = _vm->_parse->parseVarIndex();
if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) {
+
warning("Initializing new objects without having "
"cleaned up the old ones at first");
+
+ for (int i = 0; i < _vm->_mult->_objCount; i++) {
+ delete _vm->_mult->_objects[i].pPosX;
+ delete _vm->_mult->_objects[i].pPosY;
+ }
+
delete[] _vm->_mult->_objects;
delete[] _vm->_mult->_renderData;
+
_vm->_mult->_objects = 0;
_vm->_mult->_renderObjs = 0;
+
}
if (_vm->_mult->_objects == 0) {
@@ -933,8 +942,8 @@ void Inter_v1::o1_initMult() {
uint32 offPosY = i * 4 + (posYVar / 4) * 4;
uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
- _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX);
- _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY);
+ _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX);
+ _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY);
_vm->_mult->_objects[i].pAnimData =
(Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
@@ -1774,7 +1783,7 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams &params) {
gobParams.extraData = 0;
gobParams.objDesc = 0;
- gobParams.retVarPtr = (int32 *) VAR_ADDRESS(59);
+ gobParams.retVarPtr.set(*_vm->_inter->_variables, 236);
cmd = load16();
_vm->_global->_inter_execPtr += 2;
@@ -2268,49 +2277,49 @@ bool Inter_v1::o1_manageDataFile(OpFuncParams &params) {
void Inter_v1::o1_setState(OpGobParams &params) {
params.objDesc->state = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemStateVarPtr = params.extraData;
+ _vm->_goblin->_destItemStateVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setCurFrame(OpGobParams &params) {
params.objDesc->curFrame = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemFrameVarPtr = params.extraData;
+ _vm->_goblin->_destItemFrameVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setNextState(OpGobParams &params) {
params.objDesc->nextState = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemNextStateVarPtr = params.extraData;
+ _vm->_goblin->_destItemNextStateVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setMultState(OpGobParams &params) {
params.objDesc->multState = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemMultStateVarPtr = params.extraData;
+ _vm->_goblin->_destItemMultStateVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setOrder(OpGobParams &params) {
params.objDesc->order = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemOrderVarPtr = params.extraData;
+ _vm->_goblin->_destItemOrderVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setActionStartState(OpGobParams &params) {
params.objDesc->actionStartState = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemActStartStVarPtr = params.extraData;
+ _vm->_goblin->_destItemActStartStVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setCurLookDir(OpGobParams &params) {
params.objDesc->curLookDir = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemLookDirVarPtr = params.extraData;
+ _vm->_goblin->_destItemLookDirVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setType(OpGobParams &params) {
params.objDesc->type = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemTypeVarPtr = params.extraData;
+ _vm->_goblin->_destItemTypeVarPtr = (uint32) params.extraData;
if (params.extraData == 0)
params.objDesc->toRedraw = 1;
@@ -2319,107 +2328,107 @@ void Inter_v1::o1_setType(OpGobParams &params) {
void Inter_v1::o1_setNoTick(OpGobParams &params) {
params.objDesc->noTick = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemNoTickVarPtr = params.extraData;
+ _vm->_goblin->_destItemNoTickVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setPickable(OpGobParams &params) {
params.objDesc->pickable = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemPickableVarPtr = params.extraData;
+ _vm->_goblin->_destItemPickableVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setXPos(OpGobParams &params) {
params.objDesc->xPos = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemScrXVarPtr = params.extraData;
+ _vm->_goblin->_destItemScrXVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setYPos(OpGobParams &params) {
params.objDesc->yPos = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemScrYVarPtr = params.extraData;
+ _vm->_goblin->_destItemScrYVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setDoAnim(OpGobParams &params) {
params.objDesc->doAnim = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemDoAnimVarPtr = params.extraData;
+ _vm->_goblin->_destItemDoAnimVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setRelaxTime(OpGobParams &params) {
params.objDesc->relaxTime = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemRelaxVarPtr = params.extraData;
+ _vm->_goblin->_destItemRelaxVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_setMaxTick(OpGobParams &params) {
params.objDesc->maxTick = params.extraData;
if (params.objDesc == _vm->_goblin->_actDestItemDesc)
- *_vm->_goblin->_destItemMaxTickVarPtr = params.extraData;
+ _vm->_goblin->_destItemMaxTickVarPtr = (uint32) params.extraData;
}
void Inter_v1::o1_getState(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->state;
+ params.retVarPtr = (uint32) params.objDesc->state;
}
void Inter_v1::o1_getCurFrame(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->curFrame;
+ params.retVarPtr = (uint32) params.objDesc->curFrame;
}
void Inter_v1::o1_getNextState(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->nextState;
+ params.retVarPtr = (uint32) params.objDesc->nextState;
}
void Inter_v1::o1_getMultState(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->multState;
+ params.retVarPtr = (uint32) params.objDesc->multState;
}
void Inter_v1::o1_getOrder(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->order;
+ params.retVarPtr = (uint32) params.objDesc->order;
}
void Inter_v1::o1_getActionStartState(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->actionStartState;
+ params.retVarPtr = (uint32) params.objDesc->actionStartState;
}
void Inter_v1::o1_getCurLookDir(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->curLookDir;
+ params.retVarPtr = (uint32) params.objDesc->curLookDir;
}
void Inter_v1::o1_getType(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->type;
+ params.retVarPtr = (uint32) params.objDesc->type;
}
void Inter_v1::o1_getNoTick(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->noTick;
+ params.retVarPtr = (uint32) params.objDesc->noTick;
}
void Inter_v1::o1_getPickable(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->pickable;
+ params.retVarPtr = (uint32) params.objDesc->pickable;
}
void Inter_v1::o1_getObjMaxFrame(OpGobParams &params) {
- *params.retVarPtr = _vm->_goblin->getObjMaxFrame(params.objDesc);
+ params.retVarPtr = (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc);
}
void Inter_v1::o1_getXPos(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->xPos;
+ params.retVarPtr = (uint32) params.objDesc->xPos;
}
void Inter_v1::o1_getYPos(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->yPos;
+ params.retVarPtr = (uint32) params.objDesc->yPos;
}
void Inter_v1::o1_getDoAnim(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->doAnim;
+ params.retVarPtr = (uint32) params.objDesc->doAnim;
}
void Inter_v1::o1_getRelaxTime(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->relaxTime;
+ params.retVarPtr = (uint32) params.objDesc->relaxTime;
}
void Inter_v1::o1_getMaxTick(OpGobParams &params) {
- *params.retVarPtr = params.objDesc->maxTick;
+ params.retVarPtr = (uint32) params.objDesc->maxTick;
}
void Inter_v1::o1_manipulateMap(OpGobParams &params) {
@@ -2435,9 +2444,9 @@ void Inter_v1::o1_getItem(OpGobParams &params) {
int16 yPos = load16();
if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0)
- *params.retVarPtr = (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8;
+ params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8);
else
- *params.retVarPtr = _vm->_map->_itemsMap[yPos][xPos];
+ params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos];
}
void Inter_v1::o1_manipulateMapIndirect(OpGobParams &params) {
@@ -2460,9 +2469,9 @@ void Inter_v1::o1_getItemIndirect(OpGobParams &params) {
yPos = VAR(yPos);
if ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) != 0)
- *params.retVarPtr = (_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8;
+ params.retVarPtr = (uint32) ((_vm->_map->_itemsMap[yPos][xPos] & 0xFF00) >> 8);
else
- *params.retVarPtr = _vm->_map->_itemsMap[yPos][xPos];
+ params.retVarPtr = (uint32) _vm->_map->_itemsMap[yPos][xPos];
}
void Inter_v1::o1_setPassMap(OpGobParams &params) {
@@ -2500,11 +2509,11 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams &params) {
params.objDesc->curFrame = 0;
params.objDesc->state = 21;
if (_vm->_goblin->_currentGoblin == item) {
- *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos;
+ _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
- *_vm->_goblin->_curGobFrameVarPtr = 0;
- *_vm->_goblin->_curGobStateVarPtr = 18;
+ _vm->_goblin->_curGobFrameVarPtr = 0;
+ _vm->_goblin->_curGobStateVarPtr = 18;
_vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x;
_vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y;
}
@@ -2512,12 +2521,12 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams &params) {
void Inter_v1::o1_getGoblinPosXH(OpGobParams &params) {
int16 item = load16();
- *params.retVarPtr = _vm->_goblin->_gobPositions[item].x >> 1;
+ params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1);
}
void Inter_v1::o1_getGoblinPosYH(OpGobParams &params) {
int16 item = load16();
- *params.retVarPtr = _vm->_goblin->_gobPositions[item].y >> 1;
+ params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1);
}
void Inter_v1::o1_setGoblinMultState(OpGobParams &params) {
@@ -2539,14 +2548,14 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams &params) {
params.objDesc->xPos = animLayer->posX;
params.objDesc->yPos = animLayer->posY;
- *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos;
- *_vm->_goblin->_curGobFrameVarPtr = 0;
- *_vm->_goblin->_curGobStateVarPtr = params.objDesc->state;
- *_vm->_goblin->_curGobNextStateVarPtr = params.objDesc->nextState;
- *_vm->_goblin->_curGobMultStateVarPtr = params.objDesc->multState;
- *_vm->_goblin->_curGobMaxFrameVarPtr =
- _vm->_goblin->getObjMaxFrame(params.objDesc);
+ _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
+ _vm->_goblin->_curGobFrameVarPtr = 0;
+ _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state;
+ _vm->_goblin->_curGobNextStateVarPtr = (uint32) params.objDesc->nextState;
+ _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState;
+ _vm->_goblin->_curGobMaxFrameVarPtr =
+ (uint32) _vm->_goblin->getObjMaxFrame(params.objDesc);
_vm->_goblin->_noPick = 1;
return;
}
@@ -2573,12 +2582,12 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams &params) {
_vm->_goblin->_pressedMapY = yPos;
_vm->_map->_curGoblinY = yPos;
- *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos;
- *_vm->_goblin->_curGobFrameVarPtr = 0;
- *_vm->_goblin->_curGobStateVarPtr = 21;
- *_vm->_goblin->_curGobNextStateVarPtr = 21;
- *_vm->_goblin->_curGobMultStateVarPtr = -1;
+ _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
+ _vm->_goblin->_curGobFrameVarPtr = 0;
+ _vm->_goblin->_curGobStateVarPtr = 21;
+ _vm->_goblin->_curGobNextStateVarPtr = 21;
+ _vm->_goblin->_curGobMultStateVarPtr = (uint32) -1;
_vm->_goblin->_noPick = 0;
}
@@ -2598,11 +2607,11 @@ void Inter_v1::o1_setItemIndInPocket(OpGobParams &params) {
}
void Inter_v1::o1_getItemIdInPocket(OpGobParams &params) {
- *params.retVarPtr = _vm->_goblin->_itemIdInPocket;
+ params.retVarPtr = (uint32) _vm->_goblin->_itemIdInPocket;
}
void Inter_v1::o1_getItemIndInPocket(OpGobParams &params) {
- *params.retVarPtr = _vm->_goblin->_itemIndInPocket;
+ params.retVarPtr = (uint32) _vm->_goblin->_itemIndInPocket;
}
void Inter_v1::o1_setGoblinPos(OpGobParams &params) {
@@ -2632,10 +2641,10 @@ void Inter_v1::o1_setGoblinPos(OpGobParams &params) {
params.objDesc->state = 21;
if (_vm->_goblin->_currentGoblin == item) {
- *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos;
- *_vm->_goblin->_curGobFrameVarPtr = 0;
- *_vm->_goblin->_curGobStateVarPtr = 18;
+ _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
+ _vm->_goblin->_curGobFrameVarPtr = 0;
+ _vm->_goblin->_curGobStateVarPtr = 18;
_vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[item].x;
_vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[item].y;
@@ -2659,11 +2668,11 @@ void Inter_v1::o1_setGoblinState(OpGobParams &params) {
params.objDesc->yPos = animLayer->posY;
if (item == _vm->_goblin->_currentGoblin) {
- *_vm->_goblin->_curGobScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_curGobScrYVarPtr = params.objDesc->yPos;
- *_vm->_goblin->_curGobFrameVarPtr = 0;
- *_vm->_goblin->_curGobStateVarPtr = params.objDesc->state;
- *_vm->_goblin->_curGobMultStateVarPtr = params.objDesc->multState;
+ _vm->_goblin->_curGobScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_curGobScrYVarPtr = (uint32) params.objDesc->yPos;
+ _vm->_goblin->_curGobFrameVarPtr = 0;
+ _vm->_goblin->_curGobStateVarPtr = (uint32) params.objDesc->state;
+ _vm->_goblin->_curGobMultStateVarPtr = (uint32) params.objDesc->multState;
}
}
@@ -2686,13 +2695,13 @@ void Inter_v1::o1_setGoblinStateRedraw(OpGobParams &params) {
params.objDesc->toRedraw = 1;
params.objDesc->type = 0;
if (params.objDesc == _vm->_goblin->_actDestItemDesc) {
- *_vm->_goblin->_destItemScrXVarPtr = params.objDesc->xPos;
- *_vm->_goblin->_destItemScrYVarPtr = params.objDesc->yPos;
+ _vm->_goblin->_destItemScrXVarPtr = (uint32) params.objDesc->xPos;
+ _vm->_goblin->_destItemScrYVarPtr = (uint32) params.objDesc->yPos;
- *_vm->_goblin->_destItemStateVarPtr = params.objDesc->state;
- *_vm->_goblin->_destItemNextStateVarPtr = -1;
- *_vm->_goblin->_destItemMultStateVarPtr = -1;
- *_vm->_goblin->_destItemFrameVarPtr = 0;
+ _vm->_goblin->_destItemStateVarPtr = (uint32) params.objDesc->state;
+ _vm->_goblin->_destItemNextStateVarPtr = (uint32) -1;
+ _vm->_goblin->_destItemMultStateVarPtr = (uint32) -1;
+ _vm->_goblin->_destItemFrameVarPtr = 0;
}
}
@@ -2712,12 +2721,12 @@ void Inter_v1::o1_decRelaxTime(OpGobParams &params) {
void Inter_v1::o1_getGoblinPosX(OpGobParams &params) {
int16 item = load16();
- *params.retVarPtr = _vm->_goblin->_gobPositions[item].x;
+ params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x;
}
void Inter_v1::o1_getGoblinPosY(OpGobParams &params) {
int16 item = load16();
- *params.retVarPtr = _vm->_goblin->_gobPositions[item].y;
+ params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y;
}
void Inter_v1::o1_clearPathExistence(OpGobParams &params) {
@@ -2741,9 +2750,9 @@ void Inter_v1::o1_getObjectIntersect(OpGobParams &params) {
params.objDesc = _vm->_goblin->_objects[params.extraData];
if (_vm->_goblin->objIntersected(params.objDesc,
_vm->_goblin->_goblins[item]))
- *params.retVarPtr = 1;
+ params.retVarPtr = 1;
else
- *params.retVarPtr = 0;
+ params.retVarPtr = 0;
}
void Inter_v1::o1_getGoblinIntersect(OpGobParams &params) {
@@ -2753,9 +2762,9 @@ void Inter_v1::o1_getGoblinIntersect(OpGobParams &params) {
params.objDesc = _vm->_goblin->_goblins[params.extraData];
if (_vm->_goblin->objIntersected(params.objDesc,
_vm->_goblin->_goblins[item]))
- *params.retVarPtr = 1;
+ params.retVarPtr = 1;
else
- *params.retVarPtr = 0;
+ params.retVarPtr = 0;
}
void Inter_v1::o1_setItemPos(OpGobParams &params) {
@@ -2886,7 +2895,7 @@ void Inter_v1::o1_initGoblin(OpGobParams &params) {
_vm->_map->_destY = _vm->_goblin->_gobPositions[0].y;
_vm->_goblin->_gobDestY = _vm->_goblin->_gobPositions[0].y;
- *_vm->_goblin->_curGobVarPtr = 0;
+ _vm->_goblin->_curGobVarPtr = 0;
_vm->_goblin->_pathExistence = 0;
_vm->_goblin->_readyToAct = 0;
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index d8c33fcce6..2f1d2ec0be 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -880,9 +880,15 @@ void Inter_v2::o2_initMult() {
_vm->_mult->clearObjectVideos();
+ for (int i = 0; i < _vm->_mult->_objCount; i++) {
+ delete _vm->_mult->_objects[i].pPosX;
+ delete _vm->_mult->_objects[i].pPosY;
+ }
+
delete[] _vm->_mult->_objects;
delete[] _vm->_mult->_renderObjs;
delete[] _vm->_mult->_orderArray;
+
_vm->_mult->_objects = 0;
_vm->_mult->_renderObjs = 0;
_vm->_mult->_orderArray = 0;
@@ -907,8 +913,8 @@ void Inter_v2::o2_initMult() {
uint32 offPosY = i * 4 + (posYVar / 4) * 4;
uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
- _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX);
- _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY);
+ _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX);
+ _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY);
_vm->_mult->_objects[i].pAnimData =
(Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
@@ -1046,7 +1052,7 @@ void Inter_v2::o2_loadMultObject() {
} else if ((objAnim.animType != 100) && (objAnim.animType != 101)) {
- if ((*(obj.pPosX) == -1234) && (*(obj.pPosY) == -4321)) {
+ if ((((int32) *(obj.pPosX)) == -1234) && (((int32) *(obj.pPosY)) == -4321)) {
if (obj.videoSlot > 0)
_vm->_vidPlayer->slotClose(obj.videoSlot - 1);
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index 3d6a7942f9..b9373d48b3 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -93,12 +93,18 @@ Mult::Mult(GobEngine *vm) : _vm(vm) {
}
Mult::~Mult() {
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
delete[] _objects;
delete[] _orderArray;
delete[] _renderData;
delete[] _renderObjs;
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
delete _multData;
}
@@ -123,6 +129,12 @@ void Mult::freeAll(void) {
void Mult::freeMult() {
clearObjectVideos();
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
delete[] _objects;
delete[] _renderData;
delete[] _renderObjs;
@@ -203,11 +215,17 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
if (_animDataAllocated) {
clearObjectVideos();
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
delete[] _objects;
delete[] _renderData;
delete[] _renderObjs;
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
delete[] _orderArray;
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index aaf2e2826c..3bb3af17b3 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -27,6 +27,7 @@
#define GOB_MULT_H
#include "gob/video.h"
+#include "gob/variables.h"
namespace Gob {
@@ -77,8 +78,8 @@ public:
} PACKED_STRUCT;
struct Mult_Object {
- int32 *pPosX;
- int32 *pPosY;
+ VariableReference *pPosX;
+ VariableReference *pPosY;
Mult_AnimData *pAnimData;
int16 tick;
int16 lastLeft;
@@ -267,8 +268,8 @@ protected:
bool _doPalSubst;
- int32 *_animArrayX;
- int32 *_animArrayY;
+ Variables *_animArrayX;
+ Variables *_animArrayY;
Mult_AnimData *_animArrayData;
int16 _palKeyIndex;
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index 22683437e7..a369e7d297 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -216,10 +216,16 @@ void Mult_v1::freeMultKeys() {
if (_animDataAllocated) {
clearObjectVideos();
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
delete[] _objects;
delete[] _renderData;
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
_objects = 0;
@@ -263,6 +269,14 @@ void Mult_v1::playMultInit() {
_oldPalette = _vm->_global->_pPaletteDesc->vgaPal;
if (!_animSurf) {
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
+ delete[] _objects;
+
_vm->_util->setFrameRate(_multData->frameRate);
_animTop = 0;
_animLeft = 0;
@@ -270,30 +284,27 @@ void Mult_v1::playMultInit() {
_animHeight = 200;
_objCount = 4;
- delete[] _objects;
delete[] _renderData;
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
_objects = new Mult_Object[_objCount];
_renderData = new int16[9 * _objCount];
- _animArrayX = new int32[_objCount];
- _animArrayY = new int32[_objCount];
+ _animArrayX = new VariablesLE(_objCount * 4);
+ _animArrayY = new VariablesLE(_objCount * 4);
_animArrayData = new Mult_AnimData[_objCount];
memset(_objects, 0, _objCount * sizeof(Mult_Object));
memset(_renderData, 0, _objCount * 9 * sizeof(int16));
- memset(_animArrayX, 0, _objCount * sizeof(int32));
- memset(_animArrayY, 0, _objCount * sizeof(int32));
memset(_animArrayData, 0, _objCount * sizeof(Mult_AnimData));
for (_counter = 0; _counter < _objCount; _counter++) {
Mult_Object &multObj = _objects[_counter];
Mult_AnimData &animData = _animArrayData[_counter];
- multObj.pPosX = (int32 *) &_animArrayX[_counter];
- multObj.pPosY = (int32 *) &_animArrayY[_counter];
+ multObj.pPosX = new VariableReference(*_animArrayX, _counter * 4);
+ multObj.pPosY = new VariableReference(*_animArrayY, _counter * 4);
multObj.pAnimData = &animData;
animData.isStatic = 1;
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 3a83ac1867..20a81174e5 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -329,8 +329,8 @@ void Mult_v2::freeMultKeys() {
if (_animDataAllocated) {
freeMult();
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
_animArrayX = 0;
@@ -510,6 +510,13 @@ void Mult_v2::playMultInit() {
if (!_animSurf) {
int16 width, height;
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
+
+ delete[] _objects;
+
_vm->_util->setFrameRate(_multData->frameRate);
_animTop = 0;
_animLeft = 0;
@@ -517,33 +524,30 @@ void Mult_v2::playMultInit() {
_animHeight = _vm->_video->_surfHeight;
_objCount = 4;
- delete[] _objects;
delete[] _orderArray;
delete[] _renderObjs;
- delete[] _animArrayX;
- delete[] _animArrayY;
+ delete _animArrayX;
+ delete _animArrayY;
delete[] _animArrayData;
_objects = new Mult_Object[_objCount];
_orderArray = new int8[_objCount];
_renderObjs = new Mult_Object*[_objCount];
- _animArrayX = new int32[_objCount];
- _animArrayY = new int32[_objCount];
+ _animArrayX = new VariablesLE(_objCount * 4);
+ _animArrayY = new VariablesLE(_objCount * 4);
_animArrayData = new Mult_AnimData[_objCount];
memset(_objects, 0, _objCount * sizeof(Mult_Object));
memset(_orderArray, 0, _objCount * sizeof(int8));
memset(_renderObjs, 0, _objCount * sizeof(Mult_Object *));
- memset(_animArrayX, 0, _objCount * sizeof(int32));
- memset(_animArrayY, 0, _objCount * sizeof(int32));
memset(_animArrayData, 0, _objCount * sizeof(Mult_AnimData));
for (_counter = 0; _counter < _objCount; _counter++) {
Mult_Object &multObj = _objects[_counter];
Mult_AnimData &animData = _animArrayData[_counter];
- multObj.pPosX = (int32 *) &_animArrayX[_counter];
- multObj.pPosY = (int32 *) &_animArrayY[_counter];
+ multObj.pPosX = new VariableReference(*_animArrayX, _counter * 4);
+ multObj.pPosY = new VariableReference(*_animArrayY, _counter * 4);
multObj.pAnimData = &animData;
animData.isStatic = 1;
diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h
index b59510e4bb..07b5a737db 100644
--- a/engines/gob/sound/sound.h
+++ b/engines/gob/sound/sound.h
@@ -144,4 +144,4 @@ private:
} // End of namespace Gob
-#endif // GOB_SOUND_H
+#endif // GOB_SOUND_SOUND_H
diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h
index 5789885a99..3e8e6b5c1b 100644
--- a/engines/gob/sound/soundmixer.h
+++ b/engines/gob/sound/soundmixer.h
@@ -37,7 +37,7 @@ namespace Gob {
class SoundMixer : public Audio::AudioStream {
public:
- SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType);
+ SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type);
~SoundMixer();
virtual void play(SoundDesc &sndDesc, int16 repCount,
diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp
index 0eea2f6547..805aaeb839 100644
--- a/engines/gob/variables.cpp
+++ b/engines/gob/variables.cpp
@@ -308,4 +308,62 @@ uint32 VariablesBE::read32(const byte *buf) const {
return READ_BE_UINT32(buf);
}
+VariableReference::VariableReference() {
+ _vars = 0;
+ _offset = 0;
+}
+
+VariableReference::VariableReference(Variables &vars, uint32 offset, Variables::Type type) {
+ set(vars, offset, type);
+}
+
+VariableReference::~VariableReference() {
+}
+
+void VariableReference::set(Variables &vars, uint32 offset, Variables::Type type) {
+ _vars = &vars;
+ _offset = offset;
+ _type = type;
+}
+
+VariableReference &VariableReference::operator=(uint32 value) {
+ if (_vars) {
+ switch (_type) {
+ case Variables::kVariableType8:
+ _vars->writeOff8(_offset, (uint8) value);
+ break;
+ case Variables::kVariableType16:
+ _vars->writeOff16(_offset, (uint16) value);
+ break;
+ case Variables::kVariableType32:
+ _vars->writeOff32(_offset, value);
+ break;
+ }
+ }
+ return *this;
+}
+
+VariableReference::operator uint32() {
+ if (_vars) {
+ switch (_type) {
+ case Variables::kVariableType8:
+ return (uint32) _vars->readOff8(_offset);
+ case Variables::kVariableType16:
+ return (uint32) _vars->readOff16(_offset);
+ case Variables::kVariableType32:
+ return _vars->readOff32(_offset);
+ }
+ }
+
+ return 0;
+}
+
+VariableReference &VariableReference::operator+=(uint32 value) {
+ return (*this = (*this + value));
+}
+
+VariableReference &VariableReference::operator*=(uint32 value) {
+ return (*this = (*this * value));
+}
+
} // End of namespace Gob
diff --git a/engines/gob/variables.h b/engines/gob/variables.h
index 5989ed38ee..32f160a6bd 100644
--- a/engines/gob/variables.h
+++ b/engines/gob/variables.h
@@ -30,6 +30,12 @@ namespace Gob {
class Variables {
public:
+ enum Type {
+ kVariableType8,
+ kVariableType16,
+ kVariableType32
+ };
+
Variables(uint32 size);
virtual ~Variables();
@@ -142,6 +148,26 @@ protected:
uint32 read32(const byte *buf) const;
};
+class VariableReference {
+ public:
+ VariableReference();
+ VariableReference(Variables &vars, uint32 offset,
+ Variables::Type type = Variables::kVariableType32);
+ ~VariableReference();
+
+ void set(Variables &vars, uint32 offset, Variables::Type type = Variables::kVariableType32);
+
+ VariableReference &operator=(uint32 value);
+ VariableReference &operator+=(uint32 value);
+ VariableReference &operator*=(uint32 value);
+ operator uint32();
+
+ private:
+ Variables *_vars;
+ uint32 _offset;
+ Variables::Type _type;
+};
+
} // End of namespace Gob
#endif // GOB_VARIABLES_H
diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp
index 018709f34f..4d4fb97762 100644
--- a/engines/igor/igor.cpp
+++ b/engines/igor/igor.cpp
@@ -404,7 +404,7 @@ void IgorEngine::playSound(int num, int type) {
debugC(9, kDebugEngine, "playSound() %d", num);
--num;
int soundOffset = -1;
- Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType;
+ Audio::Mixer::SoundType soundType;
Audio::SoundHandle *soundHandle = 0;
if (type == 1) {
if (_mixer->isSoundHandleActive(_sfxHandle)) {
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index f55cd1ac5e..fce1e93bc2 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -527,7 +527,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_INS_FLAGS
+ KYRA3_CD_FLAGS
},
{
{
@@ -542,7 +542,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_INS_FLAGS
+ KYRA3_CD_FLAGS
},
{
{
@@ -557,7 +557,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_INS_FLAGS
+ KYRA3_CD_FLAGS
},
// installed version
@@ -574,7 +574,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_FLAGS
+ KYRA3_CD_INS_FLAGS
},
{
{
@@ -589,7 +589,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_FLAGS
+ KYRA3_CD_INS_FLAGS
},
{
{
@@ -604,7 +604,7 @@ const KYRAGameDescription adGameDescs[] = {
Common::kPlatformPC,
Common::ADGF_DROPLANGUAGE
},
- KYRA3_CD_FLAGS
+ KYRA3_CD_INS_FLAGS
},
// Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation"
@@ -654,6 +654,52 @@ const KYRAGameDescription adGameDescs[] = {
KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
},
+ // Itlian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA)
+ },
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) }
};
diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp
index b425c0929f..a4e5b58364 100644
--- a/engines/kyra/kyra_mr.cpp
+++ b/engines/kyra/kyra_mr.cpp
@@ -343,6 +343,14 @@ void KyraEngine_MR::initMainMenu() {
0x80, 0xFF
};
+ if (_flags.lang == Common::ES_ESP) {
+ for (int i = 0; i < 4; ++i)
+ data.strings[i] = _mainMenuSpanishFan[i];
+ } else if (_flags.lang == Common::IT_ITA) {
+ for (int i = 0; i < 4; ++i)
+ data.strings[i] = _mainMenuItalianFan[i];
+ }
+
MainMenu::Animation anim;
anim.anim = _menuAnim;
anim.startFrame = 29;
diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h
index 5af138373c..5f9f6f91a3 100644
--- a/engines/kyra/kyra_mr.h
+++ b/engines/kyra/kyra_mr.h
@@ -184,9 +184,12 @@ private:
private:
// main menu
- const char *const *_mainMenuStrings;
+ const char * const *_mainMenuStrings;
int _mainMenuStringsSize;
+ static const char * const _mainMenuSpanishFan[];
+ static const char * const _mainMenuItalianFan[];
+
// animator
uint8 *_gamePlayBuffer;
void restorePage3();
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index d2e0f37a60..85c03dc1bb 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -114,7 +114,7 @@ int KyraEngine_v1::init() {
_sound = new SoundTownsPC98_v2(this, _mixer);
} else if (_flags.platform == Common::kPlatformPC98) {
if (_flags.gameID == GI_KYRA1)
- _sound = new SoundPC98(this, _mixer);
+ _sound = new SoundTowns/*SoundPC98*/(this, _mixer);
else
_sound = new SoundTownsPC98_v2(this, _mixer);
} else if (midiDriver == MD_ADLIB) {
@@ -247,8 +247,14 @@ void KyraEngine_v1::delayWithTicks(int ticks) {
void KyraEngine_v1::registerDefaultSettings() {
if (_flags.gameID != GI_KYRA3)
ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98));
- if (_flags.fanLang != Common::UNK_LANG)
- ConfMan.registerDefault("subtitles", true);
+ if (_flags.fanLang != Common::UNK_LANG) {
+ // HACK/WORKAROUND: Since we can't use registerDefault here to overwrite
+ // the global subtitles settings, we're using this hack to enable subtitles
+ // for fan translations
+ const Common::ConfigManager::Domain *cur = ConfMan.getActiveDomain();
+ if (!cur || (cur && cur->get("subtitles").empty()))
+ ConfMan.setBool("subtitles", true);
+ }
}
void KyraEngine_v1::readSettings() {
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index a29cdc8ca3..b10a4b32bf 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -132,6 +132,8 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo
scriptData->opcodes = opcodes;
+ strncpy(scriptData->filename, filename, 13);
+
return true;
}
@@ -205,7 +207,7 @@ bool EMCInterpreter::run(EMCState *script) {
}
if (opcode > 18) {
- error("Script unknown command: %d", opcode);
+ error("Script unknown command: %d in file '%s' at offset 0x%.08X", opcode, script->dataPtr->filename, instOffset);
} else {
debugC(5, kDebugLevelScript, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset, _commands[opcode].desc, _parameter, (uint)_parameter);
(this->*(_commands[opcode].proc))(script);
@@ -388,7 +390,7 @@ void EMCInterpreter::cmd_execOpcode(EMCState* script) {
script->retValue = (*(*script->dataPtr->opcodes)[opcode])(script);
} else {
script->retValue = 0;
- warning("calling unimplemented opcode(0x%.02X/%d)", opcode, opcode);
+ warning("Calling unimplemented opcode(0x%.02X/%d) from file '%s'", opcode, opcode, script->dataPtr->filename);
}
}
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index de52093f66..2b97a83289 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -36,6 +36,8 @@ struct EMCState;
typedef Common::Functor1<EMCState*, int> Opcode;
struct EMCData {
+ char filename[13];
+
byte *text;
uint16 *data;
uint16 *ordr;
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp
index 6b82ba06de..4b82232049 100644
--- a/engines/kyra/script_tim.cpp
+++ b/engines/kyra/script_tim.cpp
@@ -34,6 +34,7 @@ namespace Kyra {
TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _system(system), _currentTim(0) {
#define COMMAND(x) { &TIMInterpreter::x, #x }
#define COMMAND_UNIMPL() { 0, 0 }
+#define cmd_return(n) cmd_return_##n
static const CommandEntry commandProcs[] = {
// 0x00
COMMAND(cmd_initFunc0),
@@ -66,15 +67,16 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, OSystem *system) : _vm(vm), _s
COMMAND_UNIMPL(),
COMMAND(cmd_resetAllRuntimes),
// 0x18
- COMMAND(cmd_return<1>),
+ COMMAND(cmd_return(1)),
COMMAND(cmd_execOpcode),
COMMAND(cmd_initFuncNow),
COMMAND(cmd_stopFuncNow),
// 0x1C
- COMMAND(cmd_return<1>),
- COMMAND(cmd_return<1>),
- COMMAND(cmd_return<-1>)
+ COMMAND(cmd_return(1)),
+ COMMAND(cmd_return(1)),
+ COMMAND(cmd_return(n1))
};
+#undef cmd_return
_commands = commandProcs;
_commandsSize = ARRAYSIZE(commandProcs);
@@ -122,6 +124,8 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc
for (int i = 0; i < num; ++i)
tim->func[i].avtl = tim->avtl + tim->avtl[i];
+ strncpy(tim->filename, filename, 13);
+
return tim;
}
@@ -199,12 +203,12 @@ void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) {
int TIMInterpreter::execCommand(int cmd, const uint16 *param) {
if (cmd < 0 || cmd >= _commandsSize) {
- warning("Calling unimplemented TIM command %d", cmd);
+ warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
return 0;
}
if (_commands[cmd].proc == 0) {
- warning("Calling unimplemented TIM command %d", cmd);
+ warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename);
return 0;
}
@@ -259,7 +263,7 @@ int TIMInterpreter::cmd_execOpcode(const uint16 *param) {
uint16 opcode = *param++;
if (opcode > _currentTim->opcodes->size()) {
- warning("Calling unimplemented TIM opcode(0x%.02X/%d)", opcode, opcode);
+ warning("Calling unimplemented TIM opcode(0x%.02X/%d) from file '%s'", opcode, opcode, _currentTim->filename);
return 0;
}
diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h
index cd715ff4ef..39a1d90a44 100644
--- a/engines/kyra/script_tim.h
+++ b/engines/kyra/script_tim.h
@@ -37,6 +37,8 @@ struct TIM;
typedef Common::Functor2<const TIM*, const uint16*, int> TIMOpcode;
struct TIM {
+ char filename[13];
+
int16 procFunc;
uint16 procParam;
@@ -102,8 +104,12 @@ private:
int cmd_execOpcode(const uint16 *param);
int cmd_initFuncNow(const uint16 *param);
int cmd_stopFuncNow(const uint16 *param);
- template<int T>
- int cmd_return(const uint16 *) { return T; }
+#define cmd_return(n, v) \
+ int cmd_return_##n(const uint16 *) { return v; }
+
+ cmd_return( 1, 1);
+ cmd_return(n1, -1);
+#undef cmd_return
};
} // end of namespace Kyra
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index b30568c7e2..3a497a258f 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -1083,7 +1083,7 @@ void KyraEngine_LoK::seq_playCredits() {
_screen->_charWidth = -1;
// we only need this for the fm-towns version
- if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
+ if (_flags.platform == Common::kPlatformFMTowns && _configMusic == 1)
snd_playWanderScoreViaMap(53, 1);
uint8 *buffer = 0;
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index f56c43aabd..5068268d99 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -243,27 +243,14 @@ int SoundMidiPC::open() {
}
void SoundMidiPC::close() {
- if (_driver)
+ if (_driver) {
_driver->close();
+ delete _driver;
+ }
_driver = 0;
}
void SoundMidiPC::send(uint32 b) {
- // HACK: For Kyrandia, we make the simplifying assumption that a song
- // either loops in its entirety, or not at all. So if we see a FOR_LOOP
- // controller event, we turn on looping even if there isn't any
- // corresponding NEXT_BREAK event.
- //
- // This is a gross over-simplification of how XMIDI handles loops. If
- // anyone feels like doing a proper implementation, please refer to
- // the Exult project, and do it in midiparser_xmidi.cpp
-
- if ((b & 0xFFF0) == 0x74B0 && _eventFromMusic) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "SoundMidiPC: Looping song");
- _musicParser->property(MidiParser::mpAutoLoop, true);
- return;
- }
-
if (_passThrough) {
if ((b & 0xFFF0) == 0x007BB0)
return;
diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp
index 7d6e1dd378..b43d72ebce 100644
--- a/engines/kyra/sound_lok.cpp
+++ b/engines/kyra/sound_lok.cpp
@@ -49,20 +49,23 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) {
} else if (command >= 35 && command <= 38) {
snd_playSoundEffect(command-20);
} else if (command >= 2) {
- if (_lastMusicCommand != command) {
+ if (_lastMusicCommand != command)
// the original does -2 here we handle this inside _sound->playTrack()
_sound->playTrack(command);
- }
} else {
_sound->haltTrack();
}
+ _lastMusicCommand = command;
} else if (_flags.platform == Common::kPlatformPC98) {
- if (command == 1)
+ if (command == 1) {
_sound->beginFadeOut();
- else if (command >= 2)
- _sound->playTrack(command);
- else
+ } else if (command >= 2) {
+ if (_lastMusicCommand != command)
+ _sound->playTrack(command);
+ } else {
_sound->haltTrack();
+ }
+ _lastMusicCommand = command;
} else {
KyraEngine_v1::snd_playWanderScoreViaMap(command, restart);
}
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 6be2cae7a4..0f2b916c9d 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -34,11 +34,6 @@
#include "common/util.h"
-#ifdef _MSC_VER
-#define _USE_MATH_DEFINES
-#endif
-#include <math.h>
-
#define EUPHONY_FADEOUT_TICKS 600
namespace Kyra {
@@ -2368,7 +2363,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) :
_numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false),
_numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) {
setTempo(84);
- _baserate = (3579545.0 / (double)getRate()) / 144.0;
+ _baserate = (double)getRate() / 10368.0;
}
TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
@@ -2657,7 +2652,7 @@ void TownsPC98_OpnDriver::generateTables() {
delete [] _oprSinTbl;
_oprSinTbl = new uint32[1024];
for (int i = 0; i < 1024; i++) {
- double val = sin((double) (((i << 1) + 1) * M_PI / 1024.0));
+ double val = sin((double) (((i << 1) + 1) * PI / 1024.0));
double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
int32 i_dcb = (int32)(2.0 * d_dcb);
i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
@@ -3100,8 +3095,8 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
}
bool SoundTownsPC98_v2::init() {
- _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
- TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
+ _driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ?
+ TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS);
_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
_vm->checkCD();
// FIXME: While checking for 'track1.XXX(X)' looks like
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 5d094fa13f..c05795dacd 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -1034,8 +1034,10 @@ void KyraEngine_LoK::initStaticResource() {
}
// audio data tables
+#if 0
static const char *tIntro98[] = { "intro%d.dat" };
static const char *tIngame98[] = { "kyram%d.dat" };
+#endif
static const AudioDataStruct soundData_PC[] = {
{ _soundFilesIntro, _soundFilesIntroSize, 0, 0 },
@@ -1049,18 +1051,20 @@ void KyraEngine_LoK::initStaticResource() {
{ 0, 0, 0, 0}
};
+#if 0
static const AudioDataStruct soundData_PC98[] = {
{ tIntro98, 1, 0, 0 },
{ tIngame98, 1, 0, 0 },
{ 0, 0, 0, 0}
};
+#endif
if (_flags.platform == Common::kPlatformPC)
_soundData = soundData_PC;
else if (_flags.platform == Common::kPlatformFMTowns)
_soundData = soundData_TOWNS;
else if (_flags.platform == Common::kPlatformPC98)
- _soundData = soundData_PC98;
+ _soundData = soundData_TOWNS/*soundData_PC98*/;
}
@@ -1259,9 +1263,11 @@ void KyraEngine_HoF::initStaticResource() {
static const char *fmtMusicFileListFinale[] = { "finale%d.twn" };
static const char *fmtMusicFileListIngame[] = { "km%02d.twn" };
+#if 0
static const char *pc98MusicFileListIntro[] = { "intro%d.86" };
static const char *pc98MusicFileListFinale[] = { "finale%d.86" };
static const char *pc98MusicFileListIngame[] = { "km%02d.86" };
+#endif
static const AudioDataStruct soundData_PC[] = {
{ _musicFileListIntro, _musicFileListIntroSize, 0, 0 },
@@ -1275,18 +1281,20 @@ void KyraEngine_HoF::initStaticResource() {
{ fmtMusicFileListFinale, 1, _cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1 }
};
+#if 0
static const AudioDataStruct soundData_PC98[] = {
{ pc98MusicFileListIntro, 1, 0, 0 },
{ pc98MusicFileListIngame, 1, 0, 0 },
{ pc98MusicFileListFinale, 1, 0, 0 }
};
+#endif
if (_flags.platform == Common::kPlatformPC)
_soundData = soundData_PC;
else if (_flags.platform == Common::kPlatformFMTowns)
_soundData = soundData_TOWNS;
else if (_flags.platform == Common::kPlatformPC98)
- _soundData = soundData_PC98;
+ _soundData = soundData_TOWNS/*soundData_PC98*/;
// setup sequence data
_sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize);
@@ -1976,12 +1984,26 @@ const char *KyraEngine_MR::_languageExtension[] = {
"TRE",
"TRF",
"TRG"/*,
- "TRI", Italian and Spanish were never included
- "TRS"*/
+ "TRI", Italian and Spanish were never included, the supported fan translations are using
+ "TRS" English/French extensions thus overwriting these languages */
};
const int KyraEngine_MR::_languageExtensionSize = ARRAYSIZE(KyraEngine_MR::_languageExtension);
+const char * const KyraEngine_MR::_mainMenuSpanishFan[] = {
+ "Nueva Partida",
+ "Ver Intro",
+ "Restaurar",
+ "Finalizar"
+};
+
+const char * const KyraEngine_MR::_mainMenuItalianFan[] = {
+ "Nuova Partita",
+ "Introduzione",
+ "Carica una partita",
+ "Esci dal gioco"
+};
+
const KyraEngine_MR::ShapeDesc KyraEngine_MR::_shapeDescs[] = {
{ 57, 91, -31, -82 },
{ 57, 91, -31, -82 },
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index 603102a099..922e1207d0 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -36,7 +36,7 @@ namespace Lure {
#define LURE_DAT_MAJOR 1
#define LURE_DAT_MINOR 29
#define LURE_MIN_SAVEGAME_MINOR 25
-#define LURE_SAVEGAME_MINOR 32
+#define LURE_SAVEGAME_MINOR 33
#define LURE_DEBUG 1
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index de09f982d1..92cea948f9 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -456,6 +456,8 @@ void HotspotData::saveToStream(WriteStream *stream) {
stream->writeSint16LE(startY);
stream->writeUint16LE(roomNumber);
stream->writeByte(layer);
+ stream->writeUint16LE(walkX);
+ stream->writeUint16LE(walkY);
stream->writeUint16LE(width);
stream->writeUint16LE(height);
@@ -503,6 +505,10 @@ void HotspotData::loadFromStream(ReadStream *stream) {
uint8 saveVersion = LureEngine::getReference().saveVersion();
if (saveVersion >= 29)
layer = stream->readByte();
+ if (saveVersion >= 33) {
+ walkX = stream->readUint16LE();
+ walkY = stream->readUint16LE();
+ }
width = stream->readUint16LE();
height = stream->readUint16LE();
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index a85fdea02f..5b8bdab9d6 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -380,7 +380,7 @@ void Converse::loadConversation(const char *convName) {
uint32 size;
uint32 chunk;
uint32 data = 0;
- uint32 i;
+ uint32 i = 0;
ConvEntry* curEntry = NULL;
ConvEntry* replyEntry = NULL;
int32 currentWeightedEntry = -1;
diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp
index 12d9a24d37..58c68979d1 100644
--- a/engines/m4/globals.cpp
+++ b/engines/m4/globals.cpp
@@ -75,7 +75,7 @@ bool Kernel::sendTrigger(int32 triggerNum) {
bool Kernel::handleTrigger(int32 triggerNum) {
- printf("betweenRooms = %d; triggerNum = %08X\n", betweenRooms, triggerNum);
+ printf("betweenRooms = %d; triggerNum = %08X\n", betweenRooms, (uint)triggerNum);
if (betweenRooms)
return true;
@@ -271,11 +271,13 @@ Globals::Globals(M4Engine *vm): _vm(vm) {
}
Globals::~Globals() {
- for(uint32 i = 0; i < _madsVocab.size(); i++)
+ uint32 i;
+
+ for(i = 0; i < _madsVocab.size(); i++)
free(_madsVocab[i]);
_madsVocab.clear();
- for(uint32 i = 0; i < _madsQuotes.size(); i++)
+ for(i = 0; i < _madsQuotes.size(); i++)
free(_madsQuotes[i]);
_madsQuotes.clear();
@@ -351,7 +353,7 @@ void Globals::loadMadsMessagesInfo() {
_vm->res()->toss("messages.dat");
}
-char* Globals::loadMessage(uint32 index) {
+char* Globals::loadMessage(uint index) {
if (index > _madsMessages.size() - 1) {
warning("Invalid message index: %i", index);
return NULL;
diff --git a/engines/m4/globals.h b/engines/m4/globals.h
index a0133db2d6..a80e8bf710 100644
--- a/engines/m4/globals.h
+++ b/engines/m4/globals.h
@@ -177,7 +177,7 @@ public:
void loadMadsMessagesInfo();
uint32 getMessagesSize() { return _madsMessages.size(); }
- char* loadMessage(uint32 index);
+ char* loadMessage(uint index);
};
#define PLAYER_FIELD_LENGTH 40
diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp
index 57816b6600..5070a2b79c 100644
--- a/engines/m4/resource.cpp
+++ b/engines/m4/resource.cpp
@@ -310,7 +310,7 @@ const char *MADSResourceManager::getResourceFilename(const char *resourceName) {
Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) {
Common::File hagFile;
- uint32 offset, size;
+ uint32 offset = 0, size = 0;
// If the first character is a '@' then look for an external file
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp
new file mode 100644
index 0000000000..fab92dada9
--- /dev/null
+++ b/engines/parallaction/balloons.cpp
@@ -0,0 +1,456 @@
+/* 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$
+ *
+ */
+
+#include "parallaction/graphics.h"
+#include "parallaction/parallaction.h"
+
+namespace Parallaction {
+
+
+#define BALLOON_TRANSPARENT_COLOR_NS 2
+#define BALLOON_TRANSPARENT_COLOR_BR 0
+
+#define BALLOON_TAIL_WIDTH 12
+#define BALLOON_TAIL_HEIGHT 10
+
+
+byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
+ {
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ },
+ {
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02
+ }
+};
+
+class BalloonManager_ns : public BalloonManager {
+
+ static int16 _dialogueBalloonX[5];
+
+ struct Balloon {
+ Common::Rect outerBox;
+ Common::Rect innerBox;
+ Graphics::Surface *surface;
+ GfxObj *obj;
+ } _intBalloons[5];
+
+ uint _numBalloons;
+
+ void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
+ int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
+ Balloon *getBalloon(uint id);
+
+ Gfx *_gfx;
+
+public:
+ BalloonManager_ns(Gfx *gfx);
+ ~BalloonManager_ns();
+
+ void freeBalloons();
+ int setLocationBalloon(char *text, bool endGame);
+ int setDialogueBalloon(char *text, uint16 winding, byte textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
+ void setBalloonText(uint id, char *text, byte textColor);
+ int hitTestDialogueBalloon(int x, int y);
+};
+
+int16 BalloonManager_ns::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 };
+
+BalloonManager_ns::BalloonManager_ns(Gfx *gfx) : _numBalloons(0), _gfx(gfx) {
+
+}
+
+BalloonManager_ns::~BalloonManager_ns() {
+
+}
+
+
+BalloonManager_ns::Balloon* BalloonManager_ns::getBalloon(uint id) {
+ assert(id < _numBalloons);
+ return &_intBalloons[id];
+}
+
+int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) {
+ assert(_numBalloons < 5);
+
+ int id = _numBalloons;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ int16 real_h = (winding == -1) ? h : h + 9;
+ balloon->surface = new Graphics::Surface;
+ balloon->surface->create(w, real_h, 1);
+ balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR_NS);
+
+ Common::Rect r(w, h);
+ balloon->surface->fillRect(r, 0);
+ balloon->outerBox = r;
+
+ r.grow(-borderThickness);
+ balloon->surface->fillRect(r, 1);
+ balloon->innerBox = r;
+
+ if (winding != -1) {
+ // draws tail
+ // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
+ winding = (winding == 0 ? 1 : 0);
+ Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
+ s.moveTo(r.width()/2 - 5, r.bottom - 1);
+ _gfx->blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR_NS);
+ }
+
+ _numBalloons++;
+
+ return id;
+}
+
+
+int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+5, h, winding, 1);
+ Balloon *balloon = &_intBalloons[id];
+
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = x;
+ balloon->obj->y = y;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ return id;
+}
+
+int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+5, h, winding, 1);
+ Balloon *balloon = &_intBalloons[id];
+
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = _dialogueBalloonX[id];
+ balloon->obj->y = 10;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ if (id > 0) {
+ balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].outerBox.height();
+ }
+
+
+ return id;
+}
+
+void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) {
+ Balloon *balloon = getBalloon(id);
+ balloon->surface->fillRect(balloon->innerBox, 1);
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+}
+
+
+int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS);
+ Balloon *balloon = &_intBalloons[id];
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 5;
+ balloon->obj->y = 5;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ return id;
+}
+
+int BalloonManager_ns::hitTestDialogueBalloon(int x, int y) {
+
+ Common::Point p;
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ p.x = x - _intBalloons[i].obj->x;
+ p.y = y - _intBalloons[i].obj->y;
+
+ if (_intBalloons[i].innerBox.contains(p))
+ return i;
+ }
+
+ return -1;
+}
+
+void BalloonManager_ns::freeBalloons() {
+ _gfx->destroyBalloons();
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ _intBalloons[i].obj = 0;
+ _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons
+ }
+
+ _numBalloons = 0;
+}
+
+
+
+
+
+
+
+
+class BalloonManager_br : public BalloonManager {
+
+ struct Balloon {
+ Common::Rect box;
+ Graphics::Surface *surface;
+ GfxObj *obj;
+ } _intBalloons[3];
+
+ uint _numBalloons;
+
+ Frames *_leftBalloon;
+ Frames *_rightBalloon;
+ Disk *_disk;
+ Gfx *_gfx;
+
+ void cacheAnims();
+ void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
+ int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
+ Balloon *getBalloon(uint id);
+ Graphics::Surface *expandBalloon(Frames *data, int frameNum);
+
+
+public:
+ BalloonManager_br(Disk *disk, Gfx *gfx);
+ ~BalloonManager_br();
+
+ void freeBalloons();
+ int setLocationBalloon(char *text, bool endGame);
+ int setDialogueBalloon(char *text, uint16 winding, byte textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
+ void setBalloonText(uint id, char *text, byte textColor);
+ int hitTestDialogueBalloon(int x, int y);
+};
+
+
+
+BalloonManager_br::Balloon* BalloonManager_br::getBalloon(uint id) {
+ assert(id < _numBalloons);
+ return &_intBalloons[id];
+}
+
+Graphics::Surface *BalloonManager_br::expandBalloon(Frames *data, int frameNum) {
+
+ Common::Rect rect;
+ data->getRect(frameNum, rect);
+
+ rect.translate(-rect.left, -rect.top);
+
+ Graphics::Surface *surf = new Graphics::Surface;
+ surf->create(rect.width(), rect.height(), 1);
+
+ _gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, 0, BALLOON_TRANSPARENT_COLOR_BR);
+
+ return surf;
+}
+
+int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+ cacheAnims();
+
+ int id = _numBalloons;
+ Frames *src = 0;
+ int srcFrame = 0;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ if (winding == 0) {
+ src = _leftBalloon;
+ srcFrame = 0;
+ } else
+ if (winding == 1) {
+ src = _rightBalloon;
+ srcFrame = 0;
+ }
+
+ assert(src);
+
+ balloon->surface = expandBalloon(src, srcFrame);
+ src->getRect(srcFrame, balloon->box);
+
+// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = x;
+ balloon->obj->y = y;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR;
+
+ _numBalloons++;
+
+ return id;
+}
+
+int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+ cacheAnims();
+
+ int id = _numBalloons;
+ Frames *src = 0;
+ int srcFrame = 0;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ if (winding == 0) {
+ src = _leftBalloon;
+ srcFrame = id;
+ } else
+ if (winding == 1) {
+ src = _rightBalloon;
+ srcFrame = 0;
+ }
+
+ assert(src);
+
+ balloon->surface = expandBalloon(src, srcFrame);
+ src->getRect(srcFrame, balloon->box);
+
+// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 0;
+ balloon->obj->y = 10;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR;
+
+ if (id > 0) {
+ balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].box.height();
+ }
+
+ _numBalloons++;
+
+ return id;
+}
+
+void BalloonManager_br::setBalloonText(uint id, char *text, byte textColor) { }
+
+int BalloonManager_br::setLocationBalloon(char *text, bool endGame) {
+/*
+ int16 w, h;
+
+ getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR);
+ Balloon *balloon = &_intBalloons[id];
+ drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 5;
+ balloon->obj->y = 5;
+*/
+ return 0;
+}
+
+int BalloonManager_br::hitTestDialogueBalloon(int x, int y) {
+
+ Common::Point p;
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ p.x = x - _intBalloons[i].obj->x;
+ p.y = y - _intBalloons[i].obj->y;
+
+ if (_intBalloons[i].box.contains(p))
+ return i;
+ }
+
+ return -1;
+}
+
+void BalloonManager_br::freeBalloons() {
+ _gfx->destroyBalloons();
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ _intBalloons[i].obj = 0;
+ _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons
+ }
+
+ _numBalloons = 0;
+}
+
+void BalloonManager_br::cacheAnims() {
+ if (!_leftBalloon) {
+ _leftBalloon = _disk->loadFrames("fumetto.ani");
+ _rightBalloon = _disk->loadFrames("fumdx.ani");
+ }
+}
+
+BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), _leftBalloon(0), _rightBalloon(0) {
+}
+
+BalloonManager_br::~BalloonManager_br() {
+ delete _leftBalloon;
+ delete _rightBalloon;
+}
+
+void Parallaction::setupBalloonManager() {
+ if (_vm->getGameType() == GType_Nippon) {
+ _balloonMan = new BalloonManager_ns(_vm->_gfx);
+ } else
+ if (_vm->getGameType() == GType_BRA) {
+ _balloonMan = new BalloonManager_br(_vm->_disk, _vm->_gfx);
+ } else {
+ error("Unknown game type");
+ }
+}
+
+} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 3ecc7a9534..ed60a193ce 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -341,7 +341,7 @@ void Parallaction_ns::_c_endComment(void *param) {
}
_input->waitUntilLeftClick();
- _gfx->freeBalloons();
+ _balloonMan->freeBalloons();
return;
}
@@ -424,6 +424,7 @@ void Parallaction_ns::_c_testResult(void *parm) {
}
_inTestResult = true;
+ _gfx->freeLabels();
_gfx->updateScreen();
_disk->selectArchive("disk1");
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 3b6c35d3bb..290f8cfd4f 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -42,13 +42,23 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
+
class DialogueManager {
+ enum {
+ RUN_QUESTION,
+ RUN_ANSWER,
+ NEXT_QUESTION,
+ NEXT_ANSWER,
+ DIALOGUE_OVER
+ } _state;
+
Parallaction *_vm;
- SpeakData *_data;
Dialogue *_dialogue;
bool _askPassword;
+ int _passwordLen;
+ bool _passwordChanged;
bool isNpc;
GfxObj *_questioner;
@@ -59,98 +69,70 @@ class DialogueManager {
uint16 _visAnswers[5];
int _numVisAnswers;
+ int _answerId;
+
+ int _selection, _oldSelection;
+
+ uint32 _mouseButtons;
+ Common::Point _mousePos;
+ bool _isKeyDown;
+ uint16 _downKey;
+
+
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(Parallaction *vm, ZonePtr z);
+ ~DialogueManager();
- ~DialogueManager() {
- if (isNpc) {
- delete _questioner;
- }
+ bool isOver() {
+ return _state == DIALOGUE_OVER;
}
-
void run();
+ ZonePtr _z;
+ CommandList *_cmdList;
+
protected:
- void displayQuestion();
+ bool displayQuestion();
bool displayAnswers();
bool displayAnswer(uint16 i);
- uint16 getAnswer();
- int16 selectAnswer();
- uint16 askPassword();
+ int16 selectAnswer1();
+ int16 selectAnswerN();
+ int16 askPassword();
int16 getHoverAnswer(int16 x, int16 y);
-};
-
-uint16 DialogueManager::askPassword() {
- debugC(3, kDebugExec, "checkDialoguePassword()");
-
- uint16 passwordLen = 0;
- _password[0] = '\0';
-
- _vm->_gfx->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, 0);
-
- Common::Event e;
- bool changed = true; // force first refresh
-
- while (true) {
- e.kbd.ascii = 0;
-
- if (g_system->getEventManager()->pollEvent(e)) {
- if (e.type == Common::EVENT_QUIT) {
- _engineFlags |= kEngineQuit;
- break;
- }
-
- if ((e.type == Common::EVENT_KEYDOWN) && isdigit(e.kbd.ascii)) {
- _password[passwordLen] = e.kbd.ascii;
- passwordLen++;
- _password[passwordLen] = '\0';
- changed = true;
- }
- }
-
- if (changed) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 3);
- _vm->_gfx->updateScreen();
- changed = false;
- }
-
- if ((passwordLen == MAX_PASSWORD_LENGTH) || (e.kbd.ascii == Common::KEYCODE_RETURN)) {
+ void runQuestion();
+ void runAnswer();
+ void nextQuestion();
+ void nextAnswer();
- if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))) {
+ bool checkPassword();
+ void resetPassword();
+ void accumPassword(uint16 ascii);
+};
- break;
+DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) {
+ _dialogue = _z->u.speak->_dialogue;
+ isNpc = scumm_stricmp(_z->u.speak->_name, "yourself") && _z->u.speak->_name[0] != '\0';
+ _questioner = isNpc ? _vm->_disk->loadTalk(_z->u.speak->_name) : _vm->_char._talk;
+ _answerer = _vm->_char._talk;
- } else {
- passwordLen = 0;
- _password[0] = '\0';
- changed = true;
- }
+ _askPassword = false;
+ _q = _dialogue->_questions[0];
- }
+ _cmdList = 0;
+ _answerId = 0;
- g_system->delayMillis(20);
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
+}
+DialogueManager::~DialogueManager() {
+ if (isNpc) {
+ delete _questioner;
}
-
- _vm->_gfx->hideDialogueStuff();
-
- return 0;
-
+ _z = nullZonePtr;
}
-
-
bool DialogueManager::displayAnswer(uint16 i) {
Answer *a = _q->_answers[i];
@@ -162,11 +144,11 @@ bool DialogueManager::displayAnswer(uint16 i) {
// display suitable answers
if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) {
- int id = _vm->_gfx->setDialogueBalloon(a->_text, 1, 3);
+ int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, 3);
assert(id >= 0);
_visAnswers[id] = i;
- _askPassword = (strstr(a->_text, "%p") != NULL);
+ _askPassword = (strstr(a->_text, "%P") != NULL);
_numVisAnswers++;
return true;
@@ -183,134 +165,242 @@ bool DialogueManager::displayAnswers() {
displayAnswer(i);
}
+ if (_askPassword) {
+ resetPassword();
+// _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, 0);
+ } else
+ if (_numVisAnswers == 1) {
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0);
+ } else
+ if (_numVisAnswers > 1) {
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[_visAnswers[0]]->_mood & 0xF);
+ _oldSelection = -1;
+ _selection = 0;
+ }
+
return _numVisAnswers > 0;
}
-void DialogueManager::displayQuestion() {
-
- if (!scumm_stricmp(_q->_text, "NULL")) return;
+bool DialogueManager::displayQuestion() {
+ if (!scumm_stricmp(_q->_text, "NULL")) return false;
- _vm->_gfx->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
+ _vm->_balloonMan->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y);
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
- _vm->_gfx->updateScreen();
- _vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ return true;
+}
- return;
+
+bool DialogueManager::checkPassword() {
+ return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3)));
}
-uint16 DialogueManager::getAnswer() {
+void DialogueManager::resetPassword() {
+ _passwordLen = 0;
+ _password[0] = '\0';
+ _passwordChanged = true;
+}
- uint16 answer = 0;
+void DialogueManager::accumPassword(uint16 ascii) {
+ if (!isdigit(ascii)) {
+ return;
+ }
- if (_askPassword == false) {
- answer = selectAnswer();
- } else {
- answer = askPassword();
+ _password[_passwordLen] = ascii;
+ _passwordLen++;
+ _password[_passwordLen] = '\0';
+ _passwordChanged = true;
+}
+
+int16 DialogueManager::askPassword() {
+
+ if (_isKeyDown) {
+ accumPassword(_downKey);
+ }
+
+ if (_passwordChanged) {
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
+ _passwordChanged = false;
}
- debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer);
+ if ((_passwordLen == MAX_PASSWORD_LENGTH) || ((_isKeyDown) && (_downKey == Common::KEYCODE_RETURN))) {
+ if (checkPassword()) {
+ return 0;
+ } else {
+ resetPassword();
+ }
+ }
- return answer;
+ return -1;
}
-void DialogueManager::run() {
+int16 DialogueManager::selectAnswer1() {
- _askPassword = false;
- CommandList *cmdlist = NULL;
+ if (_mouseButtons == kMouseLeftUp) {
+ return 0;
+ }
- _q = _dialogue->_questions[0];
- int16 answer;
+ return -1;
+}
- while (_q) {
+int16 DialogueManager::selectAnswerN() {
- answer = 0;
+ _selection = _vm->_balloonMan->hitTestDialogueBalloon(_mousePos.x, _mousePos.y);
- displayQuestion();
+ if (_selection != _oldSelection) {
+ if (_oldSelection != -1) {
+ _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3);
+ }
- if (_engineFlags & kEngineQuit)
- return;
+ if (_selection != -1) {
+ _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0);
+ _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF);
+ }
+ }
- if (_q->_answers[0] == NULL) break;
+ _oldSelection = _selection;
- if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
- if (!displayAnswers()) break;
- answer = getAnswer();
+ if ((_mouseButtons == kMouseLeftUp) && (_selection != -1)) {
+ return _visAnswers[_selection];
+ }
- if (_engineFlags & kEngineQuit)
- return;
+ return -1;
+}
- cmdlist = &_q->_answers[answer]->_commands;
- }
+void DialogueManager::runQuestion() {
+ debugC(9, kDebugDialogue, "runQuestion\n");
+
+ if (_mouseButtons == kMouseLeftUp) {
+ _vm->hideDialogueStuff();
+ _state = NEXT_ANSWER;
+ }
+
+}
- _q = _q->_answers[answer]->_following._question;
+
+void DialogueManager::nextAnswer() {
+ debugC(9, kDebugDialogue, "nextAnswer\n");
+
+ if (_q->_answers[0] == NULL) {
+ _state = DIALOGUE_OVER;
+ return;
}
- if (cmdlist)
- _vm->runCommands(*cmdlist);
+ if (!scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
+ _answerId = 0;
+ _state = NEXT_QUESTION;
+ return;
+ }
+ _state = displayAnswers() ? RUN_ANSWER : DIALOGUE_OVER;
}
-int16 DialogueManager::selectAnswer() {
+void DialogueManager::runAnswer() {
+ debugC(9, kDebugDialogue, "runAnswer\n");
- int16 numAvailableAnswers = _numVisAnswers;
+ if (_askPassword) {
+ _answerId = askPassword();
+ } else
+ if (_numVisAnswers == 1) {
+ _answerId = selectAnswer1();
+ } else {
+ _answerId = selectAnswerN();
+ }
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ if (_answerId != -1) {
+ _cmdList = &_q->_answers[_answerId]->_commands;
+ _vm->hideDialogueStuff();
+ _state = NEXT_QUESTION;
+ }
+}
- if (numAvailableAnswers == 1) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 0);
- _vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
- return 0;
+void DialogueManager::nextQuestion() {
+ debugC(9, kDebugDialogue, "nextQuestion\n");
+
+ _q = _q->_answers[_answerId]->_following._question;
+ if (_q == 0) {
+ _state = DIALOGUE_OVER;
+ } else {
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
}
+}
- int oldSelection = -1;
- int selection = 0;
- uint32 event;
- Common::Point p;
- while ((_engineFlags & kEngineQuit) == 0) {
+void DialogueManager::run() {
- _vm->_input->readInput();
- _vm->_input->getCursorPos(p);
- event = _vm->_input->getLastButtonEvent();
- selection = _vm->_gfx->hitTestDialogueBalloon(p.x, p.y);
+ // cache event data
+ _mouseButtons = _vm->_input->getLastButtonEvent();
+ _vm->_input->getCursorPos(_mousePos);
+ _isKeyDown = _vm->_input->getLastKeyDown(_downKey);
- if (selection != oldSelection) {
- if (oldSelection != -1) {
- _vm->_gfx->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
- }
+ switch (_state) {
+ case RUN_QUESTION:
+ runQuestion();
+ break;
- if (selection != -1) {
- _vm->_gfx->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
- _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF);
- }
- }
+ case NEXT_ANSWER:
+ nextAnswer();
+ break;
+
+ case NEXT_QUESTION:
+ nextQuestion();
+ break;
- if ((selection != -1) && (event == kMouseLeftUp)) {
- break;
+ case RUN_ANSWER:
+ runAnswer();
+ break;
+
+ case DIALOGUE_OVER:
+ if (_cmdList) {
+ _vm->_cmdExec->run(*_cmdList);
}
+ break;
- _vm->_gfx->updateScreen();
- g_system->delayMillis(20);
+ default:
+ error("unknown state in DialogueManager");
- oldSelection = selection;
}
- _vm->_gfx->hideDialogueStuff();
+}
- return _visAnswers[selection];
+void Parallaction::enterDialogueMode(ZonePtr z) {
+ debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name);
+ _dialogueMan = new DialogueManager(this, z);
+ _input->_inputMode = Input::kInputModeDialogue;
}
+void Parallaction::exitDialogueMode() {
+ debugC(1, kDebugDialogue, "Parallaction::exitDialogueMode()");
+ _input->_inputMode = Input::kInputModeGame;
-void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name);
+ // The current instance of _dialogueMan must be destroyed before the zone commands
+ // are executed, because they may create another instance of _dialogueMan that
+ // overwrite the current one. This would cause headaches (and it did, actually).
+ ZonePtr z = _dialogueMan->_z;
+ delete _dialogueMan;
+ _dialogueMan = 0;
- DialogueManager man(this, data);
- man.run();
+ _cmdExec->run(z->_commands, z);
+}
+
+void Parallaction::runDialogueFrame() {
+ if (_input->_inputMode != Input::kInputModeDialogue) {
+ return;
+ }
+
+ _dialogueMan->run();
+
+ if (_dialogueMan->isOver()) {
+ exitDialogueMode();
+ }
return;
}
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 176f10aa10..694d4efa6d 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -61,7 +61,7 @@ public:
virtual GfxObj* loadHead(const char* name) = 0;
virtual Font* loadFont(const char* name) = 0;
virtual GfxObj* loadStatic(const char* name) = 0;
- virtual GfxObj* loadFrames(const char* name) = 0;
+ virtual Frames* loadFrames(const char* name) = 0;
virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0;
virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0;
virtual Table* loadTable(const char* name) = 0;
@@ -153,7 +153,7 @@ public:
GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
GfxObj* loadStatic(const char* name);
- GfxObj* loadFrames(const char* name);
+ Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
Table* loadTable(const char* name);
@@ -187,7 +187,7 @@ public:
GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
GfxObj* loadStatic(const char* name);
- GfxObj* loadFrames(const char* name);
+ Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
Table* loadTable(const char* name);
@@ -226,7 +226,7 @@ public:
GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
GfxObj* loadStatic(const char* name);
- GfxObj* loadFrames(const char* name);
+ Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path);
Table* loadTable(const char* name);
@@ -251,7 +251,7 @@ public:
GfxObj* loadTalk(const char *name);
Font* loadFont(const char* name);
GfxObj* loadStatic(const char* name);
- GfxObj* loadFrames(const char* name);
+ Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path);
};
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 0159d9d406..ee1e111139 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -58,7 +58,7 @@ struct Sprites : public Frames {
}
~Sprites() {
- delete _sprites;
+ delete[] _sprites;
}
uint16 getNum() {
@@ -280,18 +280,21 @@ Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) {
return sprites;
}
-GfxObj* DosDisk_br::loadFrames(const char* name) {
+Frames* DosDisk_br::loadFrames(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadFrames");
char path[PATH_LEN];
sprintf(path, "%s/ani/%s", _partPath, name);
Common::File stream;
- if (!stream.open(path))
- errorFileNotFound(path);
-
+ if (!stream.open(path)) {
+ sprintf(path, "%s/ani/%s.ani", _partPath, name);
+ if (!stream.open(path)) {
+ errorFileNotFound(path);
+ }
+ }
- return new GfxObj(0, createSprites(stream), name);
+ return createSprites(stream);
}
// Slides in Nippon Safes are basically screen-sized pictures with valid
@@ -600,13 +603,13 @@ Sprites* AmigaDisk_br::createSprites(const char *path) {
return sprites;
}
-GfxObj* AmigaDisk_br::loadFrames(const char* name) {
+Frames* AmigaDisk_br::loadFrames(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadFrames '%s'", name);
char path[PATH_LEN];
sprintf(path, "%s/anims/%s", _partPath, name);
- return new GfxObj(0, createSprites(path));
+ return createSprites(path);
}
GfxObj* AmigaDisk_br::loadTalk(const char *name) {
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index f45cf83f56..55e6fc5e77 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -490,8 +490,8 @@ GfxObj* DosDisk_ns::loadStatic(const char* name) {
return new GfxObj(0, new SurfaceToFrames(cnv), name);
}
-GfxObj* DosDisk_ns::loadFrames(const char* name) {
- return new GfxObj(0, loadCnv(name), name);
+Frames* DosDisk_ns::loadFrames(const char* name) {
+ return loadCnv(name);
}
//
@@ -1258,7 +1258,7 @@ void AmigaDisk_ns::loadSlide(BackgroundInfo& info, const char *name) {
return;
}
-GfxObj* AmigaDisk_ns::loadFrames(const char* name) {
+Frames* AmigaDisk_ns::loadFrames(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name);
Common::SeekableReadStream *s;
@@ -1273,7 +1273,7 @@ GfxObj* AmigaDisk_ns::loadFrames(const char* name) {
Cnv *cnv = makeCnv(*s);
delete s;
- return new GfxObj(0, cnv, name);
+ return cnv;
}
GfxObj* AmigaDisk_ns::loadHead(const char* name) {
diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h
new file mode 100644
index 0000000000..887d6be526
--- /dev/null
+++ b/engines/parallaction/exec.h
@@ -0,0 +1,241 @@
+/* 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 PARALLACTION_EXEC_H
+#define PARALLACTION_EXEC_H
+
+#include "common/util.h"
+#include "parallaction/objects.h"
+
+
+namespace Parallaction {
+
+typedef Common::Functor0<void> Opcode;
+typedef Common::Array<const Opcode*> OpcodeSet;
+
+#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
+#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
+
+class Parallaction_ns;
+class Parallaction_br;
+
+class CommandExec {
+protected:
+ struct ParallactionStruct1 {
+ CommandPtr cmd;
+ ZonePtr z;
+ } _ctxt;
+
+ OpcodeSet _opcodes;
+
+public:
+ virtual void init() = 0;
+ virtual void run(CommandList &list, ZonePtr z = nullZonePtr);
+ CommandExec() {
+ }
+ virtual ~CommandExec() {
+ for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
+ delete *i;
+ _opcodes.clear();
+ }
+};
+
+class CommandExec_ns : public CommandExec {
+
+ Parallaction_ns *_vm;
+
+protected:
+ void updateGetZone(ZonePtr z, bool visible);
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+
+public:
+ void init();
+
+ CommandExec_ns(Parallaction_ns* vm);
+ ~CommandExec_ns();
+};
+
+class CommandExec_br : public CommandExec_ns {
+
+protected:
+ Parallaction_br *_vm;
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
+
+public:
+ void init();
+
+ CommandExec_br(Parallaction_br* vm);
+ ~CommandExec_br();
+};
+
+
+
+
+
+class ProgramExec {
+protected:
+ struct ParallactionStruct2 {
+ AnimationPtr anim;
+ ProgramPtr program;
+ InstructionList::iterator inst;
+ uint16 modCounter;
+ bool suspend;
+ } _ctxt;
+
+ OpcodeSet _opcodes;
+
+ uint16 _modCounter;
+
+public:
+ virtual void init() = 0;
+ virtual void runScripts(ProgramList::iterator first, ProgramList::iterator last);
+ ProgramExec() : _modCounter(0) {
+ }
+ virtual ~ProgramExec() {
+ for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
+ delete *i;
+ _opcodes.clear();
+ }
+};
+
+class ProgramExec_ns : public ProgramExec {
+
+ Parallaction_ns *_vm;
+
+protected:
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
+public:
+ void init();
+
+ ProgramExec_ns(Parallaction_ns *vm);
+ ~ProgramExec_ns();
+};
+
+class ProgramExec_br : public ProgramExec_ns {
+
+ Parallaction_br *_vm;
+
+protected:
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
+public:
+ void init();
+ ProgramExec_br(Parallaction_br *vm);
+ ~ProgramExec_br();
+};
+
+} // namespace Parallaction
+
+#endif
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 348af2b731..edb832cffc 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
@@ -64,12 +65,13 @@ namespace Parallaction {
#define SetOpcodeTable(x) table = &x;
-typedef Common::Functor0Mem<void, Parallaction_br> OpcodeV2;
-#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::cmdOp_##op))
-#define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op()
+typedef Common::Functor0Mem<void, CommandExec_br> OpcodeV1;
+#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_br::cmdOp_##op))
+#define DECLARE_COMMAND_OPCODE(op) void CommandExec_br::cmdOp_##op()
-#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::instOp_##op))
-#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op()
+typedef Common::Functor0Mem<void, ProgramExec_br> OpcodeV2;
+#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_br::instOp_##op))
+#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_br::instOp_##op()
void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
debugC(5, kDebugExec, "setupSubtitles(%s, %s, %i)", s, s2, y);
@@ -100,8 +102,13 @@ void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
}
void Parallaction_br::clearSubtitles() {
- _gfx->hideLabel(_subtitle[0]);
- _gfx->hideLabel(_subtitle[1]);
+ if (_subtitle[0] != -1) {
+ _gfx->hideLabel(_subtitle[0]);
+ }
+
+ if (_subtitle[1] != -1) {
+ _gfx->hideLabel(_subtitle[1]);
+ }
}
@@ -109,7 +116,7 @@ DECLARE_COMMAND_OPCODE(location) {
warning("Parallaction_br::cmdOp_location command not yet implemented");
// TODO: handle startPos and startPos2
- scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string);
+ _vm->scheduleLocationSwitch(_ctxt.cmd->u._string);
}
@@ -124,7 +131,7 @@ DECLARE_COMMAND_OPCODE(close) {
DECLARE_COMMAND_OPCODE(on) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
+ CommandData *data = &_ctxt.cmd->u;
ZonePtr z = data->_zone;
if (z) {
@@ -132,28 +139,28 @@ DECLARE_COMMAND_OPCODE(on) {
z->_flags &= ~kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
}
}
}
DECLARE_COMMAND_OPCODE(off) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
+ CommandData *data = &_ctxt.cmd->u;
ZonePtr z = data->_zone;
if (z) {
z->_flags |= kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, false);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
}
}
}
DECLARE_COMMAND_OPCODE(call) {
- callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z);
+ _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z);
}
@@ -167,17 +174,17 @@ DECLARE_COMMAND_OPCODE(move) {
}
DECLARE_COMMAND_OPCODE(start) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing;
+ _ctxt.cmd->u._zone->_flags |= kFlagsActing;
}
DECLARE_COMMAND_OPCODE(stop) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsActing;
}
DECLARE_COMMAND_OPCODE(character) {
- debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _cmdRunCtxt.cmd->u._string);
- changeCharacter(_cmdRunCtxt.cmd->u._string);
+ debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _ctxt.cmd->u._string);
+ _vm->changeCharacter(_ctxt.cmd->u._string);
}
@@ -187,12 +194,12 @@ DECLARE_COMMAND_OPCODE(followme) {
DECLARE_COMMAND_OPCODE(onmouse) {
- _input->showCursor(true);
+ _vm->_input->showCursor(true);
}
DECLARE_COMMAND_OPCODE(offmouse) {
- _input->showCursor(false);
+ _vm->_input->showCursor(false);
}
@@ -207,42 +214,42 @@ DECLARE_COMMAND_OPCODE(leave) {
DECLARE_COMMAND_OPCODE(inc) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] += _ctxt.cmd->u._rvalue;
}
DECLARE_COMMAND_OPCODE(dec) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] -= _ctxt.cmd->u._rvalue;
}
DECLARE_COMMAND_OPCODE(ifeq) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] == _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(iflt) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] < _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(ifgt) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] > _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(let) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] = _ctxt.cmd->u._rvalue;
}
@@ -252,25 +259,25 @@ DECLARE_COMMAND_OPCODE(music) {
DECLARE_COMMAND_OPCODE(fix) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsFixed;
+ _ctxt.cmd->u._zone->_flags |= kFlagsFixed;
}
DECLARE_COMMAND_OPCODE(unfix) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed;
}
DECLARE_COMMAND_OPCODE(zeta) {
- _location._zeta0 = _cmdRunCtxt.cmd->u._zeta0;
- _location._zeta1 = _cmdRunCtxt.cmd->u._zeta1;
- _location._zeta2 = _cmdRunCtxt.cmd->u._zeta2;
+ _vm->_location._zeta0 = _ctxt.cmd->u._zeta0;
+ _vm->_location._zeta1 = _ctxt.cmd->u._zeta1;
+ _vm->_location._zeta2 = _ctxt.cmd->u._zeta2;
}
DECLARE_COMMAND_OPCODE(scroll) {
warning("Parallaction_br::cmdOp_scroll not yet implemented");
- _gfx->setVar("scroll_x", _cmdRunCtxt.cmd->u._rvalue );
+ _vm->_gfx->setVar("scroll_x", _ctxt.cmd->u._rvalue );
}
@@ -285,8 +292,8 @@ DECLARE_COMMAND_OPCODE(give) {
DECLARE_COMMAND_OPCODE(text) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
- setupSubtitles(data->_string, data->_string2, data->_zeta0);
+ CommandData *data = &_ctxt.cmd->u;
+ _vm->setupSubtitles(data->_string, data->_string2, data->_zeta0);
}
@@ -297,7 +304,7 @@ DECLARE_COMMAND_OPCODE(part) {
DECLARE_COMMAND_OPCODE(testsfx) {
warning("Parallaction_br::cmdOp_testsfx not completely implemented");
- clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled
+ _vm->clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled
}
@@ -319,7 +326,7 @@ DECLARE_COMMAND_OPCODE(offsave) {
DECLARE_INSTRUCTION_OPCODE(on) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
ZonePtr z = inst->_z;
if (z) {
@@ -327,28 +334,28 @@ DECLARE_INSTRUCTION_OPCODE(on) {
z->_flags &= ~kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
}
}
}
DECLARE_INSTRUCTION_OPCODE(off) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
ZonePtr z = inst->_z;
if (z) {
z->_flags |= kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, false);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
}
}
}
DECLARE_INSTRUCTION_OPCODE(set) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 rvalue = inst->_opB.getRValue();
int16* lvalue = inst->_opA.getLValue();
@@ -359,21 +366,21 @@ DECLARE_INSTRUCTION_OPCODE(set) {
DECLARE_INSTRUCTION_OPCODE(loop) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
- _instRunCtxt.program->_loopCounter = inst->_opB.getRValue();
- _instRunCtxt.program->_loopStart = _instRunCtxt.inst;
+ _ctxt.program->_loopCounter = inst->_opB.getRValue();
+ _ctxt.program->_loopStart = _ctxt.inst;
}
DECLARE_INSTRUCTION_OPCODE(inc) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 rvalue = inst->_opB.getRValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (rvalue > 0 ? rvalue : -rvalue);
- if (_instRunCtxt.modCounter % _bx != 0) return;
+ if (_ctxt.modCounter % _bx != 0) return;
rvalue = (rvalue > 0 ? 1 : -1);
}
@@ -420,12 +427,12 @@ DECLARE_INSTRUCTION_OPCODE(wait) {
DECLARE_INSTRUCTION_OPCODE(start) {
- (*_instRunCtxt.inst)->_z->_flags |= kFlagsActing;
+ (*_ctxt.inst)->_z->_flags |= kFlagsActing;
}
DECLARE_INSTRUCTION_OPCODE(process) {
- _activeZone2 = (*_instRunCtxt.inst)->_z;
+ _vm->_activeZone2 = (*_ctxt.inst)->_z;
}
@@ -435,18 +442,18 @@ DECLARE_INSTRUCTION_OPCODE(move) {
DECLARE_INSTRUCTION_OPCODE(color) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 entry = inst->_opB.getRValue();
- _gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
+ _vm->_gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
}
DECLARE_INSTRUCTION_OPCODE(mask) {
#if 0
- Instruction *inst = *_instRunCtxt.inst;
+ Instruction *inst = *_ctxt.inst;
_gfx->_bgLayers[0] = inst->_opA.getRValue();
_gfx->_bgLayers[1] = inst->_opB.getRValue();
_gfx->_bgLayers[2] = inst->_opC.getRValue();
@@ -459,8 +466,8 @@ DECLARE_INSTRUCTION_OPCODE(print) {
}
DECLARE_INSTRUCTION_OPCODE(text) {
- InstructionPtr inst = (*_instRunCtxt.inst);
- setupSubtitles(inst->_text, inst->_text2, inst->_y);
+ InstructionPtr inst = (*_ctxt.inst);
+ _vm->setupSubtitles(inst->_text, inst->_text2, inst->_y);
}
@@ -489,21 +496,20 @@ DECLARE_INSTRUCTION_OPCODE(stop) {
}
DECLARE_INSTRUCTION_OPCODE(endscript) {
- if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) {
- _instRunCtxt.anim->_flags &= ~kFlagsActing;
- runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim);
- _instRunCtxt.program->_status = kProgramDone;
+ if ((_ctxt.anim->_flags & kFlagsLooping) == 0) {
+ _ctxt.anim->_flags &= ~kFlagsActing;
+ _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim);
+ _ctxt.program->_status = kProgramDone;
}
- _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin();
+ _ctxt.program->_ip = _ctxt.program->_instructions.begin();
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
-void Parallaction_br::initOpcodes() {
-
+void CommandExec_br::init() {
Common::Array<const Opcode*> *table = 0;
- SetOpcodeTable(_commandOpcodes);
+ SetOpcodeTable(_opcodes);
COMMAND_OPCODE(invalid);
COMMAND_OPCODE(set);
COMMAND_OPCODE(clear);
@@ -546,8 +552,21 @@ void Parallaction_br::initOpcodes() {
COMMAND_OPCODE(ret);
COMMAND_OPCODE(onsave);
COMMAND_OPCODE(offsave);
+}
+
+CommandExec_br::CommandExec_br(Parallaction_br* vm) : CommandExec_ns(vm), _vm(vm) {
+
+}
+
+CommandExec_br::~CommandExec_br() {
- SetOpcodeTable(_instructionOpcodes);
+}
+
+void ProgramExec_br::init() {
+
+ Common::Array<const Opcode*> *table = 0;
+
+ SetOpcodeTable(_opcodes);
INSTRUCTION_OPCODE(invalid);
INSTRUCTION_OPCODE(on);
INSTRUCTION_OPCODE(off);
@@ -582,6 +601,12 @@ void Parallaction_br::initOpcodes() {
INSTRUCTION_OPCODE(endscript);
}
+ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : ProgramExec_ns(vm), _vm(vm) {
+}
+
+ProgramExec_br::~ProgramExec_br() {
+}
+
#if 0
void Parallaction_br::jobWaitRemoveLabelJob(void *parm, Job *job) {
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index bd2d54c0a0..9cde27a853 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
@@ -52,18 +53,19 @@ namespace Parallaction {
#define SetOpcodeTable(x) table = &x;
-typedef Common::Functor0Mem<void, Parallaction_ns> OpcodeV2;
-#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::cmdOp_##op))
-#define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op()
+typedef Common::Functor0Mem<void, CommandExec_ns> OpcodeV1;
+#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_ns::cmdOp_##op))
+#define DECLARE_COMMAND_OPCODE(op) void CommandExec_ns::cmdOp_##op()
-#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::instOp_##op))
-#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op()
+typedef Common::Functor0Mem<void, ProgramExec_ns> OpcodeV2;
+#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_ns::instOp_##op))
+#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_ns::instOp_##op()
DECLARE_INSTRUCTION_OPCODE(on) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
inst->_a->_flags |= kFlagsActive;
inst->_a->_flags &= ~kFlagsRemove;
@@ -71,31 +73,31 @@ DECLARE_INSTRUCTION_OPCODE(on) {
DECLARE_INSTRUCTION_OPCODE(off) {
- (*_instRunCtxt.inst)->_a->_flags |= kFlagsRemove;
+ (*_ctxt.inst)->_a->_flags |= kFlagsRemove;
}
DECLARE_INSTRUCTION_OPCODE(loop) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
- _instRunCtxt.program->_loopCounter = inst->_opB.getRValue();
- _instRunCtxt.program->_loopStart = _instRunCtxt.inst;
+ _ctxt.program->_loopCounter = inst->_opB.getRValue();
+ _ctxt.program->_loopStart = _ctxt.inst;
}
DECLARE_INSTRUCTION_OPCODE(endloop) {
- if (--_instRunCtxt.program->_loopCounter > 0) {
- _instRunCtxt.inst = _instRunCtxt.program->_loopStart;
+ if (--_ctxt.program->_loopCounter > 0) {
+ _ctxt.inst = _ctxt.program->_loopStart;
}
}
DECLARE_INSTRUCTION_OPCODE(inc) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 _si = inst->_opB.getRValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (_si > 0 ? _si : -_si);
- if (_instRunCtxt.modCounter % _bx != 0) return;
+ if (_modCounter % _bx != 0) return;
_si = (_si > 0 ? 1 : -1);
}
@@ -116,7 +118,7 @@ DECLARE_INSTRUCTION_OPCODE(inc) {
DECLARE_INSTRUCTION_OPCODE(set) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 _si = inst->_opB.getRValue();
int16 *lvalue = inst->_opA.getLValue();
@@ -127,7 +129,7 @@ DECLARE_INSTRUCTION_OPCODE(set) {
DECLARE_INSTRUCTION_OPCODE(put) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
Graphics::Surface v18;
v18.w = inst->_a->width();
v18.h = inst->_a->height();
@@ -137,7 +139,7 @@ DECLARE_INSTRUCTION_OPCODE(put) {
int16 y = inst->_opB.getRValue();
bool mask = (inst->_flags & kInstMaskedPut) == kInstMaskedPut;
- _gfx->patchBackground(v18, x, y, mask);
+ _vm->_gfx->patchBackground(v18, x, y, mask);
}
DECLARE_INSTRUCTION_OPCODE(null) {
@@ -145,154 +147,165 @@ DECLARE_INSTRUCTION_OPCODE(null) {
}
DECLARE_INSTRUCTION_OPCODE(invalid) {
- error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index);
+ error("Can't execute invalid opcode %i", (*_ctxt.inst)->_index);
}
DECLARE_INSTRUCTION_OPCODE(call) {
- callFunction((*_instRunCtxt.inst)->_immediate, 0);
+ _vm->callFunction((*_ctxt.inst)->_immediate, 0);
}
DECLARE_INSTRUCTION_OPCODE(wait) {
if (_engineFlags & kEngineWalking)
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
DECLARE_INSTRUCTION_OPCODE(start) {
- (*_instRunCtxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive);
+ (*_ctxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive);
}
DECLARE_INSTRUCTION_OPCODE(sound) {
- _activeZone = (*_instRunCtxt.inst)->_z;
+ _vm->_activeZone = (*_ctxt.inst)->_z;
}
DECLARE_INSTRUCTION_OPCODE(move) {
- InstructionPtr inst = (*_instRunCtxt.inst);
+ InstructionPtr inst = (*_ctxt.inst);
int16 x = inst->_opA.getRValue();
int16 y = inst->_opB.getRValue();
- _char.scheduleWalk(x, y);
+ _vm->_char.scheduleWalk(x, y);
}
DECLARE_INSTRUCTION_OPCODE(endscript) {
- if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) {
- _instRunCtxt.anim->_flags &= ~kFlagsActing;
- runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim);
- _instRunCtxt.program->_status = kProgramDone;
+ if ((_ctxt.anim->_flags & kFlagsLooping) == 0) {
+ _ctxt.anim->_flags &= ~kFlagsActing;
+ _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim);
+ _ctxt.program->_status = kProgramDone;
}
- _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin();
+ _ctxt.program->_ip = _ctxt.program->_instructions.begin();
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
DECLARE_COMMAND_OPCODE(invalid) {
- error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id);
+ error("Can't execute invalid command '%i'", _ctxt.cmd->_id);
}
DECLARE_COMMAND_OPCODE(set) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags |= _cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags |= _ctxt.cmd->u._flags;
} else {
- setLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->setLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(clear) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags &= ~_cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags &= ~_ctxt.cmd->u._flags;
} else {
- clearLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->clearLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(start) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing;
+ _ctxt.cmd->u._zone->_flags |= kFlagsActing;
}
DECLARE_COMMAND_OPCODE(speak) {
- _activeZone = _cmdRunCtxt.cmd->u._zone;
+ if ((_ctxt.cmd->u._zone->_type & 0xFFFF) == kZoneSpeak) {
+ _vm->enterDialogueMode(_ctxt.cmd->u._zone);
+ } else {
+ _vm->_activeZone = _ctxt.cmd->u._zone;
+ }
}
DECLARE_COMMAND_OPCODE(get) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
- runZone(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ _vm->runZone(_ctxt.cmd->u._zone);
}
DECLARE_COMMAND_OPCODE(location) {
- scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string);
+ _vm->scheduleLocationSwitch(_ctxt.cmd->u._string);
}
DECLARE_COMMAND_OPCODE(open) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) {
- updateDoor(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsClosed;
+ if (_ctxt.cmd->u._zone->u.door->gfxobj) {
+ _vm->updateDoor(_ctxt.cmd->u._zone);
}
}
DECLARE_COMMAND_OPCODE(close) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) {
- updateDoor(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags |= kFlagsClosed;
+ if (_ctxt.cmd->u._zone->u.door->gfxobj) {
+ _vm->updateDoor(_ctxt.cmd->u._zone);
}
}
+void CommandExec_ns::updateGetZone(ZonePtr z, bool visible) {
+ if (!z) {
+ return;
+ }
+
+ if ((z->_type & 0xFFFF) == kZoneGet) {
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, visible);
+ }
+}
DECLARE_COMMAND_OPCODE(on) {
- ZonePtr z = _cmdRunCtxt.cmd->u._zone;
- // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
- // the pointer to get structure members, thus leading to crashes in systems with memory
- // protection.
- // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
- // (print screen handler): this suggests that a system would hang when the print screen
- // key is pressed after playing Nippon Safes, provided that this code path is taken.
+ ZonePtr z = _ctxt.cmd->u._zone;
+
if (z) {
z->_flags &= ~kFlagsRemove;
z->_flags |= kFlagsActive;
- if ((z->_type & 0xFFFF) == kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
- }
+ updateGetZone(z, true);
}
}
DECLARE_COMMAND_OPCODE(off) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove;
+ ZonePtr z = _ctxt.cmd->u._zone;
+
+ if (z) {
+ _ctxt.cmd->u._zone->_flags |= kFlagsRemove;
+ updateGetZone(z, false);
+ }
}
DECLARE_COMMAND_OPCODE(call) {
- callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z);
+ _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z);
}
DECLARE_COMMAND_OPCODE(toggle) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags ^= _cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags ^= _ctxt.cmd->u._flags;
} else {
- toggleLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->toggleLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(drop){
- dropItem( _cmdRunCtxt.cmd->u._object );
+ _vm->dropItem( _ctxt.cmd->u._object );
}
@@ -302,16 +315,17 @@ DECLARE_COMMAND_OPCODE(quit) {
DECLARE_COMMAND_OPCODE(move) {
- _char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
+ _vm->_char.scheduleWalk(_ctxt.cmd->u._move.x, _ctxt.cmd->u._move.y);
}
DECLARE_COMMAND_OPCODE(stop) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsActing;
}
void Parallaction_ns::drawAnimations() {
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
uint16 layer = 0;
@@ -352,20 +366,20 @@ void Parallaction_ns::drawAnimations() {
}
}
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
+
return;
}
-void Parallaction_ns::runScripts() {
+void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator last) {
if (_engineFlags & kEnginePauseJobs) {
return;
}
debugC(9, kDebugExec, "runScripts");
- static uint16 modCounter = 0;
-
- for (ProgramList::iterator it = _location._programs.begin(); it != _location._programs.end(); it++) {
+ for (ProgramList::iterator it = first; it != last; it++) {
AnimationPtr a = (*it)->_anim;
@@ -382,17 +396,16 @@ void Parallaction_ns::runScripts() {
debugC(9, kDebugExec, "Animation: %s, instruction: %i", a->_name, (*inst)->_index); //_instructionNamesRes[(*inst)->_index - 1]);
- _instRunCtxt.inst = inst;
- _instRunCtxt.anim = AnimationPtr(a);
- _instRunCtxt.program = *it;
- _instRunCtxt.modCounter = modCounter;
- _instRunCtxt.suspend = false;
+ _ctxt.inst = inst;
+ _ctxt.anim = AnimationPtr(a);
+ _ctxt.program = *it;
+ _ctxt.suspend = false;
- (*_instructionOpcodes[(*inst)->_index])();
+ (*_opcodes[(*inst)->_index])();
- inst = _instRunCtxt.inst; // handles endloop correctly
+ inst = _ctxt.inst; // handles endloop correctly
- if (_instRunCtxt.suspend)
+ if (_ctxt.suspend)
goto label1;
inst++;
@@ -405,44 +418,49 @@ label1:
a->_z = a->_top + a->height();
}
- _char._ani->_z = _char._ani->height() + _char._ani->_top;
- if (_char._ani->gfxobj) {
- _char._ani->gfxobj->z = _char._ani->_z;
- }
- modCounter++;
+ _modCounter++;
return;
}
-
-void Parallaction::runCommands(CommandList& list, ZonePtr z) {
- if (list.size() == 0)
+void CommandExec::run(CommandList& list, ZonePtr z) {
+ if (list.size() == 0) {
+ debugC(3, kDebugExec, "runCommands: nothing to do");
return;
+ }
- debugC(3, kDebugExec, "runCommands");
+ debugC(3, kDebugExec, "runCommands starting");
+
+ uint32 useFlags = 0;
+ bool useLocalFlags;
CommandList::iterator it = list.begin();
for ( ; it != list.end(); it++) {
-
- CommandPtr cmd = *it;
- uint32 v8 = getLocationFlags();
-
if (_engineFlags & kEngineQuit)
break;
+ CommandPtr cmd = *it;
+
if (cmd->_flagsOn & kFlagsGlobal) {
- v8 = _commandFlags | kFlagsGlobal;
+ useFlags = _commandFlags | kFlagsGlobal;
+ useLocalFlags = false;
+ } else {
+ useFlags = _vm->getLocationFlags();
+ useLocalFlags = true;
}
- if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
- if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
+ bool onMatch = (cmd->_flagsOn & useFlags) == cmd->_flagsOn;
+ bool offMatch = (cmd->_flagsOff & ~useFlags) == cmd->_flagsOff;
+
+ debugC(3, kDebugExec, "runCommands[%i] (on: %x, off: %x), (%s = %x)", cmd->_id, cmd->_flagsOn, cmd->_flagsOff,
+ useLocalFlags ? "LOCALFLAGS" : "GLOBALFLAGS", useFlags);
-// debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
+ if (!onMatch || !offMatch) continue;
- _cmdRunCtxt.z = z;
- _cmdRunCtxt.cmd = cmd;
+ _ctxt.z = z;
+ _ctxt.cmd = cmd;
- (*_commandOpcodes[cmd->_id])();
+ (*_opcodes[cmd->_id])();
}
debugC(3, kDebugExec, "runCommands completed");
@@ -451,6 +469,13 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) {
}
+CommandExec_ns::CommandExec_ns(Parallaction_ns* vm) : _vm(vm) {
+
+}
+
+CommandExec_ns::~CommandExec_ns() {
+
+}
//
// ZONE TYPE: EXAMINE
@@ -469,7 +494,7 @@ void Parallaction::displayComment(ExamineData *data) {
}
_gfx->setHalfbriteMode(true);
- _gfx->setSingleBalloon(data->_description, 0, 90, 0, 0);
+ _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, 0);
Common::Rect r;
data->_cnv->getRect(0, r);
id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2);
@@ -477,7 +502,7 @@ void Parallaction::displayComment(ExamineData *data) {
id = _gfx->setItem(_char._head, 100, 152);
_gfx->setItemFrame(id, 0);
} else {
- _gfx->setSingleBalloon(data->_description, 140, 10, 0, 0);
+ _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, 0);
id = _gfx->setItem(_char._talk, 190, 80);
_gfx->setItemFrame(id, 0);
}
@@ -518,16 +543,13 @@ uint16 Parallaction::runZone(ZonePtr z) {
break;
case kZoneSpeak:
- runDialogue(z->u.speak);
- if (_engineFlags & kEngineQuit)
- return 0;
- break;
-
+ enterDialogueMode(z);
+ return 0;
}
debugC(3, kDebugExec, "runZone completed");
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
return 0;
}
@@ -654,11 +676,34 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
}
-void Parallaction_ns::initOpcodes() {
+void CommandExec_ns::init() {
+ Common::Array<const Opcode*> *table = 0;
+
+ SetOpcodeTable(_opcodes);
+ COMMAND_OPCODE(invalid);
+ COMMAND_OPCODE(set);
+ COMMAND_OPCODE(clear);
+ COMMAND_OPCODE(start);
+ COMMAND_OPCODE(speak);
+ COMMAND_OPCODE(get);
+ COMMAND_OPCODE(location);
+ COMMAND_OPCODE(open);
+ COMMAND_OPCODE(close);
+ COMMAND_OPCODE(on);
+ COMMAND_OPCODE(off);
+ COMMAND_OPCODE(call);
+ COMMAND_OPCODE(toggle);
+ COMMAND_OPCODE(drop);
+ COMMAND_OPCODE(quit);
+ COMMAND_OPCODE(move);
+ COMMAND_OPCODE(stop);
+}
+
+void ProgramExec_ns::init() {
Common::Array<const Opcode*> *table = 0;
- SetOpcodeTable(_instructionOpcodes);
+ SetOpcodeTable(_opcodes);
INSTRUCTION_OPCODE(invalid);
INSTRUCTION_OPCODE(on);
INSTRUCTION_OPCODE(off);
@@ -680,25 +725,12 @@ void Parallaction_ns::initOpcodes() {
INSTRUCTION_OPCODE(move);
INSTRUCTION_OPCODE(endscript);
- SetOpcodeTable(_commandOpcodes);
- COMMAND_OPCODE(invalid);
- COMMAND_OPCODE(set);
- COMMAND_OPCODE(clear);
- COMMAND_OPCODE(start);
- COMMAND_OPCODE(speak);
- COMMAND_OPCODE(get);
- COMMAND_OPCODE(location);
- COMMAND_OPCODE(open);
- COMMAND_OPCODE(close);
- COMMAND_OPCODE(on);
- COMMAND_OPCODE(off);
- COMMAND_OPCODE(call);
- COMMAND_OPCODE(toggle);
- COMMAND_OPCODE(drop);
- COMMAND_OPCODE(quit);
- COMMAND_OPCODE(move);
- COMMAND_OPCODE(stop);
}
+ProgramExec_ns::ProgramExec_ns(Parallaction_ns *vm) : _vm(vm) {
+}
+
+ProgramExec_ns::~ProgramExec_ns() {
+}
} // namespace Parallaction
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 383f5d549c..e8250ac8fd 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -32,7 +32,7 @@
namespace Parallaction {
-GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(0), _keep(true) {
+GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(kGfxObjNormal), _keep(true) {
if (name) {
_name = strdup(name);
} else {
@@ -86,12 +86,14 @@ void GfxObj::clearFlags(uint32 flags) {
}
GfxObj* Gfx::loadAnim(const char *name) {
- GfxObj *obj = _disk->loadFrames(name);
+ Frames* frames = _disk->loadFrames(name);
+ assert(frames);
+
+ GfxObj *obj = new GfxObj(kGfxObjTypeAnim, frames, name);
assert(obj);
// animation Z is not set here, but controlled by game scripts and user interaction.
// it is always >=0 and <screen height
- obj->type = kGfxObjTypeAnim;
obj->transparentKey = 0;
_gfxobjList.push_back(obj);
return obj;
@@ -110,34 +112,43 @@ GfxObj* Gfx::loadGet(const char *name) {
}
GfxObj* Gfx::loadDoor(const char *name) {
- GfxObj *obj = _disk->loadFrames(name);
+ Frames *frames = _disk->loadFrames(name);
+ assert(frames);
+
+ GfxObj *obj = new GfxObj(kGfxObjTypeDoor, frames, name);
assert(obj);
obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first
- obj->type = kGfxObjTypeDoor;
obj->transparentKey = 0;
_gfxobjList.push_back(obj);
return obj;
}
-void Gfx::clearGfxObjects() {
- _gfxobjList.clear();
+void Gfx::clearGfxObjects(uint filter) {
+
+ GfxObjList::iterator b = _gfxobjList.begin();
+ GfxObjList::iterator e = _gfxobjList.end();
+
+ for ( ; b != e; ) {
+ if (((*b)->_flags & filter) != 0) {
+ b = _gfxobjList.erase(b);
+ } else {
+ b++;
+ }
+ }
+
}
void Gfx::showGfxObj(GfxObj* obj, bool visible) {
-// if (!obj || obj->isVisible() == visible) {
-// return;
-// }
-
- assert(obj);
+ if (!obj) {
+ return;
+ }
if (visible) {
obj->setFlags(kGfxObjVisible);
} else {
obj->clearFlags(kGfxObjVisible);
-// _gfxobjList.remove(obj);
}
-
}
@@ -181,8 +192,6 @@ void Gfx::drawGfxObjects(Graphics::Surface &surf) {
sortAnimations();
// TODO: some zones don't appear because of wrong masking (3 or 0?)
- // TODO: Dr.Ki is not visible inside the club
-
GfxObjList::iterator b = _gfxobjList.begin();
GfxObjList::iterator e = _gfxobjList.end();
@@ -258,9 +267,6 @@ void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte
}
-// this is the maximum size of an unpacked frame in BRA
-byte _unpackedBitmap[640*401];
-
#if 0
void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 838827b19f..9b9ea8605a 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -33,6 +33,11 @@
namespace Parallaction {
+// this is the size of the receiving buffer for unpacked frames,
+// since BRA uses some insanely big animations.
+#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401
+
+
void Gfx::registerVar(const Common::String &name, int32 initialValue) {
if (_vars.contains(name)) {
warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str());
@@ -64,10 +69,6 @@ int32 Gfx::getVar(const Common::String &name) {
#define LABEL_TRANSPARENT_COLOR 0xFF
-#define BALLOON_TRANSPARENT_COLOR 2
-
-
-int16 Gfx::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 };
void halfbritePixel(int x, int y, int color, void *data) {
byte *buffer = (byte*)data;
@@ -238,37 +239,6 @@ void Palette::rotate(uint first, uint last, bool forward) {
}
-#define BALLOON_TAIL_WIDTH 12
-#define BALLOON_TAIL_HEIGHT 10
-
-
-byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
- {
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- },
- {
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02
- }
-};
-
void Gfx::setPalette(Palette pal) {
byte sysPal[256*4];
@@ -362,15 +332,13 @@ void Gfx::drawItems() {
}
void Gfx::drawBalloons() {
- if (_numBalloons == 0) {
+ if (_balloons.size() == 0) {
return;
}
Graphics::Surface *surf = g_system->lockScreen();
- for (uint i = 0; i < _numBalloons; i++) {
- Common::Rect r(_balloons[i].surface.w, _balloons[i].surface.h);
- r.moveTo(_balloons[i].x, _balloons[i].y);
- blt(r, (byte*)_balloons[i].surface.getBasePtr(0, 0), surf, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR);
+ for (uint i = 0; i < _balloons.size(); i++) {
+ drawGfxObject(_balloons[i], *surf, false);
}
g_system->unlockScreen();
}
@@ -686,6 +654,7 @@ void Gfx::freeLabels() {
delete _labels[i];
}
_labels.clear();
+ _floatingLabel = NO_FLOATING_LABEL;
}
void Gfx::drawLabels() {
@@ -779,7 +748,6 @@ Gfx::Gfx(Parallaction* vm) :
setPalette(_palette);
- _numBalloons = 0;
_numItems = 0;
_floatingLabel = NO_FLOATING_LABEL;
@@ -789,6 +757,9 @@ Gfx::Gfx(Parallaction* vm) :
_halfbrite = false;
_hbCircleRadius = 0;
+ _unpackedBitmap = new byte[MAXIMUM_UNPACKED_BITMAP_SIZE];
+ assert(_unpackedBitmap);
+
registerVar("background_mode", 1);
_varBackgroundMode = 1;
@@ -804,6 +775,9 @@ Gfx::Gfx(Parallaction* vm) :
Gfx::~Gfx() {
freeBackground();
+ freeLabels();
+
+ delete []_unpackedBitmap;
return;
}
@@ -830,138 +804,31 @@ void Gfx::setItemFrame(uint item, uint16 f) {
_items[item].data->setFlags(kGfxObjVisible);
}
-Gfx::Balloon* Gfx::getBalloon(uint id) {
- assert(id < _numBalloons);
- return &_balloons[id];
-}
-
-int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) {
- assert(_numBalloons < 5);
-
- int id = _numBalloons;
-
- Gfx::Balloon *balloon = &_balloons[id];
-
- int16 real_h = (winding == -1) ? h : h + 9;
- balloon->surface.create(w, real_h, 1);
- balloon->surface.fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR);
- Common::Rect r(w, h);
- balloon->surface.fillRect(r, 0);
- balloon->outerBox = r;
+GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) {
- r.grow(-borderThickness);
- balloon->surface.fillRect(r, 1);
- balloon->innerBox = r;
-
- if (winding != -1) {
- // draws tail
- // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
- winding = (winding == 0 ? 1 : 0);
- Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
- s.moveTo(r.width()/2 - 5, r.bottom - 1);
- blt(s, _resBalloonTail[winding], &balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR);
- }
-
- _numBalloons++;
-
- return id;
-}
-
-int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+5, h, winding, 1);
- Gfx::Balloon *balloon = &_balloons[id];
-
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-
- balloon->x = x;
- balloon->y = y;
-
- return id;
-}
+ GfxObj *obj = new GfxObj(kGfxObjTypeBalloon, frames, text);
-int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+5, h, winding, 1);
- Gfx::Balloon *balloon = &_balloons[id];
-
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-
- balloon->x = _dialogueBalloonX[id];
- balloon->y = 10;
-
- if (id > 0) {
- balloon->y += _balloons[id - 1].y + _balloons[id - 1].outerBox.height();
- }
-
-
- return id;
-}
-
-void Gfx::setBalloonText(uint id, char *text, byte textColor) {
- Gfx::Balloon *balloon = getBalloon(id);
- balloon->surface.fillRect(balloon->innerBox, 1);
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-}
-
-
-int Gfx::setLocationBalloon(char *text, bool endGame) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR);
- Gfx::Balloon *balloon = &_balloons[id];
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, 0, MAX_BALLOON_WIDTH);
-
- balloon->x = 5;
- balloon->y = 5;
-
- return id;
-}
-
-int Gfx::hitTestDialogueBalloon(int x, int y) {
-
- Common::Point p;
-
- for (uint i = 0; i < _numBalloons; i++) {
- p.x = x - _balloons[i].x;
- p.y = y - _balloons[i].y;
+ obj->layer = LAYER_FOREGROUND;
+ obj->frame = 0;
+ obj->setFlags(kGfxObjVisible);
- if (_balloons[i].innerBox.contains(p))
- return i;
- }
+ _balloons.push_back(obj);
- return -1;
+ return obj;
}
-
-void Gfx::freeBalloons() {
- for (uint i = 0; i < _numBalloons; i++) {
- _balloons[i].surface.free();
+void Gfx::destroyBalloons() {
+ for (uint i = 0; i < _balloons.size(); i++) {
+ delete _balloons[i];
}
- _numBalloons = 0;
+ _balloons.clear();
}
void Gfx::freeItems() {
_numItems = 0;
}
-void Gfx::hideDialogueStuff() {
- freeItems();
- freeBalloons();
-}
-
void Gfx::freeBackground() {
_backgroundInfo.free();
}
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index df4cab4caf..a7242ba6f4 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -340,11 +340,15 @@ class Disk;
enum {
kGfxObjVisible = 1,
+ kGfxObjNormal = 2,
+ kGfxObjCharacter = 4,
kGfxObjTypeDoor = 0,
kGfxObjTypeGet = 1,
kGfxObjTypeAnim = 2,
- kGfxObjTypeLabel = 3
+ kGfxObjTypeLabel = 3,
+ kGfxObjTypeBalloon = 4,
+ kGfxObjTypeCharacter = 8
};
enum {
@@ -355,7 +359,6 @@ enum {
class GfxObj {
char *_name;
Frames *_frames;
- uint32 _flags;
bool _keep;
@@ -364,6 +367,7 @@ public:
int32 z;
+ uint32 _flags;
uint type;
uint frame;
@@ -449,6 +453,20 @@ enum {
kBackgroundSlide = 2
};
+
+class BalloonManager {
+public:
+ virtual ~BalloonManager() { }
+
+ virtual void freeBalloons() = 0;
+ virtual int setLocationBalloon(char *text, bool endGame) = 0;
+ virtual int setDialogueBalloon(char *text, uint16 winding, byte textColor) = 0;
+ virtual int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) = 0;
+ virtual void setBalloonText(uint id, char *text, byte textColor) = 0;
+ virtual int hitTestDialogueBalloon(int x, int y) = 0;
+};
+
+
typedef Common::HashMap<Common::String, int32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VarMap;
class Gfx {
@@ -463,7 +481,7 @@ public:
GfxObj* loadDoor(const char *name);
void drawGfxObjects(Graphics::Surface &surf);
void showGfxObj(GfxObj* obj, bool visible);
- void clearGfxObjects();
+ void clearGfxObjects(uint filter);
void sortAnimations();
@@ -478,12 +496,9 @@ public:
void freeLabels();
// dialogue balloons
- int setLocationBalloon(char *text, bool endGame);
- int setDialogueBalloon(char *text, uint16 winding, byte textColor);
- int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
- void setBalloonText(uint id, char *text, byte textColor);
- int hitTestDialogueBalloon(int x, int y);
void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height);
+ GfxObj* registerBalloon(Frames *frames, const char *text);
+ void destroyBalloons();
// other items
int setItem(GfxObj* obj, uint16 x, uint16 y, byte transparentColor = 0);
@@ -532,6 +547,8 @@ public:
uint _screenX; // scrolling position
uint _screenY;
+ byte *_unpackedBitmap;
+
protected:
Parallaction* _vm;
bool _halfbrite;
@@ -549,18 +566,6 @@ protected:
int32 getRenderMode(const char *type);
public:
- static int16 _dialogueBalloonX[5];
-
- struct Balloon {
- uint16 x;
- uint16 y;
- Common::Rect outerBox;
- Common::Rect innerBox;
- uint16 winding;
- Graphics::Surface surface;
- } _balloons[5];
-
- uint _numBalloons;
struct Item {
GfxObj *data;
@@ -573,6 +578,7 @@ public:
typedef Common::Array<GfxObj*> GfxObjArray;
GfxObjArray _labels;
+ GfxObjArray _balloons;
uint _floatingLabel;
@@ -584,9 +590,6 @@ public:
void copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst);
- int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
- Balloon *getBalloon(uint id);
-
// low level text and patches
void drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color);
void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index 5551108693..0be070e345 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -195,7 +195,7 @@ int Parallaction_br::guiShowMenu() {
}
_system->showMouse(false);
- _gfx->hideDialogueStuff();
+ hideDialogueStuff();
for (i = 0; i < availItems; i++) {
delete _lines[i];
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index e758bbd41c..9601ae3b36 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -42,12 +42,14 @@ uint16 Input::readInput() {
uint16 KeyDown = 0;
_mouseButtons = kMouseNone;
+ _lastKeyDownAscii = -1;
Common::EventManager *eventMan = _vm->_system->getEventManager();
while (eventMan->pollEvent(e)) {
switch (e.type) {
case Common::EVENT_KEYDOWN:
+ _lastKeyDownAscii = e.kbd.ascii;
if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd')
_vm->_debugger->attach();
if (_vm->getFeatures() & GF_DEMO) break;
@@ -97,6 +99,11 @@ uint16 Input::readInput() {
}
+bool Input::getLastKeyDown(uint16 &ascii) {
+ ascii = _lastKeyDownAscii;
+ return (_lastKeyDownAscii != -1);
+}
+
// FIXME: see comment for readInput()
void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) {
@@ -174,7 +181,7 @@ void Input::updateGameInput() {
void Input::updateCommentInput() {
waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
_vm->_gfx->setHalfbriteMode(false);
_inputMode = kInputModeGame;
@@ -192,11 +199,38 @@ InputData* Input::updateInput() {
case kInputModeGame:
updateGameInput();
break;
+
+ case kInputModeDialogue:
+ readInput();
+ break;
}
return &_inputData;
}
+void Input::trackMouse(ZonePtr z) {
+ if ((z != _hoverZone) && (_hoverZone)) {
+ stopHovering();
+ return;
+ }
+
+ if (!z) {
+ return;
+ }
+
+ if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
+ _hoverZone = z;
+ _vm->_gfx->showFloatingLabel(_hoverZone->_label);
+ return;
+ }
+}
+
+void Input::stopHovering() {
+ _hoverZone = nullZonePtr;
+ _vm->_gfx->hideFloatingLabel();
+}
+
+
bool Input::translateGameInput() {
if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) {
@@ -231,23 +265,10 @@ bool Input::translateGameInput() {
return true;
}
- if ((z != _hoverZone) && (_hoverZone)) {
- _hoverZone = nullZonePtr;
- _inputData._event = kEvExitZone;
- return true;
- }
-
- if (!z) {
- _inputData._event = kEvNone;
- return true;
- }
-
- if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
- _hoverZone = z;
- _inputData._event = kEvEnterZone;
- _inputData._label = z->_label;
- return true;
- }
+ trackMouse(z);
+ if (!z) {
+ return true;
+ }
if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) {
@@ -302,7 +323,7 @@ bool Input::translateInventoryInput() {
_vm->dropItem(z->u.merge->_obj1);
_vm->dropItem(z->u.merge->_obj2);
_vm->addInventoryItem(z->u.merge->_obj3);
- _vm->runCommands(z->_commands);
+ _vm->_cmdExec->run(z->_commands);
}
return true;
diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h
index e06fe96705..f260352dba 100644
--- a/engines/parallaction/input.h
+++ b/engines/parallaction/input.h
@@ -66,6 +66,7 @@ class Input {
Common::Point _mousePos;
uint16 _mouseButtons;
+ int32 _lastKeyDownAscii;
bool _mouseHidden;
ZonePtr _hoverZone;
@@ -73,7 +74,8 @@ class Input {
public:
enum {
kInputModeGame = 0,
- kInputModeComment = 1
+ kInputModeComment = 1,
+ kInputModeDialogue = 2
};
@@ -99,14 +101,13 @@ public:
uint16 readInput();
InputData* updateInput();
+ void trackMouse(ZonePtr z);
void waitUntilLeftClick();
void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1);
uint32 getLastButtonEvent() { return _mouseButtons; }
+ bool getLastKeyDown(uint16 &ascii);
- void stopHovering() {
- _hoverZone = nullZonePtr;
- }
-
+ void stopHovering();
};
} // namespace Parallaction
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index 2478b4b2e1..fb867f5285 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/parallaction
MODULE_OBJS := \
+ balloons.o \
callables_br.o \
callables_ns.o \
debug.o \
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index 54afabc318..66025cf0f7 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -54,6 +54,7 @@ Animation::Animation() {
Animation::~Animation() {
free(_scriptName);
+ gfxobj->release();
}
uint16 Animation::width() const {
@@ -182,6 +183,8 @@ Zone::~Zone() {
break;
}
+
+ free(_linkedName);
}
void Zone::getRect(Common::Rect& r) const {
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 5f5cfdb820..cd852f7c84 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -84,13 +84,15 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
Parallaction::~Parallaction() {
- clearSet(_commandOpcodes);
- clearSet(_instructionOpcodes);
-
delete _debugger;
delete _globalTable;
delete _callableNames;
+ delete _cmdExec;
+ delete _programExec;
+ _gfx->clearGfxObjects(kGfxObjCharacter | kGfxObjNormal);
+ hideDialogueStuff();
+ delete _balloonMan;
freeLocation();
freeCharacter();
@@ -134,6 +136,8 @@ int Parallaction::init() {
_debugger = new Debugger(this);
+ setupBalloonManager();
+
return 0;
}
@@ -157,6 +161,11 @@ void Parallaction::updateView() {
}
+void Parallaction::hideDialogueStuff() {
+ _gfx->freeItems();
+ _balloonMan->freeBalloons();
+}
+
void Parallaction::freeCharacter() {
debugC(1, kDebugExec, "freeCharacter()");
@@ -164,6 +173,8 @@ void Parallaction::freeCharacter() {
delete _objectsNames;
_objectsNames = 0;
+ _gfx->clearGfxObjects(kGfxObjCharacter);
+
_char.free();
return;
@@ -246,7 +257,7 @@ void Parallaction::freeLocation() {
_location._walkNodes.clear();
- _gfx->clearGfxObjects();
+ _gfx->clearGfxObjects(kGfxObjNormal);
freeBackground();
_location._programs.clear();
@@ -281,23 +292,13 @@ void Parallaction::setBackground(const char* name, const char* mask, const char*
}
void Parallaction::showLocationComment(const char *text, bool end) {
- _gfx->setLocationBalloon(const_cast<char*>(text), end);
+ _balloonMan->setLocationBalloon(const_cast<char*>(text), end);
}
void Parallaction::processInput(InputData *data) {
switch (data->_event) {
- case kEvEnterZone:
- debugC(2, kDebugInput, "processInput: kEvEnterZone");
- _gfx->showFloatingLabel(data->_label);
- break;
-
- case kEvExitZone:
- debugC(2, kDebugInput, "processInput: kEvExitZone");
- _gfx->hideFloatingLabel();
- break;
-
case kEvAction:
debugC(2, kDebugInput, "processInput: kEvAction");
_input->stopHovering();
@@ -308,7 +309,6 @@ void Parallaction::processInput(InputData *data) {
case kEvOpenInventory:
_input->stopHovering();
- _gfx->hideFloatingLabel();
if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) {
setArrowCursor();
}
@@ -357,36 +357,43 @@ void Parallaction::processInput(InputData *data) {
void Parallaction::runGame() {
InputData *data = _input->updateInput();
- if (data->_event != kEvNone) {
- processInput(data);
- }
-
if (_engineFlags & kEngineQuit)
return;
- runPendingZones();
+ if (_input->_inputMode == Input::kInputModeDialogue) {
+ runDialogueFrame();
+ } else {
+ if (data->_event != kEvNone) {
+ processInput(data);
+ }
- if (_engineFlags & kEngineQuit)
- return;
+ if (_engineFlags & kEngineQuit)
+ return;
- if (_engineFlags & kEngineChangeLocation) {
- changeLocation(_location._name);
- }
+ runPendingZones();
- if (_engineFlags & kEngineQuit)
- return;
+ if (_engineFlags & kEngineQuit)
+ return;
+
+ if (_engineFlags & kEngineChangeLocation) {
+ changeLocation(_location._name);
+ }
+ }
_gfx->beginFrame();
if (_input->_inputMode == Input::kInputModeGame) {
- runScripts();
- walk();
+ _programExec->runScripts(_location._programs.begin(), _location._programs.end());
+ _char._ani->_z = _char._ani->height() + _char._ani->_top;
+ if (_char._ani->gfxobj) {
+ _char._ani->gfxobj->z = _char._ani->_z;
+ }
+ walk(_char);
drawAnimations();
}
// change this to endFrame?
updateView();
-
}
@@ -415,14 +422,14 @@ void Parallaction::doLocationEnterTransition() {
pal.makeGrayscale();
_gfx->setPalette(pal);
- runScripts();
+ _programExec->runScripts(_location._programs.begin(), _location._programs.end());
drawAnimations();
_gfx->updateScreen();
showLocationComment(_location._comment, false);
_input->waitUntilLeftClick();
- _gfx->freeBalloons();
+ _balloonMan->freeBalloons();
// fades maximum intensity palette towards approximation of main palette
for (uint16 _si = 0; _si<6; _si++) {
@@ -493,6 +500,34 @@ void Parallaction::freeZones() {
}
+enum {
+ WALK_LEFT = 0,
+ WALK_RIGHT = 1,
+ WALK_DOWN = 2,
+ WALK_UP = 3
+};
+
+struct WalkFrames {
+ int16 stillFrame[4];
+ int16 firstWalkFrame[4];
+ int16 numWalkFrames[4];
+ int16 frameRepeat[4];
+};
+
+WalkFrames _char20WalkFrames = {
+ { 0, 7, 14, 17 },
+ { 1, 8, 15, 18 },
+ { 6, 6, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
+WalkFrames _char24WalkFrames = {
+ { 0, 9, 18, 21 },
+ { 1, 10, 19, 22 },
+ { 8, 8, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
const char Character::_prefixMini[] = "mini";
const char Character::_suffixTras[] = "tras";
const char Character::_empty[] = "\0";
@@ -503,6 +538,9 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder(
_head = NULL;
_objs = NULL;
+ _direction = WALK_DOWN;
+ _step = 0;
+
_dummy = false;
_ani->_left = 150;
@@ -567,10 +605,14 @@ void Character::setName(const char *name) {
const char *end = begin + strlen(name);
_prefix = _empty;
+ _suffix = _empty;
_dummy = IS_DUMMY_CHARACTER(name);
if (!_dummy) {
+ if (!strstr(name, "donna")) {
+ _engineFlags &= ~kEngineTransformedDonna;
+ } else
if (_engineFlags & kEngineTransformedDonna) {
_suffix = _suffixTras;
} else {
@@ -579,8 +621,6 @@ void Character::setName(const char *name) {
_engineFlags |= kEngineTransformedDonna;
_suffix = _suffixTras;
end = s;
- } else {
- _suffix = _empty;
}
}
if (IS_MINI_CHARACTER(name)) {
@@ -616,9 +656,35 @@ void Parallaction::beep() {
}
void Parallaction::scheduleLocationSwitch(const char *location) {
+ debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location);
strcpy(_location._name, location);
_engineFlags |= kEngineChangeLocation;
}
+
+
+
+void Character::updateDirection(const Common::Point& pos, const Common::Point& to) {
+
+ Common::Point dist(to.x - pos.x, to.y - pos.y);
+ WalkFrames *frames = (_ani->getFrameNum() == 20) ? &_char20WalkFrames : &_char24WalkFrames;
+
+ _step++;
+
+ if (dist.x == 0 && dist.y == 0) {
+ _ani->_frame = frames->stillFrame[_direction];
+ return;
+ }
+
+ if (dist.x < 0)
+ dist.x = -dist.x;
+ if (dist.y < 0)
+ dist.y = -dist.y;
+
+ _direction = (dist.x > dist.y) ? ((to.x > pos.x) ? WALK_LEFT : WALK_RIGHT) : ((to.y > pos.y) ? WALK_DOWN : WALK_UP);
+ _ani->_frame = frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction];
+}
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index b1a5995e28..c45d32b013 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -33,6 +33,7 @@
#include "engines/engine.h"
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/inventory.h"
#include "parallaction/parser.h"
@@ -113,8 +114,6 @@ enum EngineFlags {
enum {
kEvNone = 0,
- kEvEnterZone = 1,
- kEvExitZone = 2,
kEvAction = 3,
kEvOpenInventory = 4,
kEvCloseInventory = 5,
@@ -164,6 +163,7 @@ class Debugger;
class Gfx;
class SoundMan;
class Input;
+class DialogueManager;
struct Location {
@@ -228,18 +228,19 @@ protected:
static const char _suffixTras[];
static const char _empty[];
+ int16 _direction, _step;
+
public:
void setName(const char *name);
const char *getName() const;
const char *getBaseName() const;
const char *getFullName() const;
bool dummy() const;
-};
+ void updateDirection(const Common::Point& pos, const Common::Point& to);
+};
-#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
-#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
#define NUM_LOCATIONS 120
@@ -259,41 +260,20 @@ public:
Input *_input;
- OpcodeSet _commandOpcodes;
-
- struct ParallactionStruct1 {
- CommandPtr cmd;
- ZonePtr z;
- } _cmdRunCtxt;
-
- OpcodeSet _instructionOpcodes;
-
- struct ParallactionStruct2 {
- AnimationPtr anim;
- ProgramPtr program;
- InstructionList::iterator inst;
- uint16 modCounter;
- bool suspend;
- } _instRunCtxt;
-
void processInput(InputData* data);
void pauseJobs();
void resumeJobs();
- void finalizeWalk(WalkNodeList *list);
- int16 selectWalkFrame(const Common::Point& pos, const WalkNodePtr from);
- void clipMove(Common::Point& pos, const WalkNodePtr from);
+ void finalizeWalk(Character &character);
+ int16 selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to);
+ void clipMove(Common::Point& pos, const Common::Point& to);
ZonePtr findZone(const char *name);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
uint16 runZone(ZonePtr z);
void freeZones();
- void runDialogue(SpeakData*);
-
- void runCommands(CommandList& list, ZonePtr z = nullZonePtr);
-
AnimationPtr findAnimation(const char *name);
void freeAnimations();
@@ -327,6 +307,8 @@ public:
Gfx* _gfx;
Disk* _disk;
+ CommandExec* _cmdExec;
+ ProgramExec* _programExec;
Character _char;
void setLocationFlags(uint32 flags);
@@ -367,10 +349,8 @@ protected: // members
void runGame();
void updateView();
- void scheduleLocationSwitch(const char *location);
void doLocationEnterTransition();
virtual void changeLocation(char *location) = 0;
- virtual void changeCharacter(const char *name) = 0;
virtual void runPendingZones() = 0;
void allocateLocationSlot(const char *name);
void finalizeLocationParsing();
@@ -379,7 +359,7 @@ protected: // members
void displayComment(ExamineData *data);
- uint16 checkDoor();
+ void checkDoor(const Common::Point &foot);
void freeCharacter();
@@ -389,6 +369,9 @@ protected: // members
public:
+ void scheduleLocationSwitch(const char *location);
+ virtual void changeCharacter(const char *name) = 0;
+
virtual void callFunction(uint index, void* parm) { }
virtual void setArrowCursor() = 0;
@@ -398,12 +381,12 @@ public:
void updateDoor(ZonePtr z);
- virtual void runScripts() = 0;
- virtual void walk() = 0;
+ virtual void walk(Character &character) = 0;
virtual void drawAnimations() = 0;
void beep();
+ ZonePtr _zoneTrap;
public:
// const char **_zoneFlagNamesRes;
@@ -429,6 +412,16 @@ public:
Inventory *_inventory;
InventoryRenderer *_inventoryRenderer;
+ BalloonManager *_balloonMan;
+
+ void setupBalloonManager();
+
+ void hideDialogueStuff();
+ DialogueManager *_dialogueMan;
+ void enterDialogueMode(ZonePtr z);
+ void exitDialogueMode();
+ void runDialogueFrame();
+
};
@@ -524,7 +517,6 @@ private:
void initResources();
void initCursors();
- void initParsers();
static byte _resMouseArrow[256];
byte *_mouseArrow;
@@ -587,49 +579,12 @@ private:
const Callable *_callables;
protected:
- void runScripts();
- void walk();
+ void walk(Character &character);
void drawAnimations();
void parseLocation(const char *filename);
void loadProgram(AnimationPtr a, const char *filename);
- void initOpcodes();
-
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
-
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
-
void selectStartLocation();
void guiStart();
@@ -662,6 +617,9 @@ public:
typedef void (Parallaction_br::*Callable)(void*);
virtual void callFunction(uint index, void* parm);
void changeCharacter(const char *name);
+ void setupSubtitles(char *s, char *s2, int y);
+ void clearSubtitles();
+
public:
Table *_countersNames;
@@ -689,8 +647,6 @@ private:
void initResources();
void initFonts();
void freeFonts();
- void initOpcodes();
- void initParsers();
void setArrowCursor();
void setInventoryCursor(int pos);
@@ -732,68 +688,6 @@ private:
void parseLocation(const char* name);
void loadProgram(AnimationPtr a, const char *filename);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
-
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
-
- void setupSubtitles(char *s, char *s2, int y);
- void clearSubtitles();
#if 0
void jobWaitRemoveLabelJob(void *parm, Job *job);
void jobPauseSfx(void *parm, Job *job);
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index b22e1b0f2d..9e2a0f10f1 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -72,14 +72,21 @@ int Parallaction_br::init() {
initResources();
initFonts();
initCursors();
- initOpcodes();
_locationParser = new LocationParser_br(this);
_locationParser->init();
_programParser = new ProgramParser_br(this);
_programParser->init();
+ _cmdExec = new CommandExec_br(this);
+ _cmdExec->init();
+ _programExec = new ProgramExec_br(this);
+ _programExec->init();
+
_part = -1;
+ _subtitle[0] = -1;
+ _subtitle[1] = -1;
+
Parallaction::init();
return 0;
@@ -205,13 +212,21 @@ void Parallaction_br::runPendingZones() {
if (_activeZone) {
z = _activeZone; // speak Zone or sound
_activeZone = nullZonePtr;
- runZone(z); // FIXME: BRA doesn't handle sound yet
+ if ((z->_type & 0xFFFF) == kZoneSpeak) {
+ enterDialogueMode(z);
+ } else {
+ runZone(z); // FIXME: BRA doesn't handle sound yet
+ }
}
if (_activeZone2) {
z = _activeZone2; // speak Zone or sound
_activeZone2 = nullZonePtr;
- runZone(z);
+ if ((z->_type & 0xFFFF) == kZoneSpeak) {
+ enterDialogueMode(z);
+ } else {
+ runZone(z); // FIXME: BRA doesn't handle sound yet
+ }
}
}
@@ -221,10 +236,16 @@ void Parallaction_br::changeLocation(char *location) {
// free open location stuff
clearSubtitles();
freeBackground();
- _gfx->clearGfxObjects();
+ _gfx->clearGfxObjects(kGfxObjNormal | kGfxObjCharacter);
_location._programs.clear();
+
+ _location._animations.remove(_char._ani);
+
freeZones();
freeAnimations();
+
+ _location._animations.push_front(_char._ani);
+
// free(_location._comment);
// _location._comment = 0;
// _location._commands.clear();
@@ -233,9 +254,9 @@ void Parallaction_br::changeLocation(char *location) {
// load new location
parseLocation(location);
- runCommands(_location._commands);
+ _cmdExec->run(_location._commands);
// doLocationEnterTransition();
- runCommands(_location._aCommands);
+ _cmdExec->run(_location._aCommands);
_engineFlags &= ~kEngineChangeLocation;
}
@@ -284,12 +305,16 @@ void Parallaction_br::loadProgram(AnimationPtr a, const char *filename) {
void Parallaction_br::changeCharacter(const char *name) {
+ printf("changeCharacter(%s)\n", name);
+
const char *charName = _char.getName();
if (!scumm_stricmp(charName, name)) {
return;
}
_char.setName(name);
+ _char._ani->gfxobj = _gfx->loadAnim(name);
+ _char._ani->gfxobj->setFlags(kGfxObjCharacter);
_char._talk = _disk->loadTalk(name);
}
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index af848aa6af..9e925d1e1d 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -135,12 +135,16 @@ int Parallaction_ns::init() {
initResources();
initFonts();
initCursors();
- initOpcodes();
_locationParser = new LocationParser_ns(this);
_locationParser->init();
_programParser = new ProgramParser_ns(this);
_programParser->init();
+ _cmdExec = new CommandExec_ns(this);
+ _cmdExec->init();
+ _programExec = new ProgramExec_ns(this);
+ _programExec->init();
+
_introSarcData1 = 0;
_introSarcData2 = 1;
_introSarcData3 = 200;
@@ -187,7 +191,7 @@ void Parallaction_ns::setArrowCursor() {
debugC(1, kDebugInput, "setting mouse cursor to arrow");
// this stuff is needed to avoid artifacts with labels and selected items when switching cursors
- _gfx->hideFloatingLabel();
+ _input->stopHovering();
_input->_activeItem._id = 0;
_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
@@ -298,14 +302,16 @@ void Parallaction_ns::changeLocation(char *location) {
_soundMan->playLocationMusic(location);
- _gfx->hideFloatingLabel();
+ _input->stopHovering();
_gfx->freeLabels();
- _input->stopHovering();
+ _zoneTrap = nullZonePtr;
+
if (_engineFlags & kEngineBlockInput) {
setArrowCursor();
}
+ _gfx->showGfxObj(_char._ani->gfxobj, false);
_location._animations.remove(_char._ani);
freeLocation();
@@ -327,6 +333,7 @@ void Parallaction_ns::changeLocation(char *location) {
}
_location._animations.push_front(_char._ani);
+ _gfx->showGfxObj(_char._ani->gfxobj, true);
strcpy(_saveData1, locname.location());
parseLocation(_saveData1);
@@ -351,11 +358,11 @@ void Parallaction_ns::changeLocation(char *location) {
// and acommands are executed, so that it can be set again if needed.
_engineFlags &= ~kEngineChangeLocation;
- runCommands(_location._commands);
+ _cmdExec->run(_location._commands);
doLocationEnterTransition();
- runCommands(_location._aCommands);
+ _cmdExec->run(_location._aCommands);
if (_location._hasSound)
_soundMan->playSfx(_location._soundFile, 0, true);
@@ -411,6 +418,8 @@ void Parallaction_ns::changeCharacter(const char *name) {
Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
_char._ani->gfxobj = _gfx->loadAnim(_char.getFullName());
+ _char._ani->gfxobj->setFlags(kGfxObjCharacter);
+ _char._ani->gfxobj->clearFlags(kGfxObjNormal);
if (!_char.dummy()) {
if (getPlatform() == Common::kPlatformAmiga) {
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 51da7eb396..defc917a72 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -390,7 +390,7 @@ DECLARE_LOCATION_PARSER(flags) {
if ((_vm->getLocationFlags() & kFlagsVisited) == 0) {
// only for 1st visit
- _vm->clearLocationFlags(kFlagsAll);
+ _vm->clearLocationFlags((uint32)kFlagsAll);
int _si = 1;
do {
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index c654e3008e..2f4d2df776 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -1059,7 +1059,7 @@ DECLARE_LOCATION_PARSER(flags) {
if ((_vm->getLocationFlags() & kFlagsVisited) == 0) {
// only for 1st visit
- _vm->clearLocationFlags(kFlagsAll);
+ _vm->clearLocationFlags((uint32)kFlagsAll);
int _si = 1;
do {
diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp
index dd74e8f7aa..df6867a90c 100644
--- a/engines/parallaction/sound.cpp
+++ b/engines/parallaction/sound.cpp
@@ -175,6 +175,7 @@ void MidiPlayer::close() {
_mutex.lock();
_driver->setTimerCallback(NULL, NULL);
_driver->close();
+ delete _driver;
_driver = 0;
_parser->setMidiDriver(NULL);
delete _parser;
@@ -249,6 +250,9 @@ void DosSoundMan::stopMusic() {
}
void DosSoundMan::playCharacterMusic(const char *character) {
+ if (character == NULL) {
+ return;
+ }
if (!scumm_stricmp(_vm->_location._name, "night") ||
!scumm_stricmp(_vm->_location._name, "intsushi")) {
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 0a8ded9e29..a717b615e6 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -27,12 +27,6 @@
namespace Parallaction {
-static uint16 _doorData1 = 1000;
-static ZonePtr _zoneTrap;
-
-static uint16 walkData1 = 0;
-static uint16 walkData2 = 0; // next walk frame
-
inline byte PathBuffer::getValue(uint16 x, uint16 y) {
byte m = data[(x >> 3) + y * internalWidth];
@@ -259,172 +253,118 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNodePtr Node) {
return 1;
}
-void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr from) {
+void Parallaction::clipMove(Common::Point& pos, const Common::Point& to) {
- if ((pos.x < from->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
- pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x;
+ if ((pos.x < to.x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
+ pos.x = (pos.x + 2 < to.x) ? pos.x + 2 : to.x;
}
- if ((pos.x > from->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
- pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x;
+ if ((pos.x > to.x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
+ pos.x = (pos.x - 2 > to.x) ? pos.x - 2 : to.x;
}
- if ((pos.y < from->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
- pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y;
+ if ((pos.y < to.y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
+ pos.y = (pos.y + 2 <= to.y) ? pos.y + 2 : to.y;
}
- if ((pos.y > from->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
- pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y;
+ if ((pos.y > to.y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
+ pos.y = (pos.y - 2 >= to.y) ? pos.y - 2 : to.y;
}
return;
}
-int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr from) {
-
- Common::Point dist(from->_x - pos.x, from->_y - pos.y);
-
- if (dist.x < 0)
- dist.x = -dist.x;
- if (dist.y < 0)
- dist.y = -dist.y;
- walkData1++;
-
- // walk frame selection
- int16 v16;
- if (_char._ani->getFrameNum() == 20) {
-
- if (dist.x > dist.y) {
- walkData2 = (from->_x > pos.x) ? 0 : 7;
- walkData1 %= 12;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (from->_y > pos.y) ? 14 : 17;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- } else {
-
- if (dist.x > dist.y) {
- walkData2 = (from->_x > pos.x) ? 0 : 9;
- walkData1 %= 16;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (from->_y > pos.y) ? 18 : 21;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- }
-
- return v16;
-}
-
-uint16 Parallaction::checkDoor() {
-// printf("checkDoor()...");
-
- if (_currentLocationIndex != _doorData1) {
- _doorData1 = _currentLocationIndex;
- _zoneTrap = nullZonePtr;
- }
-
- _engineFlags &= ~kEngineWalking;
-
- Common::Point foot;
+void Parallaction::checkDoor(const Common::Point &foot) {
- _char.getFoot(foot);
ZonePtr z = hitZone(kZoneDoor, foot.x, foot.y);
-
if (z) {
-
if ((z->_flags & kFlagsClosed) == 0) {
_location._startPosition = z->u.door->_startPos;
_location._startFrame = z->u.door->_startFrame;
-
scheduleLocationSwitch(z->u.door->_location);
_zoneTrap = nullZonePtr;
-
} else {
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
}
}
- _char.getFoot(foot);
z = hitZone(kZoneTrap, foot.x, foot.y);
-
if (z) {
setLocationFlags(kFlagsEnter);
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
clearLocationFlags(kFlagsEnter);
_zoneTrap = z;
} else
if (_zoneTrap) {
setLocationFlags(kFlagsExit);
- runCommands(_zoneTrap->_commands, _zoneTrap);
+ _cmdExec->run(_zoneTrap->_commands, _zoneTrap);
clearLocationFlags(kFlagsExit);
_zoneTrap = nullZonePtr;
}
-// printf("done\n");
-
- _char._ani->_frame = walkData2;
- return _char._ani->_frame;
}
-void Parallaction::finalizeWalk(WalkNodeList *list) {
- checkDoor();
- delete list;
+void Parallaction::finalizeWalk(Character &character) {
+ _engineFlags &= ~kEngineWalking;
+
+ Common::Point foot;
+ character.getFoot(foot);
+ checkDoor(foot);
+
+ delete character._walkPath;
+ character._walkPath = 0;
}
-void Parallaction_ns::walk() {
+void Parallaction_ns::walk(Character &character) {
if ((_engineFlags & kEngineWalking) == 0) {
return;
}
- WalkNodeList *list = _char._walkPath;
-
- _char._ani->_oldPos.x = _char._ani->_left;
- _char._ani->_oldPos.y = _char._ani->_top;
-
- Common::Point pos;
- _char.getFoot(pos);
-
- WalkNodeList::iterator it = list->begin();
+ Common::Point curPos;
+ character.getFoot(curPos);
- if (it != list->end()) {
- if ((*it)->_x == pos.x && (*it)->_y == pos.y) {
+ // update target, if previous was reached
+ WalkNodeList::iterator it = character._walkPath->begin();
+ if (it != character._walkPath->end()) {
+ if ((*it)->_x == curPos.x && (*it)->_y == curPos.y) {
debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it)->_x, (*it)->_y);
- it = list->erase(it);
+ it = character._walkPath->erase(it);
}
}
- if (it == list->end()) {
- debugC(1, kDebugWalk, "walk reached last node");
-// j->_finished = 1;
- finalizeWalk(list);
- return;
- }
- _char._walkPath = list;
-
- // selectWalkFrame must be performed before position is changed by clipMove
- int16 v16 = selectWalkFrame(pos, *it);
- clipMove(pos, *it);
- _char.setFoot(pos);
+ // advance character towards the target
+ Common::Point targetPos;
+ if (it == character._walkPath->end()) {
+ debugC(1, kDebugWalk, "walk reached last node");
+ finalizeWalk(character);
+ targetPos = curPos;
+ } else {
+ if (*it) {
+ // targetPos is saved to help setting character direction
+ targetPos.x = (*it)->_x;
+ targetPos.y = (*it)->_y;
+ }
- Common::Point newpos(_char._ani->_left, _char._ani->_top);
+ Common::Point newPos(curPos);
+ clipMove(newPos, targetPos);
+ character.setFoot(newPos);
- if (newpos == _char._ani->_oldPos) {
- debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
-// j->_finished = 1;
- finalizeWalk(list);
- } else {
- _char._ani->_frame = v16 + walkData2 + 1;
+ if (newPos == curPos) {
+ debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
+ finalizeWalk(character);
+ targetPos = newPos; // when walking is interrupted, targetPos must be hacked so that a still frame can be selected
+ }
}
- return;
+ // targetPos is used to select the direction (and the walkFrame) of a character,
+ // since it doesn't cause the sudden changes in orientation that newPos would.
+ // Since newPos is 'adjusted' according to walkable areas, an imaginary line drawn
+ // from curPos to newPos is prone to abrutply change in direction, thus making the
+ // code select 'too different' frames when walking diagonally against obstacles,
+ // and yielding an annoying shaking effect in the character.
+ character.updateDirection(curPos, targetPos);
}
diff --git a/engines/queen/graphics.cpp b/engines/queen/graphics.cpp
index f863f7663c..6d0a11ccfe 100644
--- a/engines/queen/graphics.cpp
+++ b/engines/queen/graphics.cpp
@@ -1175,15 +1175,8 @@ BamScene::BamScene(QueenEngine *vm)
}
void BamScene::playSfx() {
- // Don't try to play all the sounds. This is only necessary for the
- // fight bam, in which the number of 'sfx bam frames' is too much
- // important / too much closer. The original game does not have
- // this problem since its playSfx() function returns immediately
- // if a sound is already being played.
- if (_lastSoundIndex == 0 || _index - _lastSoundIndex >= SFX_SKIP) {
- _vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
- _lastSoundIndex = _index;
- }
+ _vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
+ _lastSoundIndex = _index;
}
void BamScene::prepareAnimation() {
diff --git a/engines/queen/graphics.h b/engines/queen/graphics.h
index 6f00111635..7eadf9a191 100644
--- a/engines/queen/graphics.h
+++ b/engines/queen/graphics.h
@@ -248,10 +248,6 @@ public:
F_REQ_STOP = 2
};
- enum {
- SFX_SKIP = 8
- };
-
uint16 _flag, _index;
private:
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index d70fe7209d..f4e0116cf1 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -229,11 +229,6 @@ void PCSound::setVolume(int vol) {
_music->setVolume(vol);
}
-void PCSound::waitFinished(bool isSpeech) {
- while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle))
- _vm->input()->delay(10);
-}
-
void PCSound::playSound(const char *base, bool isSpeech) {
char name[13];
strcpy(name, base);
@@ -243,7 +238,13 @@ void PCSound::playSound(const char *base, bool isSpeech) {
name[i] = '0';
}
strcat(name, ".SB");
- waitFinished(isSpeech);
+ if (isSpeech) {
+ while (_mixer->isSoundHandleActive(_speechHandle)) {
+ _vm->input()->delay(10);
+ }
+ } else {
+ _mixer->stopHandle(_sfxHandle);
+ }
uint32 size;
Common::File *f = _vm->resource()->findSound(name, &size);
if (f) {
@@ -255,6 +256,8 @@ void PCSound::playSound(const char *base, bool isSpeech) {
}
void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
+ // In order to simplify the code, we don't parse the .sb header but hard-code the
+ // values. Refer to tracker item #1876741 for details on the format/fields.
int headerSize;
f->seek(2, SEEK_CUR);
uint16 version = f->readUint16LE();
@@ -276,7 +279,7 @@ void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *so
if (sound) {
f->read(sound, size);
byte flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE;
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, soundHandle, sound, size, 11025, flags);
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, soundHandle, sound, size, 11840, flags);
}
}
diff --git a/engines/queen/sound.h b/engines/queen/sound.h
index c2c1481cc6..331034f746 100644
--- a/engines/queen/sound.h
+++ b/engines/queen/sound.h
@@ -143,7 +143,6 @@ public:
void setVolume(int vol);
protected:
- void waitFinished(bool isSpeech);
void playSound(const char *base, bool isSpeech);
virtual void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) = 0;
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 9359c6610c..68d3010199 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -492,7 +492,7 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
// Note that GF_OLD_BUNDLE is true if and only if GF_OLD256 is false.
// Candidates: maniac enhanced, zak enhanced, indy3ega, loom
- if (g->version != 2 && g->version != 3 || (g->features & GF_OLD256))
+ if ((g->version != 2 && g->version != 3) || (g->features & GF_OLD256))
return false;
/* We distinguish the games by the presence/absence of
@@ -949,7 +949,7 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
- for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
// Obtain the last 2 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 2);
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 6d1cf1bbd8..e4e2b2b620 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -297,7 +297,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da
break;
case GUI::kListSelectionChangedCmd: {
if (_gfxWidget) {
- updateInfos();
+ updateInfos(true);
}
if (_saveMode) {
@@ -350,7 +350,7 @@ void SaveLoadChooser::reflowLayout() {
_fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR");
_fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG");
_fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB");
- updateInfos();
+ updateInfos(false);
} else {
_container->setFlags(GUI::WIDGET_INVISIBLE);
_gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
@@ -362,7 +362,7 @@ void SaveLoadChooser::reflowLayout() {
Dialog::reflowLayout();
}
-void SaveLoadChooser::updateInfos() {
+void SaveLoadChooser::updateInfos(bool redraw) {
int selItem = _list->getSelected();
Graphics::Surface *thumb;
thumb = _vm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);
@@ -376,7 +376,8 @@ void SaveLoadChooser::updateInfos() {
}
delete thumb;
- _gfxWidget->draw();
+ if (redraw)
+ _gfxWidget->draw();
InfoStuff infos;
memset(&infos, 0, sizeof(InfoStuff));
@@ -386,12 +387,14 @@ void SaveLoadChooser::updateInfos() {
(infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF,
infos.date & 0xFFFF);
_date->setLabel(buffer);
- _date->draw();
+ if (redraw)
+ _date->draw();
snprintf(buffer, 32, "Time: %.2d:%.2d",
(infos.time >> 8) & 0xFF, infos.time & 0xFF);
_time->setLabel(buffer);
- _time->draw();
+ if (redraw)
+ _time->draw();
int minutes = infos.playtime / 60;
int hours = minutes / 60;
@@ -400,19 +403,23 @@ void SaveLoadChooser::updateInfos() {
snprintf(buffer, 32, "Playtime: %.2d:%.2d",
hours & 0xFF, minutes & 0xFF);
_playtime->setLabel(buffer);
- _playtime->draw();
+ if (redraw)
+ _playtime->draw();
} else {
snprintf(buffer, 32, "No date saved");
_date->setLabel(buffer);
- _date->draw();
+ if (redraw)
+ _date->draw();
snprintf(buffer, 32, "No time saved");
_time->setLabel(buffer);
- _time->draw();
+ if (redraw)
+ _time->draw();
snprintf(buffer, 32, "No playtime saved");
_playtime->setLabel(buffer);
- _playtime->draw();
+ if (redraw)
+ _playtime->draw();
}
}
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index 7c99a0ebcc..0d04d8faea 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -69,7 +69,7 @@ protected:
uint8 _fillR, _fillG, _fillB;
- void updateInfos();
+ void updateInfos(bool redraw);
public:
SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine);
~SaveLoadChooser();
diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp
index 33e6748860..f8fb1efca2 100644
--- a/engines/scumm/he/resource_he.cpp
+++ b/engines/scumm/he/resource_he.cpp
@@ -522,12 +522,13 @@ int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base,
/* get a list of all resources at this level */
wr = list_resources(fi, base, &rescnt);
- if (wr == NULL)
+ if (wr == NULL) {
if (size != 0)
return size;
else
return 0;
-
+ }
+
/* process each resource listed */
for (c = 0 ; c < rescnt ; c++) {
/* (over)write the corresponding WinResource holder with the current */
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index 1511b9aefc..b18b0ba70f 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -102,10 +102,10 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound,
int32 version = file->readUint32BE();
if (version != 3) {
if (version == 2) {
- warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2.");
- warning("Suggested to recompress with latest tool from daily builds.");
+ warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2");
+ warning("Suggested to recompress with latest tool from daily builds");
} else
- error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d.", version);
+ error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d", version);
}
sound->bits = file->readUint32BE();
sound->freq = file->readUint32BE();
diff --git a/engines/scumm/imuse_digi/dimuse_track.h b/engines/scumm/imuse_digi/dimuse_track.h
index 33147128cb..2d4c673cf6 100644
--- a/engines/scumm/imuse_digi/dimuse_track.h
+++ b/engines/scumm/imuse_digi/dimuse_track.h
@@ -85,13 +85,15 @@ struct Track {
int getPan() const { return (pan != 64) ? 2 * pan - 127 : 0; }
int getVol() const { return vol / 1000; }
Audio::Mixer::SoundType getType() const {
- Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType;
+ Audio::Mixer::SoundType type;
if (volGroupId == 1)
type = Audio::Mixer::kSpeechSoundType;
else if (volGroupId == 2)
type = Audio::Mixer::kSFXSoundType;
else if (volGroupId == 3)
type = Audio::Mixer::kMusicSoundType;
+ else
+ error("Track::getType(): invalid sound type");
return type;
}
};
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 36b82519e9..f9e4eb415c 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -411,15 +411,15 @@ void ScummEngine::listSavegames(bool *marks, int num) {
char prefix[256];
char slot[3];
int slotNum;
- Common::StringList filenames;
+ Common::StringList files;
makeSavegameName(prefix, 99, false);
prefix[strlen(prefix)-2] = '*';
prefix[strlen(prefix)-1] = 0;
memset(marks, false, num * sizeof(bool)); //assume no savegames for this title
- filenames = _saveFileMan->listSavefiles(prefix);
+ files = _saveFileMan->listSavefiles(prefix);
- for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++){
+ for (Common::StringList::const_iterator file = files.begin(); file != files.end(); ++file) {
//Obtain the last 2 digits of the filename, since they correspond to the save slot
slot[0] = file->c_str()[file->size()-2];
slot[1] = file->c_str()[file->size()-1];
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index fd72ba8d52..3b5a09578b 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -52,9 +52,11 @@ namespace Sword2 {
static Audio::AudioStream *makeCLUStream(Common::File *fp, int size);
static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) {
- debug(3, "Playing %s from CD %d", base, cd);
+ bool alreadyOpen;
if (!fh->file.isOpen()) {
+ alreadyOpen = false;
+
struct {
const char *ext;
int mode;
@@ -75,16 +77,14 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
char filename[20];
for (int i = 0; i < ARRAYSIZE(file_types); i++) {
- Common::File f;
-
sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
- if (f.open(filename)) {
+ if (Common::File::exists(filename)) {
soundMode = file_types[i].mode;
break;
}
sprintf(filename, "%s.%s", base, file_types[i].ext);
- if (f.open(filename)) {
+ if (Common::File::exists(filename)) {
soundMode = file_types[i].mode;
break;
}
@@ -105,7 +105,8 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
fh->idxTab = NULL;
}
}
- }
+ } else
+ alreadyOpen = true;
uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3;
@@ -134,7 +135,13 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
*numSamples = len;
if (!pos || !len) {
- fh->file.close();
+ // We couldn't find the sound. Possibly as a result of a bad
+ // installation (e.g. using the music file from CD 2 as the
+ // first music file). Don't close the file if it was already
+ // open though, because something is playing from it.
+ warning("getAudioStream: Could not find %s ID %d! Possibly the wrong file", base, id);
+ if (!alreadyOpen)
+ fh->file.close();
return NULL;
}
diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h
index 70bae6f851..b89ef8f12b 100644
--- a/engines/sword2/sound.h
+++ b/engines/sword2/sound.h
@@ -106,7 +106,7 @@ private:
void refill();
inline bool eosIntern() const {
- return _pos >= _bufferEnd;
+ return !_file->isOpen() || _pos >= _bufferEnd;
}
public:
diff --git a/sound/midiparser_smf.cpp b/sound/midiparser_smf.cpp
index ed5007ecb7..89b7d3f525 100644
--- a/sound/midiparser_smf.cpp
+++ b/sound/midiparser_smf.cpp
@@ -85,16 +85,26 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
_position._running_status = info.event;
switch (info.command()) {
- case 0xC: case 0xD:
+ case 0x9: // Note On
+ info.basic.param1 = *(_position._play_pos++);
+ info.basic.param2 = *(_position._play_pos++);
+ if (info.basic.param2 == 0)
+ info.event = info.channel() | 0x80;
+ info.length = 0;
+ break;
+
+ case 0xC:
+ case 0xD:
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = 0;
break;
- case 0x8: case 0x9: case 0xA: case 0xB: case 0xE:
+ case 0x8:
+ case 0xA:
+ case 0xB:
+ case 0xE:
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = *(_position._play_pos++);
- if (info.command() == 0x9 && info.basic.param2 == 0)
- info.event = info.channel() | 0x80;
info.length = 0;
break;
@@ -110,7 +120,12 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
info.basic.param2 = 0;
break;
- case 0x6: case 0x8: case 0xA: case 0xB: case 0xC: case 0xE:
+ case 0x6:
+ case 0x8:
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xE:
info.basic.param1 = info.basic.param2 = 0;
break;
diff --git a/sound/midiparser_xmidi.cpp b/sound/midiparser_xmidi.cpp
index d2aac49351..7cf114dcc6 100644
--- a/sound/midiparser_xmidi.cpp
+++ b/sound/midiparser_xmidi.cpp
@@ -38,6 +38,14 @@ protected:
NoteTimer _notes_cache[32];
uint32 _inserted_delta; // Track simulated deltas for note-off events
+ struct Loop {
+ byte *pos;
+ byte repeat;
+ };
+
+ Loop _loop[4];
+ int _loopCount;
+
protected:
uint32 readVLQ2(byte * &data);
void resetTracking();
@@ -78,16 +86,56 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
}
break;
- case 0xC: case 0xD:
+ case 0xC:
+ case 0xD:
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = 0;
break;
- case 0x8: case 0xA: case 0xB: case 0xE:
+ case 0x8:
+ case 0xA:
+ case 0xE:
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = *(_position._play_pos++);
break;
+ case 0xB:
+ info.basic.param1 = *(_position._play_pos++);
+ info.basic.param2 = *(_position._play_pos++);
+
+ // Simplified XMIDI looping.
+ //
+ // I would really like to turn the loop events into some sort
+ // of NOP event (perhaps a dummy META event?), but for now we
+ // just pass them on to the MIDI driver. That has worked in the
+ // past, so it shouldn't cause any actual damage...
+
+ if (info.basic.param1 == 0x74) {
+ // XMIDI_CONTROLLER_FOR_LOOP
+ byte *pos = _position._play_pos;
+ if (_loopCount < ARRAYSIZE(_loop) - 1)
+ _loopCount++;
+
+ _loop[_loopCount].pos = pos;
+ _loop[_loopCount].repeat = info.basic.param2;
+ } else if (info.basic.param1 == 0x75) {
+ // XMIDI_CONTROLLER_NEXT_BREAK
+ if (_loopCount >= 0) {
+ if (info.basic.param2 < 64) {
+ // End the current loop.
+ _loopCount--;
+ } else {
+ _position._play_pos = _loop[_loopCount].pos;
+ // Repeat 0 means "loop forever".
+ if (_loop[_loopCount].repeat) {
+ if (--_loop[_loopCount].repeat == 0)
+ _loopCount--;
+ }
+ }
+ }
+ }
+ break;
+
case 0xF: // Meta or SysEx event
switch (info.event & 0x0F) {
case 0x2: // Song Position Pointer
@@ -100,7 +148,12 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
info.basic.param2 = 0;
break;
- case 0x6: case 0x8: case 0xA: case 0xB: case 0xC: case 0xE:
+ case 0x6:
+ case 0x8:
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xE:
info.basic.param1 = info.basic.param2 = 0;
break;
@@ -136,6 +189,8 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
uint32 chunk_len;
char buf[32];
+ _loopCount = -1;
+
unloadMusic();
byte *pos = data;
diff --git a/test/common/str.h b/test/common/str.h
index dcba554b5a..76574ea70f 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -5,16 +5,25 @@
class StringTestSuite : public CxxTest::TestSuite
{
public:
- void test_empty_clear( void )
- {
+ void test_constructors(void) {
+ Common::String str("test-string");
+ TS_ASSERT( str == "test-string" );
+ str = Common::String(str.c_str()+5, 3);
+ TS_ASSERT( str == "str" );
+ str = "test-string";
+ TS_ASSERT( str == "test-string" );
+ str = Common::String(str.c_str()+5, str.c_str()+8);
+ TS_ASSERT( str == "str" );
+ }
+
+ void test_empty_clear(void) {
Common::String str("test");
TS_ASSERT( !str.empty() );
str.clear();
TS_ASSERT( str.empty() );
}
- void test_lastChar( void )
- {
+ void test_lastChar(void) {
Common::String str;
TS_ASSERT_EQUALS( str.lastChar(), '\0' );
str = "test";
@@ -23,8 +32,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( str2.lastChar(), 'r' );
}
- void test_concat1( void )
- {
+ void test_concat1(void) {
Common::String str("foo");
Common::String str2("bar");
str += str2;
@@ -32,22 +40,19 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( str2, "bar" );
}
- void test_concat2( void )
- {
+ void test_concat2(void) {
Common::String str("foo");
str += "bar";
TS_ASSERT_EQUALS( str, "foobar" );
}
- void test_concat3( void )
- {
+ void test_concat3(void) {
Common::String str("foo");
str += 'X';
TS_ASSERT_EQUALS( str, "fooX" );
}
- void test_refCount( void )
- {
+ void test_refCount(void) {
Common::String foo1("foo");
Common::String foo2("foo");
Common::String foo3(foo2);
@@ -57,8 +62,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( foo3, "foo""X" );
}
- void test_refCount2( void )
- {
+ void test_refCount2(void) {
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
Common::String foo3(foo2);
@@ -68,8 +72,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""X" );
}
- void test_refCount3( void )
- {
+ void test_refCount3(void) {
Common::String foo1("0123456789abcdefghijk");
Common::String foo2("0123456789abcdefghijk");
Common::String foo3(foo2);
@@ -79,8 +82,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( foo3, "0123456789abcdefghijk""0123456789abcdefghijk" );
}
- void test_refCount4( void )
- {
+ void test_refCount4(void) {
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
Common::String foo3(foo2);
@@ -90,8 +92,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd" );
}
- void test_hasPrefix( void )
- {
+ void test_hasPrefix(void) {
Common::String str("this/is/a/test, haha");
TS_ASSERT_EQUALS( str.hasPrefix(""), true );
TS_ASSERT_EQUALS( str.hasPrefix("this"), true );
@@ -99,8 +100,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( str.hasPrefix("foo"), false );
}
- void test_hasSuffix( void )
- {
+ void test_hasSuffix(void) {
Common::String str("this/is/a/test, haha");
TS_ASSERT_EQUALS( str.hasSuffix(""), true );
TS_ASSERT_EQUALS( str.hasSuffix("haha"), true );
@@ -108,8 +108,7 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( str.hasSuffix("hahah"), false );
}
- void test_contains( void )
- {
+ void test_contains(void) {
Common::String str("this/is/a/test, haha");
TS_ASSERT_EQUALS( str.contains(""), true );
TS_ASSERT_EQUALS( str.contains("haha"), true );
@@ -117,15 +116,13 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS( str.contains("test"), true );
}
- void test_toLowercase( void )
- {
+ void test_toLowercase(void) {
Common::String str("Test it, NOW! 42");
str.toLowercase();
TS_ASSERT_EQUALS( str, "test it, now! 42" );
}
- void test_toUppercase( void )
- {
+ void test_toUppercase(void) {
Common::String str("Test it, NOW! 42");
str.toUppercase();
TS_ASSERT_EQUALS( str, "TEST IT, NOW! 42" );
diff --git a/tools/svnpropset.sh b/tools/svnpropset.sh
new file mode 100755
index 0000000000..46acba534e
--- /dev/null
+++ b/tools/svnpropset.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# This script adds common svn properties to files
+
+if [ $# -eq 0 ]; then
+ echo "Usage: $0 [FILE]..."
+ exit 1
+fi
+
+for filename in $@; do
+ if [ -f $filename ]; then
+ svn propset svn:mime-type text/plain $filename
+ svn propset svn:keywords "Date Rev Author URL Id" $filename
+ svn propset svn:eol-style native $filename
+ elif [ -e $filename ]; then
+ echo "$0: error: '$filename' is not a regular file"
+ else
+ echo "$0: error: '$filename' does not exist"
+ fi
+done