aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--AUTHORS6
-rw-r--r--Makefile9
-rw-r--r--NEWS3
-rw-r--r--audio/mixer.cpp13
-rw-r--r--audio/softsynth/mt32.cpp3
-rw-r--r--audio/softsynth/mt32/Part.cpp6
-rw-r--r--audio/softsynth/mt32/Partial.cpp1
-rw-r--r--audio/softsynth/mt32/Synth.cpp17
-rw-r--r--audio/softsynth/mt32/Synth.h8
-rw-r--r--audio/softsynth/mt32/TVA.cpp6
-rw-r--r--backends/events/default/default-events.cpp3
-rw-r--r--backends/events/sdl/sdl-events.cpp4
-rw-r--r--backends/graphics/opengl/gltexture.h4
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp23
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h3
-rw-r--r--backends/mixer/nullmixer/nullsdl-mixer.cpp75
-rw-r--r--backends/mixer/nullmixer/nullsdl-mixer.h62
-rw-r--r--backends/modular-backend.cpp5
-rw-r--r--backends/module.mk12
-rw-r--r--backends/mutex/sdl/sdl-mutex.cpp6
-rw-r--r--backends/platform/android/android.cpp2
-rw-r--r--backends/platform/android/android.h2
-rw-r--r--backends/platform/bada/bada.mk5
-rw-r--r--backends/platform/bada/form.cpp464
-rw-r--r--backends/platform/bada/form.h108
-rw-r--r--backends/platform/dc/dc.h2
-rw-r--r--backends/platform/dc/time.cpp2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h2
-rw-r--r--backends/platform/iphone/osys_main.cpp2
-rw-r--r--backends/platform/iphone/osys_main.h2
-rw-r--r--backends/platform/n64/osys_n64.h2
-rw-r--r--backends/platform/n64/osys_n64_base.cpp2
-rw-r--r--backends/platform/null/null.cpp2
-rw-r--r--backends/platform/ps2/systemps2.cpp2
-rw-r--r--backends/platform/ps2/systemps2.h2
-rw-r--r--backends/platform/psp/osys_psp.cpp2
-rw-r--r--backends/platform/psp/osys_psp.h2
-rw-r--r--backends/platform/psp/rtc.cpp2
-rw-r--r--backends/platform/psp/rtc.h2
-rw-r--r--backends/platform/sdl/sdl-sys.h3
-rw-r--r--backends/platform/sdl/sdl.cpp28
-rw-r--r--backends/platform/sdl/sdl.h3
-rw-r--r--backends/platform/tizen/README.TXT (renamed from backends/platform/bada/README.TXT)116
-rw-r--r--backends/platform/tizen/application.cpp (renamed from backends/platform/bada/application.cpp)79
-rw-r--r--backends/platform/tizen/application.h69
-rw-r--r--backends/platform/tizen/audio.cpp (renamed from backends/platform/bada/audio.cpp)111
-rw-r--r--backends/platform/tizen/audio.h (renamed from backends/platform/bada/audio.h)37
-rw-r--r--backends/platform/tizen/form.cpp419
-rw-r--r--backends/platform/tizen/form.h113
-rw-r--r--backends/platform/tizen/fs.cpp (renamed from backends/platform/bada/fs.cpp)294
-rw-r--r--backends/platform/tizen/fs.h (renamed from backends/platform/bada/fs.h)38
-rw-r--r--backends/platform/tizen/graphics.cpp (renamed from backends/platform/bada/graphics.cpp)108
-rw-r--r--backends/platform/tizen/graphics.h (renamed from backends/platform/bada/graphics.h)19
-rw-r--r--backends/platform/tizen/main.cpp (renamed from backends/platform/bada/main.cpp)36
-rw-r--r--backends/platform/tizen/missing.cpp (renamed from backends/platform/bada/missing.cpp)37
-rw-r--r--backends/platform/tizen/portdefs.h (renamed from backends/platform/bada/portdefs.h)12
-rw-r--r--backends/platform/tizen/sscanf.cpp (renamed from backends/platform/bada/sscanf.cpp)0
-rw-r--r--backends/platform/tizen/system.cpp (renamed from backends/platform/bada/system.cpp)287
-rw-r--r--backends/platform/tizen/system.h (renamed from backends/platform/bada/system.h)46
-rw-r--r--backends/platform/tizen/tizen.mk7
-rw-r--r--backends/platform/wii/osystem.cpp2
-rw-r--r--backends/platform/wii/osystem.h2
-rw-r--r--backends/saves/recorder/recorder-saves.cpp35
-rw-r--r--backends/saves/recorder/recorder-saves.h36
-rw-r--r--backends/timer/default/default-timer.cpp2
-rw-r--r--backends/timer/tizen/timer.cpp (renamed from backends/timer/bada/timer.cpp)50
-rw-r--r--backends/timer/tizen/timer.h (renamed from backends/timer/bada/timer.h)23
-rw-r--r--base/commandLine.cpp33
-rw-r--r--base/main.cpp33
-rw-r--r--common/EventDispatcher.cpp14
-rw-r--r--common/EventRecorder.cpp428
-rw-r--r--common/EventRecorder.h110
-rw-r--r--common/debug.h4
-rw-r--r--common/events.h12
-rw-r--r--common/memstream.h37
-rw-r--r--common/module.mk6
-rw-r--r--common/random.cpp9
-rw-r--r--common/recorderfile.cpp708
-rw-r--r--common/recorderfile.h180
-rw-r--r--common/str.cpp19
-rw-r--r--common/str.h5
-rw-r--r--common/system.cpp11
-rw-r--r--common/system.h18
-rwxr-xr-xconfigure174
-rw-r--r--devtools/create_project/create_project.cpp48
-rw-r--r--devtools/create_project/msbuild.cpp19
-rw-r--r--devtools/create_project/msvc12/create_project.sln20
-rw-r--r--devtools/create_project/msvc12/create_project.vcxproj132
-rw-r--r--devtools/create_project/msvc12/create_project.vcxproj.filters71
-rwxr-xr-xdevtools/credits.pl8
-rw-r--r--devtools/scumm-md5.txt3
-rw-r--r--dists/msvc12/create_msvc12.bat95
-rw-r--r--dists/msvc12/readme.txt6
-rw-r--r--engines/advancedDetector.cpp9
-rw-r--r--engines/advancedDetector.h3
-rw-r--r--engines/cge/cge.cpp1
-rw-r--r--engines/dreamweb/dreamweb.cpp1
-rw-r--r--engines/gob/surface.cpp16
-rw-r--r--engines/hopkins/hopkins.cpp5
-rw-r--r--engines/hopkins/hopkins.h3
-rw-r--r--engines/hopkins/saveload.cpp32
-rw-r--r--engines/hopkins/saveload.h2
-rw-r--r--engines/hopkins/script.cpp2
-rw-r--r--engines/kyra/kyra_rpg.cpp2
-rw-r--r--engines/kyra/screen.cpp4
-rw-r--r--engines/neverhood/console.cpp21
-rw-r--r--engines/neverhood/console.h1
-rw-r--r--engines/neverhood/detection.cpp16
-rw-r--r--engines/neverhood/gamemodule.cpp1
-rw-r--r--engines/neverhood/graphics.cpp2
-rw-r--r--engines/neverhood/menumodule.cpp83
-rw-r--r--engines/neverhood/menumodule.h2
-rw-r--r--engines/neverhood/modules/module1100.cpp5
-rw-r--r--engines/neverhood/modules/module1200.cpp2
-rw-r--r--engines/neverhood/modules/module1300.cpp2
-rw-r--r--engines/neverhood/modules/module2100.cpp2
-rw-r--r--engines/neverhood/modules/module2200.cpp1
-rw-r--r--engines/neverhood/modules/module2400.cpp2
-rw-r--r--engines/neverhood/modules/module2700.cpp6
-rw-r--r--engines/neverhood/modules/module2700.h2
-rw-r--r--engines/neverhood/modules/module2800.cpp2
-rw-r--r--engines/neverhood/modules/module3000.cpp23
-rw-r--r--engines/neverhood/navigationscene.cpp24
-rw-r--r--engines/neverhood/neverhood.cpp21
-rw-r--r--engines/neverhood/neverhood.h9
-rw-r--r--engines/neverhood/saveload.cpp19
-rw-r--r--engines/neverhood/todo.txt45
-rw-r--r--engines/saga/sndres.cpp6
-rw-r--r--engines/sci/graphics/ports.cpp4
-rw-r--r--engines/scumm/scumm-md5.h5
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp57
-rw-r--r--engines/sword25/gfx/image/renderedimage.h3
-rw-r--r--engines/tinsel/tinsel.h6
-rw-r--r--engines/toon/character.cpp9
-rw-r--r--engines/toon/character.h1
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.cpp4
-rw-r--r--engines/tsage/core.cpp2
-rw-r--r--engines/tsage/graphics.cpp13
-rw-r--r--engines/tsage/graphics.h2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp403
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.h78
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp338
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.h18
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.cpp17
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.h1
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp874
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.h20
-rw-r--r--engines/wintermute/detection_tables.h11
-rw-r--r--engines/wintermute/wintermute.cpp1
-rw-r--r--graphics/cursorman.cpp7
-rw-r--r--graphics/cursorman.h6
-rw-r--r--graphics/scaler.h6
-rw-r--r--graphics/scaler/thumbnail_intern.cpp32
-rw-r--r--graphics/thumbnail.cpp53
-rw-r--r--graphics/thumbnail.h18
-rw-r--r--graphics/yuv_to_rgb.h15
-rw-r--r--gui/EventRecorder.cpp665
-rw-r--r--gui/EventRecorder.h293
-rw-r--r--gui/ThemeEngine.cpp35
-rw-r--r--gui/ThemeEngine.h13
-rw-r--r--gui/credits.h6
-rw-r--r--gui/dialog.h3
-rw-r--r--gui/editrecorddialog.cpp87
-rw-r--r--gui/editrecorddialog.h (renamed from backends/platform/bada/application.h)52
-rw-r--r--gui/gui-manager.cpp138
-rw-r--r--gui/gui-manager.h6
-rw-r--r--gui/launcher.cpp83
-rw-r--r--gui/launcher.h15
-rw-r--r--gui/module.mk8
-rw-r--r--gui/onscreendialog.cpp231
-rw-r--r--gui/onscreendialog.h64
-rw-r--r--gui/recorderdialog.cpp291
-rw-r--r--gui/recorderdialog.h81
-rw-r--r--gui/themes/default.inc1052
-rw-r--r--gui/themes/scummclassic.zipbin104059 -> 110000 bytes
-rw-r--r--gui/themes/scummclassic/classic_layout.stx128
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx104
-rw-r--r--gui/themes/scummmodern.zipbin1462338 -> 1485763 bytes
-rw-r--r--gui/themes/scummmodern/editbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/editbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/fastreplay.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/fastreplay_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx8
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx130
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx125
-rw-r--r--gui/themes/scummmodern/stopbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/stopbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/switchbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/switchbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/widgets/edittext.cpp8
-rw-r--r--po/POTFILES2
-rw-r--r--test/common/str.h8
-rw-r--r--video/codecs/indeo3.cpp119
-rw-r--r--video/coktel_decoder.cpp8
198 files changed, 7577 insertions, 3670 deletions
diff --git a/.gitignore b/.gitignore
index b834214a00..a046909bbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -161,6 +161,10 @@ ipch/
#Ignore default Visual Studio build folders
[Dd]ebug/
[Rr]elease/
+[Dd]ebug32/
+[Rr]elease32/
+[Dd]ebug64/
+[Rr]elease64/
#Ignore Qt Creator project files
ScummVM.config
diff --git a/AUTHORS b/AUTHORS
index e6a25b5b76..0a2d2c5fe1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -238,9 +238,6 @@ ScummVM Team
Andre Heider
Angus Lees
- BADA:
- Chris Warren-Smith
-
Dreamcast:
Marcus Comstedt
@@ -288,6 +285,9 @@ ScummVM Team
Jurgen Braam
Lars Persson
+ Tizen / BADA:
+ Chris Warren-Smith
+
WebOS:
Klaus Reimer
diff --git a/Makefile b/Makefile
index 28eaead4b4..09c38b2598 100644
--- a/Makefile
+++ b/Makefile
@@ -32,8 +32,10 @@ ifeq "$(HAVE_GCC)" "1"
# being helpful.
#CXXFLAGS+= -Wmissing-format-attribute
- # Disable RTTI and exceptions
+ifneq "$(BACKEND)" "tizen"
+ # Disable RTTI and exceptions. These settings cause tizen apps to crash
CXXFLAGS+= -fno-rtti -fno-exceptions
+endif
ifneq "$(HAVE_CLANG)" "1"
# enable checking of pointers returned by "new", but only when we do not
@@ -44,6 +46,11 @@ endif
ifeq "$(HAVE_CLANG)" "1"
CXXFLAGS+= -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants
+ # We use a anonymous nested type declaration in an anonymous union in
+ # common/str.h. This is no standard construct and clang warns about it.
+ # It works for all our target systems though, thus we simply disable that
+ # warning.
+ CXXFLAGS+= -Wno-nested-anon-types
endif
ifeq "$(HAVE_ICC)" "1"
diff --git a/NEWS b/NEWS
index cf9a07e8cb..c31be14c25 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,8 @@ For a more comprehensive changelog of the latest experimental code, see:
https://github.com/scummvm/scummvm/commits/
1.7.0 (????-??-??)
-
+ Gob:
+ - Improved video quality in Urban Runner
1.6.0 (2013-05-31)
New Games:
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index 8ff364b98d..ab3ed9eb2d 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -20,6 +20,8 @@
*
*/
+#include "gui/EventRecorder.h"
+
#include "common/util.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -427,6 +429,7 @@ void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {
bool MixerImpl::isSoundIDActive(int id) {
Common::StackLock lock(_mutex);
+ g_eventRec.updateSubsystems();
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i] && _channels[i]->getId() == id)
return true;
@@ -443,6 +446,7 @@ int MixerImpl::getSoundID(SoundHandle handle) {
bool MixerImpl::isSoundHandleActive(SoundHandle handle) {
Common::StackLock lock(_mutex);
+ g_eventRec.updateSubsystems();
const int index = handle._val % NUM_CHANNELS;
return _channels[index] && _channels[index]->getHandle()._val == handle._val;
}
@@ -556,12 +560,12 @@ void Channel::pause(bool paused) {
_pauseLevel++;
if (_pauseLevel == 1)
- _pauseStartTime = g_system->getMillis();
+ _pauseStartTime = g_system->getMillis(true);
} else if (_pauseLevel > 0) {
_pauseLevel--;
if (!_pauseLevel) {
- _pauseTime = (g_system->getMillis() - _pauseStartTime);
+ _pauseTime = (g_system->getMillis(true) - _pauseStartTime);
_pauseStartTime = 0;
}
}
@@ -579,7 +583,7 @@ Timestamp Channel::getElapsedTime() {
if (isPaused())
delta = _pauseStartTime - _mixerTimeStamp;
else
- delta = g_system->getMillis() - _mixerTimeStamp - _pauseTime;
+ delta = g_system->getMillis(true) - _mixerTimeStamp - _pauseTime;
// Convert the number of samples into a time duration.
@@ -599,13 +603,12 @@ int Channel::mix(int16 *data, uint len) {
assert(_stream);
int res = 0;
-
if (_stream->endOfData()) {
// TODO: call drain method
} else {
assert(_converter);
_samplesConsumed = _samplesDecoded;
- _mixerTimeStamp = g_system->getMillis();
+ _mixerTimeStamp = g_system->getMillis(true);
_pauseTime = 0;
res = _converter->flow(*_stream, data, len, _volL, _volR);
_samplesDecoded += res;
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index 00d0469356..3281e3bebf 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -62,7 +62,8 @@ protected:
// Callback for debug messages, in vprintf() format
void printDebug(const char *fmt, va_list list) {
- debug(4, fmt, list);
+ Common::String out = Common::String::vformat(fmt, list);
+ debug(4, out.c_str());
}
// Callbacks for reporting various errors and information
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index 62ba346c35..88404316eb 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -175,6 +175,7 @@ void Part::refresh() {
patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0;
}
memcpy(currentInstr, timbreTemp->common.name, 10);
+ synth->newTimbreSet(partNum, patchTemp->patch.timbreGroup, currentInstr);
updatePitchBenderRange();
}
@@ -207,7 +208,6 @@ void RhythmPart::setTimbre(TimbreParam * /*timbre*/) {
void Part::setTimbre(TimbreParam *timbre) {
*timbreTemp = *timbre;
- synth->newTimbreSet(partNum, timbre->common.name);
}
unsigned int RhythmPart::getAbsTimbreNum() const {
@@ -533,7 +533,6 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt
#if MT32EMU_MONITOR_PARTIALS > 1
synth->printPartialUsage();
#endif
- synth->partStateChanged(partNum, true);
synth->polyStateChanged(partNum);
}
@@ -614,9 +613,6 @@ void Part::partialDeactivated(Poly *poly) {
freePolys.prepend(poly);
synth->polyStateChanged(partNum);
}
- if (activePartialCount == 0) {
- synth->partStateChanged(partNum, false);
- }
}
//#define POLY_LIST_DEBUG
diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp
index a0aec90ec4..b80a028515 100644
--- a/audio/softsynth/mt32/Partial.cpp
+++ b/audio/softsynth/mt32/Partial.cpp
@@ -87,7 +87,6 @@ void Partial::deactivate() {
if (poly != NULL) {
poly->partialDeactivated(this);
}
- synth->partialStateChanged(this, tva->getPhase(), TVA_PHASE_DEAD);
#if MT32EMU_MONITOR_PARTIALS > 2
synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum);
synth->printPartialUsage(sampleNum);
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index b7af992b99..1e1be06bc9 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -201,25 +201,12 @@ void ReportHandler::printDebug(const char *fmt, va_list list) {
printf("\n");
}
-void Synth::partStateChanged(int partNum, bool isPartActive) {
- reportHandler->onPartStateChanged(partNum, isPartActive);
-}
-
void Synth::polyStateChanged(int partNum) {
reportHandler->onPolyStateChanged(partNum);
}
-void Synth::partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase) {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (getPartial(i) == partial) {
- reportHandler->onPartialStateChanged(i, oldPartialPhase, newPartialPhase);
- break;
- }
- }
-}
-
-void Synth::newTimbreSet(int partNum, char patchName[]) {
- reportHandler->onProgramChanged(partNum, patchName);
+void Synth::newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]) {
+ reportHandler->onProgramChanged(partNum, timbreGroup, patchName);
}
void Synth::printDebug(const char *fmt, ...) {
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index 56e88e6156..b85e7ae507 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -249,10 +249,10 @@ protected:
virtual void onNewReverbMode(Bit8u /* mode */) {}
virtual void onNewReverbTime(Bit8u /* time */) {}
virtual void onNewReverbLevel(Bit8u /* level */) {}
- virtual void onPartStateChanged(int /* partNum */, bool /* isActive */) {}
+ virtual void onPartStateChanged(int /* partNum */, bool /* hasActiveNonReleasingPolys */) {}
virtual void onPolyStateChanged(int /* partNum */) {}
virtual void onPartialStateChanged(int /* partialNum */, int /* oldPartialPhase */, int /* newPartialPhase */) {}
- virtual void onProgramChanged(int /* partNum */, char * /* patchName */) {}
+ virtual void onProgramChanged(int /* partNum */, int /* bankNum */, const char * /* patchName */) {}
};
class Synth {
@@ -370,10 +370,8 @@ private:
void printPartialUsage(unsigned long sampleOffset = 0);
- void partStateChanged(int partNum, bool isPartActive);
void polyStateChanged(int partNum);
- void partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase);
- void newTimbreSet(int partNum, char patchName[]);
+ void newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]);
void printDebug(const char *fmt, ...);
public:
diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp
index 65e5256048..5438471fa4 100644
--- a/audio/softsynth/mt32/TVA.cpp
+++ b/audio/softsynth/mt32/TVA.cpp
@@ -34,9 +34,6 @@ TVA::TVA(const Partial *usePartial, LA32Ramp *useAmpRamp) :
}
void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
- if (newPhase != phase) {
- partial->getSynth()->partialStateChanged(partial, phase, newPhase);
- }
target = newTarget;
phase = newPhase;
ampRamp->startRamp(newTarget, newIncrement);
@@ -46,9 +43,6 @@ void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
}
void TVA::end(int newPhase) {
- if (newPhase != phase) {
- partial->getSynth()->partialStateChanged(partial, phase, newPhase);
- }
phase = newPhase;
playing = false;
#if MT32EMU_MONITOR_TVA >= 1
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 38a0c8d46f..bf76bbc1cb 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -84,7 +84,8 @@ void DefaultEventManager::init() {
}
bool DefaultEventManager::pollEvent(Common::Event &event) {
- uint32 time = g_system->getMillis();
+ // Skip recording of these events
+ uint32 time = g_system->getMillis(true);
bool result = false;
_dispatcher.dispatch();
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 0ca5bbb059..e2ef7f6bf6 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -106,7 +106,9 @@ void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {
}
void SdlEventSource::handleKbdMouse() {
- uint32 curTime = g_system->getMillis();
+ // Skip recording of these events
+ uint32 curTime = g_system->getMillis(true);
+
if (curTime >= _km.last_time + _km.delay_time) {
_km.last_time = curTime;
if (_km.x_down_count == 1) {
diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h
index 8ff9838ff7..6ef80923ae 100644
--- a/backends/graphics/opengl/gltexture.h
+++ b/backends/graphics/opengl/gltexture.h
@@ -44,9 +44,9 @@
#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif
-#if defined(BADA)
+#if defined(TIZEN)
#include <FGraphicsOpengl.h>
-using namespace Osp::Graphics::Opengl;
+using namespace Tizen::Graphics::Opengl;
#elif defined(USE_GLES)
#include <GLES/gl.h>
#elif defined(SDL_BACKEND)
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 02e58ab319..1ebd019488 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -40,6 +40,7 @@
#include "graphics/scaler.h"
#include "graphics/scaler/aspect.h"
#include "graphics/surface.h"
+#include "gui/EventRecorder.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{"1x", _s("Normal (no scaling)"), GFX_NORMAL},
@@ -135,6 +136,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
_graphicsMutex(0),
+ _displayDisabled(false),
#ifdef USE_SDL_DEBUG_FOCUSRECT
_enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(),
#endif
@@ -765,9 +767,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
}
- _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
- _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
- );
+
+#ifdef ENABLE_EVENTRECORDER
+ _displayDisabled = ConfMan.getBool("disable_display");
+
+ if (_displayDisabled) {
+ _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
+ } else
+#endif
+ {
+ _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
+ _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
+ );
+ }
+
#ifdef USE_RGB_COLOR
detectSupportedFormats();
#endif
@@ -1188,7 +1201,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#endif
// Finally, blit all our changes to the screen
- SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ if (!_displayDisabled) {
+ SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ }
}
_numDirtyRects = 0;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 21444cc25d..97de0f9c97 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -232,6 +232,9 @@ protected:
int _scalerType;
int _transactionMode;
+ // Indicates whether it is needed to free _hwsurface in destructor
+ bool _displayDisabled;
+
bool _screenIsLocked;
Graphics::Surface _framebuffer;
diff --git a/backends/mixer/nullmixer/nullsdl-mixer.cpp b/backends/mixer/nullmixer/nullsdl-mixer.cpp
new file mode 100644
index 0000000000..2fd652e19f
--- /dev/null
+++ b/backends/mixer/nullmixer/nullsdl-mixer.cpp
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/mixer/nullmixer/nullsdl-mixer.h"
+#include "common/savefile.h"
+
+NullSdlMixerManager::NullSdlMixerManager() : SdlMixerManager() {
+ _outputRate = 22050;
+ _callsCounter = 0;
+ _callbackPeriod = 10;
+ _samples = 8192;
+ while (_samples * 16 > _outputRate * 2)
+ _samples >>= 1;
+ _samplesBuf = new uint8[_samples * 4];
+}
+
+NullSdlMixerManager::~NullSdlMixerManager() {
+ delete _samplesBuf;
+}
+
+void NullSdlMixerManager::init() {
+ _mixer = new Audio::MixerImpl(g_system, _outputRate);
+ assert(_mixer);
+ _mixer->setReady(true);
+}
+
+void NullSdlMixerManager::suspendAudio() {
+ _audioSuspended = true;
+}
+
+int NullSdlMixerManager::resumeAudio() {
+ if (!_audioSuspended) {
+ return -2;
+ }
+ _audioSuspended = false;
+ return 0;
+}
+
+
+void NullSdlMixerManager::startAudio() {
+}
+
+void NullSdlMixerManager::callbackHandler(byte *samples, int len) {
+ assert(_mixer);
+ _mixer->mixCallback(samples, len);
+}
+
+void NullSdlMixerManager::update() {
+ if (_audioSuspended) {
+ return;
+ }
+ _callsCounter++;
+ if ((_callsCounter % _callbackPeriod) == 0) {
+ callbackHandler(_samplesBuf, _samples);
+ }
+}
diff --git a/backends/mixer/nullmixer/nullsdl-mixer.h b/backends/mixer/nullmixer/nullsdl-mixer.h
new file mode 100644
index 0000000000..94248ced66
--- /dev/null
+++ b/backends/mixer/nullmixer/nullsdl-mixer.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_MIXER_NULLSDL_H
+#define BACKENDS_MIXER_NULLSDL_H
+
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/str.h"
+
+/** Audio mixer which in fact does not output audio.
+ *
+ * It is used by events recorder since the recorder is intentionally
+ * turning sound off to avoid stuttering.
+ *
+ * It returns correct output and shoots callbacks, so all OSystem
+ * users could work without modifications.
+ */
+
+class NullSdlMixerManager : public SdlMixerManager {
+public:
+ NullSdlMixerManager();
+ virtual ~NullSdlMixerManager();
+
+ virtual void init();
+ void update();
+
+ virtual void suspendAudio();
+ virtual int resumeAudio();
+
+protected:
+
+ virtual void startAudio();
+ virtual void callbackHandler(byte *samples, int len);
+
+private:
+ uint32 _outputRate;
+ uint32 _callsCounter;
+ uint8 _callbackPeriod;
+ uint32 _samples;
+ uint8 *_samplesBuf;
+};
+
+#endif
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index b46f33a2bc..d84df75439 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -26,6 +26,7 @@
#include "backends/graphics/graphics.h"
#include "backends/mutex/mutex.h"
+#include "gui/EventRecorder.h"
#include "audio/mixer.h"
#include "graphics/pixelformat.h"
@@ -52,7 +53,7 @@ bool ModularBackend::hasFeature(Feature f) {
}
void ModularBackend::setFeatureState(Feature f, bool enable) {
- return _graphicsManager->setFeatureState(f, enable);
+ _graphicsManager->setFeatureState(f, enable);
}
bool ModularBackend::getFeatureState(Feature f) {
@@ -141,7 +142,9 @@ void ModularBackend::fillScreen(uint32 col) {
}
void ModularBackend::updateScreen() {
+ g_eventRec.preDrawOverlayGui();
_graphicsManager->updateScreen();
+ g_eventRec.postDrawOverlayGui();
}
void ModularBackend::setShakePos(int shakeOffset) {
diff --git a/backends/module.mk b/backends/module.mk
index a4f525d21d..31ac444750 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -70,7 +70,7 @@ MODULE_OBJS += \
mutex/sdl/sdl-mutex.o \
plugins/sdl/sdl-provider.o \
timer/sdl/sdl-timer.o
-
+
# SDL 1.3 removed audio CD support
ifndef USE_SDL13
MODULE_OBJS += \
@@ -120,9 +120,9 @@ MODULE_OBJS += \
mixer/sdl13/sdl13-mixer.o
endif
-ifeq ($(BACKEND),bada)
+ifeq ($(BACKEND),tizen)
MODULE_OBJS += \
- timer/bada/timer.o
+ timer/tizen/timer.o
endif
ifeq ($(BACKEND),ds)
@@ -214,5 +214,11 @@ MODULE_OBJS += \
plugins/wii/wii-provider.o
endif
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ mixer/nullmixer/nullsdl-mixer.o \
+ saves/recorder/recorder-saves.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/backends/mutex/sdl/sdl-mutex.cpp b/backends/mutex/sdl/sdl-mutex.cpp
index 8491ae468c..a51e6f0e38 100644
--- a/backends/mutex/sdl/sdl-mutex.cpp
+++ b/backends/mutex/sdl/sdl-mutex.cpp
@@ -33,15 +33,15 @@ OSystem::MutexRef SdlMutexManager::createMutex() {
}
void SdlMutexManager::lockMutex(OSystem::MutexRef mutex) {
- SDL_mutexP((SDL_mutex *) mutex);
+ SDL_mutexP((SDL_mutex *)mutex);
}
void SdlMutexManager::unlockMutex(OSystem::MutexRef mutex) {
- SDL_mutexV((SDL_mutex *) mutex);
+ SDL_mutexV((SDL_mutex *)mutex);
}
void SdlMutexManager::deleteMutex(OSystem::MutexRef mutex) {
- SDL_DestroyMutex((SDL_mutex *) mutex);
+ SDL_DestroyMutex((SDL_mutex *)mutex);
}
#endif
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f06e4be19e..ad80ea7f8c 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -450,7 +450,7 @@ bool OSystem_Android::getFeatureState(Feature f) {
}
}
-uint32 OSystem_Android::getMillis() {
+uint32 OSystem_Android::getMillis(bool skipRecord) {
timeval curTime;
gettimeofday(&curTime, 0);
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 5f2f40b726..b4813b3bdf 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -274,7 +274,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/bada/bada.mk b/backends/platform/bada/bada.mk
deleted file mode 100644
index 7c72d7752b..0000000000
--- a/backends/platform/bada/bada.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bada specific modules are built under eclipse
-
-$(EXECUTABLE): $(OBJS)
- rm -f $@
- ar Tru $@ $(OBJS)
diff --git a/backends/platform/bada/form.cpp b/backends/platform/bada/form.cpp
deleted file mode 100644
index dfa72bce08..0000000000
--- a/backends/platform/bada/form.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include <FAppApplication.h>
-
-#include "common/translation.h"
-#include "base/main.h"
-
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-
-using namespace Osp::Base::Runtime;
-using namespace Osp::Ui;
-using namespace Osp::Ui::Controls;
-
-// number of volume levels
-#define LEVEL_RANGE 5
-
-// round down small Y touch values to 1 to allow the
-// cursor to be positioned at the top of the screen
-#define MIN_TOUCH_Y 10
-
-// block for up to 2.5 seconds during shutdown to
-// allow the game thread to exit gracefully.
-#define EXIT_SLEEP_STEP 10
-#define EXIT_SLEEP 250
-
-//
-// BadaAppForm
-//
-BadaAppForm::BadaAppForm() :
- _gameThread(0),
- _state(kInitState),
- _buttonState(kLeftButton),
- _shortcut(kSetVolume) {
- _eventQueueLock = new Mutex();
- _eventQueueLock->Create();
-}
-
-result BadaAppForm::Construct() {
- result r = Form::Construct(Controls::FORM_STYLE_NORMAL);
- if (IsFailed(r)) {
- return r;
- }
-
- BadaSystem *badaSystem = NULL;
- _gameThread = NULL;
-
- badaSystem = new BadaSystem(this);
- r = badaSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
-
- if (!IsFailed(r)) {
- r = badaSystem->Construct();
- }
-
- if (!IsFailed(r)) {
- _gameThread = new Thread();
- r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
- }
-
- if (!IsFailed(r)) {
- r = _gameThread->Construct(*this);
- }
-
- if (IsFailed(r)) {
- if (badaSystem != NULL) {
- delete badaSystem;
- }
- if (_gameThread != NULL) {
- delete _gameThread;
- _gameThread = NULL;
- }
- } else {
- g_system = badaSystem;
- }
-
- return r;
-}
-
-BadaAppForm::~BadaAppForm() {
- logEntered();
-
- if (_gameThread && _state != kErrorState) {
- terminate();
-
- _gameThread->Stop();
- if (_state != kErrorState) {
- _gameThread->Join();
- }
-
- delete _gameThread;
- _gameThread = NULL;
- }
-
- if (_eventQueueLock) {
- delete _eventQueueLock;
- _eventQueueLock = NULL;
- }
-
- logLeaving();
-}
-
-//
-// abort the game thread
-//
-void BadaAppForm::terminate() {
- if (_state == kActiveState) {
- ((BadaSystem *)g_system)->setMute(true);
-
- _eventQueueLock->Acquire();
-
- Common::Event e;
- e.type = Common::EVENT_QUIT;
- _eventQueue.push(e);
- _state = kClosingState;
-
- _eventQueueLock->Release();
-
- // block while thread ends
- AppLog("waiting for shutdown");
- for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) {
- Thread::Sleep(EXIT_SLEEP);
- }
-
- if (_state == kClosingState) {
- // failed to terminate - Join() will freeze
- _state = kErrorState;
- }
- }
-}
-
-void BadaAppForm::exitSystem() {
- _state = kErrorState;
-
- if (_gameThread) {
- _gameThread->Stop();
- delete _gameThread;
- _gameThread = NULL;
- }
-}
-
-result BadaAppForm::OnInitializing(void) {
- logEntered();
-
- SetOrientation(ORIENTATION_LANDSCAPE);
- AddOrientationEventListener(*this);
- AddTouchEventListener(*this);
- AddKeyEventListener(*this);
-
- // set focus to enable receiving key events
- SetFocusable(true);
- SetFocus();
-
- return E_SUCCESS;
-}
-
-result BadaAppForm::OnDraw(void) {
- logEntered();
-
- if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
- if (graphics && graphics->isReady()) {
- g_system->updateScreen();
- }
- }
-
- return E_SUCCESS;
-}
-
-bool BadaAppForm::pollEvent(Common::Event &event) {
- bool result = false;
-
- _eventQueueLock->Acquire();
- if (!_eventQueue.empty()) {
- event = _eventQueue.pop();
- result = true;
- }
- _eventQueueLock->Release();
-
- return result;
-}
-
-void BadaAppForm::pushEvent(Common::EventType type, const Point &currentPosition) {
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
- if (graphics) {
- // graphics could be NULL at startup or when
- // displaying the system error screen
- Common::Event e;
- e.type = type;
- e.mouse.x = currentPosition.x;
- e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1;
-
- bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y);
-
- _eventQueueLock->Acquire();
-
- if (moved && type != Common::EVENT_MOUSEMOVE) {
- Common::Event moveEvent;
- moveEvent.type = Common::EVENT_MOUSEMOVE;
- moveEvent.mouse = e.mouse;
- _eventQueue.push(moveEvent);
- }
-
- _eventQueue.push(e);
- _eventQueueLock->Release();
- }
-}
-
-void BadaAppForm::pushKey(Common::KeyCode keycode) {
- Common::Event e;
- e.synthetic = false;
- e.kbd.keycode = keycode;
- e.kbd.ascii = keycode;
- e.kbd.flags = 0;
-
- _eventQueueLock->Acquire();
-
- e.type = Common::EVENT_KEYDOWN;
- _eventQueue.push(e);
- e.type = Common::EVENT_KEYUP;
- _eventQueue.push(e);
-
- _eventQueueLock->Release();
-}
-
-void BadaAppForm::OnOrientationChanged(const Control &source,
- OrientationStatus orientationStatus) {
- logEntered();
- if (_state == kInitState) {
- _state = kActiveState;
- _gameThread->Start();
- }
-}
-
-Object *BadaAppForm::Run(void) {
- scummvm_main(0, 0);
-
- if (_state == kActiveState) {
- Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL);
- }
- _state = kDoneState;
- return NULL;
-}
-
-void BadaAppForm::setButtonShortcut() {
- switch (_buttonState) {
- case kLeftButton:
- g_system->displayMessageOnOSD(_("Right Click Once"));
- _buttonState = kRightButtonOnce;
- break;
- case kRightButtonOnce:
- g_system->displayMessageOnOSD(_("Right Click"));
- _buttonState = kRightButton;
- break;
- case kRightButton:
- g_system->displayMessageOnOSD(_("Move Only"));
- _buttonState = kMoveOnly;
- break;
- case kMoveOnly:
- g_system->displayMessageOnOSD(_("Left Click"));
- _buttonState = kLeftButton;
- break;
- }
-}
-
-void BadaAppForm::setShortcut() {
- // cycle to the next shortcut
- switch (_shortcut) {
- case kControlMouse:
- g_system->displayMessageOnOSD(_("Escape Key"));
- _shortcut = kEscapeKey;
- break;
-
- case kEscapeKey:
- g_system->displayMessageOnOSD(_("Game Menu"));
- _shortcut = kGameMenu;
- break;
-
- case kGameMenu:
- g_system->displayMessageOnOSD(_("Show Keypad"));
- _shortcut = kShowKeypad;
- break;
-
- case kSetVolume:
- // fallthru
-
- case kShowKeypad:
- g_system->displayMessageOnOSD(_("Control Mouse"));
- _shortcut = kControlMouse;
- break;
- }
-}
-
-void BadaAppForm::setVolume(bool up, bool minMax) {
- int level = ((BadaSystem *)g_system)->setVolume(up, minMax);
- if (level != -1) {
- char message[32];
- char ind[LEVEL_RANGE]; // 1..5 (0=off)
- int j = LEVEL_RANGE - 1; // 0..4
- for (int i = 1; i <= LEVEL_RANGE; i++) {
- ind[j--] = level >= i ? '|' : ' ';
- }
- snprintf(message, sizeof(message), "Volume: [ %c%c%c%c%c ]",
- ind[0], ind[1], ind[2], ind[3], ind[4]);
- g_system->displayMessageOnOSD(message);
- }
-}
-
-void BadaAppForm::showKeypad() {
- // display the soft keyboard
- _buttonState = kLeftButton;
- pushKey(Common::KEYCODE_F7);
-}
-
-void BadaAppForm::OnTouchDoublePressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- }
-}
-
-void BadaAppForm::OnTouchFocusIn(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
-}
-
-void BadaAppForm::OnTouchFocusOut(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
-}
-
-void BadaAppForm::OnTouchLongPressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kLeftButton) {
- pushKey(Common::KEYCODE_RETURN);
- }
-}
-
-void BadaAppForm::OnTouchMoved(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- pushEvent(Common::EVENT_MOUSEMOVE, currentPosition);
-}
-
-void BadaAppForm::OnTouchPressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- }
-}
-
-void BadaAppForm::OnTouchReleased(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP,
- currentPosition);
- if (_buttonState == kRightButtonOnce) {
- _buttonState = kLeftButton;
- }
- // flick to skip dialog
- if (touchInfo.IsFlicked()) {
- pushKey(Common::KEYCODE_PERIOD);
- }
- }
-}
-
-void BadaAppForm::OnKeyLongPressed(const Control &source, KeyCode keyCode) {
- logEntered();
- switch (keyCode) {
- case KEY_SIDE_UP:
- _shortcut = kSetVolume;
- setVolume(true, true);
- return;
-
- case KEY_SIDE_DOWN:
- _shortcut = kSetVolume;
- setVolume(false, true);
- return;
-
- case KEY_CAMERA:
- _shortcut = kShowKeypad;
- showKeypad();
- return;
-
- default:
- break;
- }
-}
-
-void BadaAppForm::OnKeyPressed(const Control &source, KeyCode keyCode) {
- switch (keyCode) {
- case KEY_SIDE_UP:
- if (_shortcut != kSetVolume) {
- _shortcut = kSetVolume;
- } else {
- setVolume(true, false);
- }
- return;
-
- case KEY_SIDE_DOWN:
- switch (_shortcut) {
- case kControlMouse:
- setButtonShortcut();
- break;
-
- case kEscapeKey:
- pushKey(Common::KEYCODE_ESCAPE);
- break;
-
- case kGameMenu:
- _buttonState = kLeftButton;
- pushKey(Common::KEYCODE_F5);
- break;
-
- case kShowKeypad:
- showKeypad();
- break;
-
- default:
- setVolume(false, false);
- break;
- }
- break;
-
- case KEY_CAMERA:
- setShortcut();
- break;
-
- default:
- break;
- }
-}
-
-void BadaAppForm::OnKeyReleased(const Control &source, KeyCode keyCode) {
-}
diff --git a/backends/platform/bada/form.h b/backends/platform/bada/form.h
deleted file mode 100644
index 3340e2216b..0000000000
--- a/backends/platform/bada/form.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef BADA_FORM_H
-#define BADA_FORM_H
-
-#include <FApp.h>
-#include <FUi.h>
-#include <FSystem.h>
-#include <FBase.h>
-#include <FUiITouchEventListener.h>
-#include <FUiITextEventListener.h>
-
-#include "config.h"
-#include "common/scummsys.h"
-#include "common/events.h"
-#include "common/queue.h"
-#include "common/mutex.h"
-
-//
-// BadaAppForm
-//
-class BadaAppForm : public Osp::Ui::Controls::Form,
- public Osp::Ui::IOrientationEventListener,
- public Osp::Ui::ITouchEventListener,
- public Osp::Ui::IKeyEventListener,
- public Osp::Base::Runtime::IRunnable {
-public:
- BadaAppForm();
- ~BadaAppForm();
-
- result Construct();
- bool pollEvent(Common::Event &event);
- bool isClosing() { return _state == kClosingState; }
- void pushKey(Common::KeyCode keycode);
- void exitSystem();
-
-private:
- Object *Run();
- result OnInitializing(void);
- result OnDraw(void);
- void OnOrientationChanged(const Osp::Ui::Control &source,
- Osp::Ui::OrientationStatus orientationStatus);
- void OnTouchDoublePressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchFocusIn(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchFocusOut(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchLongPressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchMoved(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchPressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchReleased(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnKeyLongPressed(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
- void OnKeyPressed(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
- void OnKeyReleased(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
-
- void pushEvent(Common::EventType type,
- const Osp::Graphics::Point &currentPosition);
- void terminate();
- void setButtonShortcut();
- void setShortcut();
- void setVolume(bool up, bool minMax);
- void showKeypad();
-
- // event handling
- Osp::Base::Runtime::Thread *_gameThread;
- Osp::Base::Runtime::Mutex *_eventQueueLock;
- Common::Queue<Common::Event> _eventQueue;
- enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state;
- enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState;
- enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad, kSetVolume } _shortcut;
-};
-
-#endif
diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h
index d41839d961..d62ced02e1 100644
--- a/backends/platform/dc/dc.h
+++ b/backends/platform/dc/dc.h
@@ -151,7 +151,7 @@ public:
void setShakePos(int shake_pos);
// Get the number of milliseconds since the program was started.
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
// Delay for a specified amount of milliseconds
void delayMillis(uint msecs);
diff --git a/backends/platform/dc/time.cpp b/backends/platform/dc/time.cpp
index 8cc3a71e8d..1e5f44ec85 100644
--- a/backends/platform/dc/time.cpp
+++ b/backends/platform/dc/time.cpp
@@ -26,7 +26,7 @@
#include "dc.h"
-uint32 OSystem_Dreamcast::getMillis()
+uint32 OSystem_Dreamcast::getMillis(bool skipRecord)
{
static uint32 msecs=0;
static unsigned int t0=0;
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index 830c782b90..9dc66e80d7 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -2280,7 +2280,7 @@ void VBlankHandler(void) {
//REG_IF = IRQ_VBLANK;
}
-int getMillis() {
+int getMillis(bool skipRecord) {
return currentTimeMillis;
// return frameCount * FRAME_TIME;
}
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index ad49ae276d..5e91fae13a 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -88,7 +88,7 @@ void setGamma(int gamma);
// Timers
void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval
-int getMillis(); // Return the current runtime in milliseconds
+int getMillis(bool skipRecord = false); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index a4b9c842fc..2f6358d8ee 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -656,7 +656,7 @@ bool OSystem_DS::pollEvent(Common::Event &event) {
return false;
}
-uint32 OSystem_DS::getMillis() {
+uint32 OSystem_DS::getMillis(bool skipRecord) {
return DS::getMillis();
}
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index a6001da764..4550e22b2c 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -117,7 +117,7 @@ public:
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &t) const;
diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp
index ed2c886213..460d3fd2ac 100644
--- a/backends/platform/iphone/osys_main.cpp
+++ b/backends/platform/iphone/osys_main.cpp
@@ -166,7 +166,7 @@ void OSystem_IPHONE::suspendLoop() {
_timeSuspended += getMillis() - startTime;
}
-uint32 OSystem_IPHONE::getMillis() {
+uint32 OSystem_IPHONE::getMillis(bool skipRecord) {
//printf("getMillis()\n");
struct timeval currentTime;
diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h
index 037125490d..811a8ddb2e 100644
--- a/backends/platform/iphone/osys_main.h
+++ b/backends/platform/iphone/osys_main.h
@@ -165,7 +165,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h
index bc6b3cb1a5..10138b230a 100644
--- a/backends/platform/n64/osys_n64.h
+++ b/backends/platform/n64/osys_n64.h
@@ -184,7 +184,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp
index 1e2aca9e51..afd93f5e09 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -810,7 +810,7 @@ void OSystem_N64::setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
return;
}
-uint32 OSystem_N64::getMillis() {
+uint32 OSystem_N64::getMillis(bool skipRecord) {
return getMilliTick();
}
diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp
index 4690a67c55..9e05539799 100644
--- a/backends/platform/null/null.cpp
+++ b/backends/platform/null/null.cpp
@@ -49,7 +49,7 @@ public:
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &t) const {}
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 5628658381..a7d782b07c 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -571,7 +571,7 @@ void OSystem_PS2::displayMessageOnOSD(const char *msg) {
printf("displayMessageOnOSD: %s\n", msg);
}
-uint32 OSystem_PS2::getMillis(void) {
+uint32 OSystem_PS2::getMillis(bool skipRecord) {
return msecCount;
}
diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h
index 99482d4da4..3ba40a70f9 100644
--- a/backends/platform/ps2/systemps2.h
+++ b/backends/platform/ps2/systemps2.h
@@ -82,7 +82,7 @@ public:
virtual void warpMouse(int x, int y);
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = 0);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual bool pollEvent(Common::Event &event);
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index fb8c1c60bf..8559066e53 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -349,7 +349,7 @@ bool OSystem_PSP::pollEvent(Common::Event &event) {
return _inputHandler.getAllInputs(event);
}
-uint32 OSystem_PSP::getMillis() {
+uint32 OSystem_PSP::getMillis(bool skipRecord) {
return PspRtc::instance().getMillis();
}
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 2afdabd0fc..f4591e476d 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -125,7 +125,7 @@ public:
bool processInput(Common::Event &event);
// Time
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
void delayMillis(uint msecs);
// Timer
diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp
index cbbb7d3f80..4f15e45535 100644
--- a/backends/platform/psp/rtc.cpp
+++ b/backends/platform/psp/rtc.cpp
@@ -52,7 +52,7 @@ void PspRtc::init() { // init our starting ticks
// Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause
// unpredictable results
-uint32 PspRtc::getMillis() {
+uint32 PspRtc::getMillis(bool skipRecord) {
uint32 ticks[2];
sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays
diff --git a/backends/platform/psp/rtc.h b/backends/platform/psp/rtc.h
index 45885c3e66..d2689681dd 100644
--- a/backends/platform/psp/rtc.h
+++ b/backends/platform/psp/rtc.h
@@ -40,7 +40,7 @@ public:
init();
}
void init();
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
uint32 getMicros();
};
diff --git a/backends/platform/sdl/sdl-sys.h b/backends/platform/sdl/sdl-sys.h
index ca3c586e03..eccf73815d 100644
--- a/backends/platform/sdl/sdl-sys.h
+++ b/backends/platform/sdl/sdl-sys.h
@@ -35,8 +35,11 @@
// it with an alternate slightly less unfriendly override.
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE)
#undef FILE
+// Solaris has typedef __FILE FILE in several places already
+#if !defined(__sun)
typedef struct { int FAKE; } FAKE_FILE;
#define FILE FAKE_FILE
+#endif // (__sun)
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp)
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index d54854352d..f55dd277c7 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -30,7 +30,7 @@
#include "backends/platform/sdl/sdl.h"
#include "common/config-manager.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
#include "common/taskbar.h"
#include "common/textconsole.h"
@@ -97,7 +97,9 @@ OSystem_SDL::~OSystem_SDL() {
_audiocdManager = 0;
delete _mixerManager;
_mixerManager = 0;
- delete _timerManager;
+
+ delete g_eventRec.getTimerManager();
+
_timerManager = 0;
delete _mutexManager;
_mutexManager = 0;
@@ -131,9 +133,6 @@ void OSystem_SDL::init() {
if (_mutexManager == 0)
_mutexManager = new SdlMutexManager();
- if (_timerManager == 0)
- _timerManager = new SdlTimerManager();
-
#if defined(USE_TASKBAR)
if (_taskbarManager == 0)
_taskbarManager = new Common::TaskbarManager();
@@ -191,10 +190,12 @@ void OSystem_SDL::initBackend() {
if (_mixerManager == 0) {
_mixerManager = new SdlMixerManager();
-
// Setup and start mixer
_mixerManager->init();
}
+ g_eventRec.registerMixerManager(_mixerManager);
+
+ g_eventRec.registerTimerManager(new SdlTimerManager());
if (_audiocdManager == 0) {
// Audio CD support was removed with SDL 1.3
@@ -466,14 +467,15 @@ void OSystem_SDL::setupIcon() {
free(icon);
}
-uint32 OSystem_SDL::getMillis() {
+
+uint32 OSystem_SDL::getMillis(bool skipRecord) {
uint32 millis = SDL_GetTicks();
- g_eventRec.processMillis(millis);
+ g_eventRec.processMillis(millis, skipRecord);
return millis;
}
void OSystem_SDL::delayMillis(uint msecs) {
- if (!g_eventRec.processDelayMillis(msecs))
+ if (!g_eventRec.processDelayMillis())
SDL_Delay(msecs);
}
@@ -491,12 +493,16 @@ void OSystem_SDL::getTimeAndDate(TimeDate &td) const {
Audio::Mixer *OSystem_SDL::getMixer() {
assert(_mixerManager);
- return _mixerManager->getMixer();
+ return getMixerManager()->getMixer();
}
SdlMixerManager *OSystem_SDL::getMixerManager() {
assert(_mixerManager);
- return _mixerManager;
+ return g_eventRec.getMixerManager();
+}
+
+Common::TimerManager *OSystem_SDL::getTimerManager() {
+ return g_eventRec.getTimerManager();
}
#ifdef USE_OPENGL
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index f05207b482..840e73ff09 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -68,10 +68,11 @@ public:
virtual void setWindowCaption(const char *caption);
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &td) const;
virtual Audio::Mixer *getMixer();
+ virtual Common::TimerManager *getTimerManager();
protected:
bool _inited;
diff --git a/backends/platform/bada/README.TXT b/backends/platform/tizen/README.TXT
index c4a04d5450..def3da2cce 100644
--- a/backends/platform/bada/README.TXT
+++ b/backends/platform/tizen/README.TXT
@@ -1,77 +1,58 @@
-Build instructions:
+Build instructions (using linux)
-1. Install BADA SDK (requires free registration):
-
- http://developer.bada.com/apis/index.do
-
-2. Install Cygwin:
-
- http://www.cygwin.com/
+1. Install the Tizen SDK
- Add the following to your cygwin .bash_profile:
+http://www.tizen.org
- alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe
- export BADA_SDK=/cygdrive/c/bada/1.2.1
- export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin
- export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \
- -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \
- -fno-strict-aliasing -fno-short-enums"
- export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target"
- #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH}
- export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH}
- alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe
- alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe
+To use an alternative Java SDK to run the Tizen IDE (eclipse), edit ~/.profile
- The following were added to ~/utils for zlib:
+export JAVA_HOME=/opt/jdk1.6.0_45
+export PATH=${PATH}:${JAVA_HOME}/bin
- ar:
- #!/bin/sh
- ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $*
+2. Add the following to your ~/.bashrc file
- gcc:
- #!/bin/sh
- ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $*
+export TIZEN_SDK=${HOME}/tizen-sdk
+export TIZEN_ROOTSTRAP=${TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-device-2.1.native
+export TIZEN_BIN=${TIZEN_SDK}/tools/arm-linux-gnueabi-gcc-4.5/bin
+export TIZEN_LIBS=${HOME}/tizen-lib
+export PATH=${PATH}:${TIZEN_BIN}:~/bin
+export CHOST=arm-linux-gnueabi
+export LDFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -L${TIZEN_LIBS}/lib"
+export CPPFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -fmessage-length=0 -fPIC\
+ -I${TIZEN_ROOTSTRAP}/usr/include -I${TIZEN_LIBS}/include"
+export CFLAGS=${CPPFLAGS}
3. Build dependencies
- zlib, libogg, libvorbis, libmad, FLAC
-
- see: "Building the libraries" under:
+ See: "Building the libraries" under:
http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW#Building_the_libraries
for instructions on how to obtain these modules
- 3.1 For Target-Release configure ogg and mad with:
-
- ./configure --host=arm-samsung-nucleuseabi --disable-shared
+ 3.1 zlib
- when building vorbis and flac:
+ $ ./configure --static --prefix=${TIZEN_LIBS}
+ $ make && make install
- ./configure --host=arm-samsung-nucleuseabi --disable-shared --with-ogg=c:/cygwin/usr/local
+ 3.2 freetype, libtheora, libogg, libvorbis, libmad, FLAC
- 3.2 for each module, after a successful configure, add the following
- to the generated config.h (gzguts.h for zlib)
+ $ ./configure --host=arm-linux-gnueabi --prefix=${TIZEN_LIBS} --disable-shared
+ $ make && make install
- #undef __MINGW32__
- #undef _WIN32
- #include "c:/src/scummvm/backends/platform/bada/portdefs.h"
-
- 3.3 Additional post configure edits:
+ Note: you can ignore the ranlib errors when doing make install.
- - removed -fforce-mem from the libMAD Makefile
- - in libvorbis/lib/Makefile comment lines with vorbis_selftests
- - edit libFLAC/Makefile ... CFLAGS = $(OGG_CFLAGS)
+ Modify the resulting ~/tizen-lib/bin/freetype-config file to include -lz when printing libs
- Note: you can ignore the ranlib errors when doing make install.
+ 3.3 Linker ordering: scummvm, freetype, theoradec, vorbis, vorbisfile, mad, FLAC, ogg, z
4. Build the ScummVM base library:
- ./configure --host=bada --enable-release
+ ./configure --host=tizen --enable-release --with-freetype2-prefix=${TIZEN_LIBS}/bin
- To target the Win32 simulator:
+ For development:
- ./configure --host=bada --enable-debug
+ ./configure --host=tizen --enable-verbose-build --enable-debug
-5. Build the front end application using BADA-Ide:
+5. Build the front end application using Tizen IDE
Copy the scummvm/dists/bada folder into a clean directory
outside of the scummvm package. Start the BADA IDE then
@@ -90,3 +71,38 @@ HelvB14 font files:
Then run the following command:
$ ./ucs2any.pl 100dpi/helvB14.bdf MAPPINGS/8859-1.TXT iso8859-1 \
MAPPINGS/8859-2.TXT iso8859-2 MAPPINGS/8859-3.TXT iso8859-3
+
+=====================================================================
+Archived build instruction for BADA/cygwin
+
+1. Install BADA SDK (requires free registration):
+
+ http://developer.bada.com/apis/index.do
+
+2. Install Cygwin:
+
+ http://www.cygwin.com/
+
+ Add the following to your cygwin .bash_profile:
+
+ alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe
+ export BADA_SDK=/cygdrive/c/bada/1.2.1
+ export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin
+ export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \
+ -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \
+ -fno-strict-aliasing -fno-short-enums"
+ export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target"
+ #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH}
+ export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH}
+ alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe
+ alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe
+
+ The following were added to ~/utils for zlib:
+
+ ar:
+ #!/bin/sh
+ ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $*
+
+ gcc:
+ #!/bin/sh
+ ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $*
diff --git a/backends/platform/bada/application.cpp b/backends/platform/tizen/application.cpp
index e761649245..8236ebef67 100644
--- a/backends/platform/bada/application.cpp
+++ b/backends/platform/tizen/application.cpp
@@ -22,43 +22,55 @@
#include "engines/engine.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/application.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/application.h"
-using namespace Osp::System;
-using namespace Osp::Ui::Controls;
-
-Application *BadaScummVM::createInstance() {
- return new BadaScummVM();
+Application *TizenScummVM::createInstance() {
+ logEntered();
+ return new TizenScummVM();
}
-BadaScummVM::BadaScummVM() : _appForm(0) {
+TizenScummVM::TizenScummVM() : _appForm(0) {
+ logEntered();
}
-BadaScummVM::~BadaScummVM() {
+TizenScummVM::~TizenScummVM() {
logEntered();
if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
+ TizenSystem *system = (TizenSystem *)g_system;
system->destroyBackend();
delete system;
g_system = 0;
}
}
-bool BadaScummVM::OnAppInitializing(AppRegistry &appRegistry) {
+bool TizenScummVM::OnAppInitialized(void) {
+ logEntered();
+ _appForm->SetOrientation(Tizen::Ui::ORIENTATION_LANDSCAPE);
+ return true;
+}
+
+bool TizenScummVM::OnAppWillTerminate(void) {
+ logEntered();
+ return true;
+}
+
+bool TizenScummVM::OnAppInitializing(AppRegistry &appRegistry) {
+ logEntered();
_appForm = systemStart(this);
return (_appForm != NULL);
}
-bool BadaScummVM::OnAppTerminating(AppRegistry &appRegistry,
- bool forcedTermination) {
+bool TizenScummVM::OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination) {
logEntered();
return true;
}
-void BadaScummVM::OnUserEventReceivedN(RequestId requestId,
- Osp::Base::Collection::IList *args) {
+void TizenScummVM::OnUserEventReceivedN(RequestId requestId, IList *args) {
+ MessageBox messageBox;
+ int modalResult;
+
logEntered();
if (requestId == USER_MESSAGE_EXIT) {
@@ -73,39 +85,56 @@ void BadaScummVM::OnUserEventReceivedN(RequestId requestId,
if (!message) {
message = new String("Unknown error");
}
-
- MessageBox messageBox;
messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK);
- int modalResult;
+ messageBox.ShowAndWait(modalResult);
+ Terminate();
+ } else if (requestId == USER_MESSAGE_EXIT_ERR_CONFIG) {
+ // the config file was corrupted
+ messageBox.Construct(L"Config file corrupted",
+ L"Settings have been reverted, please restart.", MSGBOX_STYLE_OK);
messageBox.ShowAndWait(modalResult);
Terminate();
}
}
-void BadaScummVM::OnForeground(void) {
+void TizenScummVM::OnForeground(void) {
logEntered();
pauseGame(false);
}
-void BadaScummVM::OnBackground(void) {
+void TizenScummVM::OnBackground(void) {
logEntered();
pauseGame(true);
}
-void BadaScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
+void TizenScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
+ logEntered();
}
-void BadaScummVM::OnLowMemory(void) {
+void TizenScummVM::OnLowMemory(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOn(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOff(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenBrightnessChanged(int brightness) {
+ logEntered();
}
-void BadaScummVM::pauseGame(bool pause) {
+void TizenScummVM::pauseGame(bool pause) {
if (_appForm) {
if (pause && g_engine && !g_engine->isPaused()) {
_appForm->pushKey(Common::KEYCODE_SPACE);
}
if (g_system) {
- ((BadaSystem *)g_system)->setMute(pause);
+ ((TizenSystem *)g_system)->setMute(pause);
}
}
}
diff --git a/backends/platform/tizen/application.h b/backends/platform/tizen/application.h
new file mode 100644
index 0000000000..f18ccb175b
--- /dev/null
+++ b/backends/platform/tizen/application.h
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TIZEN_APPLICATION_H
+#define TIZEN_APPLICATION_H
+
+#include <FBase.h>
+#include <FApp.h>
+#include <FGraphics.h>
+#include <FUi.h>
+#include <FSystem.h>
+
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/form.h"
+
+using namespace Tizen::App;
+using namespace Tizen::System;
+using namespace Tizen::Ui;
+using namespace Tizen::Ui::Controls;
+using namespace Tizen::Base::Collection;
+
+class TizenScummVM :
+ public UiApp,
+ public IScreenEventListener {
+
+public:
+ TizenScummVM();
+ virtual ~TizenScummVM();
+
+ static UiApp *createInstance(void);
+
+ virtual bool OnAppInitializing(AppRegistry &appRegistry);
+ virtual bool OnAppInitialized(void);
+ virtual bool OnAppWillTerminate(void);
+ virtual bool OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination = false);
+ virtual void OnLowMemory(void);
+ virtual void OnBatteryLevelChanged(BatteryLevel batteryLevel);
+ virtual void OnUserEventReceivedN(RequestId requestId, IList *pArgs);
+ virtual void OnForeground(void);
+ virtual void OnBackground(void);
+ virtual void OnScreenOn(void);
+ virtual void OnScreenOff(void);
+ virtual void OnScreenBrightnessChanged(int brightness);
+
+private:
+ void pauseGame(bool pause);
+ TizenAppForm *_appForm;
+};
+
+#endif
diff --git a/backends/platform/bada/audio.cpp b/backends/platform/tizen/audio.cpp
index 65a5a80fa5..313a10eaa8 100644
--- a/backends/platform/bada/audio.cpp
+++ b/backends/platform/tizen/audio.cpp
@@ -23,18 +23,11 @@
#include <FSysSettingInfo.h>
#include <FAppAppRegistry.h>
-#include "backends/platform/bada/audio.h"
-#include "backends/platform/bada/system.h"
+#include "backends/platform/tizen/audio.h"
+#include "backends/platform/tizen/system.h"
-#define TIMER_INCREMENT 10
-#define TIMER_INTERVAL 40
-#define MIN_TIMER_INTERVAL 10
-#define MAX_TIMER_INTERVAL 160
-#define INIT_LEVEL 3
-#define CONFIG_KEY L"audiovol"
-
-// sound level pre-sets
-const int levels[] = {0, 1, 10, 45, 70, 99};
+#define TIMER_INTERVAL 10
+#define VOLUME 99
AudioThread::AudioThread() :
_mixer(0),
@@ -51,9 +44,7 @@ AudioThread::AudioThread() :
Audio::MixerImpl *AudioThread::Construct(OSystem *system) {
logEntered();
- if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN,
- DEFAULT_STACK_SIZE,
- THREAD_PRIORITY_HIGH))) {
+ if (IsFailed(EventDrivenThread::Construct(DEFAULT_STACK_SIZE, THREAD_PRIORITY_HIGH))) {
AppLog("Failed to create AudioThread");
return NULL;
}
@@ -69,7 +60,7 @@ AudioThread::~AudioThread() {
bool AudioThread::isSilentMode() {
bool silentMode;
String key(L"SilentMode");
- Osp::System::SettingInfo::GetValue(key, silentMode);
+ Tizen::System::SettingInfo::GetValue(key, silentMode);
return silentMode;
}
@@ -79,59 +70,16 @@ void AudioThread::setMute(bool on) {
if (on) {
_timer->Cancel();
} else {
- _timer->Start(_interval);
- }
- }
-}
-
-int AudioThread::setVolume(bool up, bool minMax) {
- int level = -1;
- int numLevels = sizeof(levels) / sizeof(levels[0]);
-
- if (_audioOut) {
- int volume = _audioOut->GetVolume();
- if (minMax) {
- level = up ? numLevels - 1 : 0;
- volume = levels[level];
- } else {
- // adjust volume to be one of the preset values
- for (int i = 0; i < numLevels && level == -1; i++) {
- if (volume == levels[i]) {
- level = i;
- if (up) {
- if (i + 1 < numLevels) {
- level = i + 1;
- }
- } else if (i > 0) {
- level = i - 1;
- }
- }
- }
-
- // default to INIT_LEVEL when current not preset value
- if (level == -1) {
- level = INIT_LEVEL;
- }
- volume = levels[level];
- }
-
- _audioOut->SetVolume(volume);
-
- // remember the chosen setting
- AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
- if (registry) {
- registry->Set(CONFIG_KEY, volume);
+ _timer->StartAsRepeatable(_interval);
}
}
- return level;
}
bool AudioThread::OnStart(void) {
logEntered();
- _audioOut = new Osp::Media::AudioOut();
- if (!_audioOut ||
- IsFailed(_audioOut->Construct(*this))) {
+ _audioOut = new Tizen::Media::AudioOut();
+ if (!_audioOut || IsFailed(_audioOut->Construct(*this))) {
AppLog("Failed to create AudioOut");
return false;
}
@@ -144,8 +92,7 @@ bool AudioThread::OnStart(void) {
}
if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE,
- AUDIO_CHANNEL_TYPE_STEREO,
- sampleRate))) {
+ AUDIO_CHANNEL_TYPE_STEREO, sampleRate))) {
AppLog("Failed to prepare AudioOut %d", sampleRate);
return false;
}
@@ -164,26 +111,14 @@ bool AudioThread::OnStart(void) {
return false;
}
- if (IsFailed(_timer->Start(_interval))) {
+ if (IsFailed(_timer->StartAsRepeatable(_interval))) {
AppLog("failed to start audio timer");
return false;
}
- // get the volume from the app-registry
- int volume = levels[INIT_LEVEL];
- AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
- if (registry) {
- if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) {
- registry->Add(CONFIG_KEY, volume);
- volume = levels[INIT_LEVEL];
- } else {
- AppLog("Setting volume: %d", volume);
- }
- }
-
_muted = false;
_mixer->setReady(true);
- _audioOut->SetVolume(isSilentMode() ? 0 : volume);
+ _audioOut->SetVolume(isSilentMode() ? 0 : VOLUME);
_audioOut->Start();
return true;
}
@@ -206,20 +141,20 @@ void AudioThread::OnStop(void) {
}
}
-void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) {
+void AudioThread::OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r) {
logEntered();
}
-void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutInterrupted(Tizen::Media::AudioOut &src) {
logEntered();
}
-void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutReleased(Tizen::Media::AudioOut &src) {
logEntered();
_audioOut->Start();
}
-void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src) {
if (_ready > 0) {
_playing = _tail;
_audioOut->WriteBuffer(_audioBuffer[_tail]);
@@ -228,10 +163,6 @@ void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) {
} else {
// audio buffer empty: decrease timer inverval
_playing = -1;
- _interval -= TIMER_INCREMENT;
- if (_interval < MIN_TIMER_INTERVAL) {
- _interval = MIN_TIMER_INTERVAL;
- }
}
}
@@ -243,18 +174,8 @@ void AudioThread::OnTimerExpired(Timer &timer) {
_head = (_head + 1) % NUM_AUDIO_BUFFERS;
_ready++;
}
- } else {
- // audio buffer full: increase timer inverval
- _interval += TIMER_INCREMENT;
- if (_interval > MAX_TIMER_INTERVAL) {
- _interval = MAX_TIMER_INTERVAL;
- }
}
-
if (_ready && _playing == -1) {
OnAudioOutBufferEndReached(*_audioOut);
}
-
- _timer->Start(_interval);
}
-
diff --git a/backends/platform/bada/audio.h b/backends/platform/tizen/audio.h
index 72c537a942..8d7835042d 100644
--- a/backends/platform/bada/audio.h
+++ b/backends/platform/tizen/audio.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_AUDIO_H
-#define BADA_AUDIO_H
+#ifndef TIZEN_AUDIO_H
+#define TIZEN_AUDIO_H
#include <FBase.h>
#include <FMedia.h>
@@ -33,17 +33,19 @@
#include "common/system.h"
#include "audio/mixer_intern.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Collection;
-using namespace Osp::Base::Runtime;
-using namespace Osp::Media;
-using namespace Osp::Io;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Media;
+using namespace Tizen::Io;
#define NUM_AUDIO_BUFFERS 2
-class AudioThread: public Osp::Media::IAudioOutEventListener,
- public Osp::Base::Runtime::ITimerEventListener,
- public Osp::Base::Runtime::Thread {
+class AudioThread:
+ public Tizen::Media::IAudioOutEventListener,
+ public Tizen::Base::Runtime::ITimerEventListener,
+ public Tizen::Base::Runtime::EventDrivenThread {
+
public:
AudioThread(void);
~AudioThread(void);
@@ -51,21 +53,20 @@ public:
Audio::MixerImpl *Construct(OSystem *system);
bool isSilentMode();
void setMute(bool on);
- int setVolume(bool up, bool minMax);
bool OnStart(void);
void OnStop(void);
- void OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r);
- void OnAudioOutInterrupted(Osp::Media::AudioOut &src);
- void OnAudioOutReleased(Osp::Media::AudioOut &src);
- void OnAudioOutBufferEndReached(Osp::Media::AudioOut &src);
+ void OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r);
+ void OnAudioOutInterrupted(Tizen::Media::AudioOut &src);
+ void OnAudioOutReleased(Tizen::Media::AudioOut &src);
+ void OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src);
void OnTimerExpired(Timer &timer);
private:
Audio::MixerImpl *_mixer;
- Osp::Base::Runtime::Timer *_timer;
- Osp::Media::AudioOut *_audioOut;
- Osp::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS];
+ Tizen::Base::Runtime::Timer *_timer;
+ Tizen::Media::AudioOut *_audioOut;
+ Tizen::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS];
int _head, _tail, _ready, _interval, _playing;
bool _muted;
};
diff --git a/backends/platform/tizen/form.cpp b/backends/platform/tizen/form.cpp
new file mode 100644
index 0000000000..cce4b99557
--- /dev/null
+++ b/backends/platform/tizen/form.cpp
@@ -0,0 +1,419 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <FApp.h>
+#include <FSysSystemTime.h>
+
+#include "common/translation.h"
+#include "base/main.h"
+
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Ui::Controls;
+
+// round down small Y touch values to 1 to allow the
+// cursor to be positioned at the top of the screen
+#define MIN_TOUCH_Y 20
+
+// block for up to 2.5 seconds during shutdown to
+// allow the game thread to exit gracefully.
+#define EXIT_SLEEP_STEP 10
+#define EXIT_SLEEP 250
+
+//
+// TizenAppForm
+//
+TizenAppForm::TizenAppForm() :
+ _gestureMode(false),
+ _osdMessage(NULL),
+ _gameThread(NULL),
+ _eventQueueLock(NULL),
+ _state(kInitState),
+ _buttonState(kLeftButton),
+ _shortcut(kShowKeypad) {
+}
+
+result TizenAppForm::Construct() {
+ TizenSystem *tizenSystem = NULL;
+ result r = Form::Construct(FORM_STYLE_NORMAL);
+ if (!IsFailed(r)) {
+ tizenSystem = new TizenSystem(this);
+ r = tizenSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = tizenSystem->Construct();
+ }
+ if (!IsFailed(r)) {
+ _gameThread = new Thread();
+ r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = _gameThread->Construct(*this);
+ }
+ if (!IsFailed(r)) {
+ _eventQueueLock = new Mutex();
+ r = _eventQueueLock != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = _eventQueueLock->Create();
+ }
+
+ if (!IsFailed(r)) {
+ g_system = tizenSystem;
+ } else {
+ AppLog("Form startup failed");
+ delete tizenSystem;
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+ return r;
+}
+
+TizenAppForm::~TizenAppForm() {
+ logEntered();
+
+ if (_gameThread && _state != kErrorState) {
+ terminate();
+
+ _gameThread->Stop();
+ if (_state != kErrorState) {
+ _gameThread->Join();
+ }
+
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+
+ delete _eventQueueLock;
+ _eventQueueLock = NULL;
+
+ logLeaving();
+}
+
+//
+// abort the game thread
+//
+void TizenAppForm::terminate() {
+ if (_state == kActiveState) {
+ ((TizenSystem *)g_system)->setMute(true);
+
+ _eventQueueLock->Acquire();
+
+ Common::Event e;
+ e.type = Common::EVENT_QUIT;
+ _eventQueue.push(e);
+ _state = kClosingState;
+
+ _eventQueueLock->Release();
+
+ // block while thread ends
+ AppLog("waiting for shutdown");
+ for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) {
+ Thread::Sleep(EXIT_SLEEP);
+ }
+
+ if (_state == kClosingState) {
+ // failed to terminate - Join() will freeze
+ _state = kErrorState;
+ }
+ }
+}
+
+void TizenAppForm::exitSystem() {
+ _state = kErrorState;
+
+ if (_gameThread) {
+ _gameThread->Stop();
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+}
+
+result TizenAppForm::OnInitializing(void) {
+ logEntered();
+
+ AddOrientationEventListener(*this);
+ AddTouchEventListener(*this);
+ SetMultipointTouchEnabled(true);
+
+ // set focus to enable receiving key events
+ SetEnabled(true);
+ SetFocusable(true);
+ SetFocus();
+
+ return E_SUCCESS;
+}
+
+result TizenAppForm::OnDraw(void) {
+ logEntered();
+ return E_SUCCESS;
+}
+
+void TizenAppForm::OnOrientationChanged(const Control &source, OrientationStatus orientationStatus) {
+ logEntered();
+ if (_state == kInitState) {
+ _state = kActiveState;
+ _gameThread->Start();
+ }
+}
+
+Tizen::Base::Object *TizenAppForm::Run() {
+ logEntered();
+
+ scummvm_main(0, 0);
+ if (_state == kActiveState) {
+ Tizen::App::Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL);
+ }
+ _state = kDoneState;
+ return NULL;
+}
+
+bool TizenAppForm::pollEvent(Common::Event &event) {
+ bool result = false;
+
+ _eventQueueLock->Acquire();
+ if (!_eventQueue.empty()) {
+ event = _eventQueue.pop();
+ result = true;
+ }
+ if (_osdMessage) {
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
+ if (graphics) {
+ graphics->displayMessageOnOSD(_osdMessage);
+ _osdMessage = NULL;
+ }
+ }
+ _eventQueueLock->Release();
+
+ return result;
+}
+
+void TizenAppForm::pushEvent(Common::EventType type, const Point &currentPosition) {
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
+ if (graphics) {
+ // graphics could be NULL at startup or when
+ // displaying the system error screen
+ Common::Event e;
+ e.type = type;
+ e.mouse.x = currentPosition.x;
+ e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1;
+
+ bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y);
+
+ _eventQueueLock->Acquire();
+
+ if (moved && type != Common::EVENT_MOUSEMOVE) {
+ Common::Event moveEvent;
+ moveEvent.type = Common::EVENT_MOUSEMOVE;
+ moveEvent.mouse = e.mouse;
+ _eventQueue.push(moveEvent);
+ }
+
+ _eventQueue.push(e);
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::pushKey(Common::KeyCode keycode) {
+ if (_eventQueueLock) {
+ Common::Event e;
+ e.synthetic = false;
+ e.kbd.keycode = keycode;
+ e.kbd.ascii = keycode;
+ e.kbd.flags = 0;
+
+ _eventQueueLock->Acquire();
+ e.type = Common::EVENT_KEYDOWN;
+ _eventQueue.push(e);
+ e.type = Common::EVENT_KEYUP;
+ _eventQueue.push(e);
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::setButtonShortcut() {
+ switch (_buttonState) {
+ case kLeftButton:
+ setMessage(_s("Right Click Once"));
+ _buttonState = kRightButtonOnce;
+ break;
+ case kRightButtonOnce:
+ setMessage(_s("Right Click"));
+ _buttonState = kRightButton;
+ break;
+ case kRightButton:
+ setMessage(_s("Move Only"));
+ _buttonState = kMoveOnly;
+ break;
+ case kMoveOnly:
+ setMessage(_s("Left Click"));
+ _buttonState = kLeftButton;
+ break;
+ }
+}
+
+void TizenAppForm::setMessage(const char *message) {
+ if (_eventQueueLock) {
+ _eventQueueLock->Acquire();
+ _osdMessage = message;
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::setShortcut() {
+ logEntered();
+ // cycle to the next shortcut
+ switch (_shortcut) {
+ case kControlMouse:
+ setMessage(_s("Escape Key"));
+ _shortcut = kEscapeKey;
+ break;
+
+ case kEscapeKey:
+ setMessage(_s("Game Menu"));
+ _shortcut = kGameMenu;
+ break;
+
+ case kGameMenu:
+ setMessage(_s("Show Keypad"));
+ _shortcut = kShowKeypad;
+ break;
+
+ case kShowKeypad:
+ setMessage(_s("Control Mouse"));
+ _shortcut = kControlMouse;
+ break;
+ }
+}
+
+void TizenAppForm::invokeShortcut() {
+ logEntered();
+ switch (_shortcut) {
+ case kControlMouse:
+ setButtonShortcut();
+ break;
+
+ case kEscapeKey:
+ pushKey(Common::KEYCODE_ESCAPE);
+ break;
+
+ case kGameMenu:
+ _buttonState = kLeftButton;
+ pushKey(Common::KEYCODE_F5);
+ break;
+
+ case kShowKeypad:
+ showKeypad();
+ break;
+ }
+}
+
+void TizenAppForm::showKeypad() {
+ // display the soft keyboard
+ if (_state == kActiveState) {
+ _buttonState = kLeftButton;
+ pushKey(Common::KEYCODE_F7);
+ }
+}
+
+int TizenAppForm::getTouchCount() {
+ Tizen::Ui::TouchEventManager *touch = Tizen::Ui::TouchEventManager::GetInstance();
+ IListT<TouchEventInfo *> *touchList = touch->GetTouchInfoListN();
+ int touchCount = touchList->GetCount();
+ touchList->RemoveAll();
+ delete touchList;
+ return touchCount;
+}
+
+void TizenAppForm::OnTouchDoublePressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchFocusIn(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+}
+
+void TizenAppForm::OnTouchFocusOut(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+}
+
+void TizenAppForm::OnTouchLongPressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ logEntered();
+ if (_buttonState != kLeftButton) {
+ pushKey(Common::KEYCODE_RETURN);
+ }
+}
+
+void TizenAppForm::OnTouchMoved(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (!_gestureMode) {
+ pushEvent(Common::EVENT_MOUSEMOVE, currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchPressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (getTouchCount() > 1) {
+ _gestureMode = true;
+ } else if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchReleased(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (_gestureMode) {
+ int touchCount = getTouchCount();
+ if (touchCount == 1) {
+ setShortcut();
+ } else {
+ if (touchCount == 2) {
+ invokeShortcut();
+ }
+ _gestureMode = false;
+ }
+ } else if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP,
+ currentPosition);
+ if (_buttonState == kRightButtonOnce) {
+ _buttonState = kLeftButton;
+ }
+ // flick to skip dialog
+ if (touchInfo.IsFlicked()) {
+ pushKey(Common::KEYCODE_PERIOD);
+ }
+ }
+}
+
diff --git a/backends/platform/tizen/form.h b/backends/platform/tizen/form.h
new file mode 100644
index 0000000000..64c447d409
--- /dev/null
+++ b/backends/platform/tizen/form.h
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TIZEN_FORM_H
+#define TIZEN_FORM_H
+
+#include <FApp.h>
+#include <FUi.h>
+#include <FSystem.h>
+#include <FBase.h>
+#include <FUiITouchEventListener.h>
+#include <FUiITextEventListener.h>
+
+#include "config.h"
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/queue.h"
+#include "common/mutex.h"
+#include "engines/engine.h"
+
+using namespace Tizen::Ui;
+using namespace Tizen::Graphics;
+using namespace Tizen::Base::Runtime;
+
+//
+// TizenAppForm
+//
+class TizenAppForm :
+ public Controls::Form,
+ public IRunnable,
+ public IOrientationEventListener,
+ public ITouchEventListener {
+
+public:
+ TizenAppForm();
+ virtual ~TizenAppForm();
+
+ result Construct();
+ bool pollEvent(Common::Event &event);
+ bool isClosing() { return _state == kClosingState; }
+ bool isStarting() { return _state == kInitState; }
+ void pushKey(Common::KeyCode keycode);
+ void exitSystem();
+ void showKeypad();
+
+private:
+ Tizen::Base::Object *Run();
+ result OnInitializing(void);
+ result OnDraw(void);
+ void OnOrientationChanged(const Control &source,
+ OrientationStatus orientationStatus);
+ void OnTouchDoublePressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchFocusIn(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchFocusOut(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchLongPressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchMoved(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchPressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchReleased(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+
+ void pushEvent(Common::EventType type, const Point &currentPosition);
+ void terminate();
+ void setButtonShortcut();
+ void setMessage(const char *message);
+ void setShortcut();
+ void invokeShortcut();
+ int getTouchCount();
+ bool gameActive() { return _state == kActiveState && g_engine != NULL && !g_engine->isPaused(); }
+
+ // event handling
+ bool _gestureMode;
+ const char *_osdMessage;
+ Tizen::Base::Runtime::Thread *_gameThread;
+ Tizen::Base::Runtime::Mutex *_eventQueueLock;
+ Common::Queue<Common::Event> _eventQueue;
+ enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state;
+ enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState;
+ enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad } _shortcut;
+};
+
+#endif
diff --git a/backends/platform/bada/fs.cpp b/backends/platform/tizen/fs.cpp
index 37ca496d18..f8b32f4239 100644
--- a/backends/platform/bada/fs.cpp
+++ b/backends/platform/tizen/fs.cpp
@@ -20,33 +20,38 @@
*/
#include "config.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/fs.h"
+#include "common/translation.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/fs.h"
+
+#include <FAppApp.h>
#define BUFFER_SIZE 1024
-// internal BADA paths
-#define PATH_ROOT "/"
-#define PATH_HOME "/Home"
-#define PATH_HOME_SHARE "/Home/Share"
-#define PATH_HOME_SHARE2 "/Home/Share2"
-#define PATH_HOME_X "/Home/"
-#define PATH_HOME_EXT "/HomeExt"
-#define PATH_MEDIA "/Media"
-#define PATH_CARD "/Storagecard"
-#define PATH_CARD_MEDIA "/Storagecard/Media"
+using namespace Tizen::App;
+
+//
+// converts a Tizen (wchar) String into a scummVM (char) string
+//
+Common::String fromString(const Tizen::Base::String &in) {
+ ByteBuffer *buf = StringUtil::StringToUtf8N(in);
+ Common::String result((const char*)buf->GetPointer());
+ delete buf;
+ return result;
+}
//
-// BadaFileStream
+// TizenFileStream
//
-class BadaFileStream : public Common::SeekableReadStream,
- public Common::WriteStream,
- public Common::NonCopyable {
+class TizenFileStream :
+ public Common::SeekableReadStream,
+ public Common::WriteStream,
+ public Common::NonCopyable {
public:
- static BadaFileStream *makeFromPath(const String &path, bool writeMode);
+ static TizenFileStream *makeFromPath(const String &path, bool writeMode);
- BadaFileStream(File *file, bool writeMode);
- ~BadaFileStream();
+ TizenFileStream(File *file, bool writeMode);
+ ~TizenFileStream();
bool err() const;
void clearErr();
@@ -61,81 +66,81 @@ public:
uint32 read(void *dataPtr, uint32 dataSize);
private:
- byte buffer[BUFFER_SIZE];
- uint32 bufferIndex;
- uint32 bufferLength;
- bool writeMode;
- File *file;
+ byte _buffer[BUFFER_SIZE];
+ uint32 _bufferIndex;
+ uint32 _bufferLength;
+ bool _writeMode;
+ File *_file;
};
-BadaFileStream::BadaFileStream(File *ioFile, bool writeMode) :
- bufferIndex(0),
- bufferLength(0),
- writeMode(writeMode),
- file(ioFile) {
+TizenFileStream::TizenFileStream(File *ioFile, bool writeMode) :
+ _bufferIndex(0),
+ _bufferLength(0),
+ _writeMode(writeMode),
+ _file(ioFile) {
AppAssert(ioFile != 0);
}
-BadaFileStream::~BadaFileStream() {
- if (file) {
- if (writeMode) {
+TizenFileStream::~TizenFileStream() {
+ if (_file) {
+ if (_writeMode) {
flush();
}
- delete file;
+ delete _file;
}
}
-bool BadaFileStream::err() const {
+bool TizenFileStream::err() const {
result r = GetLastResult();
return (r != E_SUCCESS && r != E_END_OF_FILE);
}
-void BadaFileStream::clearErr() {
+void TizenFileStream::clearErr() {
SetLastResult(E_SUCCESS);
}
-bool BadaFileStream::eos() const {
- return (bufferLength - bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE);
+bool TizenFileStream::eos() const {
+ return (_bufferLength - _bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE);
}
-int32 BadaFileStream::pos() const {
- return file->Tell() - (bufferLength - bufferIndex);
+int32 TizenFileStream::pos() const {
+ return _file->Tell() - (_bufferLength - _bufferIndex);
}
-int32 BadaFileStream::size() const {
- int32 oldPos = file->Tell();
- file->Seek(FILESEEKPOSITION_END, 0);
+int32 TizenFileStream::size() const {
+ int32 oldPos = _file->Tell();
+ _file->Seek(FILESEEKPOSITION_END, 0);
- int32 length = file->Tell();
- SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, oldPos));
+ int32 length = _file->Tell();
+ SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, oldPos));
return length;
}
-bool BadaFileStream::seek(int32 offs, int whence) {
+bool TizenFileStream::seek(int32 offs, int whence) {
bool result = false;
switch (whence) {
case SEEK_SET:
// set from start of file
- SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, offs));
result = (E_SUCCESS == GetLastResult());
break;
case SEEK_CUR:
// set relative to offs
- if (bufferIndex < bufferLength && bufferIndex > (uint32)-offs) {
+ if (_bufferIndex < _bufferLength && _bufferIndex > (uint32)-offs) {
// re-position within the buffer
SetLastResult(E_SUCCESS);
- bufferIndex += offs;
+ _bufferIndex += offs;
return true;
} else {
- offs -= (bufferLength - bufferIndex);
- if (offs < 0 && file->Tell() + offs < 0) {
+ offs -= (_bufferLength - _bufferIndex);
+ if (offs < 0 && _file->Tell() + offs < 0) {
// avoid negative positioning
offs = 0;
}
if (offs != 0) {
- SetLastResult(file->Seek(FILESEEKPOSITION_CURRENT, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_CURRENT, offs));
result = (E_SUCCESS == GetLastResult());
} else {
result = true;
@@ -145,7 +150,7 @@ bool BadaFileStream::seek(int32 offs, int whence) {
case SEEK_END:
// set relative to end - positive will increase the file size
- SetLastResult(file->Seek(FILESEEKPOSITION_END, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_END, offs));
result = (E_SUCCESS == GetLastResult());
break;
@@ -158,46 +163,46 @@ bool BadaFileStream::seek(int32 offs, int whence) {
AppLog("seek failed");
}
- bufferIndex = bufferLength = 0;
+ _bufferIndex = _bufferLength = 0;
return result;
}
-uint32 BadaFileStream::read(void *ptr, uint32 len) {
+uint32 TizenFileStream::read(void *ptr, uint32 len) {
uint32 result = 0;
if (!eos()) {
- if (bufferIndex < bufferLength) {
+ if (_bufferIndex < _bufferLength) {
// use existing buffer
- uint32 available = bufferLength - bufferIndex;
+ uint32 available = _bufferLength - _bufferIndex;
if (len <= available) {
// use allocation
- memcpy((byte *)ptr, &buffer[bufferIndex], len);
- bufferIndex += len;
+ memcpy((byte *)ptr, &_buffer[_bufferIndex], len);
+ _bufferIndex += len;
result = len;
} else {
// use remaining allocation
- memcpy((byte *)ptr, &buffer[bufferIndex], available);
+ memcpy((byte *)ptr, &_buffer[_bufferIndex], available);
uint32 remaining = len - available;
result = available;
if (remaining) {
- result += file->Read(((byte *)ptr) + available, remaining);
+ result += _file->Read(((byte *)ptr) + available, remaining);
}
- bufferIndex = bufferLength = 0;
+ _bufferIndex = _bufferLength = 0;
}
} else if (len < BUFFER_SIZE) {
// allocate and use buffer
- bufferIndex = 0;
- bufferLength = file->Read(buffer, BUFFER_SIZE);
- if (bufferLength) {
- if (bufferLength < len) {
- len = bufferLength;
+ _bufferIndex = 0;
+ _bufferLength = _file->Read(_buffer, BUFFER_SIZE);
+ if (_bufferLength) {
+ if (_bufferLength < len) {
+ len = _bufferLength;
}
- memcpy((byte *)ptr, buffer, len);
- result = bufferIndex = len;
+ memcpy((byte *)ptr, _buffer, len);
+ result = _bufferIndex = len;
}
} else {
- result = file->Read((byte *)ptr, len);
- bufferIndex = bufferLength = 0;
+ result = _file->Read((byte *)ptr, len);
+ _bufferIndex = _bufferLength = 0;
}
} else {
AppLog("Attempted to read past EOS");
@@ -205,59 +210,77 @@ uint32 BadaFileStream::read(void *ptr, uint32 len) {
return result;
}
-uint32 BadaFileStream::write(const void *ptr, uint32 len) {
- result r = file->Write(ptr, len);
+uint32 TizenFileStream::write(const void *ptr, uint32 len) {
+ result r = _file->Write(ptr, len);
SetLastResult(r);
return (r == E_SUCCESS ? len : 0);
}
-bool BadaFileStream::flush() {
+bool TizenFileStream::flush() {
logEntered();
- SetLastResult(file->Flush());
+ SetLastResult(_file->Flush());
return (E_SUCCESS == GetLastResult());
}
-BadaFileStream *BadaFileStream::makeFromPath(const String &path, bool writeMode) {
+TizenFileStream *TizenFileStream::makeFromPath(const String &path, bool writeMode) {
File *ioFile = new File();
String filePath = path;
if (writeMode && (path[0] != '.' && path[0] != '/')) {
- filePath.Insert(PATH_HOME_X, 0);
+ filePath.Insert(App::GetInstance()->GetAppDataPath() + L"/", 0);
}
AppLog("Open file %S", filePath.GetPointer());
-
+ TizenFileStream *stream;
result r = ioFile->Construct(filePath, writeMode ? L"w" : L"r", writeMode);
if (r == E_SUCCESS) {
- return new BadaFileStream(ioFile, writeMode);
+ stream = new TizenFileStream(ioFile, writeMode);
+ } else {
+ AppLog("Failed to open file");
+ delete ioFile;
+ stream = NULL;
}
-
- AppLog("Failed to open file");
- delete ioFile;
- return 0;
-}
-
-//
-// converts a bada (wchar) String into a scummVM (char) string
-//
-Common::String fromString(const Osp::Base::String &in) {
- ByteBuffer *buf = StringUtil::StringToUtf8N(in);
- Common::String result((const char*)buf->GetPointer());
- delete buf;
-
- return result;
+ return stream;
}
//
-// BadaFilesystemNode
+// TizenFilesystemNode
//
-BadaFilesystemNode::BadaFilesystemNode(const Common::String &nodePath) {
+TizenFilesystemNode::TizenFilesystemNode(const Common::String &nodePath) {
AppAssert(nodePath.size() > 0);
init(nodePath);
}
-BadaFilesystemNode::BadaFilesystemNode(const Common::String &root,
- const Common::String &nodePath) {
+TizenFilesystemNode::TizenFilesystemNode(SystemPath systemPath) {
+ switch (systemPath) {
+ case kData:
+ _unicodePath = App::GetInstance()->GetAppDataPath();
+ _displayName = _s("[ Data ]");
+ break;
+ case kResource:
+ _unicodePath = App::GetInstance()->GetAppResourcePath();
+ _displayName = _s("[ Resources ]");
+ break;
+ case kSdCard:
+ _unicodePath = Tizen::System::Environment::GetExternalStoragePath();
+ _displayName = _s("[ SDCard ]");
+ break;
+ case kMedia:
+ _unicodePath = Tizen::System::Environment::GetMediaPath();
+ _displayName = _s("[ Media ]");
+ break;
+ case kShared:
+ _unicodePath = App::GetInstance()->GetAppSharedPath();
+ _displayName = _s("[ Shared ]");
+ break;
+ }
+ _path = ::fromString(_unicodePath);
+ _isValid = _isVirtualDir = !IsFailed(File::GetAttributes(_unicodePath, _attr));
+}
+
+TizenFilesystemNode::TizenFilesystemNode(const Common::String &root, const Common::String &nodePath) {
+ AppLog("TizenFilesystemNode '%s' '%s'", root.c_str(), nodePath.c_str());
+
// Make sure the string contains no slashes
AppAssert(!nodePath.contains('/'));
@@ -272,71 +295,54 @@ BadaFilesystemNode::BadaFilesystemNode(const Common::String &root,
init(newPath);
}
-void BadaFilesystemNode::init(const Common::String &nodePath) {
+void TizenFilesystemNode::init(const Common::String &nodePath) {
// Normalize the path (that is, remove unneeded slashes etc.)
_path = Common::normalizePath(nodePath, '/');
_displayName = Common::lastPathComponent(_path, '/');
StringUtil::Utf8ToString(_path.c_str(), _unicodePath);
- _isVirtualDir = (_path == PATH_ROOT ||
- _path == PATH_HOME ||
- _path == PATH_HOME_SHARE ||
- _path == PATH_HOME_SHARE2 ||
- _path == PATH_CARD);
+ _isVirtualDir = (_path == "/");
_isValid = _isVirtualDir || !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
-bool BadaFilesystemNode::exists() const {
+bool TizenFilesystemNode::exists() const {
return _isValid;
}
-bool BadaFilesystemNode::isReadable() const {
+bool TizenFilesystemNode::isReadable() const {
return _isVirtualDir || _isValid;
}
-bool BadaFilesystemNode::isDirectory() const {
+bool TizenFilesystemNode::isDirectory() const {
return _isVirtualDir || (_isValid && _attr.IsDirectory());
}
-bool BadaFilesystemNode::isWritable() const {
- bool result = (_isValid && !_isVirtualDir && !_attr.IsDirectory() && !_attr.IsReadOnly());
- if (_path == PATH_HOME ||
- _path == PATH_HOME_EXT ||
- _path == PATH_HOME_SHARE ||
- _path == PATH_HOME_SHARE2) {
- result = true;
+bool TizenFilesystemNode::isWritable() const {
+ bool result = (_isValid && !_attr.IsReadOnly());
+ if (_unicodePath == App::GetInstance()->GetAppResourcePath()) {
+ result = false;
}
return result;
}
-AbstractFSNode *BadaFilesystemNode::getChild(const Common::String &n) const {
+AbstractFSNode *TizenFilesystemNode::getChild(const Common::String &n) const {
AppAssert(!_path.empty());
AppAssert(isDirectory());
- return new BadaFilesystemNode(_path, n);
+ return new TizenFilesystemNode(_path, n);
}
-bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
- ListMode mode, bool hidden) const {
+bool TizenFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
AppAssert(isDirectory());
bool result = false;
- if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly) {
- // present well known BADA file system areas
- if (_path == PATH_ROOT) {
- myList.push_back(new BadaFilesystemNode(PATH_HOME));
- myList.push_back(new BadaFilesystemNode(PATH_HOME_EXT));
- myList.push_back(new BadaFilesystemNode(PATH_MEDIA));
- myList.push_back(new BadaFilesystemNode(PATH_CARD));
- result = true; // no more entries
- } else if (_path == PATH_CARD) {
- myList.push_back(new BadaFilesystemNode(PATH_CARD_MEDIA));
- result = true; // no more entries
- } else if (_path == PATH_HOME) {
- // ensure share path is always included
- myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE));
- myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE2));
- }
+ if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly && _path == "/") {
+ // present well known TIZEN file system areas
+ myList.push_back(new TizenFilesystemNode(kData));
+ myList.push_back(new TizenFilesystemNode(kResource));
+ myList.push_back(new TizenFilesystemNode(kSdCard));
+ myList.push_back(new TizenFilesystemNode(kMedia));
+ myList.push_back(new TizenFilesystemNode(kShared));
}
if (!result) {
@@ -358,7 +364,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
DirEntry dirEntry = pDirEnum->GetCurrentDirEntry();
// skip 'invisible' files if necessary
- Osp::Base::String fileName = dirEntry.GetName();
+ Tizen::Base::String fileName = dirEntry.GetName();
if (fileName[0] == '.' && !hidden) {
continue;
@@ -374,7 +380,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
(mode == Common::FSNode::kListDirectoriesOnly && !dirEntry.IsDirectory())) {
continue;
}
- myList.push_back(new BadaFilesystemNode(_path, fromString(fileName)));
+ myList.push_back(new TizenFilesystemNode(_path, ::fromString(fileName)));
}
}
@@ -392,9 +398,9 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
return result;
}
-AbstractFSNode *BadaFilesystemNode::getParent() const {
- logEntered();
- if (_path == PATH_ROOT) {
+AbstractFSNode *TizenFilesystemNode::getParent() const {
+ logEntered();
+ if (_path == "/") {
return 0; // The filesystem root has no parent
}
@@ -412,22 +418,22 @@ AbstractFSNode *BadaFilesystemNode::getParent() const {
// there simply is no parent.
// TODO: We could also resolve this by assuming that the parent is the
// current working directory, and returning a node referring to that.
- return 0;
+ return NULL;
}
- return new BadaFilesystemNode(Common::String(start, end));
+ return new TizenFilesystemNode(Common::String(start, end));
}
-Common::SeekableReadStream *BadaFilesystemNode::createReadStream() {
- Common::SeekableReadStream *result = BadaFileStream::makeFromPath(_unicodePath, false);
+Common::SeekableReadStream *TizenFilesystemNode::createReadStream() {
+ Common::SeekableReadStream *result = TizenFileStream::makeFromPath(_unicodePath, false);
if (result != NULL) {
_isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
return result;
}
-Common::WriteStream *BadaFilesystemNode::createWriteStream() {
- Common::WriteStream *result = BadaFileStream::makeFromPath(_unicodePath, true);
+Common::WriteStream *TizenFilesystemNode::createWriteStream() {
+ Common::WriteStream *result = TizenFileStream::makeFromPath(_unicodePath, true);
if (result != NULL) {
_isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
diff --git a/backends/platform/bada/fs.h b/backends/platform/tizen/fs.h
index d7d368ac20..0356aaad33 100644
--- a/backends/platform/bada/fs.h
+++ b/backends/platform/tizen/fs.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef BADA_FILESYSTEM_H
-#define BADA_FILESYSTEM_H
+#ifndef TIZEN_FILESYSTEM_H
+#define TIZEN_FILESYSTEM_H
#include <FBaseString.h>
#include <FBaseUtilStringUtil.h>
@@ -32,23 +32,40 @@
#include "common/stream.h"
#include "backends/fs/abstract-fs.h"
-using namespace Osp::Io;
-using namespace Osp::Base;
-using namespace Osp::Base::Utility;
+using namespace Tizen::Io;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Utility;
+
+//
+// converts a Tizen (wchar) String into a scummVM (char) string
+//
+Common::String fromString(const Tizen::Base::String &in);
+
+//
+// Enumerates the possible system paths
+//
+enum SystemPath { kData, kResource, kSdCard, kMedia, kShared };
/**
- * Implementation of the ScummVM file system API based on BADA.
+ * Implementation of the ScummVM file system API based on TIZEN.
*
* Parts of this class are documented in the base interface class, AbstractFSNode.
*/
-class BadaFilesystemNode : public AbstractFSNode {
+class TizenFilesystemNode : public AbstractFSNode {
public:
/**
- * Creates a BadaFilesystemNode for a given path.
+ * Creates a TizenFilesystemNode for a given path.
+ *
+ * @param path the path the new node should point to.
+ */
+ TizenFilesystemNode(const Common::String &path);
+
+ /**
+ * Creates a TizenFilesystemNode from the given Tizen internal path
*
* @param path the path the new node should point to.
*/
- BadaFilesystemNode(const Common::String &path);
+ TizenFilesystemNode(SystemPath systemPath);
Common::String getDisplayName() const { return _displayName; }
Common::String getName() const { return _displayName; }
@@ -67,8 +84,7 @@ public:
Common::WriteStream *createWriteStream();
protected:
- BadaFilesystemNode(const Common::String &root,
- const Common::String &p);
+ TizenFilesystemNode(const Common::String &root, const Common::String &p);
void init(const Common::String &nodePath);
Common::String _displayName;
diff --git a/backends/platform/bada/graphics.cpp b/backends/platform/tizen/graphics.cpp
index bd65c597c6..bf255cd264 100644
--- a/backends/platform/bada/graphics.cpp
+++ b/backends/platform/tizen/graphics.cpp
@@ -22,29 +22,40 @@
#include "graphics/fontman.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/graphics.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/graphics.h"
//
-// BadaGraphicsManager
+// TizenGraphicsManager
//
-BadaGraphicsManager::BadaGraphicsManager(BadaAppForm *appForm) :
+TizenGraphicsManager::TizenGraphicsManager(TizenAppForm *appForm) :
_appForm(appForm),
_eglDisplay(EGL_DEFAULT_DISPLAY),
_eglSurface(EGL_NO_SURFACE),
- _eglConfig(0),
+ _eglConfig(NULL),
_eglContext(EGL_NO_CONTEXT),
_initState(true) {
assert(appForm != NULL);
_videoMode.fullscreen = true;
}
-const Graphics::Font *BadaGraphicsManager::getFontOSD() {
+TizenGraphicsManager::~TizenGraphicsManager() {
+ logEntered();
+
+ if (_eglDisplay != EGL_NO_DISPLAY) {
+ eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
+ if (_eglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(_eglDisplay, _eglContext);
+ }
+ }
+}
+
+const Graphics::Font *TizenGraphicsManager::getFontOSD() {
return FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
}
-bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) {
+bool TizenGraphicsManager::moveMouse(int16 &x, int16 &y) {
int16 currentX = _cursorState.x;
int16 currentY = _cursorState.y;
@@ -62,7 +73,7 @@ bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) {
return (currentX != x || currentY != y);
}
-Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() const {
+Common::List<Graphics::PixelFormat> TizenGraphicsManager::getSupportedFormats() const {
logEntered();
Common::List<Graphics::PixelFormat> res;
@@ -73,33 +84,37 @@ Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() c
return res;
}
-bool BadaGraphicsManager::hasFeature(OSystem::Feature f) {
+bool TizenGraphicsManager::hasFeature(OSystem::Feature f) {
bool result = (f == OSystem::kFeatureFullscreenMode ||
- f == OSystem::kFeatureVirtualKeyboard ||
- OpenGLGraphicsManager::hasFeature(f));
+ f == OSystem::kFeatureVirtualKeyboard ||
+ OpenGLGraphicsManager::hasFeature(f));
return result;
}
-void BadaGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
- OpenGLGraphicsManager::setFeatureState(f, enable);
+void TizenGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ if (f == OSystem::kFeatureVirtualKeyboard && enable) {
+ _appForm->showKeypad();
+ } else {
+ OpenGLGraphicsManager::setFeatureState(f, enable);
+ }
}
-void BadaGraphicsManager::setReady() {
+void TizenGraphicsManager::setReady() {
_initState = false;
}
-void BadaGraphicsManager::updateScreen() {
+void TizenGraphicsManager::updateScreen() {
if (_transactionMode == kTransactionNone) {
internUpdateScreen();
}
}
-bool BadaGraphicsManager::loadEgl() {
+bool TizenGraphicsManager::loadEgl() {
logEntered();
EGLint numConfigs = 1;
EGLint eglConfigList[] = {
- EGL_RED_SIZE, 5,
+ EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 0,
@@ -132,8 +147,7 @@ bool BadaGraphicsManager::loadEgl() {
return false;
}
- if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList,
- &_eglConfig, 1, &numConfigs) ||
+ if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList, &_eglConfig, 1, &numConfigs) ||
EGL_SUCCESS != eglGetError()) {
systemError("eglChooseConfig() failed");
return false;
@@ -144,15 +158,13 @@ bool BadaGraphicsManager::loadEgl() {
return false;
}
- _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig,
- (EGLNativeWindowType)_appForm, NULL);
+ _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, (EGLNativeWindowType)_appForm, NULL);
if (EGL_NO_SURFACE == _eglSurface || EGL_SUCCESS != eglGetError()) {
systemError("eglCreateWindowSurface() failed. EGL_NO_SURFACE");
return false;
}
- _eglContext = eglCreateContext(_eglDisplay, _eglConfig,
- EGL_NO_CONTEXT, eglContextList);
+ _eglContext = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, eglContextList);
if (EGL_NO_CONTEXT == _eglContext ||
EGL_SUCCESS != eglGetError()) {
systemError("eglCreateContext() failed");
@@ -169,7 +181,7 @@ bool BadaGraphicsManager::loadEgl() {
return true;
}
-bool BadaGraphicsManager::loadGFXMode() {
+bool TizenGraphicsManager::loadGFXMode() {
logEntered();
if (!loadEgl()) {
@@ -181,35 +193,28 @@ bool BadaGraphicsManager::loadGFXMode() {
_appForm->GetBounds(x, y, width, height);
_videoMode.overlayWidth = _videoMode.hardwareWidth = width;
_videoMode.overlayHeight = _videoMode.hardwareHeight = height;
- _videoMode.scaleFactor = 3; // for proportional sized cursor in the launcher
+ _videoMode.scaleFactor = 4; // for proportional sized cursor in the launcher
AppLog("screen size: %dx%d", _videoMode.hardwareWidth, _videoMode.hardwareHeight);
return OpenGLGraphicsManager::loadGFXMode();
}
-void BadaGraphicsManager::loadTextures() {
+void TizenGraphicsManager::loadTextures() {
logEntered();
-
OpenGLGraphicsManager::loadTextures();
-
- // prevent image skew in some games, see:
- // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
-void BadaGraphicsManager::internUpdateScreen() {
+void TizenGraphicsManager::internUpdateScreen() {
if (!_initState) {
OpenGLGraphicsManager::internUpdateScreen();
eglSwapBuffers(_eglDisplay, _eglSurface);
- } else {
- showSplash();
}
}
-void BadaGraphicsManager::unloadGFXMode() {
+void TizenGraphicsManager::unloadGFXMode() {
logEntered();
- if (EGL_NO_DISPLAY != _eglDisplay) {
+ if (_eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
if (_eglContext != EGL_NO_CONTEXT) {
@@ -227,35 +232,6 @@ void BadaGraphicsManager::unloadGFXMode() {
}
_eglConfig = NULL;
-
OpenGLGraphicsManager::unloadGFXMode();
logLeaving();
}
-
-// display a simple splash screen until launcher is ready
-void BadaGraphicsManager::showSplash() {
- Canvas canvas;
- canvas.Construct();
- canvas.SetBackgroundColor(Color::COLOR_BLACK);
- canvas.Clear();
-
- int x = _videoMode.hardwareWidth / 3;
- int y = _videoMode.hardwareHeight / 3;
-
- Font *pFont = new Font();
- pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 55);
- canvas.SetFont(*pFont);
- canvas.SetForegroundColor(Color::COLOR_GREEN);
- canvas.DrawText(Point(x, y), L"ScummVM");
- delete pFont;
-
- pFont = new Font();
- pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 35);
- canvas.SetFont(*pFont);
- canvas.SetForegroundColor(Color::COLOR_WHITE);
- canvas.DrawText(Point(x + 70, y + 50), L"Loading ...");
- delete pFont;
-
- canvas.Show();
-
-}
diff --git a/backends/platform/bada/graphics.h b/backends/platform/tizen/graphics.h
index b2aaca43bc..27e5a6aaeb 100644
--- a/backends/platform/bada/graphics.h
+++ b/backends/platform/tizen/graphics.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_GRAPHICS_H
-#define BADA_GRAPHICS_H
+#ifndef TIZEN_GRAPHICS_H
+#define TIZEN_GRAPHICS_H
#include <FBase.h>
#include <FGraphics.h>
@@ -33,15 +33,16 @@
#include "config.h"
#include "backends/graphics/opengl/opengl-graphics.h"
#include "graphics/font.h"
-#include "backends/platform/bada/form.h"
+#include "backends/platform/tizen/form.h"
-using namespace Osp::Graphics;
-using namespace Osp::Graphics::Opengl;
-using namespace Osp::App;
+using namespace Tizen::Graphics;
+using namespace Tizen::Graphics::Opengl;
+using namespace Tizen::App;
-class BadaGraphicsManager : public OpenGLGraphicsManager {
+class TizenGraphicsManager : public OpenGLGraphicsManager {
public:
- BadaGraphicsManager(BadaAppForm *appForm);
+ TizenGraphicsManager(TizenAppForm *appForm);
+ virtual ~TizenGraphicsManager();
Common::List<Graphics::PixelFormat> getSupportedFormats() const;
bool hasFeature(OSystem::Feature f);
@@ -61,7 +62,7 @@ private:
void showSplash();
bool loadEgl();
- BadaAppForm *_appForm;
+ TizenAppForm *_appForm;
EGLDisplay _eglDisplay;
EGLSurface _eglSurface;
EGLConfig _eglConfig;
diff --git a/backends/platform/bada/main.cpp b/backends/platform/tizen/main.cpp
index 8c40f24dd1..b12cc3adc9 100644
--- a/backends/platform/bada/main.cpp
+++ b/backends/platform/tizen/main.cpp
@@ -24,44 +24,28 @@
#include <FApp.h>
#include <FSystem.h>
-#include "backends/platform/bada/portdefs.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/application.h"
+#include "backends/platform/tizen/application.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Collection;
-
-C_LINKAGE_BEGIN
-
-_EXPORT_ int OspMain(int argc, char *pArgv[]);
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
/**
- * The entry function of bada application called by the operating system.
+ * The entry function of tizen application called by the operating system.
*/
-int OspMain(int argc, char *pArgv[]) {
+extern "C" _EXPORT_ int OspMain(int argc, char *pArgv[]) {
result r = E_SUCCESS;
AppLog("Application started.");
- ArrayList *pArgs = new ArrayList();
- pArgs->Construct();
-
+ ArrayList args(SingleObjectDeleter);
+ args.Construct();
for (int i = 0; i < argc; i++) {
- pArgs->Add(*(new String(pArgv[i])));
+ args.Add(new (std::nothrow) String(pArgv[i]));
}
- r = Osp::App::Application::Execute(BadaScummVM::createInstance, pArgs);
- if (IsFailed(r)) {
- r &= 0x0000FFFF;
- }
-
- pArgs->RemoveAll(true);
- delete pArgs;
+ r = Tizen::App::UiApp::Execute(TizenScummVM::createInstance, &args);
+ TryLog(r == E_SUCCESS, "[%s] Application execution failed", GetErrorMessage(r));
AppLog("Application finished.");
return static_cast<int>(r);
}
-C_LINKAGE_END
-
-
diff --git a/backends/platform/bada/missing.cpp b/backends/platform/tizen/missing.cpp
index 10d45ca4b5..5ac55d0f6c 100644
--- a/backends/platform/bada/missing.cpp
+++ b/backends/platform/tizen/missing.cpp
@@ -26,7 +26,7 @@
#include <FSystem.h>
#include <FBase.h>
-#include "backends/platform/bada/portdefs.h"
+#include "backends/platform/tizen/portdefs.h"
#include <stdio.h>
#include <string.h>
@@ -48,7 +48,7 @@ void __assert_func(const char *file, int line,
systemError(buffer);
}
-void stderr_fprintf(void*, const char *format, ...) {
+void stderr_fprintf(void *, const char *format, ...) {
va_list ap;
char buffer[BUF_SIZE];
@@ -59,7 +59,7 @@ void stderr_fprintf(void*, const char *format, ...) {
AppLog(buffer);
}
-void stderr_vfprintf(void*, const char *format, va_list ap) {
+void stderr_vfprintf(void *, const char *format, va_list ap) {
char buffer[BUF_SIZE];
vsnprintf(buffer, sizeof(buffer), format, ap);
AppLog(buffer);
@@ -79,35 +79,4 @@ int printf(const char *format, ...) {
return result;
}
-int sprintf(char *str, const char *format, ...) {
- va_list ap;
- int result;
- char buffer[BUF_SIZE];
-
- va_start(ap, format);
- result = vsnprintf(buffer, sizeof(buffer), format, ap);
- va_end(ap);
-
- strcpy(str, buffer);
-
- return result;
-}
-
-char *strdup(const char *strSource) {
- char *buffer;
- int len = strlen(strSource) + 1;
- buffer = (char *)malloc(len);
- if (buffer) {
- memcpy(buffer, strSource, len);
- }
- return buffer;
-}
-
-int vsprintf(char *str, const char *format, va_list ap) {
- char buffer[BUF_SIZE];
- int result = vsnprintf(buffer, sizeof(buffer), format, ap);
- strcpy(str, buffer);
- return result;
-}
-
C_LINKAGE_END
diff --git a/backends/platform/bada/portdefs.h b/backends/platform/tizen/portdefs.h
index 813c5acde3..050ce7d1e0 100644
--- a/backends/platform/bada/portdefs.h
+++ b/backends/platform/tizen/portdefs.h
@@ -43,6 +43,9 @@
#define C_LINKAGE_END
#endif
+// value missing from osp gl headers
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+
C_LINKAGE_BEGIN
// for libFLAC
@@ -51,11 +54,11 @@ C_LINKAGE_BEGIN
#define fseeko fseek
#define ftello ftell
-// overcome use of fprintf since bada/newlib (1.2) does not
+// overcome use of fprintf since newlib (1.2) does not
// support stderr/stdout (undefined reference to `_impure_ptr').
-void stderr_fprintf(void*, const char *format, ...);
-void stderr_vfprintf(void*, const char *format, va_list ap);
+void stderr_fprintf(void *, const char *format, ...);
+void stderr_vfprintf(void *, const char *format, va_list ap);
#undef fprintf
#undef vfprintf
@@ -75,10 +78,7 @@ void stderr_vfprintf(void*, const char *format, va_list ap);
#define vfprintf stderr_vfprintf
int printf(const char *format, ...);
-int sprintf(char *str, const char *format, ...);
int simple_sscanf(const char *buffer, const char *format, ...);
-char *strdup(const char *s1);
-int vsprintf(char *str, const char *format, va_list ap);
C_LINKAGE_END
diff --git a/backends/platform/bada/sscanf.cpp b/backends/platform/tizen/sscanf.cpp
index aa846698f6..aa846698f6 100644
--- a/backends/platform/bada/sscanf.cpp
+++ b/backends/platform/tizen/sscanf.cpp
diff --git a/backends/platform/bada/system.cpp b/backends/platform/tizen/system.cpp
index 3f862c2571..54d92146e5 100644
--- a/backends/platform/bada/system.cpp
+++ b/backends/platform/tizen/system.cpp
@@ -34,53 +34,53 @@
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/mutex/mutex.h"
#include "backends/fs/fs-factory.h"
-#include "backends/timer/bada/timer.h"
+#include "backends/timer/tizen/timer.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/graphics.h"
-#include "backends/platform/bada/audio.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/graphics.h"
+#include "backends/platform/tizen/audio.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Runtime;
-using namespace Osp::Locales;
-using namespace Osp::Ui::Controls;
-using namespace Osp::System;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Locales;
+using namespace Tizen::Ui;
+using namespace Tizen::Ui::Controls;
+using namespace Tizen::System;
-#define DEFAULT_CONFIG_FILE "/Home/scummvm.ini"
-#define RESOURCE_PATH "/Res"
+#define DEFAULT_CONFIG_FILE "scummvm.ini"
#define MUTEX_BUFFER_SIZE 5
//
-// BadaFilesystemFactory
+// TizenFilesystemFactory
//
-class BadaFilesystemFactory : public FilesystemFactory {
+class TizenFilesystemFactory : public FilesystemFactory {
AbstractFSNode *makeRootFileNode() const;
AbstractFSNode *makeCurrentDirectoryFileNode() const;
AbstractFSNode *makeFileNodePath(const Common::String &path) const;
};
-AbstractFSNode *BadaFilesystemFactory::makeRootFileNode() const {
- return new BadaFilesystemNode("/");
+AbstractFSNode *TizenFilesystemFactory::makeRootFileNode() const {
+ return new TizenFilesystemNode("/");
}
-AbstractFSNode *BadaFilesystemFactory::makeCurrentDirectoryFileNode() const {
- return new BadaFilesystemNode("/Home");
+AbstractFSNode *TizenFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new TizenFilesystemNode("/");
}
-AbstractFSNode *BadaFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+AbstractFSNode *TizenFilesystemFactory::makeFileNodePath(const Common::String &path) const {
AppAssert(!path.empty());
- return new BadaFilesystemNode(path);
+ return new TizenFilesystemNode(path);
}
//
-// BadaSaveFileManager
+// TizenSaveFileManager
//
-struct BadaSaveFileManager : public DefaultSaveFileManager {
+struct TizenSaveFileManager : public DefaultSaveFileManager {
bool removeSavefile(const Common::String &filename);
};
-bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
+bool TizenSaveFileManager::removeSavefile(const Common::String &filename) {
Common::String savePathName = getSavePath();
checkPath(Common::FSNode(savePathName));
@@ -95,18 +95,18 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
String unicodeFileName;
StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName);
- switch (Osp::Io::File::Remove(unicodeFileName)) {
+ switch (Tizen::Io::File::Remove(unicodeFileName)) {
case E_SUCCESS:
return true;
case E_ILLEGAL_ACCESS:
setError(Common::kWritePermissionDenied, "Search or write permission denied: " +
- file.getName());
+ file.getName());
break;
default:
setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() +
- "' does not exist or path is invalid");
+ "' does not exist or path is invalid");
break;
}
@@ -114,40 +114,40 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
}
//
-// BadaMutexManager
+// TizenMutexManager
//
-struct BadaMutexManager : public MutexManager {
- BadaMutexManager();
- ~BadaMutexManager();
+struct TizenMutexManager : public MutexManager {
+ TizenMutexManager();
+ ~TizenMutexManager();
OSystem::MutexRef createMutex();
void lockMutex(OSystem::MutexRef mutex);
void unlockMutex(OSystem::MutexRef mutex);
void deleteMutex(OSystem::MutexRef mutex);
private:
- Mutex *buffer[MUTEX_BUFFER_SIZE];
+ Mutex *_buffer[MUTEX_BUFFER_SIZE];
};
-BadaMutexManager::BadaMutexManager() {
+TizenMutexManager::TizenMutexManager() {
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- buffer[i] = NULL;
+ _buffer[i] = NULL;
}
}
-BadaMutexManager::~BadaMutexManager() {
+TizenMutexManager::~TizenMutexManager() {
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] != NULL) {
- delete buffer[i];
+ if (_buffer[i] != NULL) {
+ delete _buffer[i];
}
}
}
-OSystem::MutexRef BadaMutexManager::createMutex() {
+OSystem::MutexRef TizenMutexManager::createMutex() {
Mutex *mutex = new Mutex();
mutex->Create();
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] == NULL) {
- buffer[i] = mutex;
+ if (_buffer[i] == NULL) {
+ _buffer[i] = mutex;
break;
}
}
@@ -155,22 +155,22 @@ OSystem::MutexRef BadaMutexManager::createMutex() {
return (OSystem::MutexRef) mutex;
}
-void BadaMutexManager::lockMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::lockMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
m->Acquire();
}
-void BadaMutexManager::unlockMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::unlockMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
m->Release();
}
-void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::deleteMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] == m) {
- buffer[i] = NULL;
+ if (_buffer[i] == m) {
+ _buffer[i] = NULL;
}
}
@@ -178,84 +178,101 @@ void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) {
}
//
-// BadaEventManager
+// TizenEventManager
//
-struct BadaEventManager : public DefaultEventManager {
- BadaEventManager(Common::EventSource *boss);
+struct TizenEventManager : public DefaultEventManager {
+ TizenEventManager(Common::EventSource *boss);
void init();
int shouldQuit() const;
};
-BadaEventManager::BadaEventManager(Common::EventSource *boss) :
+TizenEventManager::TizenEventManager(Common::EventSource *boss) :
DefaultEventManager(boss) {
}
-void BadaEventManager::init() {
+void TizenEventManager::init() {
DefaultEventManager::init();
// theme and vkbd should have now loaded - clear the splash screen
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
if (graphics) {
graphics->setReady();
- graphics->updateScreen();
}
}
-int BadaEventManager::shouldQuit() const {
- BadaSystem *system = (BadaSystem *)g_system;
+int TizenEventManager::shouldQuit() const {
+ TizenSystem *system = (TizenSystem *)g_system;
return DefaultEventManager::shouldQuit() || system->isClosing();
}
//
-// BadaSystem
+// TizenAppFrame - avoid drawing the misplaced UiTheme at startup
//
-BadaSystem::BadaSystem(BadaAppForm *appForm) :
+struct TizenAppFrame : Frame {
+ result OnDraw(void) {
+ logEntered();
+ TizenAppForm *form = (TizenAppForm *)GetCurrentForm();
+ if (form->isStarting()) {
+ Canvas *canvas = GetCanvasN();
+ canvas->SetBackgroundColor(Color::GetColor(COLOR_ID_BLACK));
+ canvas->Clear();
+ delete canvas;
+ }
+ return E_SUCCESS;
+ }
+};
+
+//
+// TizenSystem
+//
+TizenSystem::TizenSystem(TizenAppForm *appForm) :
_appForm(appForm),
_audioThread(0),
_epoch(0) {
}
-result BadaSystem::Construct(void) {
+result TizenSystem::Construct(void) {
logEntered();
- _fsFactory = new BadaFilesystemFactory();
+ _fsFactory = new TizenFilesystemFactory();
if (!_fsFactory) {
return E_OUT_OF_MEMORY;
}
+ _resourcePath = fromString(App::GetInstance()->GetAppResourcePath());
return E_SUCCESS;
}
-BadaSystem::~BadaSystem() {
+TizenSystem::~TizenSystem() {
logEntered();
}
-result BadaSystem::initModules() {
+result TizenSystem::initModules() {
logEntered();
- _mutexManager = new BadaMutexManager();
+ _mutexManager = new TizenMutexManager();
if (!_mutexManager) {
return E_OUT_OF_MEMORY;
}
- _timerManager = new BadaTimerManager();
+ _timerManager = new TizenTimerManager();
if (!_timerManager) {
return E_OUT_OF_MEMORY;
}
- _savefileManager = new BadaSaveFileManager();
+ _savefileManager = new TizenSaveFileManager();
if (!_savefileManager) {
return E_OUT_OF_MEMORY;
}
- _graphicsManager = (GraphicsManager *)new BadaGraphicsManager(_appForm);
+ _graphicsManager = (GraphicsManager *)new TizenGraphicsManager(_appForm);
if (!_graphicsManager) {
return E_OUT_OF_MEMORY;
}
// depends on _graphicsManager when ENABLE_VKEYBD enabled
- _eventManager = new BadaEventManager(this);
+ _eventManager = new TizenEventManager(this);
if (!_eventManager) {
return E_OUT_OF_MEMORY;
}
@@ -284,19 +301,21 @@ result BadaSystem::initModules() {
return E_SUCCESS;
}
-void BadaSystem::initBackend() {
+void TizenSystem::initBackend() {
logEntered();
+ Common::String dataPath = fromString(App::GetInstance()->GetAppDataPath());
+
// use the mobile device theme
- ConfMan.set("gui_theme", "/Res/scummmobile");
+ ConfMan.set("gui_theme", _resourcePath + "scummmodern");
- // allow bada virtual keypad pack to be found
- ConfMan.set("vkeybdpath", "/Res/vkeybd_bada");
+ // allow tizen virtual keypad pack to be found
+ ConfMan.set("vkeybdpath", _resourcePath + "vkeybd_bada");
ConfMan.set("vkeybd_pack_name", "vkeybd_bada");
// set default save path to writable area
if (!ConfMan.hasKey("savepath")) {
- ConfMan.set("savepath", "/Home/Share");
+ ConfMan.set("savepath", dataPath);
}
// default to no auto-save
@@ -314,85 +333,93 @@ void BadaSystem::initBackend() {
AppLog("initModules failed");
} else {
OSystem::initBackend();
- }
- // replace kBigGUIFont using the large font from the scummmobile theme
- Common::File fontFile;
- Common::String fileName = "/Res/scummmobile/helvB14-iso-8859-1.fcc";
- BadaFilesystemNode file(fileName);
- if (file.exists()) {
- Common::SeekableReadStream *stream = file.createReadStream();
- if (stream) {
- if (fontFile.open(stream, fileName)) {
+ // replace kBigGUIFont for the vkbd and on-screen messages
+ Common::String fontCacheFile = dataPath + "helvR24.fcc";
+ TizenFilesystemNode file(fontCacheFile);
+ if (!file.exists()) {
+ Common::String bdfFile = _resourcePath + "fonts/helvR24.bdf";
+ TizenFilesystemNode file(bdfFile);
+ if (file.exists()) {
+ Common::SeekableReadStream *stream = file.createReadStream();
+ Common::File fontFile;
+ if (stream && fontFile.open(stream, bdfFile)) {
+ Graphics::BdfFont *font = Graphics::BdfFont::loadFont(fontFile);
+ Graphics::BdfFont::cacheFontData(*font, fontCacheFile);
+ FontMan.setFont(Graphics::FontManager::kBigGUIFont, font);
+ }
+ }
+ } else {
+ Common::SeekableReadStream *stream = file.createReadStream();
+ Common::File fontFile;
+ if (stream && fontFile.open(stream, fontCacheFile)) {
Graphics::BdfFont *font = Graphics::BdfFont::loadFromCache(fontFile);
if (font) {
- // use this font for the vkbd and on-screen messages
FontMan.setFont(Graphics::FontManager::kBigGUIFont, font);
}
}
}
}
-
logLeaving();
}
-void BadaSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+void TizenSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
// allow translations.dat and game .DAT files to be found
- s.addDirectory(RESOURCE_PATH, RESOURCE_PATH, priority);
+ s.addDirectory(_resourcePath, _resourcePath, priority);
}
-void BadaSystem::destroyBackend() {
+void TizenSystem::destroyBackend() {
closeAudio();
delete _graphicsManager;
- _graphicsManager = 0;
+ _graphicsManager = NULL;
delete _savefileManager;
- _savefileManager = 0;
+ _savefileManager = NULL;
delete _fsFactory;
- _fsFactory = 0;
+ _fsFactory = NULL;
delete _mixer;
- _mixer = 0;
+ _mixer = NULL;
delete _audiocdManager;
- _audiocdManager = 0;
+ _audiocdManager = NULL;
delete _timerManager;
- _timerManager = 0;
+ _timerManager = NULL;
delete _eventManager;
- _eventManager = 0;
+ _eventManager = NULL;
delete _mutexManager;
- _mutexManager = 0;
+ _mutexManager = NULL;
}
-bool BadaSystem::pollEvent(Common::Event &event) {
+bool TizenSystem::pollEvent(Common::Event &event) {
return _appForm->pollEvent(event);
}
-uint32 BadaSystem::getMillis() {
+uint32 TizenSystem::getMillis(bool skipRecord) {
long long result, ticks = 0;
SystemTime::GetTicks(ticks);
result = ticks - _epoch;
return result;
}
-void BadaSystem::delayMillis(uint msecs) {
+void TizenSystem::delayMillis(uint msecs) {
if (!_appForm->isClosing()) {
Thread::Sleep(msecs);
}
}
-void BadaSystem::updateScreen() {
+void TizenSystem::updateScreen() {
if (_graphicsManager != NULL) {
_graphicsManager->updateScreen();
}
}
-void BadaSystem::getTimeAndDate(TimeDate &td) const {
+void TizenSystem::getTimeAndDate(TimeDate &td) const {
DateTime currentTime;
if (E_SUCCESS == SystemTime::GetCurrentTime(WALL_TIME, currentTime)) {
@@ -410,11 +437,11 @@ void BadaSystem::getTimeAndDate(TimeDate &td) const {
}
}
-void BadaSystem::fatalError() {
+void TizenSystem::fatalError() {
systemError("ScummVM: Fatal internal error.");
}
-void BadaSystem::exitSystem() {
+void TizenSystem::exitSystem() {
if (_appForm) {
closeAudio();
closeGraphics();
@@ -422,7 +449,7 @@ void BadaSystem::exitSystem() {
}
}
-void BadaSystem::logMessage(LogMessageType::Type type, const char *message) {
+void TizenSystem::logMessage(LogMessageType::Type type, const char *message) {
if (type == LogMessageType::kError) {
systemError(message);
} else {
@@ -430,69 +457,70 @@ void BadaSystem::logMessage(LogMessageType::Type type, const char *message) {
}
}
-Common::SeekableReadStream *BadaSystem::createConfigReadStream() {
- BadaFilesystemNode file(DEFAULT_CONFIG_FILE);
+Common::SeekableReadStream *TizenSystem::createConfigReadStream() {
+ TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE);
return file.createReadStream();
}
-Common::WriteStream *BadaSystem::createConfigWriteStream() {
- BadaFilesystemNode file(DEFAULT_CONFIG_FILE);
+Common::WriteStream *TizenSystem::createConfigWriteStream() {
+ TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE);
return file.createWriteStream();
}
-void BadaSystem::closeAudio() {
+void TizenSystem::closeAudio() {
if (_audioThread) {
- _audioThread->Stop();
+ _audioThread->Quit();
_audioThread->Join();
delete _audioThread;
- _audioThread = 0;
+ _audioThread = NULL;
}
}
-void BadaSystem::closeGraphics() {
+void TizenSystem::closeGraphics() {
if (_graphicsManager) {
delete _graphicsManager;
- _graphicsManager = 0;
+ _graphicsManager = NULL;
}
}
-void BadaSystem::setMute(bool on) {
+void TizenSystem::setMute(bool on) {
// only change mute after eventManager init() has completed
if (_audioThread) {
- BadaGraphicsManager *graphics = getGraphics();
+ TizenGraphicsManager *graphics = getGraphics();
if (graphics && graphics->isReady()) {
_audioThread->setMute(on);
}
}
}
-int BadaSystem::setVolume(bool up, bool minMax) {
- int level = -1;
- if (_audioThread) {
- level = _audioThread->setVolume(up, minMax);
- }
- return level;
-}
-
//
// create the ScummVM system
//
-BadaAppForm *systemStart(Osp::App::Application *app) {
+TizenAppForm *systemStart(Tizen::App::Application *app) {
logEntered();
- BadaAppForm *appForm = new BadaAppForm();
+ Frame *appFrame = new (std::nothrow) TizenAppFrame();
+ if (!appFrame || appFrame->Construct() == E_FAILURE) {
+ AppLog("Failed to create appFrame");
+ return NULL;
+ }
+ app->AddFrame(*appFrame);
+
+ TizenAppForm *appForm = new TizenAppForm();
if (!appForm) {
AppLog("Failed to create appForm");
return NULL;
}
if (E_SUCCESS != appForm->Construct() ||
- E_SUCCESS != app->GetAppFrame()->GetFrame()->AddControl(*appForm)) {
+ E_SUCCESS != appFrame->AddControl(*appForm)) {
delete appForm;
AppLog("Failed to construct appForm");
return NULL;
}
+ appFrame->SetCurrentForm(appForm);
+ logLeaving();
return appForm;
}
@@ -502,13 +530,18 @@ BadaAppForm *systemStart(Osp::App::Application *app) {
void systemError(const char *message) {
AppLog("Fatal system error: %s", message);
- ArrayList *args = new ArrayList();
- args->Construct();
- args->Add(*(new String(message)));
- Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args);
+ if (strspn(message, "Config file buggy:") > 0) {
+ Tizen::Io::File::Remove(DEFAULT_CONFIG_FILE);
+ Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR_CONFIG, NULL);
+ } else {
+ ArrayList *args = new ArrayList();
+ args->Construct();
+ args->Add(*(new String(message)));
+ Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args);
+ }
if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
+ TizenSystem *system = (TizenSystem *)g_system;
system->exitSystem();
}
}
diff --git a/backends/platform/bada/system.h b/backends/platform/tizen/system.h
index c28686cb3d..b38940cc95 100644
--- a/backends/platform/bada/system.h
+++ b/backends/platform/tizen/system.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_SYSTEM_H
-#define BADA_SYSTEM_H
+#ifndef TIZEN_SYSTEM_H
+#define TIZEN_SYSTEM_H
#include <FApp.h>
#include <FGraphics.h>
@@ -34,47 +34,46 @@
#include "common/scummsys.h"
#include "backends/modular-backend.h"
-#include "backends/platform/bada/fs.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/audio.h"
-#include "backends/platform/bada/graphics.h"
+#include "backends/platform/tizen/fs.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/audio.h"
+#include "backends/platform/tizen/graphics.h"
#if defined(_DEBUG)
-#define logEntered() AppLog("%s entered (%s %d)", \
- __FUNCTION__, __FILE__, __LINE__);
-#define logLeaving() AppLog("%s leaving (%s %d)", \
- __FUNCTION__, __FILE__, __LINE__);
+#define logEntered() AppLog("%s entered (%s %d)", __FUNCTION__, __FILE__, __LINE__);
+#define logLeaving() AppLog("%s leaving (%s %d)", __FUNCTION__, __FILE__, __LINE__);
#else
#define logEntered()
#define logLeaving()
#endif
-BadaAppForm *systemStart(Osp::App::Application *app);
+TizenAppForm *systemStart(Tizen::App::Application *app);
void systemError(const char *message);
-#define USER_MESSAGE_EXIT 1000
-#define USER_MESSAGE_EXIT_ERR 1001
+#define USER_MESSAGE_EXIT 1000
+#define USER_MESSAGE_EXIT_ERR 1001
+#define USER_MESSAGE_EXIT_ERR_CONFIG 1002
//
-// BadaSystem
+// TizenSystem
//
-class BadaSystem : public ModularBackend,
- Common::EventSource {
+class TizenSystem :
+ public ModularBackend,
+ Common::EventSource {
public:
- BadaSystem(BadaAppForm *appForm);
- ~BadaSystem();
+ TizenSystem(TizenAppForm *appForm);
+ ~TizenSystem();
result Construct();
void closeAudio();
void closeGraphics();
void destroyBackend();
void setMute(bool on);
- int setVolume(bool up, bool minMax);
void exitSystem();
bool isClosing() { return _appForm->isClosing(); }
- BadaGraphicsManager *getGraphics() {
- return (BadaGraphicsManager *)_graphicsManager;
+ TizenGraphicsManager *getGraphics() {
+ return (TizenGraphicsManager *)_graphicsManager;
}
private:
@@ -83,7 +82,7 @@ private:
void updateScreen();
bool pollEvent(Common::Event &event);
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
void delayMillis(uint msecs);
void getTimeAndDate(TimeDate &t) const;
void fatalError();
@@ -94,9 +93,10 @@ private:
Common::SeekableReadStream *createConfigReadStream();
Common::WriteStream *createConfigWriteStream();
- BadaAppForm *_appForm;
+ TizenAppForm *_appForm;
AudioThread *_audioThread;
long long _epoch;
+ Common::String _resourcePath;
};
#endif
diff --git a/backends/platform/tizen/tizen.mk b/backends/platform/tizen/tizen.mk
new file mode 100644
index 0000000000..d8925b62dc
--- /dev/null
+++ b/backends/platform/tizen/tizen.mk
@@ -0,0 +1,7 @@
+# port files built under eclipse
+
+MODULE := backends/platform/tizen
+
+$(EXECUTABLE): $(OBJS)
+ rm -f $@
+ arm-linux-gnueabi-ar Tru $@ $(OBJS)
diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
index 22a6495f8f..9d3a7473e3 100644
--- a/backends/platform/wii/osystem.cpp
+++ b/backends/platform/wii/osystem.cpp
@@ -203,7 +203,7 @@ bool OSystem_Wii::getFeatureState(Feature f) {
}
}
-uint32 OSystem_Wii::getMillis() {
+uint32 OSystem_Wii::getMillis(bool skipRecord) {
return ticks_to_millisecs(diff_ticks(_startup_time, gettime()));
}
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
index 5d6998d0b6..287c70ad6b 100644
--- a/backends/platform/wii/osystem.h
+++ b/backends/platform/wii/osystem.h
@@ -193,7 +193,7 @@ public:
const Graphics::PixelFormat *format);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex();
diff --git a/backends/saves/recorder/recorder-saves.cpp b/backends/saves/recorder/recorder-saves.cpp
new file mode 100644
index 0000000000..49b4672913
--- /dev/null
+++ b/backends/saves/recorder/recorder-saves.cpp
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/saves/recorder/recorder-saves.h"
+#include "gui/EventRecorder.h"
+#include "common/savefile.h"
+
+Common::InSaveFile *RecorderSaveFileManager::openForLoading(const Common::String &filename) {
+ Common::InSaveFile *result = g_eventRec.processSaveStream(filename);
+ return result;
+}
+
+Common::StringArray RecorderSaveFileManager::listSaveFiles(const Common::String &pattern) {
+ return g_eventRec.listSaveFiles(pattern);
+}
+
diff --git a/backends/saves/recorder/recorder-saves.h b/backends/saves/recorder/recorder-saves.h
new file mode 100644
index 0000000000..692aeca329
--- /dev/null
+++ b/backends/saves/recorder/recorder-saves.h
@@ -0,0 +1,36 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKEND_SAVES_RECORDER_H
+#define BACKEND_SAVES_RECORDER_H
+
+#include "backends/saves/default/default-saves.h"
+
+/**
+ * Provides a savefile manager implementation for event recorder.
+ */
+class RecorderSaveFileManager : public DefaultSaveFileManager {
+ virtual Common::StringArray listSaveFiles(const Common::String &pattern);
+ virtual Common::InSaveFile *openForLoading(const Common::String &filename);
+};
+
+#endif
diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp
index 9f56d58b12..ce93320f3d 100644
--- a/backends/timer/default/default-timer.cpp
+++ b/backends/timer/default/default-timer.cpp
@@ -80,7 +80,7 @@ DefaultTimerManager::~DefaultTimerManager() {
void DefaultTimerManager::handler() {
Common::StackLock lock(_mutex);
- const uint32 curTime = g_system->getMillis();
+ uint32 curTime = g_system->getMillis(true);
// Repeat as long as there is a TimerSlot that is scheduled to fire.
TimerSlot *slot = _head->next;
diff --git a/backends/timer/bada/timer.cpp b/backends/timer/tizen/timer.cpp
index e41ecd4864..fa226ce747 100644
--- a/backends/timer/bada/timer.cpp
+++ b/backends/timer/tizen/timer.cpp
@@ -20,15 +20,14 @@
*
*/
-#if defined(BADA)
+#if defined(TIZEN)
-#include "backends/timer/bada/timer.h"
+#include "backends/timer/tizen/timer.h"
//
-// TimerSlot
+// TimerSlot - an event driven thread
//
-TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback,
- uint32 interval, void *refCon) :
+TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon) :
_timer(0),
_callback(callback),
_interval(interval),
@@ -36,16 +35,17 @@ TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback,
}
TimerSlot::~TimerSlot() {
+ delete _timer;
}
bool TimerSlot::OnStart() {
- _timer = new Osp::Base::Runtime::Timer();
+ _timer = new Tizen::Base::Runtime::Timer();
if (!_timer || IsFailed(_timer->Construct(*this))) {
AppLog("Failed to create timer");
return false;
}
- if (IsFailed(_timer->Start(_interval))) {
+ if (IsFailed(_timer->StartAsRepeatable(_interval))) {
AppLog("failed to start timer");
return false;
}
@@ -65,28 +65,28 @@ void TimerSlot::OnStop() {
void TimerSlot::OnTimerExpired(Timer &timer) {
_callback(_refCon);
- timer.Start(_interval);
}
//
-// BadaTimerManager
+// TizenTimerManager
//
-BadaTimerManager::BadaTimerManager() {
+TizenTimerManager::TizenTimerManager() {
}
-BadaTimerManager::~BadaTimerManager() {
- for (Common::List<TimerSlot>::iterator slot = _timers.begin();
- slot != _timers.end(); ) {
- slot->Stop();
- slot = _timers.erase(slot);
+TizenTimerManager::~TizenTimerManager() {
+ for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ) {
+ TimerSlot *slot = (*it);
+ slot->Quit();
+ slot->Join();
+ delete slot;
+ it = _timers.erase(it);
}
}
-bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon,
- const Common::String &id) {
+bool TizenTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id) {
TimerSlot *slot = new TimerSlot(proc, interval / 1000, refCon);
- if (IsFailed(slot->Construct(THREAD_TYPE_EVENT_DRIVEN))) {
+ if (IsFailed(slot->Construct())) {
AppLog("Failed to create timer thread");
delete slot;
return false;
@@ -98,16 +98,18 @@ bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *re
return false;
}
- _timers.push_back(*slot);
+ _timers.push_back(slot);
return true;
}
-void BadaTimerManager::removeTimerProc(TimerProc proc) {
- for (Common::List<TimerSlot>::iterator slot = _timers.begin();
- slot != _timers.end(); ++slot) {
+void TizenTimerManager::removeTimerProc(TimerProc proc) {
+ for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ++it) {
+ TimerSlot *slot = (*it);
if (slot->_callback == proc) {
- slot->Stop();
- slot = _timers.erase(slot);
+ slot->Quit();
+ slot->Join();
+ delete slot;
+ it = _timers.erase(it);
}
}
}
diff --git a/backends/timer/bada/timer.h b/backends/timer/tizen/timer.h
index 826064d7ff..4b2596401a 100644
--- a/backends/timer/bada/timer.h
+++ b/backends/timer/tizen/timer.h
@@ -20,20 +20,18 @@
*
*/
-#ifndef BADA_TIMER_H
-#define BADA_TIMER_H
+#ifndef TIZEN_TIMER_H
+#define TIZEN_TIMER_H
#include <FBase.h>
#include "common/timer.h"
#include "common/list.h"
-using namespace Osp::Base::Runtime;
+using namespace Tizen::Base::Runtime;
-struct TimerSlot: public ITimerEventListener, public Thread {
- TimerSlot(Common::TimerManager::TimerProc callback,
- uint32 interval,
- void *refCon);
+struct TimerSlot: public EventDrivenThread, public ITimerEventListener {
+ TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon);
~TimerSlot();
bool OnStart(void);
@@ -46,17 +44,16 @@ struct TimerSlot: public ITimerEventListener, public Thread {
void *_refCon;
};
-class BadaTimerManager : public Common::TimerManager {
+class TizenTimerManager : public Common::TimerManager {
public:
- BadaTimerManager();
- ~BadaTimerManager();
+ TizenTimerManager();
+ ~TizenTimerManager();
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon,
- const Common::String &id);
+ bool installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id);
void removeTimerProc(TimerProc proc);
private:
- Common::List<TimerSlot> _timers;
+ Common::List<TimerSlot *> _timers;
};
#endif
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 42a3a64d34..a39c748adc 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -118,6 +118,13 @@ static const char HELP_STRING[] =
" --aspect-ratio Enable aspect ratio correction\n"
" --render-mode=MODE Enable additional render modes (cga, ega, hercGreen,\n"
" hercAmber, amiga)\n"
+#ifdef ENABLE_EVENTRECORDER
+ " --record-mode=MODE Specify record mode for event recorder (record, playback,\n"
+ " passthrough [default])\n"
+ " --record-file-name=FILE Specify record file name\n"
+ " --disable-display Disable any gfx output. Used for headless events\n"
+ " playback by Event Recorder\n"
+#endif
"\n"
#if defined(ENABLE_SKY) || defined(ENABLE_QUEEN)
" --alt-intro Use alternative intro for CD versions of Beneath a\n"
@@ -232,10 +239,9 @@ void registerDefaults() {
ConfMan.registerDefault("confirm_exit", false);
ConfMan.registerDefault("disable_sdl_parachute", false);
+ ConfMan.registerDefault("disable_display", false);
ConfMan.registerDefault("record_mode", "none");
ConfMan.registerDefault("record_file_name", "record.bin");
- ConfMan.registerDefault("record_temp_file_name", "record.tmp");
- ConfMan.registerDefault("record_time_file_name", "record.time");
ConfMan.registerDefault("gui_saveload_chooser", "grid");
ConfMan.registerDefault("gui_saveload_last_pos", "0");
@@ -424,6 +430,17 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_OPTION_BOOL('f', "fullscreen")
END_OPTION
+#ifdef ENABLE_EVENTRECORDER
+ DO_LONG_OPTION_INT("disable-display")
+ END_OPTION
+
+ DO_LONG_OPTION("record-mode")
+ END_OPTION
+
+ DO_LONG_OPTION("record-file-name")
+ END_OPTION
+#endif
+
DO_LONG_OPTION("opl-driver")
END_OPTION
@@ -569,18 +586,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
END_OPTION
#endif
- DO_LONG_OPTION("record-mode")
- END_OPTION
-
- DO_LONG_OPTION("record-file-name")
- END_OPTION
-
- DO_LONG_OPTION("record-temp-file-name")
- END_OPTION
-
- DO_LONG_OPTION("record-time-file-name")
- END_OPTION
-
#ifdef IPHONE
// This is automatically set when launched from the Springboard.
DO_LONG_OPTION_OPT("launchedFromSB", 0)
diff --git a/base/main.cpp b/base/main.cpp
index 355a65f883..3f51c97949 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -42,8 +42,11 @@
#include "common/debug.h"
#include "common/debug-channels.h" /* for debug manager */
#include "common/events.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
#include "common/fs.h"
+#ifdef ENABLE_EVENTRECORDER
+#include "common/recorderfile.h"
+#endif
#include "common/system.h"
#include "common/textconsole.h"
#include "common/tokenizer.h"
@@ -409,7 +412,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
settings["gfx-mode"] = "default";
}
}
-
+ if (settings.contains("disable-display")) {
+ ConfMan.setInt("disable-display", 1, Common::ConfigManager::kTransientDomain);
+ }
setupGraphics(system);
// Init the different managers that are used by the engines.
@@ -428,7 +433,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// TODO: This is just to match the current behavior, when we further extend
// our event recorder, we might do this at another place. Or even change
// the whole API for that ;-).
- g_eventRec.init();
+ g_eventRec.RegisterEventSource();
// Now as the event manager is created, setup the keymapper
setupKeymapper(system);
@@ -448,6 +453,21 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// to save memory
PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, plugin);
+#ifdef ENABLE_EVENTRECORDER
+ Common::String recordMode = ConfMan.get("record_mode");
+ Common::String recordFileName = ConfMan.get("record_file_name");
+
+ if (recordMode == "record") {
+ g_eventRec.init(g_eventRec.generateRecordFileName(ConfMan.getActiveDomainName()), GUI::EventRecorder::kRecorderRecord);
+ } else if (recordMode == "playback") {
+ g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderPlayback);
+ } else if ((recordMode == "info") && (!recordFileName.empty())) {
+ Common::PlaybackFile record;
+ record.openRead(recordFileName);
+ debug("info:author=%s name=%s description=%s", record.getHeader().author.c_str(), record.getHeader().name.c_str(), record.getHeader().description.c_str());
+ break;
+ }
+#endif
// Try to run the game
Common::Error result = runGame(plugin, system, specialDebug);
@@ -478,6 +498,11 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
#ifdef FORCE_RTL
g_system->getEventManager()->resetQuit();
#endif
+ #ifdef ENABLE_EVENTRECORDER
+ if (g_eventRec.checkForContinueGame()) {
+ continue;
+ }
+ #endif
// Discard any command line options. It's unlikely that the user
// wanted to apply them to *all* games ever launched.
@@ -501,7 +526,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
GUI::GuiManager::destroy();
Common::ConfigManager::destroy();
Common::DebugManager::destroy();
- Common::EventRecorder::destroy();
+ GUI::EventRecorder::destroy();
Common::SearchManager::destroy();
#ifdef USE_TRANSLATION
Common::TranslationManager::destroy();
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index 012a2dfce5..e60c1aa7ff 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -24,7 +24,7 @@
namespace Common {
-EventDispatcher::EventDispatcher() : _mapper(0) {
+EventDispatcher::EventDispatcher() : _autoFreeMapper(false), _mapper(0) {
}
EventDispatcher::~EventDispatcher() {
@@ -38,7 +38,9 @@ EventDispatcher::~EventDispatcher() {
delete i->observer;
}
- delete _mapper;
+ if (_autoFreeMapper) {
+ delete _mapper;
+ }
_mapper = 0;
}
@@ -68,11 +70,15 @@ void EventDispatcher::dispatch() {
}
}
-void EventDispatcher::registerMapper(EventMapper *mapper) {
- delete _mapper;
+void EventDispatcher::registerMapper(EventMapper *mapper, bool autoFree) {
+ if (_autoFreeMapper) {
+ delete _mapper;
+ }
_mapper = mapper;
+ _autoFreeMapper = autoFree;
}
+
void EventDispatcher::registerSource(EventSource *source, bool autoFree) {
SourceEntry newEntry;
diff --git a/common/EventRecorder.cpp b/common/EventRecorder.cpp
deleted file mode 100644
index 5e24f128c3..0000000000
--- a/common/EventRecorder.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/EventRecorder.h"
-
-#include "common/bufferedstream.h"
-#include "common/config-manager.h"
-#include "common/random.h"
-#include "common/savefile.h"
-#include "common/textconsole.h"
-
-namespace Common {
-
-DECLARE_SINGLETON(EventRecorder);
-
-#define RECORD_SIGNATURE 0x54455354
-#define RECORD_VERSION 1
-
-uint32 readTime(ReadStream *inFile) {
- uint32 d = inFile->readByte();
- if (d == 0xff) {
- d = inFile->readUint32LE();
- }
-
- return d;
-}
-
-void writeTime(WriteStream *outFile, uint32 d) {
- //Simple RLE compression
- if (d >= 0xff) {
- outFile->writeByte(0xff);
- outFile->writeUint32LE(d);
- } else {
- outFile->writeByte(d);
- }
-}
-
-void readRecord(SeekableReadStream *inFile, uint32 &diff, Event &event, uint32 &millis) {
- millis = readTime(inFile);
-
- diff = inFile->readUint32LE();
-
- event.type = (EventType)inFile->readUint32LE();
-
- switch (event.type) {
- case EVENT_KEYDOWN:
- case EVENT_KEYUP:
- event.kbd.keycode = (KeyCode)inFile->readSint32LE();
- event.kbd.ascii = inFile->readUint16LE();
- event.kbd.flags = inFile->readByte();
- break;
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- case EVENT_MBUTTONDOWN:
- case EVENT_MBUTTONUP:
- event.mouse.x = inFile->readSint16LE();
- event.mouse.y = inFile->readSint16LE();
- break;
- default:
- break;
- }
-}
-
-void writeRecord(WriteStream *outFile, uint32 diff, const Event &event, uint32 millis) {
- writeTime(outFile, millis);
-
- outFile->writeUint32LE(diff);
-
- outFile->writeUint32LE((uint32)event.type);
-
- switch (event.type) {
- case EVENT_KEYDOWN:
- case EVENT_KEYUP:
- outFile->writeSint32LE(event.kbd.keycode);
- outFile->writeUint16LE(event.kbd.ascii);
- outFile->writeByte(event.kbd.flags);
- break;
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- case EVENT_MBUTTONDOWN:
- case EVENT_MBUTTONUP:
- outFile->writeSint16LE(event.mouse.x);
- outFile->writeSint16LE(event.mouse.y);
- break;
- default:
- break;
- }
-}
-
-EventRecorder::EventRecorder() {
- _recordFile = NULL;
- _recordTimeFile = NULL;
- _playbackFile = NULL;
- _playbackTimeFile = NULL;
- _timeMutex = g_system->createMutex();
- _recorderMutex = g_system->createMutex();
-
- _eventCount = 0;
- _lastEventCount = 0;
- _lastMillis = 0;
- _lastEventMillis = 0;
-
- _recordMode = kPassthrough;
-}
-
-EventRecorder::~EventRecorder() {
- deinit();
-
- g_system->deleteMutex(_timeMutex);
- g_system->deleteMutex(_recorderMutex);
-}
-
-void EventRecorder::init() {
- String recordModeString = ConfMan.get("record_mode");
- if (recordModeString.compareToIgnoreCase("record") == 0) {
- _recordMode = kRecorderRecord;
-
- debug(3, "EventRecorder: record");
- } else {
- if (recordModeString.compareToIgnoreCase("playback") == 0) {
- _recordMode = kRecorderPlayback;
- debug(3, "EventRecorder: playback");
- } else {
- _recordMode = kPassthrough;
- debug(3, "EventRecorder: passthrough");
- }
- }
-
- _recordFileName = ConfMan.get("record_file_name");
- if (_recordFileName.empty()) {
- _recordFileName = "record.bin";
- }
- _recordTempFileName = ConfMan.get("record_temp_file_name");
- if (_recordTempFileName.empty()) {
- _recordTempFileName = "record.tmp";
- }
- _recordTimeFileName = ConfMan.get("record_time_file_name");
- if (_recordTimeFileName.empty()) {
- _recordTimeFileName = "record.time";
- }
-
- // recorder stuff
- if (_recordMode == kRecorderRecord) {
- _recordCount = 0;
- _recordTimeCount = 0;
- _recordFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTempFileName), 128 * 1024);
- _recordTimeFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTimeFileName), 128 * 1024);
- _recordSubtitles = ConfMan.getBool("subtitles");
- }
-
- uint32 sign;
- uint32 randomSourceCount;
- if (_recordMode == kRecorderPlayback) {
- _playbackCount = 0;
- _playbackTimeCount = 0;
- _playbackFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordFileName), 128 * 1024, DisposeAfterUse::YES);
- _playbackTimeFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordTimeFileName), 128 * 1024, DisposeAfterUse::YES);
-
- if (!_playbackFile) {
- warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str());
- _recordMode = kPassthrough;
- }
-
- if (!_playbackTimeFile) {
- warning("Cannot open playback time file %s. Playback was switched off", _recordTimeFileName.c_str());
- _recordMode = kPassthrough;
- }
- }
-
- if (_recordMode == kRecorderPlayback) {
- sign = _playbackFile->readUint32LE();
- if (sign != RECORD_SIGNATURE) {
- error("Unknown record file signature");
- }
-
- _playbackFile->readUint32LE(); // version
-
- // conf vars
- ConfMan.setBool("subtitles", _playbackFile->readByte() != 0);
-
- _recordCount = _playbackFile->readUint32LE();
- _recordTimeCount = _playbackFile->readUint32LE();
-
- randomSourceCount = _playbackFile->readUint32LE();
- for (uint i = 0; i < randomSourceCount; ++i) {
- RandomSourceRecord rec;
- rec.name = "";
- uint32 sLen = _playbackFile->readUint32LE();
- for (uint j = 0; j < sLen; ++j) {
- char c = _playbackFile->readSByte();
- rec.name += c;
- }
- rec.seed = _playbackFile->readUint32LE();
- _randomSourceRecords.push_back(rec);
- }
-
- _hasPlaybackEvent = false;
- }
-
- g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
- g_system->getEventManager()->getEventDispatcher()->registerObserver(this, EventManager::kEventRecorderPriority, false, true);
-}
-
-void EventRecorder::deinit() {
- debug(3, "EventRecorder: deinit");
-
- g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
- g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
-
- g_system->lockMutex(_timeMutex);
- g_system->lockMutex(_recorderMutex);
- _recordMode = kPassthrough;
- g_system->unlockMutex(_timeMutex);
- g_system->unlockMutex(_recorderMutex);
-
- delete _playbackFile;
- delete _playbackTimeFile;
-
- if (_recordFile != NULL) {
- _recordFile->finalize();
- delete _recordFile;
- _recordTimeFile->finalize();
- delete _recordTimeFile;
-
- _playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName);
-
- assert(_playbackFile);
-
- _recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName);
- _recordFile->writeUint32LE(RECORD_SIGNATURE);
- _recordFile->writeUint32LE(RECORD_VERSION);
-
- // conf vars
- _recordFile->writeByte(_recordSubtitles ? 1 : 0);
-
- _recordFile->writeUint32LE(_recordCount);
- _recordFile->writeUint32LE(_recordTimeCount);
-
- _recordFile->writeUint32LE(_randomSourceRecords.size());
- for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
- _recordFile->writeUint32LE(_randomSourceRecords[i].name.size());
- _recordFile->writeString(_randomSourceRecords[i].name);
- _recordFile->writeUint32LE(_randomSourceRecords[i].seed);
- }
-
- for (uint i = 0; i < _recordCount; ++i) {
- uint32 tempDiff;
- Event tempEvent;
- uint32 millis;
- readRecord(_playbackFile, tempDiff, tempEvent, millis);
- writeRecord(_recordFile, tempDiff, tempEvent, millis);
- }
-
- _recordFile->finalize();
- delete _recordFile;
- delete _playbackFile;
-
- //TODO: remove recordTempFileName'ed file
- }
-}
-
-void EventRecorder::registerRandomSource(RandomSource &rnd, const String &name) {
- if (_recordMode == kRecorderRecord) {
- RandomSourceRecord rec;
- rec.name = name;
- rec.seed = rnd.getSeed();
- _randomSourceRecords.push_back(rec);
- }
-
- if (_recordMode == kRecorderPlayback) {
- for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
- if (_randomSourceRecords[i].name == name) {
- rnd.setSeed(_randomSourceRecords[i].seed);
- _randomSourceRecords.remove_at(i);
- break;
- }
- }
- }
-}
-
-void EventRecorder::processMillis(uint32 &millis) {
- uint32 d;
- if (_recordMode == kPassthrough) {
- return;
- }
-
- g_system->lockMutex(_timeMutex);
- if (_recordMode == kRecorderRecord) {
- d = millis - _lastMillis;
- writeTime(_recordTimeFile, d);
-
- _recordTimeCount++;
- }
-
- if (_recordMode == kRecorderPlayback) {
- if (_recordTimeCount > _playbackTimeCount) {
- d = readTime(_playbackTimeFile);
-
- while ((_lastMillis + d > millis) && (_lastMillis + d - millis > 50)) {
- _recordMode = kPassthrough;
- g_system->delayMillis(50);
- millis = g_system->getMillis();
- _recordMode = kRecorderPlayback;
- }
-
- millis = _lastMillis + d;
- _playbackTimeCount++;
- }
- }
-
- _lastMillis = millis;
- g_system->unlockMutex(_timeMutex);
-}
-
-bool EventRecorder::processDelayMillis(uint &msecs) {
- if (_recordMode == kRecorderPlayback) {
- _recordMode = kPassthrough;
-
- uint32 millis = g_system->getMillis();
-
- _recordMode = kRecorderPlayback;
-
- if (_lastMillis > millis) {
- // Skip delay if we're getting late
- return true;
- }
- }
-
- return false;
-}
-
-bool EventRecorder::notifyEvent(const Event &ev) {
- if (_recordMode != kRecorderRecord)
- return false;
-
- StackLock lock(_recorderMutex);
- ++_eventCount;
-
- writeRecord(_recordFile, _eventCount - _lastEventCount, ev, _lastMillis - _lastEventMillis);
-
- _recordCount++;
- _lastEventCount = _eventCount;
- _lastEventMillis = _lastMillis;
-
- return false;
-}
-
-bool EventRecorder::notifyPoll() {
- if (_recordMode != kRecorderRecord)
- return false;
-
- ++_eventCount;
-
- return false;
-}
-
-bool EventRecorder::pollEvent(Event &ev) {
- uint32 millis;
-
- if (_recordMode != kRecorderPlayback)
- return false;
-
- StackLock lock(_recorderMutex);
- ++_eventCount;
-
- if (!_hasPlaybackEvent) {
- if (_recordCount > _playbackCount) {
- readRecord(_playbackFile, const_cast<uint32&>(_playbackDiff), _playbackEvent, millis);
- _playbackCount++;
- _hasPlaybackEvent = true;
- }
- }
-
- if (_hasPlaybackEvent) {
- if (_playbackDiff <= (_eventCount - _lastEventCount)) {
- switch (_playbackEvent.type) {
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- g_system->warpMouse(_playbackEvent.mouse.x, _playbackEvent.mouse.y);
- break;
- default:
- break;
- }
- ev = _playbackEvent;
- _hasPlaybackEvent = false;
- _lastEventCount = _eventCount;
- return true;
- }
- }
-
- return false;
-}
-
-} // End of namespace Common
diff --git a/common/EventRecorder.h b/common/EventRecorder.h
deleted file mode 100644
index 43a08b08cd..0000000000
--- a/common/EventRecorder.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef COMMON_EVENTRECORDER_H
-#define COMMON_EVENTRECORDER_H
-
-#include "common/scummsys.h"
-#include "common/events.h"
-#include "common/singleton.h"
-#include "common/mutex.h"
-#include "common/array.h"
-
-#define g_eventRec (Common::EventRecorder::instance())
-
-namespace Common {
-
-class RandomSource;
-class SeekableReadStream;
-class WriteStream;
-
-/**
- * Our generic event recorder.
- *
- * TODO: Add more documentation.
- */
-class EventRecorder : private EventSource, private EventObserver, public Singleton<EventRecorder> {
- friend class Singleton<SingletonBaseType>;
- EventRecorder();
- ~EventRecorder();
-public:
- void init();
- void deinit();
-
- /** Register random source so it can be serialized in game test purposes */
- void registerRandomSource(RandomSource &rnd, const String &name);
-
- /** TODO: Add documentation, this is only used by the backend */
- void processMillis(uint32 &millis);
-
- /** TODO: Add documentation, this is only used by the backend */
- bool processDelayMillis(uint &msecs);
-
-private:
- bool notifyEvent(const Event &ev);
- bool notifyPoll();
- bool pollEvent(Event &ev);
- bool allowMapping() const { return false; }
-
- class RandomSourceRecord {
- public:
- String name;
- uint32 seed;
- };
- Array<RandomSourceRecord> _randomSourceRecords;
-
- bool _recordSubtitles;
- volatile uint32 _recordCount;
- volatile uint32 _lastRecordEvent;
- volatile uint32 _recordTimeCount;
- volatile uint32 _lastEventMillis;
- WriteStream *_recordFile;
- WriteStream *_recordTimeFile;
- MutexRef _timeMutex;
- MutexRef _recorderMutex;
- volatile uint32 _lastMillis;
-
- volatile uint32 _playbackCount;
- volatile uint32 _playbackDiff;
- volatile bool _hasPlaybackEvent;
- volatile uint32 _playbackTimeCount;
- Event _playbackEvent;
- SeekableReadStream *_playbackFile;
- SeekableReadStream *_playbackTimeFile;
-
- volatile uint32 _eventCount;
- volatile uint32 _lastEventCount;
-
- enum RecordMode {
- kPassthrough = 0,
- kRecorderRecord = 1,
- kRecorderPlayback = 2
- };
- volatile RecordMode _recordMode;
- String _recordFileName;
- String _recordTempFileName;
- String _recordTimeFileName;
-};
-
-} // End of namespace Common
-
-#endif
diff --git a/common/debug.h b/common/debug.h
index dc94839082..859f3c41b3 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -117,5 +117,9 @@ void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3);
*/
extern int gDebugLevel;
+//Global constant for EventRecorder debug channel
+enum GlobalDebugLevels {
+ kDebugLevelEventRec = 1 << 30
+};
#endif
diff --git a/common/events.h b/common/events.h
index 7366c51d36..9029a4096a 100644
--- a/common/events.h
+++ b/common/events.h
@@ -288,11 +288,14 @@ public:
* to the EventDispatcher, thus it will be deleted
* with "delete", when EventDispatcher is destroyed.
*
- * Note there is only one mapper per EventDispatcher
- * possible, thus when this method is called twice,
- * the former mapper will be destroied.
+ * @param autoFree Destroy previous mapper [default]
+ * Normally we allow only one event mapper to exists,
+ * However Event Recorder must intervent into normal
+ * event flow without altering its semantics. Thus during
+ * Event Recorder playback and recording we allow
+ * two mappers.
*/
- void registerMapper(EventMapper *mapper);
+ void registerMapper(EventMapper *mapper, bool autoFree = true);
/**
* Queries the setup event mapper.
@@ -326,6 +329,7 @@ public:
*/
void unregisterObserver(EventObserver *obs);
private:
+ bool _autoFreeMapper;
EventMapper *_mapper;
struct Entry {
diff --git a/common/memstream.h b/common/memstream.h
index 260fb64d84..7fa6500753 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -89,8 +89,9 @@ public:
*/
class MemoryWriteStream : public WriteStream {
private:
- byte *_ptr;
const uint32 _bufSize;
+protected:
+ byte *_ptr;
uint32 _pos;
bool _err;
public:
@@ -117,6 +118,40 @@ public:
};
/**
+ * MemoryWriteStream subclass with ability to set stream position indicator.
+ */
+class SeekableMemoryWriteStream : public MemoryWriteStream {
+private:
+ byte *_ptrOrig;
+public:
+ SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
+ uint32 seek(uint32 offset, int whence = SEEK_SET) {
+ switch (whence) {
+ case SEEK_END:
+ // SEEK_END works just like SEEK_SET, only 'reversed',
+ // i.e. from the end.
+ offset = size() + offset;
+ // Fall through
+ case SEEK_SET:
+ _ptr = _ptrOrig + offset;
+ _pos = offset;
+ break;
+ case SEEK_CUR:
+ _ptr += offset;
+ _pos += offset;
+ break;
+ }
+ // Post-Condition
+ if (_pos > size()) {
+ _pos = size();
+ _ptr = _ptrOrig + _pos;
+ }
+ return _pos;
+ }
+};
+
+
+/**
* A sort of hybrid between MemoryWriteStream and Array classes. A stream
* that grows as it's written to.
*/
diff --git a/common/module.mk b/common/module.mk
index d96b11ee40..9f9126c8ef 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -10,7 +10,6 @@ MODULE_OBJS := \
error.o \
EventDispatcher.o \
EventMapper.o \
- EventRecorder.o \
file.o \
fs.o \
gui_options.o \
@@ -51,5 +50,10 @@ MODULE_OBJS += \
rdft.o \
sinetables.o
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ recorderfile.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/common/random.cpp b/common/random.cpp
index fd75534c44..a74ab831ea 100644
--- a/common/random.cpp
+++ b/common/random.cpp
@@ -21,7 +21,7 @@
#include "common/random.h"
#include "common/system.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
namespace Common {
@@ -30,13 +30,8 @@ RandomSource::RandomSource(const String &name) {
// Use system time as RNG seed. Normally not a good idea, if you are using
// a RNG for security purposes, but good enough for our purposes.
assert(g_system);
- uint32 seed = g_system->getMillis();
+ uint32 seed = g_eventRec.getRandomSeed(name);
setSeed(seed);
-
- // Register this random source with the event recorder. This may end
- // up querying or resetting the current seed, so we must call it
- // *after* the initial seed has been set.
- g_eventRec.registerRandomSource(*this, name);
}
void RandomSource::setSeed(uint32 seed) {
diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp
new file mode 100644
index 0000000000..60c47e11ce
--- /dev/null
+++ b/common/recorderfile.cpp
@@ -0,0 +1,708 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "gui/EventRecorder.h"
+#include "common/md5.h"
+#include "common/recorderfile.h"
+#include "common/savefile.h"
+#include "common/bufferedstream.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/scaler.h"
+
+#define RECORD_VERSION 1
+
+namespace Common {
+
+PlaybackFile::PlaybackFile() : _tmpRecordFile(_tmpBuffer, kRecordBuffSize), _tmpPlaybackFile(_tmpBuffer, kRecordBuffSize) {
+ _readStream = NULL;
+ _writeStream = NULL;
+ _screenshotsFile = NULL;
+ _mode = kClosed;
+}
+
+PlaybackFile::~PlaybackFile() {
+ close();
+}
+
+bool PlaybackFile::openWrite(const String &fileName) {
+ close();
+ _header.fileName = fileName;
+ _writeStream = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(fileName), 128 * 1024);
+ _headerDumped = false;
+ _recordCount = 0;
+ if (_writeStream == NULL) {
+ return false;
+ }
+ _mode = kWrite;
+ return true;
+}
+
+bool PlaybackFile::openRead(const String &fileName) {
+ close();
+ _header.fileName = fileName;
+ _eventsSize = 0;
+ _tmpPlaybackFile.seek(0);
+ _readStream = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(fileName), 128 * 1024, DisposeAfterUse::YES);
+ if (_readStream == NULL) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"file %s not found\"", fileName.c_str());
+ return false;
+ }
+ if (!parseHeader()) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"header parsing failed\"");
+ return false;
+ }
+ _screenshotsFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving("screenshots.bin"), 128 * 1024);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=success");
+ _mode = kRead;
+ return true;
+}
+
+void PlaybackFile::close() {
+ delete _readStream;
+ _readStream = NULL;
+ if (_writeStream != NULL) {
+ dumpRecordsToFile();
+ _writeStream->finalize();
+ delete _writeStream;
+ _writeStream = NULL;
+ updateHeader();
+ }
+ if (_screenshotsFile != NULL) {
+ _screenshotsFile->finalize();
+ delete _screenshotsFile;
+ _screenshotsFile = NULL;
+ }
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ free(i->_value.buffer);
+ }
+ _header.saveFiles.clear();
+ _mode = kClosed;
+}
+
+bool PlaybackFile::parseHeader() {
+ PlaybackFileHeader result;
+ ChunkHeader nextChunk;
+ _playbackParseState = kFileStateCheckFormat;
+ if (!readChunkHeader(nextChunk)) {
+ _playbackParseState = kFileStateError;
+ return false;
+ }
+ while ((_playbackParseState != kFileStateDone) && (_playbackParseState != kFileStateError)) {
+ if (processChunk(nextChunk)) {
+ if (!readChunkHeader(nextChunk)) {
+ warning("Error in header parsing");
+ _playbackParseState = kFileStateError;
+ }
+ }
+ }
+ return _playbackParseState == kFileStateDone;
+}
+
+bool PlaybackFile::checkPlaybackFileVersion() {
+ uint32 version;
+ version = _readStream->readUint32LE();
+ if (version != RECORD_VERSION) {
+ warning("Incorrect playback file version. Expected version %d, but got %d.", RECORD_VERSION, version);
+ return false;
+ }
+ return true;
+}
+
+
+String PlaybackFile::readString(int len) {
+ String result;
+ char buf[50];
+ int readSize = 49;
+ while (len > 0) {
+ if (len <= 49) {
+ readSize = len;
+ }
+ _readStream->read(buf, readSize);
+ buf[readSize] = 0;
+ result += buf;
+ len -= readSize;
+ }
+ return result;
+}
+
+bool PlaybackFile::readChunkHeader(PlaybackFile::ChunkHeader &nextChunk) {
+ nextChunk.id = (FileTag)_readStream->readUint32LE();
+ nextChunk.len = _readStream->readUint32LE();
+ return !_readStream->err() && !_readStream->eos();
+}
+
+bool PlaybackFile::processChunk(ChunkHeader &nextChunk) {
+ switch (_playbackParseState) {
+ case kFileStateCheckFormat:
+ if (nextChunk.id == kFormatIdTag) {
+ _playbackParseState = kFileStateCheckVersion;
+ } else {
+ warning("Unknown playback file signature");
+ _playbackParseState = kFileStateError;
+ }
+ break;
+ case kFileStateCheckVersion:
+ if ((nextChunk.id == kVersionTag) && checkPlaybackFileVersion()) {
+ _playbackParseState = kFileStateSelectSection;
+ } else {
+ _playbackParseState = kFileStateError;
+ }
+ break;
+ case kFileStateSelectSection:
+ switch (nextChunk.id) {
+ case kHeaderSectionTag:
+ _playbackParseState = kFileStateProcessHeader;
+ break;
+ case kHashSectionTag:
+ _playbackParseState = kFileStateProcessHash;
+ break;
+ case kRandomSectionTag:
+ _playbackParseState = kFileStateProcessRandom;
+ break;
+ case kEventTag:
+ case kScreenShotTag:
+ _readStream->seek(-8, SEEK_CUR);
+ _playbackParseState = kFileStateDone;
+ return false;
+ case kSaveTag:
+ _playbackParseState = kFileStateProcessSave;
+ break;
+ case kSettingsSectionTag:
+ _playbackParseState = kFileStateProcessSettings;
+ warning("Loading record header");
+ break;
+ default:
+ _readStream->skip(nextChunk.len);
+ break;
+ }
+ break;
+ case kFileStateProcessSave:
+ if (nextChunk.id == kSaveRecordTag) {
+ readSaveRecord();
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessHeader:
+ switch (nextChunk.id) {
+ case kAuthorTag:
+ _header.author = readString(nextChunk.len);
+ break;
+ case kCommentsTag:
+ _header.notes = readString(nextChunk.len);
+ break;
+ case kNameTag:
+ _header.name = readString(nextChunk.len);
+ break;
+ default:
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessHash:
+ if (nextChunk.id == kHashRecordTag) {
+ readHashMap(nextChunk);
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessRandom:
+ if (nextChunk.id == kRandomRecordTag) {
+ processRndSeedRecord(nextChunk);
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessSettings:
+ if (nextChunk.id == kSettingsRecordTag) {
+ if (!processSettingsRecord()) {
+ _playbackParseState = kFileStateError;
+ return false;
+ }
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void PlaybackFile::returnToChunkHeader() {
+ _readStream->seek(-8, SEEK_CUR);
+}
+
+void PlaybackFile::readHashMap(ChunkHeader chunk) {
+ String hashName = readString(chunk.len - 32);
+ String hashMd5 = readString(32);
+ _header.hashRecords[hashName] = hashMd5;
+}
+
+void PlaybackFile::processRndSeedRecord(ChunkHeader chunk) {
+ String randomSourceName = readString(chunk.len - 4);
+ uint32 randomSourceSeed = _readStream->readUint32LE();
+ _header.randomSourceRecords[randomSourceName] = randomSourceSeed;
+}
+
+bool PlaybackFile::processSettingsRecord() {
+ ChunkHeader keyChunk;
+ if (!readChunkHeader(keyChunk) || (keyChunk.id != kSettingsRecordKeyTag)) {
+ warning("Invalid format of settings section");
+ return false;
+ }
+ String key = readString(keyChunk.len);
+ ChunkHeader valueChunk;
+ if (!readChunkHeader(valueChunk) || (valueChunk.id != kSettingsRecordValueTag)) {
+ warning("Invalid format of settings section");
+ return false;
+ }
+ String value = readString(valueChunk.len);
+ _header.settingsRecords[key] = value;
+ return true;
+}
+
+
+bool PlaybackFile::readSaveRecord() {
+ ChunkHeader fileNameChunk;
+ if (!readChunkHeader(fileNameChunk) || (fileNameChunk.id != kSaveRecordNameTag)) {
+ warning("Invalid format of save section");
+ return false;
+ }
+ String fileName = readString(fileNameChunk.len);
+ ChunkHeader saveBufferChunk;
+ if (!readChunkHeader(saveBufferChunk) || (saveBufferChunk.id != kSaveRecordBufferTag)) {
+ warning("Invalid format of save section");
+ return false;
+ }
+ SaveFileBuffer buf;
+ buf.size = saveBufferChunk.len;
+ buf.buffer = (byte *)malloc(saveBufferChunk.len);
+ _readStream->read(buf.buffer, buf.size);
+ _header.saveFiles[fileName] = buf;
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load save file\" filename=%s len=%d", fileName.c_str(), buf.size);
+ return true;
+}
+
+
+
+RecorderEvent PlaybackFile::getNextEvent() {
+ assert(_mode == kRead);
+ if (isEventsBufferEmpty()) {
+ PlaybackFile::ChunkHeader header;
+ header.id = kFormatIdTag;
+ while (header.id != kEventTag) {
+ if (!readChunkHeader(header) || _readStream->eos()) {
+ break;
+ }
+ switch (header.id) {
+ case kEventTag:
+ readEventsToBuffer(header.len);
+ break;
+ case kScreenShotTag:
+ _readStream->seek(-4, SEEK_CUR);
+ header.len = _readStream->readUint32BE();
+ _readStream->skip(header.len-8);
+ break;
+ case kMD5Tag:
+ checkRecordedMD5();
+ break;
+ default:
+ _readStream->skip(header.len);
+ break;
+ }
+ }
+ }
+ RecorderEvent result;
+ readEvent(result);
+ return result;
+}
+
+bool PlaybackFile::isEventsBufferEmpty() {
+ return (uint32)_tmpPlaybackFile.pos() == _eventsSize;
+}
+
+void PlaybackFile::readEvent(RecorderEvent& event) {
+ event.recordedtype = (RecorderEventType)_tmpPlaybackFile.readByte();
+ switch (event.recordedtype) {
+ case kRecorderEventTypeTimer:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ break;
+ case kRecorderEventTypeNormal:
+ event.type = (EventType)_tmpPlaybackFile.readUint32LE();
+ switch (event.type) {
+ case EVENT_KEYDOWN:
+ case EVENT_KEYUP:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ event.kbd.keycode = (KeyCode)_tmpPlaybackFile.readSint32LE();
+ event.kbd.ascii = _tmpPlaybackFile.readUint16LE();
+ event.kbd.flags = _tmpPlaybackFile.readByte();
+ break;
+ case EVENT_MOUSEMOVE:
+ case EVENT_LBUTTONDOWN:
+ case EVENT_LBUTTONUP:
+ case EVENT_RBUTTONDOWN:
+ case EVENT_RBUTTONUP:
+ case EVENT_WHEELUP:
+ case EVENT_WHEELDOWN:
+ case EVENT_MBUTTONDOWN:
+ case EVENT_MBUTTONUP:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ event.mouse.x = _tmpPlaybackFile.readSint16LE();
+ event.mouse.y = _tmpPlaybackFile.readSint16LE();
+ break;
+ default:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ break;
+ }
+ break;
+ }
+ event.synthetic = true;
+}
+
+void PlaybackFile::readEventsToBuffer(uint32 size) {
+ _readStream->read(_tmpBuffer, size);
+ _tmpPlaybackFile.seek(0);
+ _eventsSize = size;
+}
+
+void PlaybackFile::saveScreenShot(Graphics::Surface &screen, byte md5[16]) {
+ dumpRecordsToFile();
+ _writeStream->writeUint32LE(kMD5Tag);
+ _writeStream->writeUint32LE(16);
+ _writeStream->write(md5, 16);
+ Graphics::saveThumbnail(*_writeStream, screen);
+}
+
+void PlaybackFile::dumpRecordsToFile() {
+ if (!_headerDumped) {
+ dumpHeaderToFile();
+ _headerDumped = true;
+ }
+ if (_recordCount == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kEventTag);
+ _writeStream->writeUint32LE(_tmpRecordFile.pos());
+ _writeStream->write(_tmpBuffer, _tmpRecordFile.pos());
+ _tmpRecordFile.seek(0);
+ _recordCount = 0;
+}
+
+void PlaybackFile::dumpHeaderToFile() {
+ _writeStream->writeUint32LE(kFormatIdTag);
+ // Specify size for first tag as NULL since we cannot calculate
+ // size of the file at time of the header dumping
+ _writeStream->writeUint32LE(0);
+ _writeStream->writeUint32LE(kVersionTag);
+ _writeStream->writeUint32LE(4);
+ _writeStream->writeUint32LE(RECORD_VERSION);
+ writeHeaderSection();
+ writeGameHash();
+ writeRandomRecords();
+ writeGameSettings();
+ writeSaveFilesSection();
+}
+
+void PlaybackFile::writeHeaderSection() {
+ uint32 headerSize = 0;
+ if (!_header.author.empty()) {
+ headerSize = _header.author.size() + 8;
+ }
+ if (!_header.notes.empty()) {
+ headerSize += _header.notes.size() + 8;
+ }
+ if (!_header.name.empty()) {
+ headerSize += _header.name.size() + 8;
+ }
+ if (headerSize == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kHeaderSectionTag);
+ _writeStream->writeUint32LE(headerSize);
+ if (!_header.author.empty()) {
+ _writeStream->writeUint32LE(kAuthorTag);
+ _writeStream->writeUint32LE(_header.author.size());
+ _writeStream->writeString(_header.author);
+ }
+ if (!_header.notes.empty()) {
+ _writeStream->writeUint32LE(kCommentsTag);
+ _writeStream->writeUint32LE(_header.notes.size());
+ _writeStream->writeString(_header.notes);
+ }
+ if (!_header.name.empty()) {
+ _writeStream->writeUint32LE(kNameTag);
+ _writeStream->writeUint32LE(_header.name.size());
+ _writeStream->writeString(_header.name);
+ }
+}
+
+void PlaybackFile::writeGameHash() {
+ uint32 hashSectionSize = 0;
+ for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) {
+ hashSectionSize = hashSectionSize + i->_key.size() + i->_value.size() + 8;
+ }
+ if (_header.hashRecords.size() == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kHashSectionTag);
+ _writeStream->writeUint32LE(hashSectionSize);
+ for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kHashRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + i->_value.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeString(i->_value);
+ }
+}
+
+void PlaybackFile::writeRandomRecords() {
+ uint32 randomSectionSize = 0;
+ for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) {
+ randomSectionSize = randomSectionSize + i->_key.size() + 12;
+ }
+ if (_header.randomSourceRecords.size() == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kRandomSectionTag);
+ _writeStream->writeUint32LE(randomSectionSize);
+ for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kRandomRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + 4);
+ _writeStream->writeString(i->_key);
+ _writeStream->writeUint32LE(i->_value);
+ }
+}
+
+void PlaybackFile::writeEvent(const RecorderEvent &event) {
+ assert(_mode == kWrite);
+ _recordCount++;
+ _tmpRecordFile.writeByte(event.recordedtype);
+ switch (event.recordedtype) {
+ case kRecorderEventTypeTimer:
+ _tmpRecordFile.writeUint32LE(event.time);
+ break;
+ case kRecorderEventTypeNormal:
+ _tmpRecordFile.writeUint32LE((uint32)event.type);
+ switch(event.type) {
+ case EVENT_KEYDOWN:
+ case EVENT_KEYUP:
+ _tmpRecordFile.writeUint32LE(event.time);
+ _tmpRecordFile.writeSint32LE(event.kbd.keycode);
+ _tmpRecordFile.writeUint16LE(event.kbd.ascii);
+ _tmpRecordFile.writeByte(event.kbd.flags);
+ break;
+ case EVENT_MOUSEMOVE:
+ case EVENT_LBUTTONDOWN:
+ case EVENT_LBUTTONUP:
+ case EVENT_RBUTTONDOWN:
+ case EVENT_RBUTTONUP:
+ case EVENT_WHEELUP:
+ case EVENT_WHEELDOWN:
+ case EVENT_MBUTTONDOWN:
+ case EVENT_MBUTTONUP:
+ _tmpRecordFile.writeUint32LE(event.time);
+ _tmpRecordFile.writeSint16LE(event.mouse.x);
+ _tmpRecordFile.writeSint16LE(event.mouse.y);
+ break;
+ default:
+ _tmpRecordFile.writeUint32LE(event.time);
+ break;
+ }
+ break;
+ }
+ if (_recordCount == kMaxBufferedRecords) {
+ dumpRecordsToFile();
+ }
+}
+
+void PlaybackFile::writeGameSettings() {
+ _writeStream->writeUint32LE(kSettingsSectionTag);
+ uint32 settingsSectionSize = 0;
+ for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
+ settingsSectionSize += i->_key.size() + i->_value.size() + 24;
+ }
+ _writeStream->writeUint32LE(settingsSectionSize);
+ for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kSettingsRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + i->_value.size() + 16);
+ _writeStream->writeUint32LE(kSettingsRecordKeyTag);
+ _writeStream->writeUint32LE(i->_key.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeUint32LE(kSettingsRecordValueTag);
+ _writeStream->writeUint32LE(i->_value.size());
+ _writeStream->writeString(i->_value);
+ }
+}
+
+int PlaybackFile::getScreensCount() {
+ if (_mode != kRead) {
+ return 0;
+ }
+ _readStream->seek(0);
+ int result = 0;
+ while (skipToNextScreenshot()) {
+ uint32 size = _readStream->readUint32BE();
+ _readStream->skip(size-8);
+ ++result;
+ }
+ return result;
+}
+
+bool PlaybackFile::skipToNextScreenshot() {
+ while (true) {
+ FileTag id = (FileTag)_readStream->readUint32LE();
+ if (_readStream->eos()) {
+ break;
+ }
+ if (id == kScreenShotTag) {
+ return true;
+ }
+ else {
+ uint32 size = _readStream->readUint32LE();
+ _readStream->skip(size);
+ }
+ }
+ return false;
+}
+
+Graphics::Surface *PlaybackFile::getScreenShot(int number) {
+ if (_mode != kRead) {
+ return NULL;
+ }
+ _readStream->seek(0);
+ int screenCount = 1;
+ while (skipToNextScreenshot()) {
+ if (screenCount == number) {
+ screenCount++;
+ _readStream->seek(-4, SEEK_CUR);
+ return Graphics::loadThumbnail(*_readStream);
+ } else {
+ uint32 size = _readStream->readUint32BE();
+ _readStream->skip(size-8);
+ screenCount++;
+ }
+ }
+ return NULL;
+}
+
+void PlaybackFile::updateHeader() {
+ if (_mode == kWrite) {
+ _readStream = g_system->getSavefileManager()->openForLoading(_header.fileName);
+ }
+ _readStream->seek(0);
+ skipHeader();
+ String tmpFilename = "_" + _header.fileName;
+ _writeStream = g_system->getSavefileManager()->openForSaving(tmpFilename);
+ dumpHeaderToFile();
+ uint32 readedSize = 0;
+ do {
+ readedSize = _readStream->read(_tmpBuffer, kRecordBuffSize);
+ _writeStream->write(_tmpBuffer, readedSize);
+ } while (readedSize != 0);
+ delete _writeStream;
+ _writeStream = NULL;
+ delete _readStream;
+ _readStream = NULL;
+ g_system->getSavefileManager()->removeSavefile(_header.fileName);
+ g_system->getSavefileManager()->renameSavefile(tmpFilename, _header.fileName);
+ if (_mode == kRead) {
+ openRead(_header.fileName);
+ }
+}
+
+void PlaybackFile::skipHeader() {
+ while (true) {
+ uint32 id = _readStream->readUint32LE();
+ if (_readStream->eos()) {
+ break;
+ }
+ if ((id == kScreenShotTag) || (id == kEventTag) || (id == kMD5Tag)) {
+ _readStream->seek(-4, SEEK_CUR);
+ return;
+ }
+ else {
+ uint32 size = _readStream->readUint32LE();
+ _readStream->skip(size);
+ }
+ }
+}
+
+void PlaybackFile::addSaveFile(const String &fileName, InSaveFile *saveStream) {
+ uint oldPos = saveStream->pos();
+ saveStream->seek(0);
+ _header.saveFiles[fileName].buffer = (byte *)malloc(saveStream->size());
+ _header.saveFiles[fileName].size = saveStream->size();
+ saveStream->read(_header.saveFiles[fileName].buffer, saveStream->size());
+ saveStream->seek(oldPos);
+}
+
+void PlaybackFile::writeSaveFilesSection() {
+ uint size = 0;
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ size += i->_value.size + i->_key.size() + 24;
+ }
+ if (size == 0) {
+ return;
+ }
+ _writeStream->writeSint32LE(kSaveTag);
+ _writeStream->writeSint32LE(size);
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ _writeStream->writeSint32LE(kSaveRecordTag);
+ _writeStream->writeSint32LE(i->_key.size() + i->_value.size + 16);
+ _writeStream->writeSint32LE(kSaveRecordNameTag);
+ _writeStream->writeSint32LE(i->_key.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeSint32LE(kSaveRecordBufferTag);
+ _writeStream->writeSint32LE(i->_value.size);
+ _writeStream->write(i->_value.buffer, i->_value.size);
+ }
+}
+
+
+void PlaybackFile::checkRecordedMD5() {
+ uint8 currentMD5[16];
+ uint8 savedMD5[16];
+ Graphics::Surface screen;
+ _readStream->read(savedMD5, 16);
+ if (!g_eventRec.grabScreenAndComputeMD5(screen, currentMD5)) {
+ return;
+ }
+ uint32 seconds = g_system->getMillis(true) / 1000;
+ String screenTime = String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60);
+ if (memcmp(savedMD5, currentMD5, 16) != 0) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = fail", screenTime.c_str());
+ warning("Recorded and current screenshots are different");
+ } else {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = success", screenTime.c_str());
+ }
+ Graphics::saveThumbnail(*_screenshotsFile, screen);
+ screen.free();
+}
+
+
+}
diff --git a/common/recorderfile.h b/common/recorderfile.h
new file mode 100644
index 0000000000..1c95e5a915
--- /dev/null
+++ b/common/recorderfile.h
@@ -0,0 +1,180 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMMON_RECORDERFILE_H
+#define COMMON_RECORDERFILE_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/mutex.h"
+#include "common/memstream.h"
+#include "common/config-manager.h"
+#include "common/savefile.h"
+
+//capacity of records buffer
+#define kMaxBufferedRecords 10000
+#define kRecordBuffSize sizeof(RecorderEvent) * kMaxBufferedRecords
+
+namespace Common {
+
+enum RecorderEventType {
+ kRecorderEventTypeNormal = 0,
+ kRecorderEventTypeTimer = 1
+};
+
+struct RecorderEvent : Event {
+ RecorderEventType recordedtype;
+ uint32 time;
+};
+
+
+
+class PlaybackFile {
+ typedef HashMap<String, uint32, IgnoreCase_Hash, IgnoreCase_EqualTo> RandomSeedsDictionary;
+ enum fileMode {
+ kRead = 0,
+ kWrite = 1,
+ kClosed = 2
+ };
+ enum PlaybackFileState {
+ kFileStateCheckFormat,
+ kFileStateCheckVersion,
+ kFileStateProcessHash,
+ kFileStateProcessHeader,
+ kFileStateProcessRandom,
+ kFileStateSelectSection,
+ kFileStateProcessSettings,
+ kFileStateProcessSave,
+ kFileStateDone,
+ kFileStateError
+ };
+ enum FileTag {
+ kFormatIdTag = MKTAG('P','B','C','K'),
+ kVersionTag = MKTAG('V','E','R','S'),
+ kHeaderSectionTag = MKTAG('H','E','A','D'),
+ kHashSectionTag = MKTAG('H','A','S','H'),
+ kRandomSectionTag = MKTAG('R','A','N','D'),
+ kEventTag = MKTAG('E','V','N','T'),
+ kScreenShotTag = MKTAG('B','M','H','T'),
+ kSettingsSectionTag = MKTAG('S','E','T','T'),
+ kAuthorTag = MKTAG('H','A','U','T'),
+ kCommentsTag = MKTAG('H','C','M','T'),
+ kNameTag = MKTAG('H','N','A','M'),
+ kHashRecordTag = MKTAG('H','R','C','D'),
+ kRandomRecordTag = MKTAG('R','R','C','D'),
+ kSettingsRecordTag = MKTAG('S','R','E','C'),
+ kSettingsRecordKeyTag = MKTAG('S','K','E','Y'),
+ kSettingsRecordValueTag = MKTAG('S','V','A','L'),
+ kSaveTag = MKTAG('S','A','V','E'),
+ kSaveRecordTag = MKTAG('R','S','A','V'),
+ kSaveRecordNameTag = MKTAG('S','N','A','M'),
+ kSaveRecordBufferTag = MKTAG('S','B','U','F'),
+ kMD5Tag = MKTAG('M','D','5',' ')
+ };
+ struct ChunkHeader {
+ FileTag id;
+ uint32 len;
+ };
+public:
+ struct SaveFileBuffer {
+ byte *buffer;
+ uint32 size;
+ };
+ struct PlaybackFileHeader {
+ String fileName;
+ String author;
+ String name;
+ String notes;
+ String description;
+ StringMap hashRecords;
+ StringMap settingsRecords;
+ HashMap<String, SaveFileBuffer> saveFiles;
+ RandomSeedsDictionary randomSourceRecords;
+ };
+ PlaybackFile();
+ ~PlaybackFile();
+
+ bool openWrite(const String &fileName);
+ bool openRead(const String &fileName);
+ void close();
+
+ RecorderEvent getNextEvent();
+ void writeEvent(const RecorderEvent &event);
+
+ void saveScreenShot(Graphics::Surface &screen, byte md5[16]);
+ Graphics::Surface *getScreenShot(int number);
+ int getScreensCount();
+
+ bool isEventsBufferEmpty();
+ PlaybackFileHeader &getHeader() {return _header;}
+ void updateHeader();
+ void addSaveFile(const String &fileName, InSaveFile *saveStream);
+private:
+ WriteStream *_recordFile;
+ WriteStream *_writeStream;
+ WriteStream *_screenshotsFile;
+ MemoryReadStream _tmpPlaybackFile;
+ SeekableReadStream *_readStream;
+ SeekableMemoryWriteStream _tmpRecordFile;
+
+ fileMode _mode;
+ bool _headerDumped;
+ int _recordCount;
+ uint32 _eventsSize;
+ byte _tmpBuffer[kRecordBuffSize];
+ PlaybackFileHeader _header;
+ PlaybackFileState _playbackParseState;
+
+ void skipHeader();
+ bool parseHeader();
+ bool processChunk(ChunkHeader &nextChunk);
+ void returnToChunkHeader();
+
+ bool readSaveRecord();
+ void checkRecordedMD5();
+ bool readChunkHeader(ChunkHeader &nextChunk);
+ void processRndSeedRecord(ChunkHeader chunk);
+ bool processSettingsRecord();
+
+ bool checkPlaybackFileVersion();
+
+ void dumpHeaderToFile();
+ void writeSaveFilesSection();
+ void writeGameSettings();
+ void writeHeaderSection();
+ void writeGameHash();
+ void writeRandomRecords();
+
+ void dumpRecordsToFile();
+
+ String readString(int len);
+ void readHashMap(ChunkHeader chunk);
+
+ bool skipToNextScreenshot();
+ void readEvent(RecorderEvent& event);
+ void readEventsToBuffer(uint32 size);
+ bool grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]);
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/common/str.cpp b/common/str.cpp
index 5d647ee4f0..4a10792373 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -361,6 +361,25 @@ void String::deleteChar(uint32 p) {
_size--;
}
+void String::erase(uint32 p, uint32 len) {
+ assert(p < _size);
+
+ makeUnique();
+ // If len == npos or p + len is over the end, remove all the way to the end
+ if (len == npos || p + len >= _size) {
+ // Delete char at p as well. So _size = (p - 1) + 1
+ _size = p;
+ // Null terminate
+ _str[_size] = 0;
+ return;
+ }
+
+ for ( ; p + len <= _size; p++) {
+ _str[p] = _str[p + len];
+ }
+ _size -= len;
+}
+
void String::clear() {
decRefCount(_extern._refCount);
diff --git a/common/str.h b/common/str.h
index 5039130707..6b4475e1c4 100644
--- a/common/str.h
+++ b/common/str.h
@@ -43,6 +43,8 @@ namespace Common {
* behavior in some operations.
*/
class String {
+public:
+ static const uint32 npos = 0xFFFFFFFF;
protected:
/**
* The size of the internal storage. Increasing this means less heap
@@ -191,6 +193,9 @@ public:
/** Remove the character at position p from the string. */
void deleteChar(uint32 p);
+ /** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */
+ void erase(uint32 p, uint32 len = npos);
+
/** Set character c at position p, replacing the previous character there. */
void setChar(char c, uint32 p);
diff --git a/common/system.cpp b/common/system.cpp
index 59210544ab..b40072afad 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -30,6 +30,7 @@
#include "common/taskbar.h"
#include "common/updates.h"
#include "common/textconsole.h"
+#include "gui/EventRecorder.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/fs/fs-factory.h"
@@ -84,7 +85,7 @@ void OSystem::initBackend() {
error("Backend failed to instantiate audio CD manager");
if (!_eventManager)
error("Backend failed to instantiate event manager");
- if (!_timerManager)
+ if (!getTimerManager())
error("Backend failed to instantiate timer manager");
// TODO: We currently don't check _savefileManager, because at least
@@ -152,3 +153,11 @@ Common::String OSystem::getDefaultConfigFileName() {
Common::String OSystem::getSystemLanguage() const {
return "en_US";
}
+
+Common::TimerManager *OSystem::getTimerManager() {
+ return _timerManager;
+}
+
+Common::SaveFileManager *OSystem::getSavefileManager() {
+ return g_eventRec.getSaveManager(_savefileManager);
+}
diff --git a/common/system.h b/common/system.h
index 99b947d7f3..81c4bdf34e 100644
--- a/common/system.h
+++ b/common/system.h
@@ -890,8 +890,14 @@ public:
/** @name Events and Time */
//@{
- /** Get the number of milliseconds since the program was started. */
- virtual uint32 getMillis() = 0;
+ /** Get the number of milliseconds since the program was started.
+
+ @param skipRecord Skip recording of this value by event recorder.
+ This could be needed particularly when we are in
+ an on-screen GUI loop where player can pause
+ the recording.
+ */
+ virtual uint32 getMillis(bool skipRecord = false) = 0;
/** Delay/sleep for the specified amount of milliseconds. */
virtual void delayMillis(uint msecs) = 0;
@@ -907,9 +913,7 @@ public:
* Return the timer manager singleton. For more information, refer
* to the TimerManager documentation.
*/
- inline Common::TimerManager *getTimerManager() {
- return _timerManager;
- }
+ virtual Common::TimerManager *getTimerManager();
/**
* Return the event manager singleton. For more information, refer
@@ -1086,9 +1090,7 @@ public:
* and other modifiable persistent game data. For more information,
* refer to the SaveFileManager documentation.
*/
- inline Common::SaveFileManager *getSavefileManager() {
- return _savefileManager;
- }
+ Common::SaveFileManager *getSavefileManager();
#if defined(USE_TASKBAR)
/**
diff --git a/configure b/configure
index eedd83eb7b..22f2377167 100755
--- a/configure
+++ b/configure
@@ -139,9 +139,10 @@ _build_hq_scalers=yes
_enable_prof=no
_global_constructors=no
_bink=yes
-# Default vkeybd/keymapper options
+# Default vkeybd/keymapper/eventrec options
_vkeybd=no
_keymapper=no
+_eventrec=auto
# GUI translation options
_translation=yes
# Default platform settings
@@ -817,7 +818,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
- --backend=BACKEND backend to build (android, bada, dc, dingux, ds, gph,
+ --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gph,
iphone, linuxmoto, maemo, n64, null, openpandora, ps2,
psp, samsungtv, sdl, webos, wii, wince) [sdl]
@@ -846,7 +847,7 @@ Fine tuning of the installation directories:
Special configuration feature:
--host=HOST cross-compile to target HOST (arm-linux, ...)
special targets: android for Android
- bada for Samsung BADA
+ tizen for Samsung Tizen
caanoo for Caanoo
dingux for Dingux
dreamcast for Sega Dreamcast
@@ -1042,6 +1043,8 @@ for ac_option in $@; do
--disable-vkeybd) _vkeybd=no ;;
--enable-keymapper) _keymapper=yes ;;
--disable-keymapper) _keymapper=no ;;
+ --enable-eventrecorder) _eventrec=yes ;;
+ --disable-eventrecorder) _eventrec=no ;;
--enable-text-console) _text_console=yes ;;
--disable-text-console) _text_console=no ;;
--with-fluidsynth-prefix=*)
@@ -1258,16 +1261,6 @@ arm-riscos)
_host_os=riscos
_host_cpu=arm
;;
-bada)
- _host_os=bada
- if test "$_debug_build" = yes; then
- _host_cpu=i686
- _host_alias=i686-mingw32
- else
- _host_cpu=arm
- _host_alias=arm-samsung-nucleuseabi
- fi
- ;;
caanoo)
_host_os=gph-linux
_host_cpu=arm
@@ -1393,6 +1386,11 @@ samsungtv)
_host_cpu=arm
_host_alias=arm-linux-gnueabi
;;
+tizen)
+ _host_os=tizen
+ _host_cpu=arm
+ _host_alias=arm-linux-gnueabi
+ ;;
webos)
_host_os=webos
_host_cpu=arm
@@ -1502,12 +1500,6 @@ android)
exit 1
fi
;;
-bada)
- if test -z "$BADA_SDK"; then
- echo "Please set BADA_SDK in your environment. export BADA_SDK=<path to Bada SDK>"
- exit 1
- fi
- ;;
ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
@@ -1549,6 +1541,12 @@ psp)
exit 1
fi
;;
+tizen)
+ if test -z "$TIZEN_ROOTSTRAP"; then
+ echo "Please set TIZEN_ROOTSTRAP in your environment. export TIZEN_ROOTSTRAP=<path to Tizen SDK device profile>"
+ exit 1
+ fi
+ ;;
webos)
if test -z "$WEBOS_SDK"; then
echo "Please set WEBOS_SDK in your environment. export WEBOS_SDK=<path to WebOS SDK>"
@@ -1742,7 +1740,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- amigaos* | android | bada | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | wii | wince )
+ amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
;;
*)
CXXFLAGS="$CXXFLAGS -ansi"
@@ -1778,7 +1776,7 @@ echo $_use_cxx11
# However, some platforms use GNU extensions in system header files, so
# for these we must not use -pedantic.
case $_host_os in
-android | gamecube | psp | wii | webos)
+android | gamecube | psp | tizen | wii | webos)
;;
*)
# ICC does not support pedantic, while GCC and clang do.
@@ -2062,16 +2060,6 @@ case $_host_os in
add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
_seq_midi=no
;;
- bada)
- BADA_SDK_ROOT="`cygpath -m ${BADA_SDK}`"
- add_line_to_config_mk "BADA_SDK = $BADA_SDK"
- add_line_to_config_mk "BADA_SDK_ROOT = $BADA_SDK_ROOT"
-
- # assume dependencies have been installed in cygwin's /usr/local
- CYGWIN_USR_LOCAL="`cygpath -m /usr/local`"
- LDFLAGS="$LDFLAGS -L${CYGWIN_USR_LOCAL}/lib"
- CXXFLAGS="$CXXFLAGS -I${CYGWIN_USR_LOCAL}/include"
- ;;
beos*)
DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lbind -lsocket for the timidity MIDI driver
@@ -2187,7 +2175,7 @@ case $_host_os in
# When not cross-compiling, enable large file support, but don't
# care if getconf doesn't exist or doesn't recognize LFS_CFLAGS.
if test -z "$_host"; then
- CXXFLAGS="$CXXFLAGS $(getconf LFS_CFLAGS 2>/dev/null)"
+ CXXFLAGS="$CXXFLAGS `getconf LFS_CFLAGS 2>/dev/null`"
fi
;;
maemo)
@@ -2249,6 +2237,12 @@ case $_host_os in
# Needs -lbind -lsocket for the timidity MIDI driver
LIBS="$LIBS -lnsl -lsocket"
;;
+ tizen)
+ add_line_to_config_mk "TIZEN_ROOTSTRAP = $TIZEN_ROOTSTRAP"
+ LDFLAGS="$LDFLAGS --sysroot=${TIZEN_ROOTSTRAP}"
+ LDFLAGS="$LDFLAGS -L${TIZEN_LIBS}/lib"
+ CXXFLAGS="$CXXFLAGS -I${TIZEN_LIBS}/include"
+ ;;
webos)
CXXFLAGS="$CXXFLAGS --sysroot=$WEBOS_PDK/arm-gcc/sysroot"
CXXFLAGS="$CXXFLAGS -I$WEBOS_PDK/include"
@@ -2327,22 +2321,6 @@ if test -n "$_host"; then
arm-riscos|linupy)
DEFINES="$DEFINES -DLINUPY"
;;
- bada)
- _unix=yes
- _backend="bada"
- _port_mk="backends/platform/bada/bada.mk"
- if test "$_debug_build" = yes; then
- _arm_asm=no
- else
- _arm_asm=yes
- fi
- _taskbar=no
- _build_scalers=no
- _seq_midi=no
- _mt32emu=no
- _timidity=no
- _vkeybd=yes
- ;;
bfin*)
;;
caanoo)
@@ -2655,6 +2633,18 @@ if test -n "$_host"; then
_mt32emu=no
_vkeybd=yes
;;
+ tizen)
+ _unix=yes
+ _backend="tizen"
+ _port_mk="backends/platform/tizen/tizen.mk"
+ _arm_asm=yes
+ _taskbar=no
+ _build_scalers=no
+ _seq_midi=no
+ _mt32emu=no
+ _timidity=no
+ _vkeybd=yes
+ ;;
webos)
_backend="webos"
_port_mk="backends/platform/webos/webos.mk"
@@ -2705,34 +2695,6 @@ case $_backend in
LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
INCLUDES="$INCLUDES -I$ANDROID_NDK/sources/cxx-stl/system/include"
;;
- bada)
- # dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
- DEFINES="$DEFINES -DBADA -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
- DEFINES="$DEFINES -DNO_STDERR_STDOUT"
- DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
- INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/bada '
- INCLUDES="$INCLUDES "'-I$(BADA_SDK)/include'
- INCLUDES="$INCLUDES "'-I$(BADA_SDK_ROOT)/Include'
- if test "$_debug_build" = yes; then
- # debug using with the simulator
- CXXFLAGS="$CXXFLAGS -D_DEBUG -DSHP -DBUILD_DLL -fmessage-length=0"
- else
- # created a shared library for inclusion via the eclipse build
- CXXFLAGS="$CXXFLAGS -DSHP"
- CXXFLAGS="$CXXFLAGS -fpic"
- CXXFLAGS="$CXXFLAGS -fshort-wchar"
- CXXFLAGS="$CXXFLAGS -mcpu=cortex-a8"
- CXXFLAGS="$CXXFLAGS -mfpu=vfpv3"
- CXXFLAGS="$CXXFLAGS -mfloat-abi=hard"
- CXXFLAGS="$CXXFLAGS -mlittle-endian"
- CXXFLAGS="$CXXFLAGS -mthumb-interwork"
- CXXFLAGS="$CXXFLAGS -Wno-psabi"
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- CXXFLAGS="$CXXFLAGS -fno-short-enums"
- fi
- HOSTEXEPRE=lib
- HOSTEXEEXT=.a
- ;;
dc)
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc'
INCLUDES="$INCLUDES "'-isystem $(ronindir)/include'
@@ -2815,6 +2777,25 @@ case $_backend in
LDFLAGS="$LDFLAGS -shared"
LDFLAGS="$LDFLAGS -fpic"
;;
+ tizen)
+ # dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
+ DEFINES="$DEFINES -DTIZEN -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
+ DEFINES="$DEFINES -DNO_STDERR_STDOUT"
+ DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
+ INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/tizen'
+ INCLUDES="$INCLUDES "'-I$(TIZEN_ROOTSTRAP)/usr/include'
+ INCLUDES="$INCLUDES "'-I$(TIZEN_ROOTSTRAP)/usr/include/osp'
+ if test "$_debug_build" = yes; then
+ CXXFLAGS="$CXXFLAGS -D_DEBUG -DBUILD_DLL -O0 -g3"
+ fi
+ # created a shared library for inclusion via the eclipse build
+ CXXFLAGS="$CXXFLAGS -Wno-psabi"
+ CXXFLAGS="$CXXFLAGS --sysroot=${TIZEN_ROOTSTRAP}"
+ CXXFLAGS="$CXXFLAGS -fmessage-length=0"
+ CXXFLAGS="$CXXFLAGS -fPIC"
+ HOSTEXEPRE=lib
+ HOSTEXEEXT=.a
+ ;;
webos)
# There is no sdl-config in the WebOS PDK so we don't use find_sdlconfig here.
# The PDL library acts as the WebOS device toolchain, and is required to control the virtual keyboard among other OS-level events.
@@ -2880,7 +2861,7 @@ esac
# Enable 16bit support only for backends which support it
#
case $_backend in
- android | bada | dingux | dc | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | webos | wii)
+ android | dingux | dc | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -2893,6 +2874,20 @@ case $_backend in
esac
#
+# Enable Event Recorder only for backends that support it
+#
+case $_backend in
+ sdl)
+ if test "$_eventrec" = auto ; then
+ _eventrec=yes
+ fi
+ ;;
+ *)
+ _eventrec=no
+ ;;
+esac
+
+#
# Disable savegame timestamp support for backends which don't have a reliable real time clock
#
case $_backend in
@@ -3620,8 +3615,8 @@ if test "$_libunity" = auto ; then
;;
*)
# Unity has a lots of dependencies, update the libs and cflags var with them
- LIBUNITY_LIBS="$LIBUNITY_LIBS $(pkg-config --libs unity = 3.8.4 2>> "$TMPLOG")"
- LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS $(pkg-config --cflags unity = 3.8.4 2>> "$TMPLOG")"
+ LIBUNITY_LIBS="$LIBUNITY_LIBS `pkg-config --libs unity = 3.8.4 2>> "$TMPLOG"`"
+ LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS `pkg-config --cflags unity = 3.8.4 2>> "$TMPLOG"`"
_libunity=no
cat > $TMPC << EOF
#include <unity.h>
@@ -3778,7 +3773,7 @@ EOF
fi
case $_host_os in
- bada)
+ tizen)
# components live in non-standard locations so just assume sane SDK
_opengl=yes
_opengles=yes
@@ -3854,10 +3849,21 @@ fi
define_in_config_if_yes $_nasm 'USE_NASM'
#
-# Enable vkeybd / keymapper
+# Enable vkeybd / keymapper / event recorder
#
define_in_config_if_yes $_vkeybd 'ENABLE_VKEYBD'
define_in_config_if_yes $_keymapper 'ENABLE_KEYMAPPER'
+define_in_config_if_yes $_eventrec 'ENABLE_EVENTRECORDER'
+
+#
+# Check if the keymapper and the event recorder are enabled simultaneously
+#
+if test "$_keymapper" = yes ; then
+ if test "$_eventrec" = yes ; then
+ echo "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two"
+ exit 1
+ fi
+fi
# Check whether to build translation support
#
@@ -4003,7 +4009,11 @@ if test "$_vkeybd" = yes ; then
fi
if test "$_keymapper" = yes ; then
- echo ", keymapper"
+ echo_n ", keymapper"
+fi
+
+if test "$_eventrec" = yes ; then
+ echo ", event recorder"
else
echo
fi
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index a8e09ff5eb..480f6a926a 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -189,7 +189,7 @@ int main(int argc, char *argv[]) {
msvcVersion = atoi(argv[++i]);
- if (msvcVersion != 8 && msvcVersion != 9 && msvcVersion != 10 && msvcVersion != 11) {
+ if (msvcVersion != 8 && msvcVersion != 9 && msvcVersion != 10 && msvcVersion != 11 && msvcVersion != 12) {
std::cerr << "ERROR: Unsupported version: \"" << msvcVersion << "\" passed to \"--msvc-version\"!\n";
return -1;
}
@@ -310,6 +310,17 @@ int main(int argc, char *argv[]) {
cout << " " << i->description << '\n';
}
+ // Check if the keymapper and the event recorder are enabled simultaneously
+ bool keymapperEnabled = false;
+ for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
+ if (i->enable && !strcmp(i->name, "keymapper"))
+ keymapperEnabled = true;
+ if (i->enable && !strcmp(i->name, "eventrecorder") && keymapperEnabled) {
+ std::cerr << "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two\n";
+ return -1;
+ }
+ }
+
// Setup defines and libraries
setup.defines = getEngineDefines(setup.engines);
setup.libraries = getFeatureLibraries(setup.features);
@@ -588,7 +599,7 @@ void displayHelp(const char *exe) {
" Additionally there are the following switches for changing various settings:\n"
"\n"
"Project specific settings:\n"
- " --codeblock build Code::Blocks project files\n"
+ " --codeblocks build Code::Blocks project files\n"
" --msvc build Visual Studio project files\n"
" --xcode build XCode project files\n"
" --file-prefix prefix allow overwriting of relative file prefix in the\n"
@@ -609,9 +620,9 @@ void displayHelp(const char *exe) {
" (default: false)\n"
" --installer Create NSIS installer after the build (implies --build-events)\n"
" (default: false)\n"
- " --tools Create project files for the devtools\n"
- " (ignores --build-events and --installer, as well as engine settings)\n"
- " (default: false)\n"
+ " --tools Create project files for the devtools\n"
+ " (ignores --build-events and --installer, as well as engine settings)\n"
+ " (default: false)\n"
"\n"
"Engines settings:\n"
" --list-engines list all available engines and their default state\n"
@@ -809,19 +820,20 @@ const Feature s_features[] = {
{"freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
// Feature flags
- { "bink", "USE_BINK", "", true, "Bink video support" },
- { "scalers", "USE_SCALERS", "", true, "Scalers" },
- { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
- { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
- { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
- { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
- { "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" },
- { "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" },
- { "translation", "USE_TRANSLATION", "", true, "Translation support" },
- { "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"},
- { "keymapper","ENABLE_KEYMAPPER", "", false, "Keymapper support"},
- { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
- // is just no current way of properly detecting this...
+ { "bink", "USE_BINK", "", true, "Bink video support" },
+ { "scalers", "USE_SCALERS", "", true, "Scalers" },
+ { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
+ { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
+ { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
+ { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
+ { "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" },
+ { "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" },
+ { "translation", "USE_TRANSLATION", "", true, "Translation support" },
+ { "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"},
+ { "keymapper", "ENABLE_KEYMAPPER", "", false, "Keymapper support"},
+ { "eventrecorder", "ENABLE_EVENTRECORDER", "", false, "Event recorder support"},
+ { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
+ // is just no current way of properly detecting this...
};
const Tool s_tools[] = {
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index 0f77d91852..6af9323fcd 100644
--- a/devtools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
@@ -52,6 +52,9 @@ int MSBuildProvider::getVisualStudioVersion() {
if (_version == 11)
return 2012;
+ if (_version == 12)
+ return 2013;
+
error("Unsupported version passed to getVisualStudioVersion");
}
@@ -88,7 +91,7 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
error("Could not open \"" + projectFile + "\" for writing");
project << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<ItemGroup Label=\"ProjectConfigurations\">\n";
outputConfiguration(project, "Debug", "Win32");
@@ -105,7 +108,7 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
"\t\t<ProjectGuid>{" << uuid << "}</ProjectGuid>\n"
"\t\t<RootNamespace>" << name << "</RootNamespace>\n"
"\t\t<Keyword>Win32Proj</Keyword>\n"
- "\t\t<VCTargetsPath Condition=\"'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''\">$(VCTargetsPath11)</VCTargetsPath>\n"
+ "\t\t<VCTargetsPath Condition=\"'$(VCTargetsPath" << _version << ")' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''\">$(VCTargetsPath" << _version << ")</VCTargetsPath>\n"
"\t</PropertyGroup>\n";
// Shared configuration
@@ -184,7 +187,7 @@ void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::stri
error("Could not open \"" + filtersFile + "\" for writing");
filters << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
+ "<Project ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
// Output the list of filters
filters << "\t<ItemGroup>\n";
@@ -314,9 +317,8 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
definesList += REVISION_DEFINE ";";
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<PropertyGroup>\n"
- "\t\t<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\n"
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n"
"\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(ExecutablePath)</ExecutablePath>\n"
"\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
@@ -368,12 +370,11 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<ImportGroup Label=\"PropertySheets\">\n"
"\t\t<Import Project=\"" << setup.projectDescription << "_Global" << (isWin32 ? "" : "64") << ".props\" />\n"
"\t</ImportGroup>\n"
"\t<PropertyGroup>\n"
- "\t\t<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\n"
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_" << outputType << outputBitness << "</_PropertySheetDisplayName>\n"
"\t\t<LinkIncremental>" << (isRelease ? "false" : "true") << "</LinkIncremental>\n"
"\t</PropertyGroup>\n"
@@ -383,7 +384,7 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
if (isRelease) {
properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n"
"\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n"
- "\t\t\t<PreprocessorDefinitions>WIN32;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<StringPooling>true</StringPooling>\n"
"\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
"\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
@@ -395,7 +396,7 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t\t\t<SetChecksum>true</SetChecksum>\n";
} else {
properties << "\t\t\t<Optimization>Disabled</Optimization>\n"
- "\t\t\t<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<MinimalRebuild>true</MinimalRebuild>\n"
"\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n"
"\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n"
diff --git a/devtools/create_project/msvc12/create_project.sln b/devtools/create_project/msvc12/create_project.sln
new file mode 100644
index 0000000000..759d5430f5
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_project", "create_project.vcxproj", "{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.Build.0 = Debug|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.ActiveCfg = Release|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/devtools/create_project/msvc12/create_project.vcxproj b/devtools/create_project/msvc12/create_project.vcxproj
new file mode 100644
index 0000000000..c26b1e5f45
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.vcxproj
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CF177559-077D-4A08-AABE-BE0FD35F6C63}</ProjectGuid>
+ <RootNamespace>create_project</RootNamespace>
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''">$(VCTargetsPath11)</VCTargetsPath>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableLanguageExtensions>false</DisableLanguageExtensions>
+ <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ <PostBuildEvent>
+ <Command>@echo off
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc12\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc11\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc10\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc9\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc8\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\codeblocks\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\iphone\"</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>@echo off
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc12\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc11\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc10\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc9\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc8\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\codeblocks\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\iphone\"</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\codeblocks.cpp" />
+ <ClCompile Include="..\create_project.cpp" />
+ <ClCompile Include="..\msbuild.cpp" />
+ <ClCompile Include="..\msvc.cpp" />
+ <ClCompile Include="..\visualstudio.cpp" />
+ <ClCompile Include="..\xcode.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\codeblocks.h" />
+ <ClInclude Include="..\config.h" />
+ <ClInclude Include="..\create_project.h" />
+ <ClInclude Include="..\msbuild.h" />
+ <ClInclude Include="..\msvc.h" />
+ <ClInclude Include="..\visualstudio.h" />
+ <ClInclude Include="..\xcode.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\scripts\installer.vbs" />
+ <None Include="..\scripts\postbuild.cmd" />
+ <None Include="..\scripts\prebuild.cmd" />
+ <None Include="..\scripts\revision.vbs" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/devtools/create_project/msvc12/create_project.vcxproj.filters b/devtools/create_project/msvc12/create_project.vcxproj.filters
new file mode 100644
index 0000000000..436d1d3436
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.vcxproj.filters
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{2e3580c8-ec3a-4c81-8351-b668c668db2a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{31aaf58c-d3cb-4ed6-8eca-163b4a9b31a6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="scripts">
+ <UniqueIdentifier>{f980f6fb-41b6-4161-b035-58b200c85cad}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\codeblocks.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\create_project.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msvc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msbuild.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\visualstudio.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\xcode.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\codeblocks.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\create_project.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\msvc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\msbuild.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\visualstudio.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\xcode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\scripts\prebuild.cmd">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\revision.vbs">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\postbuild.cmd">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\installer.vbs">
+ <Filter>scripts</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 06df7fa50e..7d39730c63 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -754,10 +754,6 @@ begin_credits("Credits");
add_person("Angus Lees", "Gus", "");
end_section();
- begin_section("BADA");
- add_person("Chris Warren-Smith", "", "");
- end_section();
-
begin_section("Dreamcast");
add_person("Marcus Comstedt", "", "");
end_section();
@@ -818,6 +814,10 @@ begin_credits("Credits");
add_person("Lars Persson", "AnotherGuest", "");
end_section();
+ begin_section("Tizen / BADA");
+ add_person("Chris Warren-Smith", "", "");
+ end_section();
+
begin_section("WebOS");
add_person("Klaus Reimer", "kayahr", "");
end_section();
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt
index 414a25e906..6e3bae1d7e 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -346,7 +346,8 @@ ft Full Throttle
4bedb49943df95a9c900a5a82ccbe9de -1 fr All? - - - cyx
8bdb0bf87b5e303dd35693afb9351215 -1 de All? - - - dhewg
55518cd73cf9c6d23ea29c51ee06bdfe -1 it All? - - - delfino
- 55e4cc866ff9046824e1c638ba2b8c7f -1 ru All? - - - sev
+ 55e4cc866ff9046824e1c638ba2b8c7f -1 ru All? - Akella - sev
+ 291fb06071e65897f755846611f5ad40 19697 ru All? - 7-Wolf - sev
e72bb4c2b613db2cf50f89ff6350e70a -1 es All? - - -
fe381e45117878b1e942cb876b050fd6 513243679 en Mac - - Mac bundle Fingolfin
04401d747f1a2c1c4b388daff71ed378 535405461 de Mac - - Mac bundle Fingolfin
diff --git a/dists/msvc12/create_msvc12.bat b/dists/msvc12/create_msvc12.bat
new file mode 100644
index 0000000000..fe12a9b288
--- /dev/null
+++ b/dists/msvc12/create_msvc12.bat
@@ -0,0 +1,95 @@
+@echo off
+
+echo.
+echo Automatic creation of the MSVC12 project files
+echo.
+
+if "%~1"=="/stable" goto stable
+if "%~1"=="/STABLE" goto stable
+if "%~1"=="/all" goto all
+if "%~1"=="/ALL" goto all
+if "%~1"=="/tools" goto tools
+if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/clean" goto clean_check
+if "%~1"=="/CLEAN" goto clean_check
+if "%~1"=="/help" goto command_help
+if "%~1"=="/HELP" goto command_help
+if "%~1"=="/?" goto command_help
+
+if "%~1"=="" goto check_tool
+
+echo Invalid command parameter: %~1
+echo.
+
+:command_help
+echo Valid command parameters are:
+echo stable Generated stable engines project files
+echo all Generate all engines project files
+echo tools Generate project files for the devtools
+echo clean Clean generated project files
+echo help Show help message
+goto done
+
+:check_tool
+if not exist create_project.exe goto no_tool
+
+:question
+echo.
+set batchanswer=S
+set /p batchanswer="Enable stable engines only, or all engines? (S/a)"
+if "%batchanswer%"=="s" goto stable
+if "%batchanswer%"=="S" goto stable
+if "%batchanswer%"=="a" goto all
+if "%batchanswer%"=="A" goto all
+goto question
+
+:no_tool
+echo create_project.exe not found in the current folder.
+echo You need to build it first and copy it in this
+echo folder
+goto done
+
+:all
+echo.
+echo Creating project files with all engines enabled (stable and unstable)
+echo.
+create_project ..\.. --enable-all-engines --msvc --msvc-version 12 --build-events
+goto done
+
+:stable
+echo.
+echo Creating normal project files, with only the stable engines enabled
+echo.
+create_project ..\.. --msvc --msvc-version 12
+goto done
+
+:tools
+echo.
+echo Creating tools project files
+echo.
+create_project ..\.. --tools --msvc --msvc-version 12
+goto done
+
+:clean_check
+echo.
+set cleananswer=N
+set /p cleananswer="This will remove all project files. Are you sure you want to continue? (N/y)"
+if "%cleananswer%"=="n" goto done
+if "%cleananswer%"=="N" goto done
+if "%cleananswer%"=="y" goto clean
+if "%cleananswer%"=="Y" goto clean
+goto clean_check
+
+:clean
+echo.
+echo Removing all project files
+del /Q *.vcxproj* > NUL 2>&1
+del /Q *.props > NUL 2>&1
+del /Q *.sln* > NUL 2>&1
+del /Q scummvm* > NUL 2>&1
+del /Q devtools* > NUL 2>&1
+goto done
+
+:done
+echo.
+pause
diff --git a/dists/msvc12/readme.txt b/dists/msvc12/readme.txt
new file mode 100644
index 0000000000..760f9ff601
--- /dev/null
+++ b/dists/msvc12/readme.txt
@@ -0,0 +1,6 @@
+The Visual Studio project files can now be created automatically from the GCC
+files using the create_project tool inside the /devtools/create_project folder.
+
+To create the default project files, build create_project.exe, copy it inside
+this folder and run the create_msvc12.bat file for a default build. You can run
+create_project.exe with no parameters to check the possible command-line options
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b1d1008b60..9023548c83 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -29,7 +29,7 @@
#include "common/system.h"
#include "common/textconsole.h"
#include "common/translation.h"
-
+#include "gui/EventRecorder.h"
#include "engines/advancedDetector.h"
#include "engines/obsolete.h"
@@ -301,6 +301,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
return Common::kUserCanceled;
debug(2, "Running %s", gameDescriptor.description().c_str());
+ initSubSystems(agdDesc);
if (!createInstance(syst, engine, agdDesc))
return Common::kNoGameDataFoundError;
else
@@ -606,3 +607,9 @@ AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, con
_maxScanDepth = 1;
_directoryGlobs = NULL;
}
+
+void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const {
+ if (gameDesc) {
+ g_eventRec.processGameDescription(gameDesc);
+ }
+}
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 3eec33abe5..71d2c4a446 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -280,6 +280,9 @@ protected:
return 0;
}
+private:
+ void initSubSystems(const ADGameDescription *gameDesc) const;
+
protected:
/**
* Detect games in specified directory.
diff --git a/engines/cge/cge.cpp b/engines/cge/cge.cpp
index 6cc0c45963..af7e91f7eb 100644
--- a/engines/cge/cge.cpp
+++ b/engines/cge/cge.cpp
@@ -25,7 +25,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
#include "engines/advancedDetector.h"
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index c3ede46df2..08838a784a 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -23,7 +23,6 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/func.h"
#include "common/system.h"
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 6b65eb6ab9..839378a412 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -45,7 +45,7 @@ static void plotPixel(int x, int y, int color, void *data) {
Pixel::Pixel(byte *vidMem, uint8 bpp, byte *min, byte *max) :
_vidMem(vidMem), _bpp(bpp), _min(min), _max(max) {
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
assert(_vidMem >= _min);
assert(_vidMem < _max);
}
@@ -91,6 +91,8 @@ uint32 Pixel::get() const {
return *((byte *) _vidMem);
if (_bpp == 2)
return *((uint16 *) _vidMem);
+ if (_bpp == 4)
+ return *((uint32 *) _vidMem);
return 0;
}
@@ -103,6 +105,8 @@ void Pixel::set(uint32 p) {
*((byte *) _vidMem) = (byte) p;
if (_bpp == 2)
*((uint16 *) _vidMem) = (uint16) p;
+ if (_bpp == 4)
+ *((uint32 *) _vidMem) = (uint32) p;
}
bool Pixel::isValid() const {
@@ -113,7 +117,7 @@ bool Pixel::isValid() const {
ConstPixel::ConstPixel(const byte *vidMem, uint8 bpp, const byte *min, const byte *max) :
_vidMem(vidMem), _bpp(bpp), _min(min), _max(max) {
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
assert(_vidMem >= _min);
assert(_vidMem < _max);
}
@@ -159,6 +163,8 @@ uint32 ConstPixel::get() const {
return *((const byte *) _vidMem);
if (_bpp == 2)
return *((const uint16 *) _vidMem);
+ if (_bpp == 4)
+ return *((const uint32 *) _vidMem);
return 0;
}
@@ -172,7 +178,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem) :
_width(width), _height(height), _bpp(bpp), _vidMem(vidMem) {
assert((_width > 0) && (_height > 0));
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
if (!_vidMem) {
_vidMem = new byte[_bpp * _width * _height];
@@ -187,7 +193,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, const byte *vidMem) :
_width(width), _height(height), _bpp(bpp), _vidMem(0) {
assert((_width > 0) && (_height > 0));
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
_vidMem = new byte[_bpp * _width * _height];
_ownVidMem = true;
@@ -504,7 +510,7 @@ void Surface::fillRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uin
return;
}
- assert(_bpp == 2);
+ assert((_bpp == 2) || (_bpp == 4));
// Otherwise, we have to fill by pixel
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index 81dbcabd57..b773808c50 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -35,12 +35,9 @@
namespace Hopkins {
-HopkinsEngine *g_vm;
-
HopkinsEngine::HopkinsEngine(OSystem *syst, const HopkinsGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Hopkins") {
DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level");
- g_vm = this;
_animMan = new AnimationManager(this);
_computer = new ComputerManager(this);
_dialog = new DialogsManager(this);
@@ -1138,12 +1135,14 @@ bool HopkinsEngine::runFull() {
break;
case 30:
+ // Shooting
_linesMan->setMaxLineIdx(15);
_globals->_characterMaxPosY = 440;
_objectsMan->sceneControl2("IM30", "IM30", "ANIM30", "IM30", 24, false);
break;
case 31:
+ // Shooting target
_objectsMan->sceneControl("IM31", "IM31", "ANIM31", "IM31", 10, true);
break;
diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h
index 777fd1c335..398e41a4d2 100644
--- a/engines/hopkins/hopkins.h
+++ b/engines/hopkins/hopkins.h
@@ -183,9 +183,6 @@ public:
virtual void syncSoundSettings();
};
-// Global reference to the HopkinsEngine object
-extern HopkinsEngine *g_vm;
-
} // End of namespace Hopkins
#endif /* HOPKINS_HOPKINS_H */
diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp
index 45b4885c90..98fb15046e 100644
--- a/engines/hopkins/saveload.cpp
+++ b/engines/hopkins/saveload.cpp
@@ -43,12 +43,12 @@ SaveLoadManager::SaveLoadManager(HopkinsEngine *vm) {
}
bool SaveLoadManager::save(const Common::String &file, const void *buf, size_t n) {
- Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(file);
+ Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(file);
- if (f) {
- size_t bytesWritten = f->write(buf, n);
- f->finalize();
- delete f;
+ if (savefile) {
+ size_t bytesWritten = savefile->write(buf, n);
+ savefile->finalize();
+ delete savefile;
return bytesWritten == n;
} else
@@ -69,13 +69,13 @@ void SaveLoadManager::initSaves() {
}
void SaveLoadManager::load(const Common::String &file, byte *buf) {
- Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(file);
- if (f == NULL)
- error("Error openinig file - %s", file.c_str());
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
+ if (savefile == NULL)
+ error("Error opening file - %s", file.c_str());
- int32 filesize = f->size();
- f->read(buf, filesize);
- delete f;
+ int32 filesize = savefile->size();
+ savefile->read(buf, filesize);
+ delete savefile;
}
bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header) {
@@ -215,13 +215,13 @@ Common::Error SaveLoadManager::loadGame(int slot) {
bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header) {
// Try and open the save file for reading
- Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
- g_vm->generateSaveName(slot));
- if (!saveFile)
+ Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(
+ _vm->generateSaveName(slot));
+ if (!savefile)
return false;
- bool result = readSavegameHeader(saveFile, header);
- delete saveFile;
+ bool result = readSavegameHeader(savefile, header);
+ delete savefile;
return result;
}
diff --git a/engines/hopkins/saveload.h b/engines/hopkins/saveload.h
index 221a445fd2..6fee814180 100644
--- a/engines/hopkins/saveload.h
+++ b/engines/hopkins/saveload.h
@@ -63,7 +63,7 @@ public:
static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header);
void writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header);
- static bool readSavegameHeader(int slot, hopkinsSavegameHeader &header);
+ bool readSavegameHeader(int slot, hopkinsSavegameHeader &header);
Common::Error saveGame(int slot, const Common::String &saveName);
Common::Error loadGame(int slot);
diff --git a/engines/hopkins/script.cpp b/engines/hopkins/script.cpp
index 3d298b2e9e..7e150624b8 100644
--- a/engines/hopkins/script.cpp
+++ b/engines/hopkins/script.cpp
@@ -1217,6 +1217,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 88:
+ // Shooting target - Shooting at target
if (_vm->_globals->_saveData->_data[svField183] == 1) {
_vm->_objectsMan->setBobAnimDataIdx(1, 0);
_vm->_objectsMan->setBobAnimDataIdx(2, 0);
@@ -1294,6 +1295,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
break;
case 90:
+ // Shooting target - Using the level
_vm->_soundMan->playSoundFile("SOUND52.WAV");
if (!_vm->_globals->_saveData->_data[svField186]) {
_vm->_animMan->playSequence("CIB5A.SEQ", 1, 12, 1, false, false);
diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp
index f8eb7d00cd..4f7adcc6e5 100644
--- a/engines/kyra/kyra_rpg.cpp
+++ b/engines/kyra/kyra_rpg.cpp
@@ -213,7 +213,7 @@ void KyraRpgEngine::drawDialogueButtons() {
screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xC1 : 0xE1, 0);
} else {
- int sjisYOffset = (_flags.lang == Common::JA_JPN && _dialogueButtonString[i][0] < 0) ? 2 : 0;
+ int sjisYOffset = (_flags.lang == Common::JA_JPN && (_dialogueButtonString[i][0] & 0x80)) ? 2 : 0;
gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonWidth, guiSettings()->buttons.height, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonWidth >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2,
(_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2 - sjisYOffset, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 419b630714..054397a34a 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -1256,7 +1256,7 @@ int Screen::getTextWidth(const char *str) {
while (1) {
if (_sjisMixedFontMode)
- setFont(*str < 0 ? FID_SJIS_FNT : curFont);
+ setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
uint c = fetchChar(str);
@@ -1296,7 +1296,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
while (1) {
if (_sjisMixedFontMode)
- setFont(*str < 0 ? FID_SJIS_FNT : curFont);
+ setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
uint8 charHeightFnt = getFontHeight();
diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp
index 7b5add65c7..e676da3727 100644
--- a/engines/neverhood/console.cpp
+++ b/engines/neverhood/console.cpp
@@ -25,6 +25,7 @@
#include "neverhood/neverhood.h"
#include "neverhood/gamemodule.h"
#include "neverhood/scene.h"
+#include "neverhood/sound.h"
#include "neverhood/modules/module1600.h"
namespace Neverhood {
@@ -34,6 +35,7 @@ Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars));
DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces));
+ DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound));
}
Console::~Console() {
@@ -79,7 +81,7 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n");
DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n");
DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n");
- DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10, can be used anywhere\n");
+ DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n");
return true;
}
@@ -169,4 +171,21 @@ bool Console::Cmd_Dumpvars(int argc, const char **argv) {
return true;
}
+bool Console::Cmd_PlaySound(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: %s <sound hash>\n", argv[0]);
+ } else {
+ uint32 soundHash = strtol(argv[1], NULL, 0);
+ AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash);
+ soundItem->setVolume(100);
+ soundItem->playSound(false);
+ while (soundItem->isPlaying()) {
+ _vm->_system->delayMillis(10);
+ }
+ delete soundItem;
+ }
+
+ return true;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/console.h b/engines/neverhood/console.h
index 40c11b50e3..62d65bd693 100644
--- a/engines/neverhood/console.h
+++ b/engines/neverhood/console.h
@@ -41,6 +41,7 @@ private:
bool Cmd_Surfaces(int argc, const char **argv);
bool Cmd_Cheat(int argc, const char **argv);
bool Cmd_Dumpvars(int argc, const char **argv);
+ bool Cmd_PlaySound(int argc, const char **argv);
};
} // End of namespace Neverhood
diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp
index 5f860f8519..3de087051a 100644
--- a/engines/neverhood/detection.cpp
+++ b/engines/neverhood/detection.cpp
@@ -24,6 +24,7 @@
#include "engines/advancedDetector.h"
#include "common/file.h"
+#include "common/translation.h"
#include "neverhood/neverhood.h"
@@ -143,6 +144,13 @@ static const NeverhoodGameDescription gameDescriptions[] = {
} // End of namespace Neverhood
+static const ExtraGuiOption neverhoodExtraGuiOption = {
+ _s("Use original save/load screens"),
+ _s("Use the original save/load screens, instead of the ScummVM ones"),
+ "originalsaveload",
+ false
+};
+
class NeverhoodMetaEngine : public AdvancedMetaEngine {
public:
NeverhoodMetaEngine() : AdvancedMetaEngine(Neverhood::gameDescriptions, sizeof(Neverhood::NeverhoodGameDescription), neverhoodGames) {
@@ -160,7 +168,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
-
+ virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
void removeSaveState(const char *target, int slot) const;
@@ -194,6 +202,12 @@ bool NeverhoodMetaEngine::createInstance(OSystem *syst, Engine **engine, const A
return gd != 0;
}
+const ExtraGuiOptions NeverhoodMetaEngine::getExtraGuiOptions(const Common::String &target) const {
+ ExtraGuiOptions options;
+ options.push_back(neverhoodExtraGuiOption);
+ return options;
+}
+
SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Neverhood::NeverhoodEngine::SaveHeader header;
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index 96e8cc13a6..b3589837df 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -786,6 +786,7 @@ void GameModule::openMainMenu() {
createModule(1000, 0);
}
_vm->_screen->saveParams();
+ _vm->_screen->update();
_mainMenuRequested = false;
createMenuModule();
}
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index 8a30b20df4..66a7999e59 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -343,7 +343,7 @@ void unpackSpriteNormal(const byte *source, int width, int height, byte *dest, i
int calcDistance(int16 x1, int16 y1, int16 x2, int16 y2) {
const int16 deltaX = ABS(x1 - x2);
const int16 deltaY = ABS(y1 - y2);
- return sqrt((double)(deltaX * deltaX + deltaY * deltaY));
+ return (int)sqrt((double)(deltaX * deltaX + deltaY * deltaY));
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp
index 368bfd60a7..da7abd41e1 100644
--- a/engines/neverhood/menumodule.cpp
+++ b/engines/neverhood/menumodule.cpp
@@ -20,6 +20,11 @@
*
*/
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+#include "gui/saveload.h"
+
#include "neverhood/menumodule.h"
#include "neverhood/gamemodule.h"
@@ -73,12 +78,14 @@ MenuModule::MenuModule(NeverhoodEngine *vm, Module *parentModule, int which)
_savedPaletteData = _vm->_screen->getPaletteData();
_vm->_mixer->pauseAll(true);
+ _vm->toggleSoundUpdate(false);
createScene(MAIN_MENU, -1);
}
MenuModule::~MenuModule() {
_vm->_mixer->pauseAll(false);
+ _vm->toggleSoundUpdate(true);
_vm->_screen->setPaletteData(_savedPaletteData);
}
@@ -191,24 +198,26 @@ uint32 MenuModule::handleMessage(int messageNum, const MessageParam &param, Enti
}
void MenuModule::createLoadGameMenu() {
- _savegameSlot = -1;
- _savegameList = new SavegameList();
- loadSavegameList();
+ refreshSaveGameList();
_childObject = new LoadGameMenu(_vm, this, _savegameList);
}
void MenuModule::createSaveGameMenu() {
- _savegameSlot = -1;
- _savegameList = new SavegameList();
- loadSavegameList();
+ refreshSaveGameList();
_childObject = new SaveGameMenu(_vm, this, _savegameList);
}
void MenuModule::createDeleteGameMenu() {
+ refreshSaveGameList();
+ _childObject = new DeleteGameMenu(_vm, this, _savegameList);
+}
+
+void MenuModule::refreshSaveGameList() {
_savegameSlot = -1;
+ delete _savegameList;
+ _savegameList = NULL;
_savegameList = new SavegameList();
loadSavegameList();
- _childObject = new DeleteGameMenu(_vm, this, _savegameList);
}
void MenuModule::handleLoadGameMenuAction(bool doLoad) {
@@ -757,9 +766,7 @@ void SavegameListBox::onClick() {
mousePos.y -= _y + _rect.y1;
if (mousePos.x >= 0 && mousePos.x <= _rect.x2 - _rect.x1 &&
mousePos.y >= 0 && mousePos.y <= _rect.y2 - _rect.y1) {
- // We add 1 to the char height to ensure that the correct entry is chosen if the
- // user clicks at the bottom the text entry
- int newIndex = _firstVisibleItem + mousePos.y / (_fontSurface->getCharHeight() + 1);
+ int newIndex = _firstVisibleItem + mousePos.y / _fontSurface->getCharHeight();
if (newIndex <= _lastVisibleItem) {
_currIndex = newIndex;
refresh();
@@ -846,6 +853,36 @@ void SavegameListBox::pageDown() {
}
}
+int GameStateMenu::scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc) {
+ const EnginePlugin *plugin = NULL;
+ EngineMan.findGame(ConfMan.get("gameid"), &plugin);
+ GUI::SaveLoadChooser *dialog;
+ Common::String desc;
+ int slot;
+
+ if (isSave) {
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ desc = dialog->getResultString();
+
+ if (desc.empty())
+ desc = dialog->createDefaultSaveDescription(slot);
+
+ if (desc.size() > 29)
+ desc = Common::String(desc.c_str(), 29);
+
+ saveDesc = desc;
+ } else {
+ dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+ }
+
+ delete dialog;
+
+ return slot;
+}
+
GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList,
const uint32 *buttonFileHashes, const NRect *buttonCollisionBounds,
uint32 backgroundFileHash, uint32 fontFileHash,
@@ -855,8 +892,29 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
uint32 textFileHash1, uint32 textFileHash2)
: Scene(vm, parentModule), _currWidget(NULL), _savegameList(savegameList) {
+ bool isSave = (textEditCursorFileHash != 0);
+
_fontSurface = new FontSurface(_vm, fontFileHash, 32, 7, 32, 11, 17);
-
+
+ if (!ConfMan.getBool("originalsaveload")) {
+ Common::String saveDesc;
+ int saveCount = savegameList->size();
+ int slot = scummVMSaveLoadDialog(isSave, saveDesc);
+
+ if (slot >= 0) {
+ if (!isSave) {
+ ((MenuModule*)_parentModule)->setLoadgameInfo(slot);
+ } else {
+ ((MenuModule*)_parentModule)->setSavegameInfo(saveDesc,
+ slot, slot >= saveCount);
+ }
+ leaveScene(0);
+ } else {
+ leaveScene(1);
+ }
+ return;
+ }
+
setBackground(backgroundFileHash);
setPalette(backgroundFileHash);
insertScreenMouse(mouseFileHash, mouseRect);
@@ -869,7 +927,7 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
_textEditWidget = new TextEditWidget(_vm, textEditX, textEditY, this, 29,
_fontSurface, textEditBackgroundFileHash, textEditRect);
- if (textEditCursorFileHash != 0)
+ if (isSave)
_textEditWidget->setCursor(textEditCursorFileHash, 2, 13);
else
_textEditWidget->setReadOnly(true);
@@ -884,7 +942,6 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
SetUpdateHandler(&Scene::update);
SetMessageHandler(&GameStateMenu::handleMessage);
-
}
GameStateMenu::~GameStateMenu() {
diff --git a/engines/neverhood/menumodule.h b/engines/neverhood/menumodule.h
index 08858ad204..6ee990de67 100644
--- a/engines/neverhood/menumodule.h
+++ b/engines/neverhood/menumodule.h
@@ -45,6 +45,7 @@ public:
void setLoadgameInfo(uint index);
void setSavegameInfo(const Common::String &description, uint index, bool newSavegame);
void setDeletegameInfo(uint index);
+ void refreshSaveGameList();
protected:
int _sceneNum;
byte *_savedPaletteData;
@@ -229,6 +230,7 @@ protected:
Common::String _savegameDescription;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
virtual void performAction();
+ int scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc);
};
class SaveGameMenu : public GameStateMenu {
diff --git a/engines/neverhood/modules/module1100.cpp b/engines/neverhood/modules/module1100.cpp
index 0c09ed5242..dbd8c60210 100644
--- a/engines/neverhood/modules/module1100.cpp
+++ b/engines/neverhood/modules/module1100.cpp
@@ -64,6 +64,7 @@ Module1100::~Module1100() {
void Module1100::createScene(int sceneNum, int which) {
static const uint32 kSmackerFileHashList06[] = {0x10880805, 0x1088081D, 0};
static const uint32 kSmackerFileHashList07[] = {0x00290321, 0x01881000, 0};
+ static const byte kNavigationTypes02[] = {1, 0, 4, 1};
debug(1, "Module1100::createScene(%d, %d)", sceneNum, which);
_sceneNum = sceneNum;
switch (_sceneNum) {
@@ -80,9 +81,9 @@ void Module1100::createScene(int sceneNum, int which) {
case 2:
_vm->gameState().sceneNum = 2;
if (getGlobalVar(V_ROBOT_TARGET)) {
- createNavigationScene(0x004B84F0, which);
+ createNavigationScene(0x004B84F0, which, kNavigationTypes02);
} else {
- createNavigationScene(0x004B8490, which);
+ createNavigationScene(0x004B8490, which, kNavigationTypes02);
}
break;
case 3:
diff --git a/engines/neverhood/modules/module1200.cpp b/engines/neverhood/modules/module1200.cpp
index 3e67ddb35a..ae84d59113 100644
--- a/engines/neverhood/modules/module1200.cpp
+++ b/engines/neverhood/modules/module1200.cpp
@@ -133,7 +133,7 @@ SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 poi
if (x < 300)
loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50);
else
- loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y);
+ loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y - 20);
setClipRect(0, 0, 640, clipY2);
}
diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp
index cc5c22085c..062434f064 100644
--- a/engines/neverhood/modules/module1300.cpp
+++ b/engines/neverhood/modules/module1300.cpp
@@ -800,7 +800,7 @@ void AsScene1306Elevator::update() {
if (_isUp && _countdown != 0 && (--_countdown == 0))
stGoingDown();
AnimatedSprite::update();
- if (_currFrameIndex == 7) {
+ if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) {
playSound(1);
_asElevatorDoor->setVisible(false);
}
diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp
index b664e93dde..7f9ca94430 100644
--- a/engines/neverhood/modules/module2100.cpp
+++ b/engines/neverhood/modules/module2100.cpp
@@ -210,7 +210,7 @@ Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which)
_ssFloorButton = insertSprite<SsCommonFloorButton>(this, 0x72427010, 0x32423010, 200, 0);
_asTape1 = insertSprite<AsScene1201Tape>(this, 18, 1100, 412, 443, 0x9148A011);
addCollisionSprite(_asTape1);
- _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9148A011);
+ _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9048A093);
addCollisionSprite(_asTape2);
if (which < 0) {
diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp
index 08ed274eb3..04e3f0bfee 100644
--- a/engines/neverhood/modules/module2200.cpp
+++ b/engines/neverhood/modules/module2200.cpp
@@ -50,6 +50,7 @@ void Module2200::createScene(int sceneNum, int which) {
switch (_sceneNum) {
case 0:
_vm->gameState().sceneNum = 0;
+ _vm->_soundMan->startMusic(0x601C908C, 0, 2);
_childObject = new Scene2201(_vm, this, which);
break;
case 1:
diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp
index 47f842b939..8d3b763f72 100644
--- a/engines/neverhood/modules/module2400.cpp
+++ b/engines/neverhood/modules/module2400.cpp
@@ -30,7 +30,7 @@ Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which)
_vm->_soundMan->addMusic(0x202D1010, 0xB110382D);
if (which < 0)
- createScene(_vm->gameState().sceneNum, _vm->gameState().which);
+ createScene(_vm->gameState().sceneNum, -1);
else
createScene(0, 0);
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index 19655d128b..e9ea10bd16 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -83,7 +83,7 @@ static const uint32 kScene2725StaticSprites[] = {
};
Module2700::Module2700(NeverhoodEngine *vm, Module *parentModule, int which)
- : Module(vm, parentModule), _soundIndex(0), _raidoMusicInitialized(false) {
+ : Module(vm, parentModule), _soundIndex(0), _radioMusicInitialized(false) {
_vm->_soundMan->addMusic(0x42212411, 0x04020210);
_vm->_soundMan->startMusic(0x04020210, 24, 2);
@@ -500,7 +500,7 @@ void Module2700::updateScene() {
} else {
switch (_sceneNum) {
case 21:
- if (!_raidoMusicInitialized) {
+ if (!_radioMusicInitialized) {
_vm->_soundMan->stopMusic(0x04020210, 0, 1);
_vm->gameModule()->initRadioPuzzle();
_musicFileHash = getGlobalVar(V_GOOD_RADIO_MUSIC_NAME);
@@ -508,7 +508,7 @@ void Module2700::updateScene() {
_vm->_soundMan->startMusic(_musicFileHash, 0, 2);
_vm->_soundMan->addSound(0x42212411, 0x44014282);
_vm->_soundMan->setSoundParams(0x44014282, true, 120, 360, 72, 0);
- _raidoMusicInitialized = true;
+ _radioMusicInitialized = true;
}
break;
}
diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h
index 003666bb7f..158bb609e9 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -39,7 +39,7 @@ public:
protected:
int _sceneNum;
int _soundIndex;
- bool _raidoMusicInitialized;
+ bool _radioMusicInitialized;
uint32 _scene2711StaticSprites[6];
uint32 _musicFileHash;
void createScene(int sceneNum, int which);
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index 3d76d05762..7ab732b4ac 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -3120,7 +3120,7 @@ Scene2822::Scene2822(NeverhoodEngine *vm, Module *parentModule, int which)
addBackground(_background);
_background->getSurface()->getDrawRect().y = -10;
setPalette(0xD542022E);
- insertPuzzleMouse(0x0028D089, 20, 620);
+ insertPuzzleMouse(0x2022AD5C, 20, 620);
_ssButton = insertStaticSprite(0x1A4D4120, 1100);
_ssButton->setVisible(false);
loadSound(2, 0x19044E72);
diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp
index 373bfb57f6..f483e0c95f 100644
--- a/engines/neverhood/modules/module3000.cpp
+++ b/engines/neverhood/modules/module3000.cpp
@@ -49,7 +49,7 @@ Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which)
_isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0;
- if (_isWallBroken) {
+ if (!_isWallBroken) {
_vm->_soundMan->setSoundVolume(0x90F0D1C3, 0);
_vm->_soundMan->playSoundLooping(0x90F0D1C3);
}
@@ -73,15 +73,16 @@ Module3000::~Module3000() {
}
void Module3000::createScene(int sceneNum, int which) {
- static const byte kNavigationTypes05[] = {3, 0};
+ static const byte kNavigationTypes05[] = {2, 0};
static const byte kNavigationTypes06[] = {5};
debug(1, "Module3000::createScene(%d, %d)", sceneNum, which);
_vm->gameState().sceneNum = sceneNum;
+ _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0;
switch (_vm->gameState().sceneNum) {
case 1:
if (!getGlobalVar(V_BOLT_DOOR_OPEN)) {
createNavigationScene(0x004B7C80, which);
- } else if (getGlobalVar(V_WALL_BROKEN)) {
+ } else if (_isWallBroken) {
createNavigationScene(0x004B7CE0, which);
} else {
createNavigationScene(0x004B7CB0, which);
@@ -89,11 +90,11 @@ void Module3000::createScene(int sceneNum, int which) {
break;
case 2:
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
- if (_isWallBroken) {
+ if (!_isWallBroken) {
_soundVolume = 90;
_vm->_soundMan->setSoundVolume(0x90F0D1C3, 90);
}
- if (getGlobalVar(V_WALL_BROKEN)) {
+ if (_isWallBroken) {
createNavigationScene(0x004B7D58, which);
} else {
createNavigationScene(0x004B7D10, which);
@@ -102,7 +103,7 @@ void Module3000::createScene(int sceneNum, int which) {
case 3:
if (getGlobalVar(V_STAIRS_DOWN))
createNavigationScene(0x004B7E60, which);
- else if (getGlobalVar(V_WALL_BROKEN))
+ else if (_isWallBroken)
createNavigationScene(0x004B7DA0, which);
else
createNavigationScene(0x004B7E00, which);
@@ -150,12 +151,12 @@ void Module3000::createScene(int sceneNum, int which) {
// NOTE: Newly introduced sceneNums
case 1001:
if (!getGlobalVar(V_BOLT_DOOR_OPEN))
- if (getGlobalVar(V_WALL_BROKEN))
+ if (_isWallBroken)
createSmackerScene(0x00940021, true, true, false);
else
createSmackerScene(0x01140021, true, true, false);
else
- if (getGlobalVar(V_WALL_BROKEN))
+ if (_isWallBroken)
createSmackerScene(0x001011B1, true, true, false);
else
createSmackerScene(0x001021B1, true, true, false);
@@ -299,7 +300,7 @@ void Module3000::updateScene() {
} else if (frameNumber == 10) {
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
}
- if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
if (frameNumber == 0)
_soundVolume = 40;
else
@@ -313,7 +314,7 @@ void Module3000::updateScene() {
if (navigationScene()->isWalkingForward()) {
uint32 frameNumber = navigationScene()->getFrameNumber();
int navigationIndex = navigationScene()->getNavigationIndex();
- if (_isWallBroken && _soundVolume > 1 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume > 1 && frameNumber % 2) {
_soundVolume--;
_vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume);
}
@@ -338,7 +339,7 @@ void Module3000::updateScene() {
if (frameNumber == 40) {
_vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0);
}
- if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
+ if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) {
if (frameNumber == 0)
_soundVolume = 40;
else
diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp
index 33e2a264a8..073d18f47b 100644
--- a/engines/neverhood/navigationscene.cpp
+++ b/engines/neverhood/navigationscene.cpp
@@ -25,6 +25,11 @@
namespace Neverhood {
+enum AreaType {
+ kAreaCanMoveForward = 0,
+ kAreaCannotMoveForward = 1
+};
+
NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes)
: Scene(vm, parentModule), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false),
_isWalkingForward(false), _isTurning(false), _smackerFileHash(0), _interactive(true), _leaveSceneAfter(false) {
@@ -49,7 +54,6 @@ NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
sendMessage(_parentModule, 0x100A, _navigationIndex);
-
}
NavigationScene::~NavigationScene() {
@@ -121,34 +125,29 @@ uint32 NavigationScene::handleMessage(int messageNum, const MessageParam &param,
}
void NavigationScene::createMouseCursor() {
-
const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
uint32 mouseCursorFileHash;
int areaType;
- if (_mouseCursor) {
+ if (_mouseCursor)
deleteSprite((Sprite**)&_mouseCursor);
- }
mouseCursorFileHash = navigationItem.mouseCursorFileHash;
if (mouseCursorFileHash == 0)
mouseCursorFileHash = 0x63A40028;
- if (_itemsTypes) {
+ if (_itemsTypes)
areaType = _itemsTypes[_navigationIndex];
- } else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag) {
- areaType = 0;
- } else {
- areaType = 1;
- }
+ else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag)
+ areaType = kAreaCanMoveForward;
+ else
+ areaType = kAreaCannotMoveForward;
insertNavigationMouse(mouseCursorFileHash, areaType);
sendPointMessage(_mouseCursor, 0x4002, _vm->getMousePos());
-
}
void NavigationScene::handleNavigation(const NPoint &mousePos) {
-
const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
bool oldIsWalkingForward = _isWalkingForward;
bool oldIsTurning = _isTurning;
@@ -210,7 +209,6 @@ void NavigationScene::handleNavigation(const NPoint &mousePos) {
if (oldIsWalkingForward != _isWalkingForward)
_vm->_soundMan->setTwoSoundsPlayFlag(_isWalkingForward);
-
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index 57fce58b94..e7c9f32d45 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -77,6 +77,9 @@ Common::Error NeverhoodEngine::run() {
_gameState.sceneNum = 0;
_gameState.which = 0;
+ // Assign default values to the config manager, in case settings are missing
+ ConfMan.registerDefault("originalsaveload", "false");
+
_staticData = new StaticData();
_staticData->load("neverhood.dat");
_gameVars = new GameVars();
@@ -105,7 +108,8 @@ Common::Error NeverhoodEngine::run() {
_gameModule = new GameModule(this);
_isSaveAllowed = true;
-
+ _updateSound = true;
+
if (isDemo()) {
// Adjust this navigation list for the demo version
NavigationList *navigationList = _staticData->getNavigationList(0x004B67E8);
@@ -119,9 +123,10 @@ Common::Error NeverhoodEngine::run() {
(*navigationList)[5].middleFlag = 1;
}
- if (ConfMan.hasKey("save_slot"))
- loadGameState(ConfMan.getInt("save_slot"));
- else
+ if (ConfMan.hasKey("save_slot")) {
+ if (loadGameState(ConfMan.getInt("save_slot")).getCode() != Common::kNoError)
+ _gameModule->startup();
+ } else
_gameModule->startup();
mainLoop();
@@ -186,8 +191,12 @@ void NeverhoodEngine::mainLoop() {
_screen->update();
nextFrameTime = _screen->getNextFrameTime();
};
- _soundMan->update();
- _audioResourceMan->updateMusic();
+
+ if (_updateSound) {
+ _soundMan->update();
+ _audioResourceMan->updateMusic();
+ }
+
_system->updateScreen();
_system->delayMillis(10);
}
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 18f2cc9f64..773e80df7d 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -122,8 +122,8 @@ public:
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &description);
Common::Error removeGameState(int slot);
- void savegame(const char *filename, const char *description);
- void loadgame(const char *filename);
+ bool savegame(const char *filename, const char *description);
+ bool loadgame(const char *filename);
const char *getSavegameFilename(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
@@ -134,7 +134,10 @@ public:
int16 getMouseY() const { return _mouseY; }
NPoint getMousePos();
-public:
+ void toggleSoundUpdate(bool state) { _updateSound = state; }
+
+private:
+ bool _updateSound;
};
diff --git a/engines/neverhood/saveload.cpp b/engines/neverhood/saveload.cpp
index 578d9858ff..ae93a0cea4 100644
--- a/engines/neverhood/saveload.cpp
+++ b/engines/neverhood/saveload.cpp
@@ -61,12 +61,12 @@ NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::Se
return ((in->eos() || in->err()) ? kRSHEIoError : kRSHENoError);
}
-void NeverhoodEngine::savegame(const char *filename, const char *description) {
+bool NeverhoodEngine::savegame(const char *filename, const char *description) {
Common::OutSaveFile *out;
if (!(out = g_system->getSavefileManager()->openForSaving(filename))) {
warning("Can't create file '%s', game not saved", filename);
- return;
+ return false;
}
TimeDate curTime;
@@ -99,13 +99,14 @@ void NeverhoodEngine::savegame(const char *filename, const char *description) {
out->finalize();
delete out;
+ return true;
}
-void NeverhoodEngine::loadgame(const char *filename) {
+bool NeverhoodEngine::loadgame(const char *filename) {
Common::InSaveFile *in;
if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
warning("Can't open file '%s', game not loaded", filename);
- return;
+ return false;
}
SaveHeader header;
@@ -115,7 +116,7 @@ void NeverhoodEngine::loadgame(const char *filename) {
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
delete in;
- return;
+ return false;
}
g_engine->setTotalPlayTime(header.playTime * 1000);
@@ -128,18 +129,20 @@ void NeverhoodEngine::loadgame(const char *filename) {
_gameModule->requestRestoreGame();
delete in;
-
+ return true;
}
Common::Error NeverhoodEngine::loadGameState(int slot) {
const char *fileName = getSavegameFilename(slot);
- loadgame(fileName);
+ if (!loadgame(fileName))
+ return Common::kReadingFailed;
return Common::kNoError;
}
Common::Error NeverhoodEngine::saveGameState(int slot, const Common::String &description) {
const char *fileName = getSavegameFilename(slot);
- savegame(fileName, description.c_str());
+ if (!savegame(fileName, description.c_str()))
+ return Common::kWritingFailed;
return Common::kNoError;
}
diff --git a/engines/neverhood/todo.txt b/engines/neverhood/todo.txt
deleted file mode 100644
index 9d781e06ec..0000000000
--- a/engines/neverhood/todo.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-NOTE:
--------
-Some of the TODOs should be done AFTER the whole game logic is implemented
-else the game disasm and reimplemtation code become even more different
-(unless I decide it's ok to do it :)
-
-TODOs which can be done any time:
------------------------------------
-- Cleanup
-- Clean up staticdata structs to look more like the ones in create_neverhood
- (e.g. by using template classes etc.)
- - Or use a common base class and manage all stuff in one single table and cast stuff accordingly
-
-TODOs which should be done only after the game logic is finished:
--------------------------------------------------------------------
-- Maybe rework organization of files (e.g. put ALL Sprites into one separate file, same with Modules and Scenes)
- - This would solve the problem of how to organize stuff which is used several times, and less headers would have to be included
- - The move special scenes (SmackerScene) into the scenes file
-
-DONE:
--------
-- Implement game menus
-- Rework sound system (I don't like that SoundResources need to be explicitly initialized in Scene constructors)
- - Should be just a handle object which initializes itself
- - Play routine should fill the handle so it can be stopped/queried later
- - Basically like ScummVM own sound handles
-- RE and implement yet unknown music/sound stuff
-- Implement clever sprite redrawing code (dirty rectangles, microtiles etc.), only redraw what's neccessary
-- Rework the resource system
- - The current system can be simplified a lot
- - Also resource purging needs to be implemented
-- Maybe merge CollisionMan with Scene (since it's so far never used independently)
-- Give placeholder stuff (e.g. sub?????, _flag??? etc.) better fitting names
-- Use CursorMan for the mouse cursor (instead of using it like a normal sprite)
- - This whould make it neccessary to call _system->updateScreen more often else
- the mouse movement would be choppy
-
-TODOs which are experimental:
--------------------------------
-NOTE: Since they affect the whole game, they really should be only implemented once the full game logic is implemented.
-These are nothing more than wild ideas for now, any might never be implemented.
-- Use states instead of separate callback methods
-- Try to move more stuff to neverhood.dat
-- Try to use more template functions instead of manually creating functions
- (Can be coupled with the above to move parameters to the dat and only use IDs)
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index 49d24753a1..ca843af465 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -249,11 +249,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
if (!memcmp(header, "Creative", 8)) {
resourceType = kSoundVOC;
- } else if (!memcmp(header, "RIFF", 4) != 0) {
+ } else if (!memcmp(header, "RIFF", 4)) {
resourceType = kSoundWAV;
- } else if (!memcmp(header, "FORM", 4) != 0) {
+ } else if (!memcmp(header, "FORM", 4)) {
resourceType = kSoundAIFF;
- } else if (!memcmp(header, "ajkg", 4) != 0) {
+ } else if (!memcmp(header, "ajkg", 4)) {
resourceType = kSoundShorten;
}
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 527e2ae973..6d9dc03195 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -116,7 +116,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
setPort(_wmgrPort);
// SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow
// We leave _wmgrPort top at 0, so the adjustment wont get done
- if (!g_sci->_features->usesOldGfxFunctions()) {
+ if (!_usesOldGfxFunctions) {
setOrigin(0, offTop);
_wmgrPort->rect.bottom = _screen->getHeight() - offTop;
} else {
@@ -131,7 +131,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
_picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true);
// For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead
// Because of the menu/status bar
- if (g_sci->_features->usesOldGfxFunctions())
+ if (_usesOldGfxFunctions)
_picWind->top = offTop;
kernelInitPriorityBands();
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 6aad52578d..db8da21bbc 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Thu May 2 21:27:50 2013
+ This file was generated by the md5table tool on Sun Jun 23 22:18:47 2013
DO NOT EDIT MANUALLY!
*/
@@ -124,6 +124,7 @@ static const MD5Table md5table[] = {
{ "28d24a33448fab6795850bc9f159a4a2", "atlantis", "FM-TOWNS", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns },
{ "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformDOS },
{ "28f07458f1b6c24e118a1ea056827701", "lost", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "291fb06071e65897f755846611f5ad40", "ft", "", "7-Wolf", 19697, Common::RU_RUS, Common::kPlatformUnknown },
{ "2a208ffbcd0e83e86f4356e6f64aa6e1", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformDOS },
{ "2a41b53cf1a90b6e6f26c10cc6041084", "tentacle", "", "Demo", 2439158, Common::EN_ANY, Common::kPlatformMacintosh },
{ "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows },
@@ -238,7 +239,7 @@ static const MD5Table md5table[] = {
{ "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown },
{ "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga },
{ "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown },
- { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown },
+ { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "Akella", -1, Common::RU_RUS, Common::kPlatformUnknown },
{ "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows },
{ "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows },
{ "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii },
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index c8a6666046..81a29c727f 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -41,6 +41,7 @@
#include "sword25/gfx/renderobjectmanager.h"
#include "common/system.h"
+#include "graphics/thumbnail.h"
namespace Sword25 {
@@ -509,60 +510,4 @@ void RenderedImage::checkForTransparency() {
}
}
-/**
- * Scales a passed surface, creating a new surface with the result
- * @param srcImage Source image to scale
- * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero)
- * @remarks Caller is responsible for freeing the returned surface
- */
-Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
- Graphics::Surface *s = new Graphics::Surface();
- s->create(xSize, ySize, srcImage.format);
-
- int *horizUsage = scaleLine(xSize, srcImage.w);
- int *vertUsage = scaleLine(ySize, srcImage.h);
-
- // Loop to create scaled version
- for (int yp = 0; yp < ySize; ++yp) {
- const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]);
- byte *destP = (byte *)s->getBasePtr(0, yp);
-
- for (int xp = 0; xp < xSize; ++xp) {
- const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel);
- for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) {
- *destP++ = *tempSrcP++;
- }
- }
- }
-
- // Delete arrays and return surface
- delete[] horizUsage;
- delete[] vertUsage;
- return s;
-}
-
-/**
- * Returns an array indicating which pixels of a source image horizontally or vertically get
- * included in a scaled image
- */
-int *RenderedImage::scaleLine(int size, int srcSize) {
- int scale = 100 * size / srcSize;
- assert(scale > 0);
- int *v = new int[size];
- Common::fill(v, &v[size], 0);
-
- int distCtr = 0;
- int *destP = v;
- for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
- distCtr += scale;
- while (distCtr >= 100) {
- assert(destP < &v[size]);
- *destP++ = distIndex;
- distCtr -= 100;
- }
- }
-
- return v;
-}
-
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index a25b258592..116f97de26 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -104,8 +104,6 @@ public:
return true;
}
- static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
-
void setIsTransparent(bool isTransparent) { _isTransparent = isTransparent; }
virtual bool isSolid() const { return !_isTransparent; }
@@ -119,7 +117,6 @@ private:
Graphics::Surface *_backSurface;
void checkForTransparency();
- static int *scaleLine(int size, int srcSize);
};
} // End of namespace Sword25
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 56fed3007f..5eb3b7d7b8 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -226,7 +226,11 @@ public:
Graphics::Surface &screen() { return _screenSurface; }
Common::Point getMousePosition() const { return _mousePos; }
- void setMousePosition(const Common::Point &pt) {
+ void setMousePosition(Common::Point pt) {
+ // Clip mouse position to be within the screen coordinates
+ pt.x = CLIP<int16>(pt.x, 0, SCREEN_WIDTH - 1);
+ pt.y = CLIP<int16>(pt.y, 0, SCREEN_HEIGHT - 1);
+
int yOffset = TinselV2 ? (g_system->getHeight() - _screenSurface.h) / 2 : 0;
g_system->warpMouse(pt.x, pt.y + yOffset);
_mousePos = pt;
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index 479f4965f3..83c9e3ec70 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -58,6 +58,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_animSpecialDefaultId = 0;
_currentPathNode = 0;
_currentWalkStamp = 0;
+ _currentFacingStamp = 0;
_visible = true;
_speed = 150; // 150 = nominal drew speed
_lastWalkTime = 0;
@@ -99,6 +100,9 @@ void Character::setFacing(int32 facing) {
if (_blockingWalk) {
_flags |= 2;
+ _currentFacingStamp++;
+ int32 localFacingStamp = _currentFacingStamp;
+
int32 dir = 0;
_lastWalkTime = _vm->_system->getMillis();
@@ -127,6 +131,11 @@ void Character::setFacing(int32 facing) {
else
playWalkAnim(0, 0);
_vm->doFrame();
+
+ if (_currentFacingStamp != localFacingStamp) {
+ // another setFacing was started in doFrame, we need to cancel this one.
+ return;
+ }
};
_flags &= ~2;
diff --git a/engines/toon/character.h b/engines/toon/character.h
index d33c314bf7..b248e7ccf2 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -143,6 +143,7 @@ protected:
Common::Array<Common::Point> _currentPath;
uint32 _currentPathNode;
int32 _currentWalkStamp;
+ int32 _currentFacingStamp;
};
} // End of namespace Toon
diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp
index 1cb8191640..52115b95fe 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes9.cpp
@@ -705,6 +705,10 @@ void Scene900::process(Event &event) {
void Scene900::dispatch() {
SceneExt::dispatch();
+ // WORKAROUND:: Fix for invalid data in the Blue Force floppy version when opening gate
+ if (_sceneMode == 9006 && (g_vm->getFeatures() & GF_FLOPPY) && BF_GLOBALS._player._endFrame == 8)
+ BF_GLOBALS._player._endFrame = 6;
+
if (BF_GLOBALS.getFlag(fWithLyle) && _lyle.isNoMover()) {
_lyle.updateAngle(BF_GLOBALS._player._position);
}
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index 4a90e23a33..131b70c4bd 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -3157,6 +3157,8 @@ void Visage::setVisage(int resNum, int rlbNum) {
_flipHoriz = flags & 1;
_data = g_resourceManager->getResource(RES_VISAGE, resNum, rlbNum);
+
+ DEALLOCATE(indexData);
}
}
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index fb0b0b0cbb..af6e6f9b13 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -234,10 +234,15 @@ GfxSurface::GfxSurface(const GfxSurface &s) {
}
GfxSurface::~GfxSurface() {
+ clear();
+}
+
+void GfxSurface::clear() {
if (_customSurface) {
_customSurface->free();
delete _customSurface;
- }
+ _customSurface = NULL;
+ }
}
/**
@@ -1322,6 +1327,12 @@ void GfxManager::copyFrom(GfxSurface &src, int destX, int destY) {
_surface.copyFrom(src, destX, destY);
}
+void GfxManager::copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds) {
+ _surface.setBounds(_bounds);
+
+ _surface.copyFrom(src, srcBounds, destBounds);
+}
+
/*--------------------------------------------------------------------------*/
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index 826f2fef6f..7239a99a68 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -100,6 +100,7 @@ public:
void unlockSurface();
void synchronize(Serializer &s);
void create(int width, int height);
+ void clear();
void setBounds(const Rect &bounds) { _bounds = bounds; }
const Rect &getBounds() const { return _bounds; }
@@ -302,6 +303,7 @@ public:
}
void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL);
void copyFrom(GfxSurface &src, int destX, int destY);
+ void copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds);
GfxSurface &getSurface() {
_surface.setBounds(_bounds);
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index 97042cb621..b7034fd49c 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -21,6 +21,8 @@
*/
#include "common/config-manager.h"
+#include "common/rect.h"
+#include "tsage/graphics.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
@@ -166,7 +168,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Ice Maze: Large empty room
return new Scene2400();
case 2425:
- // Ice Maze:
+ // Ice Maze: The Hall of Records
return new Scene2425();
case 2430:
// Ice Maze: Bedroom
@@ -213,7 +215,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
case 2900:
error("Missing scene %d from group 2", sceneNumber);
/* Scene group #3 */
- //
+ // ARM Base Hanager
case 3100:
return new Scene3100();
case 3125:
@@ -258,16 +260,22 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Cutscene - Ship landing
return new Scene3350();
case 3375:
+ // Outer walkway
return new Scene3375();
case 3385:
+ // Corridor
return new Scene3385();
case 3395:
+ // Walkway
return new Scene3395();
case 3400:
+ // Confrontation
return new Scene3400();
case 3500:
+ // Maze action sequencec
return new Scene3500();
case 3600:
+ // Cutscene - walking at gunpoint
return new Scene3600();
case 3700:
// Cutscene - Teleport outside
@@ -1268,287 +1276,202 @@ void SceneAreaObject::setDetails(int resNum, int lookLineNum, int talkLineNum, i
/*****************************************************************************/
-UnkObject1200::UnkObject1200() {
- _field16 = _field3A = NULL;
- _field12 = _field14 = 0;
- _field26 = _field28 = _field2A = _field2C = _field2E = _field30 = 0;
- _field32 = _field34 = _field36 = _field38 = _field3E = _field40 = 0;
+MazeUI::MazeUI() {
+ _mapData = NULL;
+ _cellsVisible.x = _cellsVisible.y = 0;
+ _mapCells.x = _mapCells.y = 0;
+ _cellSize.x = _cellSize.y = 0;
+ _mapOffset.x = _mapOffset.y = 0;
+ _resNum = _cellsResNum = 0;
+ _frameCount = _resCount = _mapImagePitch = _unused = 0;
}
-void UnkObject1200::synchronize(Serializer &s) {
- SavedObject::synchronize(s);
+MazeUI::~MazeUI() {
+ DEALLOCATE(_mapData);
+}
- _rect1.synchronize(s);
- _rect2.synchronize(s);
+void MazeUI::synchronize(Serializer &s) {
+ SavedObject::synchronize(s);
- // FIXME: syncrhonize _field16 and _field3A
+ s.syncAsSint16LE(_resNum);
+ if (s.isLoading())
+ load(_resNum);
- s.syncAsSint16LE(_field12);
- s.syncAsSint16LE(_field14);
- s.syncAsSint16LE(_field26);
- s.syncAsSint16LE(_field28);
- s.syncAsSint16LE(_field2A);
- s.syncAsSint16LE(_field2C);
- s.syncAsSint16LE(_field2E);
- s.syncAsSint16LE(_field30);
- s.syncAsSint16LE(_field32);
- s.syncAsSint16LE(_field34);
- s.syncAsSint16LE(_field36);
- s.syncAsSint16LE(_field38);
- s.syncAsSint16LE(_field3E);
- s.syncAsSint16LE(_field40);
+ s.syncAsSint16LE(_mapOffset.x);
+ s.syncAsSint16LE(_mapOffset.y);
+ s.syncAsSint16LE(_unused);
}
-void UnkObject1200::sub51AE9(int arg1) {
- warning("STUB: UnkObject1200::sub51AE9()");
-}
+void MazeUI::load(int resNum) {
+ clear();
+ _resNum = resNum;
-int UnkObject1200::sub51AF8(Common::Point pt) {
- if (!_rect1.contains(pt))
- return -1;
+ const byte *header = g_resourceManager->getResource(RT17, resNum, 0);
- int tmp1 = (pt.x - _rect1.left + _field2E) / _field2A;
- int tmp2 = (pt.y - _rect1.top + _field30) / _field2C;
+ _cellsResNum = resNum + 1000;
+ _mapCells.x = READ_LE_UINT16(header + 2);
+ _mapCells.y = READ_LE_UINT16(header + 4);
+ _frameCount = 10;
+ _resCount = _frameCount << 3;
- if ((tmp1 >= 0) && (tmp2 >= 0) && (_field26 > tmp1) && (_field28 > tmp2))
- return _field16[(((_field26 * tmp2) + tmp1)* 2)];
+ Visage visage;
+ visage.setVisage(_cellsResNum, 1);
- return -1;
+ GfxSurface frame = visage.getFrame(2);
+ _cellSize.x = frame.getBounds().width();
+ _cellSize.y = frame.getBounds().height();
+
+ _mapData = g_resourceManager->getResource(RT17, resNum, 1);
+
+ _mapOffset.y = _mapOffset.x = 0;
+ _cellsVisible.x = (_displayBounds.width() + _cellSize.x - 1) / _cellSize.x;
+ _cellsVisible.y = (_displayBounds.height() + _cellSize.y - 1) / _cellSize.y;
+
+ _mapImagePitch = (_cellsVisible.x + 1) * _cellSize.x;
+ _mapImage.create(_mapImagePitch, _cellSize.y);
+
+ _mapBounds = Rect(0, 0, _cellSize.x * _mapCells.x, _cellSize.y * _mapCells.y);
+}
+
+void MazeUI::clear() {
+ if (!_resNum)
+ _resNum = 1;
+
+ if (_mapData)
+ DEALLOCATE(_mapData);
+ _mapData = NULL;
+
+ _mapImage.clear();
}
-bool UnkObject1200::sub51AFD(Common::Point pt) {
- int retval = false;
+bool MazeUI::setMazePosition(const Common::Point &pt) {
+ bool retval = false;
- _field2E = pt.x;
- _field30 = pt.y;
+ _mapOffset = pt;
- if (_field2E < _rect2.top) {
- _field2E = _rect2.top;
+ if (_mapOffset.x < _mapBounds.top) {
+ _mapOffset.x = _mapBounds.top;
retval = true;
}
- if (_field30 < _rect2.left) {
- _field30 = _rect2.left;
+ if (_mapOffset.y < _mapBounds.left) {
+ _mapOffset.y = _mapBounds.left;
retval = true;
}
- if (_field2E + _rect1.width() > _rect2.right) {
- _field2E = _rect2.right - _rect1.width();
+ if (_mapOffset.x + _displayBounds.width() > _mapBounds.right) {
+ _mapOffset.x = _mapBounds.right - _displayBounds.width();
retval = true;
}
- if (_field30 + _rect1.height() > _rect2.bottom) {
- _field30 = _rect2.bottom - _rect1.height();
+ if (_mapOffset.y + _displayBounds.height() > _mapBounds.bottom) {
+ _mapOffset.y = _mapBounds.bottom - _displayBounds.height();
retval = true;
}
return retval;
}
-void UnkObject1200::sub51B02() {
- warning("STUB: UnkObject1200::sub51B02()");
-}
+void MazeUI::draw() {
+ int yPos = 0;
+ int ySize;
+ Visage visage;
-void UnkObject1200::sub9EDE8(Rect rect) {
- _rect1 = rect;
- warning("FIXME: UnkObject1200::sub9EDE8()");
-// _rect1.clip(g_globals->gfxManager()._bounds);
-}
+ _cellsVisible.y = ((_mapOffset.y % _cellSize.y) + _displayBounds.height() +
+ (_cellSize.y - 1)) / _cellSize.y;
-int UnkObject1200::sub9EE22(int &arg1, int &arg2) {
- arg1 /= _field2A;
- arg2 /= _field2C;
+ // Loop to handle the cell rows of the visible display area one at a time
+ for (int yCtr = 0; yCtr < _cellsVisible.y; ++yCtr, yPos += ySize) {
+ int cellY = _mapOffset.y / _cellSize.y + yCtr;
+
+ // Loop to iterate through the horizontal visible cells to build up
+ // an entire cell high horizontal slice of the map
+ for (int xCtr = 0; xCtr < _cellsVisible.x; ++xCtr) {
+ int cellX = _mapOffset.x / _cellSize.x + xCtr;
- if ((arg1 >= 0) && (arg2 >= 0) && (_field26 > arg1) && (_field28 > arg2)) {
- return _field16[(((_field26 * arg2) + arg1) * 2)];
- }
+ // Get the type of content to display in the cell
+ int cell = getCellFromCellXY(Common::Point(cellX, cellY)) - 1;
+ if (cell >= 0) {
+ int frameNum = (cell % _frameCount) + 1;
+ int rlbNum = (cell % _resCount) / _frameCount + 1;
+ int resNum = _cellsResNum + (cell / _resCount);
- return -1;
-}
+ visage.setVisage(resNum, rlbNum);
+ GfxSurface frame = visage.getFrame(frameNum);
-void Scene1200::sub9DAD6(int indx) {
- _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ _mapImage.copyFrom(frame, xCtr * _cellSize.x, 0);
+ } else {
+ GfxSurface emptyRect;
+ emptyRect.create(_cellSize.x, _cellSize.y);
- switch (indx) {
- case 0:
- if ( ((_object1.sub51AF8(Common::Point(200, 50)) > 36) || (_object1.sub51AF8(Common::Point(200, 88)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4))
- || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2))
- || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1200;
- setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(200, 69)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 15;
- else
- _sceneMode = 10;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 76;
- else
- _sceneMode = 75;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 101;
- else
- _sceneMode = 100;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 111;
- else
- _sceneMode = 110;
- break;
- default:
- break;
+ _mapImage.copyFrom(emptyRect, xCtr * _cellSize.x, 0);
}
- R2_GLOBALS._player.disableControl();
- _field412 = 1;
- signal();
}
- break;
- case 1:
- if ( ((_object1.sub51AF8(Common::Point(120, 50)) > 36) || (_object1.sub51AF8(Common::Point(120, 88)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1))
- || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1201;
- setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(120, 69)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 56;
- else
- _sceneMode = 55;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 25;
- else
- _sceneMode = 20;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 91;
- else
- _sceneMode = 90;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 121;
- else
- _sceneMode = 120;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _field412 = 2;
- signal();
- }
- break;
- case 2:
- if ( ((_object1.sub51AF8(Common::Point(140, 110)) > 36) || (_object1.sub51AF8(Common::Point(178, 110)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5) && (_field418 != 3))
- || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1203;
- setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(160, 110)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 51;
- else
- _sceneMode = 50;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 81;
- else
- _sceneMode = 80;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 35;
- else
- _sceneMode = 30;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 116;
- else
- _sceneMode = 115;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _field412 = 3;
- signal();
- }
- break;
- case 3:
- if ( ((_object1.sub51AF8(Common::Point(140, 30)) > 36) || (_object1.sub51AF8(Common::Point(178, 30)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9) && (_field418 != 3))
- || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1202;
- setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(160, 30)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 61;
- else
- _sceneMode = 60;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 71;
- else
- _sceneMode = 70;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 96;
- else
- _sceneMode = 95;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 45;
- else
- _sceneMode = 40;
- break;
- default:
- _sceneMode = 1;
- R2_GLOBALS._player.setup(3156, 4, 6);
- break;
+
+ if (yPos == 0) {
+ // First line of the map to be displayed - only the bottom portion of that
+ // first cell row may be visible
+ yPos = _displayBounds.top;
+ ySize = _cellSize.y - (_mapOffset.y % _cellSize.y);
+
+ Rect srcBounds(_mapOffset.x % _cellSize.x, _mapOffset.y % _cellSize.y,
+ (_mapOffset.x % _cellSize.x) + _displayBounds.width(), _cellSize.y);
+ Rect destBounds(_displayBounds.left, yPos, _displayBounds.right, yPos + ySize);
+
+ R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds);
+ } else {
+ if ((yPos + _cellSize.y) < _displayBounds.bottom) {
+ ySize = _cellSize.y;
+ } else {
+ ySize = _displayBounds.bottom - yPos;
}
- R2_GLOBALS._player.disableControl();
- _field412 = 4;
- signal();
+
+ Rect srcBounds(_mapOffset.x % _cellSize.x, 0,
+ (_mapOffset.x % _cellSize.x) + _displayBounds.width(), ySize);
+ Rect destBounds(_displayBounds.left, yPos, _displayBounds.right, yPos + ySize);
+
+ R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds);
}
- break;
- default:
- break;
}
}
+int MazeUI::getCellFromPixelXY(const Common::Point &pt) {
+ if (!_displayBounds.contains(pt))
+ return -1;
+
+ int cellX = (pt.x - _displayBounds.left + _mapOffset.x) / _cellSize.x;
+ int cellY = (pt.y - _displayBounds.top + _mapOffset.y) / _cellSize.y;
+
+ if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y))
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2);
+
+ return -1;
+}
+
+int MazeUI::getCellFromCellXY(const Common::Point &p) {
+ if (p.x < 0 || p.y < 0 || p.x >= _mapCells.x || p.y >= _mapCells.y) {
+ return -1;
+ } else {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * p.y + p.x) * 2);
+ }
+}
+
+int MazeUI::pixelToCellXY(Common::Point &pt) {
+ pt.x /= _cellSize.x;
+ pt.y /= _cellSize.y;
+
+ if ((pt.x >= 0) && (pt.y >= 0) && (pt.x < _mapCells.x) && (pt.y < _mapCells.y)) {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * pt.y + pt.x) * 2);
+ }
+
+ return -1;
+}
+
+void MazeUI::setDisplayBounds(const Rect &r) {
+ _displayBounds = r;
+ _displayBounds.clip(g_globals->gfxManager()._bounds);
+}
+
/*--------------------------------------------------------------------------*/
void AnimationSlice::load(Common::File &f) {
diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h
index 0b573bf7f0..5a0eecc56c 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.h
+++ b/engines/tsage/ringworld2/ringworld2_logic.h
@@ -276,6 +276,49 @@ public:
}
};
+enum MazeDirection { MAZEDIR_NONE = 0, MAZEDIR_NORTH = 1, MAZEDIR_NORTHEAST = 2, MAZEDIR_EAST = 3,
+ MAZEDIR_SOUTHEAST = 4, MAZEDIR_SOUTH = 5, MAZEDIR_SOUTHWEST = 6, MAZEDIR_WEST = 7,
+ MAZEDIR_NORTHWEST = 8 };
+
+class MazeUI: public SavedObject {
+private:
+ void clear();
+public:
+ // Position on screen to show map
+ Rect _displayBounds;
+ // The dimensions (in cells) of the entire maze map
+ Rect _mapBounds;
+
+ // Encoded cell map specifying the features of the maze
+ byte *_mapData;
+ // Image surface used to store a line of the map for rendering
+ GfxSurface _mapImage;
+
+ Common::Point _cellsVisible;
+ Common::Point _mapCells;
+ Common::Point _cellSize;
+ Common::Point _mapOffset;
+ int _resNum;
+ int _cellsResNum;
+ int _frameCount;
+ int _resCount;
+ int _mapImagePitch;
+ int _unused;
+public:
+ MazeUI();
+ virtual ~MazeUI();
+ void setDisplayBounds(const Rect &r);
+ bool setMazePosition(const Common::Point &pt);
+ void load(int resNum);
+ void draw();
+ int getCellFromPixelXY(const Common::Point &pt);
+ int getCellFromCellXY(const Common::Point &p);
+ int pixelToCellXY(Common::Point &pt);
+
+ virtual Common::String getClassName() { return "MazeUI"; }
+ void synchronize(Serializer &s);
+};
+
class SceneAreaObject: public SceneArea {
class Object1: public SceneActor {
public:
@@ -290,41 +333,6 @@ public:
void setDetails(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
};
-class UnkObject1200 : public SavedObject {
-public:
- Rect _rect1;
- Rect _rect2;
-
- int *_field16;
- int *_field3A;
-
- int _field12;
- int _field14;
- int _field26;
- int _field28;
- int _field2A;
- int _field2C;
- int _field2E;
- int _field30;
- int _field32;
- int _field34;
- int _field36;
- int _field38;
- int _field3E;
- int _field40;
-
- UnkObject1200();
- void synchronize(Serializer &s);
-
- void sub51AE9(int arg1);
- int sub51AF8(Common::Point pt);
- bool sub51AFD(Common::Point pt);
- void sub51B02();
- void sub9EDE8(Rect rect);
- int sub9EE22(int &arg1, int &arg2);
- virtual Common::String getClassName() { return "UnkObject1200"; }
-};
-
/*--------------------------------------------------------------------------*/
class AnimationSlice {
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
index af62ab6916..7cd1e92b8b 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -858,9 +858,10 @@ void Scene1100::saveCharacter(int characterIndex) {
}
/*--------------------------------------------------------------------------
- * Scene 1200 -
+ * Scene 1200 - Air Ducts Maze
*
*--------------------------------------------------------------------------*/
+
Scene1200::Scene1200() {
_field412 = 0;
_field414 = 0;
@@ -881,17 +882,17 @@ void Scene1200::synchronize(Serializer &s) {
s.syncAsSint16LE(_field41C);
}
-Scene1200::Area1::Area1() {
+Scene1200::LaserPanel::LaserPanel() {
_field20 = 0;
}
-void Scene1200::Area1::synchronize(Serializer &s) {
+void Scene1200::LaserPanel::synchronize(Serializer &s) {
SceneArea::synchronize(s);
s.syncAsByte(_field20);
}
-void Scene1200::Area1::Actor3::init(int state) {
+void Scene1200::LaserPanel::Jumper::init(int state) {
_state = state;
SceneActor::postInit();
@@ -912,6 +913,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 2:
switch (R2_GLOBALS._v56AA7) {
case 1:
@@ -929,6 +931,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 3:
switch (R2_GLOBALS._v56AA8) {
case 1:
@@ -942,6 +945,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
default:
break;
}
@@ -949,7 +953,7 @@ void Scene1200::Area1::Actor3::init(int state) {
setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL);
}
-bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
+bool Scene1200::LaserPanel::Jumper::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -1018,7 +1022,7 @@ bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1200::Area1::postInit(SceneObjectList *OwnerList) {
+void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field41A = 1;
@@ -1026,24 +1030,24 @@ void Scene1200::Area1::postInit(SceneObjectList *OwnerList) {
proc12(1003, 1, 1, 100, 40);
proc13(1200, 11, -1, -1);
R2_GLOBALS._sound2.play(259);
- _actor3.init(1);
- _actor4.init(2);
- _actor5.init(3);
+ _jumper1.init(1);
+ _jumper2.init(2);
+ _jumper3.init(3);
R2_GLOBALS._player._canWalk = false;
}
-void Scene1200::Area1::remove() {
+void Scene1200::LaserPanel::remove() {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field41A = 0;
warning("Unexpected _sceneAreas.remove() call");
-// scene->_sceneAreas.remove(&_actor3);
-// scene->_sceneAreas.remove(&_actor4);
-// scene->_sceneAreas.remove(&_actor5);
- _actor3.remove();
- _actor4.remove();
- _actor5.remove();
+// scene->_sceneAreas.remove(&_jumper1);
+// scene->_sceneAreas.remove(&_jumper2);
+// scene->_sceneAreas.remove(&_jumper3);
+ _jumper1.remove();
+ _jumper2.remove();
+ _jumper3.remove();
// sub201EA
R2_GLOBALS._sceneItems.remove((SceneItem *)this);
@@ -1055,7 +1059,7 @@ void Scene1200::Area1::remove() {
R2_GLOBALS._player._canWalk = true;
}
-void Scene1200::Area1::process(Event &event) {
+void Scene1200::LaserPanel::process(Event &event) {
if (_field20 != R2_GLOBALS._insetUp)
return;
@@ -1081,7 +1085,7 @@ void Scene1200::Area1::process(Event &event) {
}
}
-void Scene1200::Area1::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
+void Scene1200::LaserPanel::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
_actor2.postInit();
@@ -1094,13 +1098,11 @@ void Scene1200::Area1::proc12(int visage, int stripFrameNum, int frameNum, int p
_field20 = R2_GLOBALS._insetUp;
}
-void Scene1200::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
+void Scene1200::LaserPanel::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
_actor2.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
void Scene1200::postInit(SceneObjectList *OwnerList) {
- Rect tmpRect;
-
loadScene(1200);
SceneExt::postInit();
@@ -1133,13 +1135,12 @@ void Scene1200::postInit(SceneObjectList *OwnerList) {
_actor1.postInit();
_actor1.hide();
- tmpRect.set(110, 20, 210, 120);
- _object1.sub9EDE8(tmpRect);
+ _mazeUI.setDisplayBounds(Rect(110, 20, 210, 120));
- _object1.sub51AE9(1);
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
+ _mazeUI.load(1);
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
+ _mazeUI.draw();
warning("set_pane_p(unk);");
R2_GLOBALS._player.enableControl();
@@ -1396,50 +1397,52 @@ void Scene1200::process(Event &event) {
return;
if (event.eventType == EVENT_BUTTON_DOWN) {
- _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
- int unk = _object1.sub51AF8(event.mousePos);
+ Common::Point cellPos(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ _mazeUI.pixelToCellXY(cellPos);
+
+ int cellId = _mazeUI.getCellFromPixelXY(event.mousePos);
switch (R2_GLOBALS._events.getCursor()) {
- case CURSOR_ARROW:
+ case CURSOR_WALK:
event.handled = true;
if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- sub9DAD6(1);
+ startCrawling(1);
if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- sub9DAD6(2);
+ startCrawling(2);
if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120))
- sub9DAD6(3);
+ startCrawling(3);
if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50))
- sub9DAD6(4);
+ startCrawling(4);
break;
case CURSOR_USE:
- if (unk > 36) {
- if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33))
- || ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41))
- || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5))
- || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9))
- || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) ) {
- _area1.postInit();
+ if (cellId > 36) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 33))
+ || ((cellPos.x == 7) && (cellPos.y == 33))
+ || ((cellPos.x == 33) && (cellPos.y == 41))
+ || ((cellPos.x == 5) && (cellPos.y == 5))
+ || ((cellPos.x == 13) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 5))
+ || ((cellPos.x == 17) && (cellPos.y == 9))
+ || ((cellPos.x == 29) && (cellPos.y == 17))
+ || ((cellPos.x == 33) && (cellPos.y == 17))
+ || ((cellPos.x == 35) && (cellPos.y == 17))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) ) {
+ _laserPanel.postInit();
event.handled = true;
}
}
- if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) {
- if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 9))
- || ((R2_GLOBALS._v56AA2 == 11) && (R2_GLOBALS._v56AA4 == 27))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 7))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 27))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 33))
- || (R2_GLOBALS._v56AA2 == 33) ) {
- switch (R2_GLOBALS._v56AA2) {
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 9))
+ || ((cellPos.x == 11) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 7))
+ || ((cellPos.x == 17) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 33))
+ || (cellPos.x == 33) ) {
+ switch (cellPos.x) {
case 3:
R2_GLOBALS._sceneManager.changeScene(3150);
break;
@@ -1458,23 +1461,25 @@ void Scene1200::process(Event &event) {
}
break;
case CURSOR_LOOK:
- if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) {
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
event.handled = true;
- switch (R2_GLOBALS._v56AA2) {
+ switch (cellPos.x) {
case 3:
+ // It was your cell.
SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
case 9:
R2_GLOBALS._sceneManager.changeScene(3240);
break;
case 11:
- if (R2_GLOBALS._v56AA4 == 27)
+ if (cellPos.y == 27)
R2_GLOBALS._sceneManager.changeScene(3210);
else
+ // A vent grill
SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
case 17:
- switch (R2_GLOBALS._v56AA4) {
+ switch (cellPos.y) {
case 5:
R2_GLOBALS._sceneManager.changeScene(3230);
break;
@@ -1485,6 +1490,7 @@ void Scene1200::process(Event &event) {
R2_GLOBALS._sceneManager.changeScene(3200);
break;
default:
+ // A vent grill
SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
}
@@ -1496,7 +1502,8 @@ void Scene1200::process(Event &event) {
break;
}
}
- if (unk > 36) {
+ if (cellId > 36) {
+ // "An anti-pest laser"
event.handled = true;
SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
}
@@ -1516,19 +1523,19 @@ void Scene1200::process(Event &event) {
switch (event.kbd.keycode) {
case Common::KEYCODE_1:
warning("FIXME: keycode = 0x4800");
- sub9DAD6(4);
+ startCrawling(4);
break;
case Common::KEYCODE_2:
warning("FIXME: keycode = 0x4B00");
- sub9DAD6(2);
+ startCrawling(2);
break;
case Common::KEYCODE_3:
warning("FIXME: keycode = 0x4D00");
- sub9DAD6(1);
+ startCrawling(1);
break;
case Common::KEYCODE_4:
warning("FIXME: keycode = 0x5000");
- sub9DAD6(3);
+ startCrawling(3);
break;
default:
event.handled = false;
@@ -1544,13 +1551,14 @@ void Scene1200::dispatch() {
Rect tmpRect;
Scene::dispatch();
if (_field41C != 0) {
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
- warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
+ _mazeUI.draw();
+
warning("_gfxManager.sub294AC(unk);");
warning("tmpRect.sub14DF3();");
_field41C = 0;
}
+ _mazeUI.draw(); //**DEBUG**
if (_field414 != 0) {
tmpRect.set(110, 20, 210, 120);
@@ -1571,9 +1579,9 @@ void Scene1200::dispatch() {
default:
break;
}
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
+ _mazeUI.draw();
warning("_gfxManager.sub294AC(unk);");
warning("tmpRect.sub14DF3();");
@@ -1608,6 +1616,190 @@ void Scene1200::saveCharacter(int characterIndex) {
SceneExt::saveCharacter(characterIndex);
}
+void Scene1200::startCrawling(int indx) {
+ Common::Point cellPos = Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ _mazeUI.pixelToCellXY(cellPos);
+
+ switch (indx) {
+ case 1:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(200, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(200, 88)) > 36))
+ && ( ((cellPos.x == 3) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 13) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 29) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 33) && (cellPos.y == 41)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1200;
+ setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(200, 69)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 15;
+ else
+ _sceneMode = 10;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 76;
+ else
+ _sceneMode = 75;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 101;
+ else
+ _sceneMode = 100;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 111;
+ else
+ _sceneMode = 110;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 1;
+ signal();
+ }
+ break;
+ case 2:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(120, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(120, 88)) > 36))
+ && ( ((cellPos.x == 7) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 17) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 33) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 5) && (cellPos.y == 5)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1201;
+ setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(120, 69)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 56;
+ else
+ _sceneMode = 55;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 25;
+ else
+ _sceneMode = 20;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 91;
+ else
+ _sceneMode = 90;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 121;
+ else
+ _sceneMode = 120;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 2;
+ signal();
+ }
+ break;
+ case 3:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 110)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 110)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 5) && (_field418 != 3))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1203;
+ setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 110)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 51;
+ else
+ _sceneMode = 50;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 81;
+ else
+ _sceneMode = 80;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 35;
+ else
+ _sceneMode = 30;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 116;
+ else
+ _sceneMode = 115;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 3;
+ signal();
+ }
+ break;
+ case 4:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 30)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 30)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 9) && (_field418 != 3))
+ || ((cellPos.x == 35) && (cellPos.y == 17)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1202;
+ setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 30)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 61;
+ else
+ _sceneMode = 60;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 71;
+ else
+ _sceneMode = 70;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 96;
+ else
+ _sceneMode = 95;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 45;
+ else
+ _sceneMode = 40;
+ break;
+ default:
+ _sceneMode = 1;
+ R2_GLOBALS._player.setup(3156, 4, 6);
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 4;
+ signal();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
/*--------------------------------------------------------------------------
* Scene 1337 - Card game
*
@@ -6924,7 +7116,7 @@ void Scene1550::UnkArea1550::remove() {
}
void Scene1550::UnkArea1550::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
+// This is a copy of Scene1200::LaserPanel::process
if (_field20 != R2_GLOBALS._insetUp)
return;
@@ -6988,7 +7180,7 @@ void Scene1550::UnkArea1550::proc12(int visage, int stripFrameNum, int frameNum,
}
void Scene1550::UnkArea1550::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13
+ // Copy of Scene1200::LaserPanel::proc13
_areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
@@ -12947,7 +13139,7 @@ void Scene1950::Area1::remove() {
}
void Scene1950::Area1::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
+// This is a copy of Scene1200::LaserPanel::process
if (_field20 != R2_GLOBALS._insetUp)
return;
@@ -13000,7 +13192,7 @@ void Scene1950::Area1::proc12(int visage, int stripFrameNum, int frameNum, int p
}
void Scene1950::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13()
+ // Copy of Scene1200::LaserPanel::proc13()
_areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h
index f65a89972d..626e596f0b 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.h
@@ -118,22 +118,22 @@ public:
};
class Scene1200 : public SceneExt {
- class Area1: public SceneArea {
+ class LaserPanel: public SceneArea {
public:
- class Actor3 : public SceneActorExt {
+ class Jumper : public SceneActorExt {
public:
void init(int state);
virtual bool startAction(CursorType action, Event &event);
};
SceneActor _actor2;
- Actor3 _actor3;
- Actor3 _actor4;
- Actor3 _actor5;
+ Jumper _jumper1;
+ Jumper _jumper2;
+ Jumper _jumper3;
byte _field20;
- Area1();
+ LaserPanel();
void synchronize(Serializer &s);
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -146,8 +146,8 @@ class Scene1200 : public SceneExt {
public:
NamedHotspot _item1;
SceneActor _actor1;
- Area1 _area1;
- UnkObject1200 _object1;
+ LaserPanel _laserPanel;
+ MazeUI _mazeUI;
SequenceManager _sequenceManager;
int _field412;
@@ -160,7 +160,7 @@ public:
Scene1200();
void synchronize(Serializer &s);
- void sub9DAD6(int indx);
+ void startCrawling(int indx);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
index 6a030e5b44..02a0c05c0c 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
@@ -630,6 +630,7 @@ void Scene2000::Exit3::changeScene() {
break;
}
}
+
void Scene2000::Exit4::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
@@ -756,19 +757,21 @@ void Scene2000::Exit5::changeScene() {
}
}
-void Scene2000::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
- loadScene(2000);
-
+Scene2000::Scene2000(): SceneExt() {
if (R2_GLOBALS._sceneManager._previousScene != -1) {
R2_GLOBALS._v56605[1] = 21;
R2_GLOBALS._v56605[2] = 21;
}
- if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex] != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) {
+ if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex]
+ != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex])
+ && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 0;
}
+
_exitingFlag = false;
+}
+void Scene2000::postInit(SceneObjectList *OwnerList) {
_exit1.setDetails(Rect(0, 100, 14, 140), EXITCURSOR_W, 2000);
_exit1.setDest(Common::Point(14, 129));
_exit2.setDetails(Rect(305, 100, 320, 140), EXITCURSOR_E, 2000);
@@ -917,6 +920,8 @@ void Scene2000::postInit(SceneObjectList *OwnerList) {
initPlayer();
_item1.setDetails(Rect(0, 0, 320, 200), 2000, 0, -1, 23, 1, NULL);
+
+ SceneExt::postInit();
}
void Scene2000::remove() {
@@ -998,6 +1003,8 @@ void Scene2000::signal() {
g_globals->_sceneManager.changeScene(2350);
break;
default:
+ R2_GLOBALS._v56AAB = 0;
+ R2_GLOBALS._player.enableControl();
break;
}
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.h b/engines/tsage/ringworld2/ringworld2_scenes2.h
index 281d1da366..feceaa1537 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.h
@@ -80,6 +80,7 @@ public:
Action1 _action1, _action2, _action3, _action4, _action5;
SequenceManager _sequenceManager;
+ Scene2000();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void signal();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index 61711d0a4f..d5e7b1b9c1 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -2885,9 +2885,10 @@ void Scene3400::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 3500 -
+ * Scene 3500 - Cavern Maze
*
*--------------------------------------------------------------------------*/
+
Scene3500::Action1::Action1() {
_field1E = 0;
_field20 = 0;
@@ -2919,9 +2920,10 @@ void Scene3500::Action1::sub108670(int arg1) {
else
scene->_actor5.show();
- if (scene->_actor1._frame % 2 == 0)
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ if (scene->_actor1._frame % 2 == 0) {
+ scene->_actor1._frameChange = _field1E;
+ scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ }
setActionIndex(0);
}
@@ -2977,219 +2979,6 @@ void Scene3500::Action1::sub108732(int arg1) {
}
}
-Scene3500::Action2::Action2() {
- _field1E = 0;
-}
-
-void Scene3500::Action2::synchronize(Serializer &s) {
- Action::synchronize(s);
-
- s.syncAsSint16LE(_field1E);
-}
-
-Scene3500::Item4::Item4() {
- _field34 = 0;
-}
-
-void Scene3500::Item4::synchronize(Serializer &s) {
- NamedHotspot::synchronize(s);
-
- s.syncAsSint16LE(_field34);
-}
-
-Scene3500::Actor7::Actor7() {
- _fieldA4 = 0;
- _fieldA6 = 0;
- _fieldA8 = 0;
- _fieldAA = 0;
- _fieldAC = 0;
- _fieldAE = 0;
-}
-
-void Scene3500::Actor7::synchronize(Serializer &s) {
- SceneActor::synchronize(s);
-
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
- s.syncAsSint16LE(_fieldA8);
- s.syncAsSint16LE(_fieldAA);
- s.syncAsSint16LE(_fieldAC);
- s.syncAsSint16LE(_fieldAE);
-}
-
-void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) {
- _fieldAE = 0;
- _fieldA4 = arg1;
- _fieldA6 = arg2;
- _fieldA8 = arg3;
- _fieldAA = arg4;
- _fieldAC = _fieldAA / _fieldA8;
-
- postInit();
- setup(10501, 3, 1);
- fixPriority(255);
- sub109663(arg5);
-}
-
-void Scene3500::Actor7::sub1094ED() {
- Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
-
- scene->_field1270 = _position.x - _fieldA4;
-}
-
-void Scene3500::Actor7::sub109663(int arg1){
- sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1)));
-}
-
-void Scene3500::Actor7::sub109693(Common::Point Pt) {
- setPosition(Pt);
-}
-
-int Scene3500::UnkObject3500::sub1097C9(int arg1) {
- return (_field2A / 2) + arg1 - (arg1 % _field2A);
-}
-
-int Scene3500::UnkObject3500::sub1097EF(int arg1) {
- return (_field2C / 2) + arg1 - (arg1 % _field2C);
-}
-
-int Scene3500::UnkObject3500::sub109C09(Common::Point pt) {
- int vx = pt.x / _field2A;
- int vy = pt.y / _field2C;
-
- if ((vx >= 0) && (_field26 > vx) && (_field28 > vy)) {
- return _field16[((_field26 * vy) + vx) * 2];
- } else
- return -1;
-}
-
-int Scene3500::UnkObject3500::sub109C5E(int &x, int &y) {
- int retVal = sub51AFD(Common::Point(x, y));
- x = _field2E;
- y = _field30;
-
- return retVal;
-}
-
-Scene3500::Scene3500() {
- _fieldAF8 = 0;
- _fieldB9E = 0;
- _rotation = NULL;
- _field126E = 0;
- _field1270 = 0;
- _field1272 = 0;
- _field1274 = 0;
- _field1276 = 0;
- _field1278 = 0;
- _field127A = 0;
- _field127C = 0;
- _field127E = 0;
- _field1280 = 0;
- _field1282 = 0;
- _field1284 = 0;
- _field1286 = 0;
-}
-
-void Scene3500::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
- SYNC_POINTER(_rotation);
-
- s.syncAsSint16LE(_fieldAF8);
- s.syncAsSint16LE(_fieldB9E);
- s.syncAsSint16LE(_field126E);
- s.syncAsSint16LE(_field1270);
- s.syncAsSint16LE(_field1272);
- s.syncAsSint16LE(_field1274);
- s.syncAsSint16LE(_field1276);
- s.syncAsSint16LE(_field1278);
- s.syncAsSint16LE(_field127A);
- s.syncAsSint16LE(_field127C);
- s.syncAsSint16LE(_field127E);
- s.syncAsSint16LE(_field1280);
- s.syncAsSint16LE(_field1282);
- s.syncAsSint16LE(_field1284);
- s.syncAsSint16LE(_field1286);
-}
-
-void Scene3500::sub107F71(int arg1) {
- switch (arg1) {
- case -1:
- _actor7.sub1094ED();
- if (_field1270 != 0) {
- _field1270--;
- _actor7.sub109663(_field1270);
- }
- if (_action1._field24 != 0)
- _field1270 = 0;
- break;
- case 1:
- _actor7.sub1094ED();
- if (_field1270 < 16) {
- ++_field1270;
- _actor7.sub109663(_field1270);
- }
- if (_action1._field24 != 0)
- _field1270 = 0;
- break;
- case 88:
- if ((_action == 0) || (_action1._field24 == 0)) {
- // The original makes a second useless check on action, skipped
- _action2.sub10831F(2);
- if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) {
- _action2.signal();
- } else {
- _actor9.setAction(&_action2, &_actor9, NULL);
- }
- }
- break;
- case 96:
- if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) {
- _field1278 = 0;
- _action1.sub108732(0);
- } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
- _field1278 = arg1;
- } else if ((_action) && (_action1._field24 == 0)) {
- _action1.sub108670(1);
- _action1.signal();
- } else if (_action == 0) {
- _action1.sub108670(1);
- setAction(&_action1, &_actor1, NULL);
- }
- break;
- case 104:
- if ((_action == 0) || (_action1._field24 == 0)) {
- _action2.sub10831F(-1);
- if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) {
- _action2.signal();
- } else {
- _actor9.setAction(&_action2, &_actor9, NULL);
- }
- }
- break;
- case 112:
- if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) {
- _field1278 = 0;
- _action1.sub108732(0);
- } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
- _field1278 = arg1;
- } else if ((_action) && (_action1._field24 == 0)) {
- _action1.sub108670(-1);
- _action1.signal();
- } else if (_action == 0) {
- _action1.sub108670(-1);
- setAction(&_action1, &_actor1, NULL);
- }
- break;
- default:
- _field1270 = arg1;
- _actor7.sub109663(arg1);
- if (_action1._field24 != 0) {
- _field1270 = 0;
- }
- break;
- }
-}
-
void Scene3500::Action1::signal() {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
@@ -3199,13 +2988,13 @@ void Scene3500::Action1::signal() {
scene->_field1286 = 0;
if (scene->_field1270 != 0) {
scene->_field1270 = 0;
- scene->_field126E = 0;
+ scene->_mazeChangeAmount = 0;
scene->_field1272 = 0;
scene->_rotation->_idxChange = 0;
}
break;
case 1:
- if ((scene->_actor1._frame % 2) == 0) {
+ if ((scene->_actor1._frame % 2) == 1) {
setDelay(1);
return;
}
@@ -3216,25 +3005,28 @@ void Scene3500::Action1::signal() {
setDelay(1);
break;
case 4: {
- int si = scene->_unkObj1.sub109C09(Common::Point(scene->_field127A + 70, scene->_field127C + 46));
- int var2 = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70;
- int var4 = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46;
- int di = abs(var2 - scene->_field127A);
- int var6 = abs(var4 - scene->_field127C);
+ int si = scene->_mazeUI.getCellFromMapXY(Common::Point(scene->_mazePosition.x + 70, scene->_mazePosition.y + 46));
+ int var2 = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70;
+ int var4 = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46;
+ int di = abs(var2 - scene->_mazePosition.x);
+ int var6 = abs(var4 - scene->_mazePosition.y);
if ((scene->_actor1._frame % 2) != 0) {
scene->_actor1._frameChange = _field1E;
scene->_actor1.setFrame(scene->_actor1.changeFrame());
}
- int var8 = (scene->_action1._field1E * 2 + scene->_field1276);
- if (var8 > 7)
- var8 = 1;
- else if (var8 < 1)
- var8 = 7;
+ // Get the new direction starting on
+ int var8 = (scene->_action1._field1E * 2 + scene->_mazeDirection);
+ if (var8 > MAZEDIR_NORTHWEST)
+ var8 = MAZEDIR_NORTH;
+ else if (var8 < MAZEDIR_NORTH)
+ var8 = MAZEDIR_WEST;
+ // Check whether movement is allowed in that direction. If so, then
+ // movement is started again
switch (var8) {
- case 0:
+ case MAZEDIR_NORTH:
if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 23) && (si != 24) && (si != 4) && (si != 11))
|| (var6 != 0)) {
if ((si != 25) && (si != 26) && (si != 5) && (si != 14) && (si != 15))
@@ -3246,7 +3038,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 2:
+ case MAZEDIR_EAST:
if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 26) && (si != 24) && (si != 15) && (si != 6) && (si != 31))
|| (di != 0)) {
if ((si != 25) && (si != 23) && (si != 14) && (si != 5) && (si != 4))
@@ -3258,7 +3050,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 4:
+ case MAZEDIR_SOUTH:
if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 25) && (si != 26) && (si != 5) && (si != 16) && (si != 31))
|| (var6 != 0)) {
if ((si != 23) && (si != 24) && (si != 4) && (si != 14) && (si != 15))
@@ -3270,7 +3062,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 6:
+ case MAZEDIR_WEST:
if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 25) && (si != 23) && (si != 14) && (si != 1) && (si != 31))
|| (var6 != 0)) {
if ((si != 26) && (si != 24) && (si != 15) && (si != 5) && (si != 4))
@@ -3288,14 +3080,14 @@ void Scene3500::Action1::signal() {
// No break on purpose
case 2: {
scene->_actor8.setPosition(Common::Point(160, 73));
- scene->_actor8._moveDiff.x = 160 - scene->_field126E;
+ scene->_actor8._moveDiff.x = 160 - scene->_mazeChangeAmount;
scene->_fieldAF8 = 160 - ((_field1E * 2) * 160);
Common::Point pt(scene->_fieldAF8, 73);
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, this);
scene->_actor9.setPosition(Common::Point(160 + ((_field1E * 2) * 160), 73));
- scene->_actor9._moveDiff.x = 160 - scene->_field126E;
+ scene->_actor9._moveDiff.x = 160 - scene->_mazeChangeAmount;
scene->_fieldB9E = 160;
Common::Point pt2(scene->_fieldB9E, 73);
NpcMover *mover2 = new NpcMover();
@@ -3304,8 +3096,8 @@ void Scene3500::Action1::signal() {
break;
case 5:
scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ scene->_mazeDirection = scene->_actor1.changeFrame();
+ scene->_actor1.setFrame(scene->_mazeDirection);
setDelay(1);
break;
case 6:
@@ -3325,8 +3117,8 @@ void Scene3500::Action1::signal() {
case 7:
if ((scene->_actor1._frame % 2) == 0) {
scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ scene->_mazeDirection = scene->_actor1.changeFrame();
+ scene->_actor1.setFrame(scene->_mazeDirection);
}
setDelay(1);
break;
@@ -3342,7 +3134,7 @@ void Scene3500::Action1::signal() {
// but it's clearly a cut and paste error from case 4.
// The following code allows the switch to work properly.
warning("Checkme: fix for dead code");
- int var_8 = (_field1E * 2 + scene->_field1276);
+ int var_8 = (_field1E * 2 + scene->_mazeDirection);
if (var_8 > 7)
var_8 = 1;
else if (var_8 < 1)
@@ -3353,12 +3145,12 @@ void Scene3500::Action1::signal() {
case 0:
// No break on purpose
case 4:
- scene->_field127A = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70;
+ scene->_mazePosition.x = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70;
break;
case 2:
// No break on purpose
case 6:
- scene->_field127C = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46;
+ scene->_mazePosition.y = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46;
break;
default:
break;
@@ -3368,7 +3160,7 @@ void Scene3500::Action1::signal() {
_field24 = 0;
if (_field20 == 0) {
scene->_actor7.sub1094ED();
- if (scene->_field126E == scene->_field1270)
+ if (scene->_mazeChangeAmount == scene->_field1270)
scene->_aSound1.play(276);
}
break;
@@ -3416,12 +3208,232 @@ void Scene3500::Action1::dispatch() {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
Action::dispatch();
- if ((_actionIndex == 1) && (scene->_field126E <= 4)) {
+ if ((_actionIndex == 1) && (scene->_mazeChangeAmount <= 4)) {
scene->_rotation->_idxChange = 0;
signal();
}
}
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Action2::Action2() {
+ _field1E = 0;
+}
+
+void Scene3500::Action2::synchronize(Serializer &s) {
+ Action::synchronize(s);
+
+ s.syncAsSint16LE(_field1E);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Item4::Item4() {
+ _field34 = 0;
+}
+
+void Scene3500::Item4::synchronize(Serializer &s) {
+ NamedHotspot::synchronize(s);
+
+ s.syncAsSint16LE(_field34);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Actor7::Actor7() {
+ _fieldA4 = 0;
+ _fieldA6 = 0;
+ _fieldA8 = 0;
+ _fieldAA = 0;
+ _fieldAC = 0;
+ _fieldAE = 0;
+}
+
+void Scene3500::Actor7::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_fieldA4);
+ s.syncAsSint16LE(_fieldA6);
+ s.syncAsSint16LE(_fieldA8);
+ s.syncAsSint16LE(_fieldAA);
+ s.syncAsSint16LE(_fieldAC);
+ s.syncAsSint16LE(_fieldAE);
+}
+
+void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) {
+ _fieldAE = 0;
+ _fieldA4 = arg1;
+ _fieldA6 = arg2;
+ _fieldA8 = arg3;
+ _fieldAA = arg4;
+ _fieldAC = _fieldAA / _fieldA8;
+
+ postInit();
+ setup(1050, 3, 1);
+ fixPriority(255);
+ sub109663(arg5);
+}
+
+void Scene3500::Actor7::sub1094ED() {
+ Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_field1270 = _position.x - _fieldA4;
+}
+
+void Scene3500::Actor7::sub109663(int arg1){
+ sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1)));
+}
+
+void Scene3500::Actor7::sub109693(Common::Point Pt) {
+ setPosition(Pt);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int Scene3500::MazeUI3500::cellFromX(int x) {
+ return (_cellSize.x / 2) + x - (x % _cellSize.x);
+}
+
+int Scene3500::MazeUI3500::cellFromY(int y) {
+ return (_cellSize.y / 2) + y - (y % _cellSize.y) - 1;
+}
+
+int Scene3500::MazeUI3500::getCellFromMapXY(Common::Point pt) {
+ int cellX = pt.x / _cellSize.x;
+ int cellY = pt.y / _cellSize.y;
+
+ if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y)) {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2);
+ } else
+ return -1;
+}
+
+bool Scene3500::MazeUI3500::setMazePosition2(Common::Point &p) {
+ bool retVal = setMazePosition(p);
+ p = _mapOffset;
+
+ return retVal;
+}
+
+Scene3500::Scene3500() {
+ _fieldAF8 = 0;
+ _fieldB9E = 0;
+ _rotation = NULL;
+ _mazeChangeAmount = 0;
+ _field1270 = 0;
+ _field1272 = 0;
+ _field1274 = 0;
+ _mazeDirection = MAZEDIR_NONE;
+ _field1278 = 0;
+ _mazePosition.x = 0;
+ _mazePosition.y = 0;
+ _field127E = 0;
+ _field1280 = 0;
+ _field1282 = 0;
+ _field1284 = 0;
+ _field1286 = 0;
+}
+
+void Scene3500::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+ SYNC_POINTER(_rotation);
+
+ s.syncAsSint16LE(_fieldAF8);
+ s.syncAsSint16LE(_fieldB9E);
+ s.syncAsSint16LE(_mazeChangeAmount);
+ s.syncAsSint16LE(_field1270);
+ s.syncAsSint16LE(_field1272);
+ s.syncAsSint16LE(_field1274);
+ s.syncAsSint16LE(_mazeDirection);
+ s.syncAsSint16LE(_field1278);
+ s.syncAsSint16LE(_mazePosition.x);
+ s.syncAsSint16LE(_mazePosition.y);
+ s.syncAsSint16LE(_field127E);
+ s.syncAsSint16LE(_field1280);
+ s.syncAsSint16LE(_field1282);
+ s.syncAsSint16LE(_field1284);
+ s.syncAsSint16LE(_field1286);
+}
+
+void Scene3500::sub107F71(int arg1) {
+ switch (arg1) {
+ case -1:
+ _actor7.sub1094ED();
+ if (_field1270 != 0) {
+ _field1270--;
+ _actor7.sub109663(_field1270);
+ }
+ if (_action1._field24 != 0)
+ _field1270 = 0;
+ break;
+ case 1:
+ _actor7.sub1094ED();
+ if (_field1270 < 16) {
+ ++_field1270;
+ _actor7.sub109663(_field1270);
+ }
+ if (_action1._field24 != 0)
+ _field1270 = 0;
+ break;
+ case 88:
+ if ((_action == 0) || (_action1._field24 == 0)) {
+ // The original makes a second useless check on action, skipped
+ _action2.sub10831F(2);
+ if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) {
+ _action2.signal();
+ } else {
+ _actor9.setAction(&_action2, &_actor9, NULL);
+ }
+ }
+ break;
+ case 96:
+ if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) {
+ _field1278 = 0;
+ _action1.sub108732(0);
+ } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
+ _field1278 = arg1;
+ } else if ((_action) && (_action1._field24 == 0)) {
+ _action1.sub108670(1);
+ _action1.signal();
+ } else if (_action == 0) {
+ _action1.sub108670(1);
+ setAction(&_action1, &_actor1, NULL);
+ }
+ break;
+ case 104:
+ if ((_action == 0) || (_action1._field24 == 0)) {
+ _action2.sub10831F(-1);
+ if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) {
+ _action2.signal();
+ } else {
+ _actor9.setAction(&_action2, &_actor9, NULL);
+ }
+ }
+ break;
+ case 112:
+ if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) {
+ _field1278 = 0;
+ _action1.sub108732(0);
+ } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
+ _field1278 = arg1;
+ } else if ((_action) && (_action1._field24 == 0)) {
+ _action1.sub108670(-1);
+ _action1.signal();
+ } else if (_action == 0) {
+ _action1.sub108670(-1);
+ setAction(&_action1, &_actor1, NULL);
+ }
+ break;
+ default:
+ _field1270 = arg1;
+ _actor7.sub109663(arg1);
+ if (_action1._field24 != 0) {
+ _field1270 = 0;
+ }
+ break;
+ }
+}
+
void Scene3500::Action2::sub10831F(int arg1) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
@@ -3452,17 +3464,17 @@ void Scene3500::Action2::signal() {
di = scene->_fieldB9E;
}
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt(si, 73 - (_field1E * 12));
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt2(di, 73 - (_field1E * 12));
NpcMover *mover2 = new NpcMover();
scene->_actor9.addMover(mover2, &pt2, NULL);
- scene->_field126E = (scene->_field126E / 2) + (scene->_field126E % 2);
- setDelay(17 - scene->_field126E);
+ scene->_mazeChangeAmount = (scene->_mazeChangeAmount / 2) + (scene->_mazeChangeAmount % 2);
+ setDelay(17 - scene->_mazeChangeAmount);
}
break;
case 1: {
@@ -3477,12 +3489,12 @@ void Scene3500::Action2::signal() {
scene->_actor7.sub1094ED();
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt(si, 73);
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt2(di, 73);
NpcMover *mover2 = new NpcMover();
scene->_actor9.addMover(mover2, &pt2, NULL);
@@ -3559,7 +3571,6 @@ bool Scene3500::Actor7::startAction(CursorType action, Event &event) {
void Scene3500::postInit(SceneObjectList *OwnerList) {
byte tmpPal[768];
- Rect tmpRect;
loadScene(1050);
R2_GLOBALS._uiElements._active = false;
@@ -3574,9 +3585,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_field1278 = 0;
_field1272 = 1;
_field1270 = 4;
- _field126E = 4;
- _field127A = 860;
- _field127C = 891;
+ _mazeChangeAmount = 4;
+ _mazePosition = Common::Point(860, 891);
_rotation = R2_GLOBALS._scenePalette.addRotation(240, 254, -1);
_rotation->setDelay(0);
_rotation->_idxChange = 1;
@@ -3615,7 +3625,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_item7.setDetails(96, 3500, 12, 10, -1);
_actor8.postInit();
- _actor8.setup(10501, 1, 1);
+ _actor8.setup(1050, 1, 1);
_actor8.setPosition(Common::Point(160, 73));
_actor8.fixPriority(1);
@@ -3630,8 +3640,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_item1.setDetails(Rect(0, 0, 320, 200), 3500, 0, -1, 2, 1, NULL);
_actor1.postInit();
- _field1276 = 1;
- _actor1.setup(1004, 1, _field1276);
+ _mazeDirection = MAZEDIR_NORTH;
+ _actor1.setup(1004, 1, _mazeDirection);
_actor1.setPosition(Common::Point(230, 135));
_actor1.fixPriority(200);
_actor1._frameChange = 1;
@@ -3654,7 +3664,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_actor6.hide();
_actor2.postInit();
- _actor2.setup(1004, 4, _field126E + 1);
+ _actor2.setup(1004, 4, _mazeChangeAmount + 1);
_actor2.setPosition(Common::Point(126, 137));
_actor2.fixPriority(200);
@@ -3663,15 +3673,12 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_actor3.setPosition(Common::Point(126, 108));
_actor3.fixPriority(200);
- tmpRect.set(160, 89, 299, 182);
- _unkObj1.sub9EDE8(tmpRect);
- _unkObj1.sub51AE9(2);
- _unkObj1.sub51AFD(Common::Point(_field127A, _field127C));
+ _mazeUI.setDisplayBounds(Rect(160, 89, 299, 182));
+ _mazeUI.load(2);
+ _mazeUI.setMazePosition(_mazePosition);
_action1._field24 = 0;
- warning("gfx_set_pane_p()");
- _unkObj1.sub51B02();
- warning("gfx_set_pane_p()");
+ _mazeUI.draw();
_field1286 = 1;
R2_GLOBALS._player.postInit();
@@ -3682,7 +3689,6 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
}
void Scene3500::remove() {
- _rotation->remove();
R2_GLOBALS._sound2.fadeOut2(NULL);
SceneExt::remove();
}
@@ -3699,64 +3705,58 @@ void Scene3500::process(Event &event) {
if (event.eventType == EVENT_KEYPRESS) {
switch (event.kbd.keycode) {
- case Common::KEYCODE_1:
- warning("FIXME: keycode = 0x4700");
+ case Common::KEYCODE_KP7:
R2_GLOBALS._sound2.play(338);
sub107F71(16);
event.handled = true;
break;
- case Common::KEYCODE_2:
- warning("FIXME: keycode = 0x4800");
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(88);
event.handled = true;
break;
- case Common::KEYCODE_3:
- warning("FIXME: keycode = 0x4900");
+ case Common::KEYCODE_KP9:
if (_field1270 < 16)
R2_GLOBALS._sound2.play(338);
sub107F71(1);
event.handled = true;
break;
- case Common::KEYCODE_4:
- warning("FIXME: keycode = 0x4B00");
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_LEFT:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(112);
event.handled = true;
break;
- case Common::KEYCODE_5:
- warning("FIXME: keycode = 0x4D00");
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_RIGHT:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(96);
event.handled = true;
break;
- case Common::KEYCODE_6:
- warning("FIXME: keycode = 0x4F00");
+ case Common::KEYCODE_KP1:
R2_GLOBALS._sound2.play(338);
sub107F71(0);
event.handled = true;
break;
- case Common::KEYCODE_7:
- warning("FIXME: keycode = 0x5000");
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_DOWN:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(104);
event.handled = true;
break;
- case Common::KEYCODE_8:
- warning("FIXME: keycode = 0x5100");
+ case Common::KEYCODE_KP3:
if (_field1270 != 0)
R2_GLOBALS._sound2.play(338);
sub107F71(-1);
event.handled = true;
break;
- case Common::KEYCODE_9:
- warning("FIXME: keycode = 0x5200");
+ case Common::KEYCODE_KP0:
R2_GLOBALS._sound2.play(338);
sub107F71(8);
event.handled = true;
break;
- case Common::KEYCODE_0:
- warning("FIXME: keycode = 0x5300");
+ case Common::KEYCODE_KP_PERIOD:
R2_GLOBALS._sound2.play(338);
sub107F71(4);
event.handled = true;
@@ -3787,9 +3787,10 @@ void Scene3500::process(Event &event) {
void Scene3500::dispatch() {
Rect tmpRect;
Scene::dispatch();
+
if (((_actor1._frame % 2) == 0) && (_action1._field24 == 0)) {
_actor1.setFrame(_actor1.changeFrame());
- _field1276 = _actor1._frame;
+ _mazeDirection = _actor1._frame;
}
int oldField1278;
if ((_field1278 != 0) && (_action1._field24 == 0)) {
@@ -3801,90 +3802,90 @@ void Scene3500::dispatch() {
if (!_rotation)
return;
- int var_field127A = 0;
- int di = 0;
+ int newMazeX = 0;
+ int newMazeY = 0;
int var_4 = 0;
int var_6 = 0;
int var_8 = 0;
int var_a = 0;
int dx = 0;
- int tmpVar = 0;
+ int cellId = 0;
- if ((_field126E == 0) && (_field1282 == 0)) {
+ if ((_mazeChangeAmount == 0) && (_field1282 == 0)) {
if (_field1284 == 2)
R2_GLOBALS._sceneManager.changeScene(1000);
} else {
_field1282 = 0;
tmpRect.set(160, 89, 299, 182);
- var_field127A = _field127A;
- di = _field127C;
- var_4 = _unkObj1.sub1097C9(70) - 70;
- var_6 = _unkObj1.sub1097EF(_field127C + 46) - 46;
- var_8 = abs(var_4 - var_field127A);
- var_a = abs(var_6 - di);
+ newMazeX = _mazePosition.x;
+ newMazeY = _mazePosition.y;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_6 = _mazeUI.cellFromY(_mazePosition.y + 46) - 46;
+ var_8 = abs(var_4 - newMazeX);
+ var_a = abs(var_6 - newMazeY);
dx = 0;
- switch (_field1276) {
- case 0:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, 46));
- if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1))
- || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) {
+ switch (_mazeDirection) {
+ case MAZEDIR_NORTH:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1)) ||
+ ((cellId == 25 || cellId == 26 || cellId == 5 || cellId == 14 || cellId == 15) && var_8 > 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- di = _field127C - _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (tmpVar != dx)) {
- di = var_6;
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y - _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (cellId != dx)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 11) && (tmpVar != dx)) {
- di = var_6 + 3;
+ } else if ((cellId == 11) && (cellId != dx)) {
+ newMazeY = var_6 + 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- var_a = abs(var_6 - di);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
-
- if ( (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (di <= var_6) && (_field127C>= var_6))
- || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E > 3) && (_action1._field24 != 0)) ) {
- di = var_6;
- if ((tmpVar != 25) && (tmpVar != 26) && (tmpVar != 5) && (tmpVar != 14) && (tmpVar == 15))
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ var_a = abs(var_6 - newMazeY);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= var_6) && (_mazePosition.y>= var_6))
+ || (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount > 3) && (_action1._field24 != 0)) ) {
+ newMazeY = var_6;
+ if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 11) && (var_6 + 3 >= di) && (_field127C >= var_6 + 3)) {
+ } else if ((cellId == 11) && (var_6 + 3 >= newMazeY) && (_mazePosition.y >= var_6 + 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) {
- var_field127A = var_4;
+ } else if (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3892,65 +3893,65 @@ void Scene3500::dispatch() {
}
}
break;
- case 2:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31))
- || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) {
+ case MAZEDIR_EAST:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31))
+ || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_field127A = _field127A + _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (tmpVar != dx)) {
- var_field127A = var_4;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x + _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (cellId != dx)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 6) && (tmpVar != dx)) {
- var_field127A = var_4 - 5;
+ } else if ((cellId == 6) && (cellId != dx)) {
+ newMazeX = var_4 - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_8 = abs(var_field127A - var_4);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, tmpVar + 46));
- if ( (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (var_field127A >= var_4) && (_field127A <= var_4))
- || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) {
- var_field127A = var_4;
- if ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4))
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_8 = abs(newMazeX - var_4);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (newMazeX >= var_4) && (_mazePosition.x <= var_4))
+ || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) {
+ newMazeX = var_4;
+ if ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 6) && (var_4 - 5 <= var_field127A) && (_field127A <= var_4 - 5)) {
- var_field127A = var_4 - 5;
+ } else if ((cellId == 6) && (var_4 - 5 <= newMazeX) && (_mazePosition.x <= var_4 - 5)) {
+ newMazeX = var_4 - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) {
- di = var_6;
+ } else if (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3958,84 +3959,87 @@ void Scene3500::dispatch() {
}
}
break;
- case 4:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1))
- || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) {
+ case MAZEDIR_SOUTH:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1))
+ || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- di = _field127C + _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (tmpVar == dx)) {
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y + _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (cellId != dx)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 16) && (tmpVar == dx)) {
- di = var_6 - 3;
+ } else if ((cellId == 16) && (cellId != dx)) {
+ newMazeY = var_6 - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 31) && (tmpVar == dx)) {
- di = var_6 + 4;
+ } else if ((cellId == 31) && (cellId != dx)) {
+ newMazeY = var_6 + 4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- var_a = abs(di - var_6);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (di >= var_6) && (_field127C <= var_6))
- || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E <= 3) && (_action1._field24 != 0)) ){
- if ((tmpVar != 23) && (tmpVar != 24) && (tmpVar != 4) && (tmpVar != 14) && (tmpVar != 15))
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ var_a = abs(newMazeY - var_6);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (newMazeY >= var_6) && (_mazePosition.y <= var_6))
+ || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ){
+ newMazeY = var_6;
+
+ if ((cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 14) && (cellId != 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 16) && (var_6 - 3 <= di) && (_field127C <= var_6 - 3)) {
- di = var_6 - 3;
+ } else if ((cellId == 16) && (var_6 - 3 <= newMazeY) && (_mazePosition.y <= var_6 - 3)) {
+ newMazeY = var_6 - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 31) && (var_6 + 4 <= di) && (_field127C <= var_6 + 4)) {
- di = var_6 + 4;
+ } else if ((cellId == 31) && (var_6 + 4 <= newMazeY) && (_mazePosition.y <= var_6 + 4)) {
+ newMazeY = var_6 + 4;
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- if ((var_field127A == 660) && (_field126E + 306 <= di) && (di <= 307))
+ if ((newMazeX == 660) && (_mazeChangeAmount + 306 <= newMazeY) && (newMazeY <= 307))
++_field1284;
else
R2_GLOBALS._sound2.play(339);
- } else if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) {
- var_field127A = var_4;
+ } else if (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4043,65 +4047,65 @@ void Scene3500::dispatch() {
}
}
break;
- case 6:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31))
- || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) {
+ case MAZEDIR_WEST:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31))
+ || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_field127A = _field127A - _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (tmpVar != dx)) {
- var_field127A = var_4;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x - _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (cellId != dx)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 1) && (tmpVar != dx)) {
- var_field127A = var_4 + 5;
+ } else if ((cellId == 1) && (cellId != dx)) {
+ newMazeX = var_4 + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_8 = abs(var_4 - var_field127A);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (var_field127A <= var_4) && (_field127A >= var_4))
- || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) {
- var_field127A = var_4;
- if ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4))
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_8 = abs(var_4 - newMazeX);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (newMazeX <= var_4) && (_mazePosition.x >= var_4))
+ || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) {
+ newMazeX = var_4;
+ if ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 1) && (var_field127A >= var_4 + 5) && (_field127A >= var_4 + 5)) {
- var_field127A = var_4 + 5;
+ } else if ((cellId == 1) && (newMazeX >= var_4 + 5) && (_mazePosition.x >= var_4 + 5)) {
+ newMazeX = var_4 + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) {
- di = var_6;
+ } else if (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4114,49 +4118,49 @@ void Scene3500::dispatch() {
}
if (_field1284 < 2) {
- _field127A = var_field127A;
- _field127C = di;
- if (_unkObj1.sub109C5E(_field127A, _field127C) != 0) {
+ _mazePosition.x = newMazeX;
+ _mazePosition.y = newMazeY;
+ if (_mazeUI.setMazePosition2(_mazePosition) != 0) {
_field1272 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1270 = 0;
_rotation->setDelay(0);
_rotation->_idxChange = 0;
}
- warning("gfx_set_pane_p");
- _unkObj1.sub51B02();
+
+ _mazeUI.draw();
if (_field1284 != 0)
++_field1284;
}
}
if (_field1272 == 0) {
- if (_field126E != _field1270) {
- if (_field126E >= _field1270) {
- if (_field126E == 1) {
+ if (_mazeChangeAmount != _field1270) {
+ if (_mazeChangeAmount >= _field1270) {
+ if (_mazeChangeAmount == 1) {
if (_action1._field24 != 0) {
- if ( ((_field1276 == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)))
- || ((_field1276 == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)))
- || ((_field1276 == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)))
- || ((_field1276 == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4))) ){
- _field126E = 1;
+ if ( ((_mazeDirection == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)))
+ || ((_mazeDirection == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))) ){
+ _mazeChangeAmount = 1;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- ++_field126E;
+ ++_mazeChangeAmount;
_field1272 = 1;
}
- _actor2.setFrame2(_field126E);
+ _actor2.setFrame2(_mazeChangeAmount + 1);
}
if (_field1272 == 1) {
- if (_field126E == 0)
+ if (_mazeChangeAmount == 0)
_rotation->_idxChange = 0;
- else if (_field126E > 8)
+ else if (_mazeChangeAmount > 8)
_rotation->_idxChange = 2;
else
_rotation->_idxChange = 1;
@@ -4165,9 +4169,9 @@ void Scene3500::dispatch() {
if (_field1272 != 0)
_field1272--;
- if (_field126E != 0) {
- R2_GLOBALS._player._uiEnabled = false;
- if (_field126E != _field1270)
+ if (_mazeChangeAmount != 0) {
+ R2_GLOBALS._player._uiEnabled = false;
+ if (_mazeChangeAmount != _field1270)
_aSound1.play(276);
} else {
R2_GLOBALS._player._uiEnabled = true;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.h b/engines/tsage/ringworld2/ringworld2_scenes3.h
index 44787b9eef..85e5674433 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.h
@@ -633,12 +633,12 @@ class Scene3500 : public SceneExt {
// TODO: double check if nothing specific is present, then remove this class
};
- class UnkObject3500 : public UnkObject1200 {
+ class MazeUI3500 : public MazeUI {
public:
- int sub1097C9(int arg1);
- int sub1097EF(int arg1);
- int sub109C09(Common::Point pt);
- int sub109C5E(int &x, int &y);
+ int cellFromX(int arg1);
+ int cellFromY(int arg1);
+ int getCellFromMapXY(Common::Point pt);
+ bool setMazePosition2(Common::Point &p);
};
public:
Action1 _action1;
@@ -650,6 +650,7 @@ public:
Item4 _item5;
Item4 _item6;
Item4 _item7;
+ // Glyph of vessel on top of the maze ui
SceneActor _actor1;
SceneActor _actor2;
SceneActor _actor3;
@@ -660,20 +661,19 @@ public:
Actor8 _actor8;
Actor8 _actor9;
ASoundExt _aSound1;
- UnkObject3500 _unkObj1;
+ MazeUI3500 _mazeUI;
SequenceManager _sequenceManager;
int _fieldAF8;
int _fieldB9E;
PaletteRotation *_rotation;
- int _field126E;
+ int _mazeChangeAmount;
int _field1270;
int _field1272;
int _field1274;
- int _field1276;
+ int _mazeDirection;
int _field1278;
- int _field127A;
- int _field127C;
+ Common::Point _mazePosition;
int _field127E;
int _field1280;
int _field1282;
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index ad4256e6b9..09426c9307 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -324,6 +324,17 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DEMO,
GUIO0()
},
+ // J.U.L.I.A. (English) (Greenlight Demo)
+ {
+ "julia",
+ "Greenlight Demo",
+ AD_ENTRY1s("data.dcp", "4befd448d36b0dae9c3ab1aa7cb8b78d", 7271886),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
// Mirage
{
"mirage",
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 89a6f1b3e0..19848b002e 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -26,7 +26,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/tokenizer.h"
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index c818101645..6825767dfd 100644
--- a/graphics/cursorman.cpp
+++ b/graphics/cursorman.cpp
@@ -48,6 +48,9 @@ bool CursorManager::isVisible() {
bool CursorManager::showMouse(bool visible) {
if (_cursorStack.empty())
return false;
+ if (_locked) {
+ return false;
+ }
_cursorStack.top()->_visible = visible;
@@ -225,6 +228,10 @@ void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint nu
}
}
+void CursorManager::lock(bool locked) {
+ _locked = locked;
+}
+
CursorManager::Cursor::Cursor(const void *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
#ifdef USE_RGB_COLOR
if (!format)
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index 66e8d1ba56..b4d8ad94ce 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -160,12 +160,15 @@ public:
*/
void replaceCursorPalette(const byte *colors, uint start, uint num);
+ void lock(bool locked);
private:
friend class Common::Singleton<SingletonBaseType>;
// Even though this is basically the default constructor we implement it
// ourselves, so it is private and thus there is no way to create this class
// except from the Singleton code.
- CursorManager() {}
+ CursorManager() {
+ _locked = false;
+ }
~CursorManager();
struct Cursor {
@@ -198,6 +201,7 @@ private:
};
Common::Stack<Cursor *> _cursorStack;
Common::Stack<Palette *> _cursorPaletteStack;
+ bool _locked;
};
} // End of namespace Graphics
diff --git a/graphics/scaler.h b/graphics/scaler.h
index 1e5b796631..54d022d202 100644
--- a/graphics/scaler.h
+++ b/graphics/scaler.h
@@ -89,4 +89,10 @@ extern bool createThumbnailFromScreen(Graphics::Surface *surf);
*/
extern bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette);
+/**
+ * Downscale screenshot to thumbnale size.
+ *
+ */
+extern bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in);
+
#endif
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index 88f3cc2077..8a98263eee 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -134,7 +134,7 @@ static bool grabScreen565(Graphics::Surface *surf) {
return true;
}
-static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
+bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
uint16 width = in.w;
uint16 inHeight = in.h;
@@ -206,7 +206,7 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
return true;
}
-bool createThumbnailFromScreen(Graphics::Surface* surf) {
+bool createThumbnailFromScreen(Graphics::Surface *surf) {
assert(surf);
Graphics::Surface screen;
@@ -236,3 +236,31 @@ bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h,
return createThumbnail(*surf, screen);
}
+
+// this is somewhat awkward, but createScreenShot should logically be in graphics,
+// but moving other functions in this file into that namespace breaks several engines
+namespace Graphics {
+bool createScreenShot(Graphics::Surface &surf) {
+ Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
+ //convert surface to 2 bytes pixel format to avoid problems with palette saving and loading
+ if ((screenFormat.bytesPerPixel == 1) || (screenFormat.bytesPerPixel == 2)) {
+ return grabScreen565(&surf);
+ } else {
+ Graphics::Surface *screen = g_system->lockScreen();
+ if (!screen) {
+ return false;
+ }
+ surf.create(screen->w, screen->h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+ for (uint y = 0; y < screen->h; ++y) {
+ for (uint x = 0; x < screen->w; ++x) {
+ byte r = 0, g = 0, b = 0, a = 0;
+ uint32 col = READ_UINT32(screen->getBasePtr(x, y));
+ screenFormat.colorToARGB(col, a, r, g, b);
+ ((uint32 *)surf.pixels)[y * surf.w + x] = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b);
+ }
+ }
+ g_system->unlockScreen();
+ return true;
+ }
+}
+} // End of namespace Graphics
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index ddb377306d..d04c218624 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -23,6 +23,7 @@
#include "graphics/scaler.h"
#include "graphics/colormasks.h"
#include "common/endian.h"
+#include "common/algorithm.h"
#include "common/system.h"
#include "common/stream.h"
#include "common/textconsole.h"
@@ -143,7 +144,6 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
assert(0);
}
}
-
return to;
}
@@ -216,4 +216,55 @@ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) {
return true;
}
+
+/**
+ * Returns an array indicating which pixels of a source image horizontally or vertically get
+ * included in a scaled image
+ */
+int *scaleLine(int size, int srcSize) {
+ int scale = 100 * size / srcSize;
+ assert(scale > 0);
+ int *v = new int[size];
+ Common::fill(v, &v[size], 0);
+
+ int distCtr = 0;
+ int *destP = v;
+ for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
+ distCtr += scale;
+ while (distCtr >= 100) {
+ assert(destP < &v[size]);
+ *destP++ = distIndex;
+ distCtr -= 100;
+ }
+ }
+
+ return v;
+}
+
+Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
+ Graphics::Surface *s = new Graphics::Surface();
+ s->create(xSize, ySize, srcImage.format);
+
+ int *horizUsage = scaleLine(xSize, srcImage.w);
+ int *vertUsage = scaleLine(ySize, srcImage.h);
+
+ // Loop to create scaled version
+ for (int yp = 0; yp < ySize; ++yp) {
+ const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]);
+ byte *destP = (byte *)s->getBasePtr(0, yp);
+
+ for (int xp = 0; xp < xSize; ++xp) {
+ const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel);
+ for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) {
+ *destP++ = *tempSrcP++;
+ }
+ }
+ }
+
+ // Delete arrays and return surface
+ delete[] horizUsage;
+ delete[] vertUsage;
+ return s;
+}
+
} // End of namespace Graphics
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
index 45a0fdbf07..c857809c91 100644
--- a/graphics/thumbnail.h
+++ b/graphics/thumbnail.h
@@ -64,6 +64,24 @@ bool saveThumbnail(Common::WriteStream &out);
*/
bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb);
+/**
+ * Grabs framebuffer into surface
+ *
+ * @param surf a surface
+ * @return false if a error occurred
+ */
+bool createScreenShot(Graphics::Surface &surf);
+
+/**
+ * Scales a passed surface, creating a new surface with the result
+ * @param srcImage Source image to scale
+ * @param xSize New surface width
+ * @param ySize New surface height
+ * @remarks Caller is responsible for freeing the returned surface
+ */
+Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
+
+
} // End of namespace Graphics
#endif
diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h
index f785422c5a..a1e61ec705 100644
--- a/graphics/yuv_to_rgb.h
+++ b/graphics/yuv_to_rgb.h
@@ -22,10 +22,17 @@
/**
* @file
- * YUV to RGB conversion used in engines:
- * - mohawk
- * - scumm (he)
- * - sword25
+ * YUV to RGB conversion.
+ *
+ * Used in graphics:
+ * - JPEGDecoder
+ *
+ * Used in video:
+ * - BinkDecoder
+ * - Indeo3Decoder
+ * - PSXStreamDecoder
+ * - TheoraDecoder
+ * - SVQ1Decoder
*/
#ifndef GRAPHICS_YUV_TO_RGB_H
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
new file mode 100644
index 0000000000..47358a0b3d
--- /dev/null
+++ b/gui/EventRecorder.cpp
@@ -0,0 +1,665 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "gui/EventRecorder.h"
+
+namespace Common {
+DECLARE_SINGLETON(GUI::EventRecorder);
+}
+
+#ifdef ENABLE_EVENTRECORDER
+
+#include "common/debug-channels.h"
+#include "backends/timer/sdl/sdl-timer.h"
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/config-manager.h"
+#include "common/md5.h"
+#include "gui/gui-manager.h"
+#include "gui/widget.h"
+#include "gui/onscreendialog.h"
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/textconsole.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/scaler.h"
+
+namespace GUI {
+
+
+const int kMaxRecordsNames = 0x64;
+const int kDefaultScreenshotPeriod = 60000;
+const int kDefaultBPP = 2;
+
+uint32 readTime(Common::ReadStream *inFile) {
+ uint32 d = inFile->readByte();
+ if (d == 0xff) {
+ d = inFile->readUint32LE();
+ }
+
+ return d;
+}
+
+void writeTime(Common::WriteStream *outFile, uint32 d) {
+ //Simple RLE compression
+ if (d >= 0xff) {
+ outFile->writeByte(0xff);
+ outFile->writeUint32LE(d);
+ } else {
+ outFile->writeByte(d);
+ }
+}
+
+EventRecorder::EventRecorder() {
+ _timerManager = NULL;
+ _recordMode = kPassthrough;
+ _fakeMixerManager = NULL;
+ _initialized = false;
+ _needRedraw = false;
+ _fastPlayback = false;
+ DebugMan.addDebugChannel(kDebugLevelEventRec, "EventRec", "Event recorder debug level");
+}
+
+EventRecorder::~EventRecorder() {
+ if (_timerManager != NULL) {
+ delete _timerManager;
+ }
+}
+
+void EventRecorder::deinit() {
+ if (!_initialized) {
+ return;
+ }
+ setFileHeader();
+ _needRedraw = false;
+ _initialized = false;
+ _recordMode = kPassthrough;
+ delete _fakeMixerManager;
+ _fakeMixerManager = NULL;
+ controlPanel->close();
+ delete controlPanel;
+ debugC(1, kDebugLevelEventRec, "playback:action=stopplayback");
+ g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
+ _recordMode = kPassthrough;
+ _playbackFile->close();
+ delete _playbackFile;
+ switchMixer();
+ switchTimerManagers();
+ DebugMan.disableDebugChannel("EventRec");
+}
+
+void EventRecorder::processMillis(uint32 &millis, bool skipRecord) {
+ if (!_initialized) {
+ return;
+ }
+ if (skipRecord) {
+ millis = _fakeTimer;
+ return;
+ }
+ if (_recordMode == kRecorderPlaybackPause) {
+ millis = _fakeTimer;
+ }
+ uint32 millisDelay;
+ Common::RecorderEvent timerEvent;
+ switch (_recordMode) {
+ case kRecorderRecord:
+ updateSubsystems();
+ millisDelay = millis - _lastMillis;
+ _lastMillis = millis;
+ _fakeTimer += millisDelay;
+ controlPanel->setReplayedTime(_fakeTimer);
+ timerEvent.recordedtype = Common::kRecorderEventTypeTimer;
+ timerEvent.time = _fakeTimer;
+ _playbackFile->writeEvent(timerEvent);
+ takeScreenshot();
+ _timerManager->handler();
+ break;
+ case kRecorderPlayback:
+ updateSubsystems();
+ if (_nextEvent.recordedtype == Common::kRecorderEventTypeTimer) {
+ _fakeTimer = _nextEvent.time;
+ _nextEvent = _playbackFile->getNextEvent();
+ _timerManager->handler();
+ } else {
+ if (_nextEvent.type == Common::EVENT_RTL) {
+ error("playback:action=stopplayback");
+ } else {
+ uint32 seconds = _fakeTimer / 1000;
+ Common::String screenTime = Common::String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60);
+ error("playback:action=error reason=\"synchronization error\" time = %s", screenTime.c_str());
+ }
+ }
+ millis = _fakeTimer;
+ controlPanel->setReplayedTime(_fakeTimer);
+ break;
+ case kRecorderPlaybackPause:
+ millis = _fakeTimer;
+ break;
+ default:
+ break;
+ }
+}
+
+bool EventRecorder::processDelayMillis() {
+ return _fastPlayback;
+}
+
+void EventRecorder::checkForKeyCode(const Common::Event &event) {
+ if ((event.type == Common::EVENT_KEYDOWN) && (event.kbd.flags & Common::KBD_CTRL) && (event.kbd.keycode == Common::KEYCODE_p) && (!event.synthetic)) {
+ togglePause();
+ }
+}
+
+bool EventRecorder::pollEvent(Common::Event &ev) {
+ if ((_recordMode != kRecorderPlayback) || !_initialized)
+ return false;
+
+ if ((_nextEvent.recordedtype == Common::kRecorderEventTypeTimer) || (_nextEvent.type == Common::EVENT_INVALID)) {
+ return false;
+ }
+
+ switch (_nextEvent.type) {
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_WHEELUP:
+ case Common::EVENT_WHEELDOWN:
+ g_system->warpMouse(_nextEvent.mouse.x, _nextEvent.mouse.y);
+ break;
+ default:
+ break;
+ }
+ ev = _nextEvent;
+ _nextEvent = _playbackFile->getNextEvent();
+ return true;
+}
+
+void EventRecorder::switchFastMode() {
+ if (_recordMode == kRecorderPlaybackPause) {
+ _fastPlayback = !_fastPlayback;
+ }
+}
+
+void EventRecorder::togglePause() {
+ RecordMode oldState;
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ case kRecorderRecord:
+ oldState = _recordMode;
+ _recordMode = kRecorderPlaybackPause;
+ controlPanel->runModal();
+ _recordMode = oldState;
+ _initialized = true;
+ break;
+ case kRecorderPlaybackPause:
+ controlPanel->close();
+ break;
+ default:
+ break;
+ }
+}
+
+void EventRecorder::RegisterEventSource() {
+ g_system->getEventManager()->getEventDispatcher()->registerMapper(this, false);
+}
+
+uint32 EventRecorder::getRandomSeed(const Common::String &name) {
+ uint32 result = g_system->getMillis();
+ if (_recordMode == kRecorderRecord) {
+ _playbackFile->getHeader().randomSourceRecords[name] = result;
+ } else if (_recordMode == kRecorderPlayback) {
+ result = _playbackFile->getHeader().randomSourceRecords[name];
+ }
+ return result;
+}
+
+Common::String EventRecorder::generateRecordFileName(const Common::String &target) {
+ Common::String pattern(target+".r??");
+ Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern);
+ for (int i = 0; i < kMaxRecordsNames; ++i) {
+ Common::String recordName = Common::String::format("%s.r%02d", target.c_str(), i);
+ if (find(files.begin(), files.end(), recordName) != files.end()) {
+ continue;
+ }
+ return recordName;
+ }
+ return "";
+}
+
+
+void EventRecorder::init(Common::String recordFileName, RecordMode mode) {
+ _fakeMixerManager = new NullSdlMixerManager();
+ _fakeMixerManager->init();
+ _fakeMixerManager->suspendAudio();
+ _fakeTimer = 0;
+ _lastMillis = g_system->getMillis();
+ _playbackFile = new Common::PlaybackFile();
+ _lastScreenshotTime = 0;
+ _recordMode = mode;
+ _needcontinueGame = false;
+ if (ConfMan.hasKey("disable_display")) {
+ DebugMan.enableDebugChannel("EventRec");
+ gDebugLevel = 1;
+ }
+ if (_recordMode == kRecorderPlayback) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load file\" filename=%s", recordFileName.c_str());
+ }
+ g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
+ _screenshotPeriod = ConfMan.getInt("screenshot_period");
+ if (_screenshotPeriod == 0) {
+ _screenshotPeriod = kDefaultScreenshotPeriod;
+ }
+ if (!openRecordFile(recordFileName)) {
+ deinit();
+ error("playback:action=error reason=\"Record file loading error\"");
+ return;
+ }
+ if (_recordMode != kPassthrough) {
+ controlPanel = new GUI::OnScreenDialog(_recordMode == kRecorderRecord);
+ }
+ if (_recordMode == kRecorderPlayback) {
+ applyPlaybackSettings();
+ _nextEvent = _playbackFile->getNextEvent();
+ }
+ if (_recordMode == kRecorderRecord) {
+ getConfig();
+ }
+
+ switchMixer();
+ switchTimerManagers();
+ _needRedraw = true;
+ _initialized = true;
+}
+
+
+/**
+ * Opens or creates file depend of recording mode.
+ *
+ *@param id of recording or playing back game
+ *@return true in case of success, false in case of error
+ *
+ */
+bool EventRecorder::openRecordFile(const Common::String &fileName) {
+ bool result;
+ switch (_recordMode) {
+ case kRecorderRecord:
+ return _playbackFile->openWrite(fileName);
+ case kRecorderPlayback:
+ _recordMode = kPassthrough;
+ result = _playbackFile->openRead(fileName);
+ _recordMode = kRecorderPlayback;
+ return result;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool EventRecorder::checkGameHash(const ADGameDescription *gameDesc) {
+ if ((gameDesc == NULL) && (_playbackFile->getHeader().hashRecords.size() != 0)) {
+ warning("Engine doesn't contain description table");
+ return false;
+ }
+ for (const ADGameFileDescription *fileDesc = gameDesc->filesDescriptions; fileDesc->fileName; fileDesc++) {
+ if (_playbackFile->getHeader().hashRecords.find(fileDesc->fileName) == _playbackFile->getHeader().hashRecords.end()) {
+ warning("MD5 hash for file %s not found in record file", fileDesc->fileName);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=\"\" result=different", fileDesc->fileName, fileDesc->md5);
+ return false;
+ }
+ if (_playbackFile->getHeader().hashRecords[fileDesc->fileName] != fileDesc->md5) {
+ warning("Incorrect version of game file %s. Stored MD5 is %s. MD5 of loaded game is %s", fileDesc->fileName, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str(), fileDesc->md5);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=%s result=different", fileDesc->fileName, fileDesc->md5, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str());
+ return false;
+ }
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=%s result=equal", fileDesc->fileName, fileDesc->md5, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str());
+ }
+ return true;
+}
+
+void EventRecorder::registerMixerManager(SdlMixerManager *mixerManager) {
+ _realMixerManager = mixerManager;
+}
+
+void EventRecorder::switchMixer() {
+ if (_recordMode == kPassthrough) {
+ _realMixerManager->resumeAudio();
+ } else {
+ _realMixerManager->suspendAudio();
+ _fakeMixerManager->resumeAudio();
+ }
+}
+
+SdlMixerManager *EventRecorder::getMixerManager() {
+ if (_recordMode == kPassthrough) {
+ return _realMixerManager;
+ } else {
+ return _fakeMixerManager;
+ }
+}
+
+void EventRecorder::getConfigFromDomain(Common::ConfigManager::Domain *domain) {
+ for (Common::ConfigManager::Domain::iterator entry = domain->begin(); entry!= domain->end(); ++entry) {
+ _playbackFile->getHeader().settingsRecords[entry->_key] = entry->_value;
+ }
+}
+
+void EventRecorder::getConfig() {
+ getConfigFromDomain(ConfMan.getDomain(ConfMan.kApplicationDomain));
+ getConfigFromDomain(ConfMan.getActiveDomain());
+ _playbackFile->getHeader().settingsRecords["save_slot"] = ConfMan.get("save_slot");
+}
+
+
+void EventRecorder::applyPlaybackSettings() {
+ for (Common::StringMap::iterator i = _playbackFile->getHeader().settingsRecords.begin(); i != _playbackFile->getHeader().settingsRecords.end(); ++i) {
+ Common::String currentValue = ConfMan.get(i->_key);
+ if (currentValue != i->_value) {
+ ConfMan.set(i->_key, i->_value, ConfMan.kTransientDomain);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" key=%s storedvalue=%s currentvalue=%s result=different", i->_key.c_str(), i->_value.c_str(), currentValue.c_str());
+ } else {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" key=%s storedvalue=%s currentvalue=%s result=equal", i->_key.c_str(), i->_value.c_str(), currentValue.c_str());
+ }
+ }
+ removeDifferentEntriesInDomain(ConfMan.getDomain(ConfMan.kApplicationDomain));
+ removeDifferentEntriesInDomain(ConfMan.getActiveDomain());
+}
+
+void EventRecorder::removeDifferentEntriesInDomain(Common::ConfigManager::Domain *domain) {
+ for (Common::ConfigManager::Domain::iterator entry = domain->begin(); entry!= domain->end(); ++entry) {
+ if (_playbackFile->getHeader().settingsRecords.find(entry->_key) == _playbackFile->getHeader().settingsRecords.end()) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" checksettings:key=%s storedvalue=%s currentvalue="" result=different", entry->_key.c_str(), entry->_value.c_str());
+ domain->erase(entry->_key);
+ }
+ }
+}
+
+DefaultTimerManager *EventRecorder::getTimerManager() {
+ return _timerManager;
+}
+
+void EventRecorder::registerTimerManager(DefaultTimerManager *timerManager) {
+ _timerManager = timerManager;
+}
+
+void EventRecorder::switchTimerManagers() {
+ delete _timerManager;
+ if (_recordMode == kPassthrough) {
+ _timerManager = new SdlTimerManager();
+ } else {
+ _timerManager = new DefaultTimerManager();
+ }
+}
+
+void EventRecorder::updateSubsystems() {
+ if (_recordMode == kPassthrough) {
+ return;
+ }
+ RecordMode oldRecordMode = _recordMode;
+ _recordMode = kPassthrough;
+ _fakeMixerManager->update();
+ _recordMode = oldRecordMode;
+}
+
+Common::List<Common::Event> EventRecorder::mapEvent(const Common::Event &ev, Common::EventSource *source) {
+ if ((!_initialized) && (_recordMode != kRecorderPlaybackPause)) {
+ return DefaultEventMapper::mapEvent(ev, source);
+ }
+
+ checkForKeyCode(ev);
+ Common::Event evt = ev;
+ evt.mouse.x = evt.mouse.x * (g_system->getOverlayWidth() / g_system->getWidth());
+ evt.mouse.y = evt.mouse.y * (g_system->getOverlayHeight() / g_system->getHeight());
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ if (ev.synthetic != true) {
+ return Common::List<Common::Event>();
+ }
+ return Common::DefaultEventMapper::mapEvent(ev, source);
+ break;
+ case kRecorderRecord:
+ g_gui.processEvent(evt, controlPanel);
+ if (((evt.type == Common::EVENT_LBUTTONDOWN) || (evt.type == Common::EVENT_LBUTTONUP) || (evt.type == Common::EVENT_MOUSEMOVE)) && controlPanel->isMouseOver()) {
+ return Common::List<Common::Event>();
+ } else {
+ Common::RecorderEvent e;
+ memcpy(&e, &ev, sizeof(ev));
+ e.recordedtype = Common::kRecorderEventTypeNormal;
+ e.time = _fakeTimer;
+ _playbackFile->writeEvent(e);
+ return DefaultEventMapper::mapEvent(ev, source);
+ }
+ break;
+ case kRecorderPlaybackPause: {
+ Common::Event dialogEvent;
+ if (controlPanel->isEditDlgVisible()) {
+ dialogEvent = ev;
+ } else {
+ dialogEvent = evt;
+ }
+ g_gui.processEvent(dialogEvent, controlPanel->getActiveDlg());
+ if (((dialogEvent.type == Common::EVENT_LBUTTONDOWN) || (dialogEvent.type == Common::EVENT_LBUTTONUP) || (dialogEvent.type == Common::EVENT_MOUSEMOVE)) && controlPanel->isMouseOver()) {
+ return Common::List<Common::Event>();
+ }
+ return Common::DefaultEventMapper::mapEvent(dialogEvent, source);
+ }
+ break;
+ default:
+ return Common::DefaultEventMapper::mapEvent(ev, source);
+ }
+}
+
+void EventRecorder::setGameMd5(const ADGameDescription *gameDesc) {
+ for (const ADGameFileDescription *fileDesc = gameDesc->filesDescriptions; fileDesc->fileName; fileDesc++) {
+ if (fileDesc->md5 != NULL) {
+ _playbackFile->getHeader().hashRecords[fileDesc->fileName] = fileDesc->md5;
+ }
+ }
+}
+
+void EventRecorder::processGameDescription(const ADGameDescription *desc) {
+ if (_recordMode == kRecorderRecord) {
+ setGameMd5(desc);
+ }
+ if ((_recordMode == kRecorderPlayback) && !checkGameHash(desc)) {
+ deinit();
+ error("playback:action=error reason=\"\"");
+ }
+}
+
+void EventRecorder::deleteRecord(const Common::String& fileName) {
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+void EventRecorder::takeScreenshot() {
+ if ((_fakeTimer - _lastScreenshotTime) > _screenshotPeriod) {
+ Graphics::Surface screen;
+ uint8 md5[16];
+ if (grabScreenAndComputeMD5(screen, md5)) {
+ _lastScreenshotTime = _fakeTimer;
+ _playbackFile->saveScreenShot(screen, md5);
+ screen.free();
+ }
+ }
+}
+
+bool EventRecorder::grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]) {
+ if (!createScreenShot(screen)) {
+ warning("Can't save screenshot");
+ return false;
+ }
+ Common::MemoryReadStream bitmapStream((const byte*)screen.pixels, screen.w * screen.h * screen.format.bytesPerPixel);
+ computeStreamMD5(bitmapStream, md5);
+ return true;
+}
+
+Common::SeekableReadStream *EventRecorder::processSaveStream(const Common::String &fileName) {
+ Common::InSaveFile *saveFile;
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Process save file\" filename=%s len=%d", fileName.c_str(), _playbackFile->getHeader().saveFiles[fileName].size);
+ return new Common::MemoryReadStream(_playbackFile->getHeader().saveFiles[fileName].buffer, _playbackFile->getHeader().saveFiles[fileName].size);
+ case kRecorderRecord:
+ saveFile = _realSaveManager->openForLoading(fileName);
+ if (saveFile != NULL) {
+ _playbackFile->addSaveFile(fileName, saveFile);
+ saveFile->seek(0);
+ }
+ return saveFile;
+ default:
+ return NULL;
+ break;
+ }
+}
+
+Common::SaveFileManager *EventRecorder::getSaveManager(Common::SaveFileManager *realSaveManager) {
+ _realSaveManager = realSaveManager;
+ if (_recordMode != kPassthrough) {
+ return &_fakeSaveManager;
+ } else {
+ return realSaveManager;
+ }
+}
+
+void EventRecorder::preDrawOverlayGui() {
+ if ((_initialized) || (_needRedraw)) {
+ RecordMode oldMode = _recordMode;
+ _recordMode = kPassthrough;
+ g_system->showOverlay();
+ g_gui.theme()->clearAll();
+ g_gui.theme()->openDialog(true, GUI::ThemeEngine::kShadingNone);
+ controlPanel->drawDialog();
+ g_gui.theme()->finishBuffering();
+ g_gui.theme()->updateScreen();
+ _recordMode = oldMode;
+ }
+}
+
+void EventRecorder::postDrawOverlayGui() {
+ if ((_initialized) || (_needRedraw)) {
+ RecordMode oldMode = _recordMode;
+ _recordMode = kPassthrough;
+ g_system->hideOverlay();
+ _recordMode = oldMode;
+ }
+}
+
+Common::StringArray EventRecorder::listSaveFiles(const Common::String &pattern) {
+ if (_recordMode == kRecorderPlayback) {
+ Common::StringArray result;
+ for (Common::HashMap<Common::String, Common::PlaybackFile::SaveFileBuffer>::iterator i = _playbackFile->getHeader().saveFiles.begin(); i != _playbackFile->getHeader().saveFiles.end(); ++i) {
+ if (i->_key.matchString(pattern, false, true)) {
+ result.push_back(i->_key);
+ }
+ }
+ return result;
+ } else {
+ return _realSaveManager->listSavefiles(pattern);
+ }
+}
+
+void EventRecorder::setFileHeader() {
+ if (_recordMode != kRecorderRecord) {
+ return;
+ }
+ TimeDate t;
+ const EnginePlugin *plugin = 0;
+ GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName(), &plugin);
+ g_system->getTimeAndDate(t);
+ if (_author.empty()) {
+ setAuthor("Unknown Author");
+ }
+ if (_name.empty()) {
+ g_eventRec.setName(Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description());
+ }
+ _playbackFile->getHeader().author = _author;
+ _playbackFile->getHeader().notes = _desc;
+ _playbackFile->getHeader().name = _name;
+}
+
+SDL_Surface *EventRecorder::getSurface(int width, int height) {
+ // Create a RGB565 surface of the requested dimensions.
+ return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16, 0xF800, 0x07E0, 0x001F, 0x0000);
+}
+
+bool EventRecorder::switchMode() {
+ const Common::String gameId = ConfMan.get("gameid");
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+ bool metaInfoSupport = (*plugin)->hasFeature(MetaEngine::kSavesSupportMetaInfo);
+ bool featuresSupport = metaInfoSupport &&
+ g_engine->canSaveGameStateCurrently() &&
+ (*plugin)->hasFeature(MetaEngine::kSupportsListSaves) &&
+ (*plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
+ if (!featuresSupport) {
+ return false;
+ }
+
+ int emptySlot = 1;
+ SaveStateList saveList = (*plugin)->listSaves(gameId.c_str());
+ for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
+ int saveSlot = x->getSaveSlot();
+ if (saveSlot == 0) {
+ continue;
+ }
+ if (emptySlot != saveSlot) {
+ break;
+ }
+ emptySlot++;
+ }
+ Common::String saveName;
+ if (emptySlot >= 0) {
+ saveName = Common::String::format("Save %d", emptySlot + 1);
+ Common::Error status = g_engine->saveGameState(emptySlot, saveName);
+ if (status.getCode() == Common::kNoError) {
+ Common::Event eventRTL;
+ eventRTL.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(eventRTL);
+ }
+ }
+ ConfMan.set("record_mode", "", Common::ConfigManager::kTransientDomain);
+ ConfMan.setInt("save_slot", emptySlot, Common::ConfigManager::kTransientDomain);
+ _needcontinueGame = true;
+ return true;
+}
+
+bool EventRecorder::checkForContinueGame() {
+ bool result = _needcontinueGame;
+ _needcontinueGame = false;
+ return result;
+}
+
+void EventRecorder::deleteTemporarySave() {
+ if (_temporarySlot == -1) return;
+ const Common::String gameId = ConfMan.get("gameid");
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+ (*plugin)->removeSaveState(gameId.c_str(), _temporarySlot);
+ _temporarySlot = -1;
+}
+
+} // End of namespace GUI
+
+#endif // ENABLE_EVENTRECORDER
+
diff --git a/gui/EventRecorder.h b/gui/EventRecorder.h
new file mode 100644
index 0000000000..3e32d89232
--- /dev/null
+++ b/gui/EventRecorder.h
@@ -0,0 +1,293 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_EVENTRECORDER_H
+#define GUI_EVENTRECORDER_H
+
+#include "common/system.h"
+
+#include "common/events.h"
+#include "common/savefile.h"
+#include "common/singleton.h"
+
+#include "engines/advancedDetector.h"
+
+#ifdef ENABLE_EVENTRECORDER
+
+#include "common/mutex.h"
+#include "common/array.h"
+#include "common/memstream.h"
+#include "backends/keymapper/keymapper.h"
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+#include "backends/timer/sdl/sdl-timer.h"
+#include "common/config-manager.h"
+#include "common/recorderfile.h"
+#include "backends/saves/recorder/recorder-saves.h"
+#include "backends/mixer/nullmixer/nullsdl-mixer.h"
+#include "backends/saves/default/default-saves.h"
+
+
+#define g_eventRec (GUI::EventRecorder::instance())
+
+namespace GUI {
+ class OnScreenDialog;
+}
+
+namespace GUI {
+class RandomSource;
+class SeekableReadStream;
+class WriteStream;
+
+
+/**
+ * Our generic event recorder.
+ *
+ * TODO: Add more documentation.
+ */
+class EventRecorder : private Common::EventSource, public Common::Singleton<EventRecorder>, private Common::DefaultEventMapper {
+ friend class Common::Singleton<SingletonBaseType>;
+ EventRecorder();
+ ~EventRecorder();
+public:
+ /** Specify operation mode of Event Recorder */
+ enum RecordMode {
+ kPassthrough = 0, /**< kPassthrough, do nothing */
+ kRecorderRecord = 1, /**< kRecorderRecord, do the recording */
+ kRecorderPlayback = 2, /**< kRecorderPlayback, playback existing recording */
+ kRecorderPlaybackPause = 3 /**< kRecordetPlaybackPause, interal state when user pauses the playback */
+ };
+
+ void init(Common::String recordFileName, RecordMode mode);
+ void deinit();
+ bool processDelayMillis();
+ uint32 getRandomSeed(const Common::String &name);
+ void processMillis(uint32 &millis, bool skipRecord);
+ bool processAudio(uint32 &samples, bool paused);
+ void processGameDescription(const ADGameDescription *desc);
+ Common::SeekableReadStream *processSaveStream(const Common::String & fileName);
+
+ /** Hooks for intercepting into GUI processing, so required events could be shoot
+ * or filtered out */
+ void preDrawOverlayGui();
+ void postDrawOverlayGui();
+
+ /** Set recording author
+ *
+ * @see getAuthor
+ */
+ void setAuthor(const Common::String &author) {
+ _author = author;
+ }
+
+ /** Set recording notes
+ *
+ * @see getNotes
+ */
+ void setNotes(const Common::String &desc){
+ _desc = desc;
+ }
+
+ /** Set descriptive name of the recording
+ *
+ * @see getName
+ */
+ void setName(const Common::String &name) {
+ _name = name;
+ }
+
+ /** Get recording author
+ *
+ * @see getAuthor
+ */
+ const Common::String getAuthor() {
+ return _author;
+ }
+
+ /** Get recording notes
+ *
+ * @see setNotes
+ */
+ const Common::String getNotes() {
+ return _desc;
+ }
+
+ /** Get recording name
+ *
+ * @see setName
+ */
+ const Common::String getName() {
+ return _name;
+ }
+ void setRedraw(bool redraw) {
+ _needRedraw = redraw;
+ }
+
+ void registerMixerManager(SdlMixerManager *mixerManager);
+ void registerTimerManager(DefaultTimerManager *timerManager);
+
+ SdlMixerManager *getMixerManager();
+ DefaultTimerManager *getTimerManager();
+
+ void deleteRecord(const Common::String& fileName);
+ bool checkForContinueGame();
+
+ void suspendRecording() {
+ _savedState = _initialized;
+ _initialized = false;
+ }
+
+ void resumeRecording() {
+ _initialized = _savedState;
+ }
+
+ Common::StringArray listSaveFiles(const Common::String &pattern);
+ Common::String generateRecordFileName(const Common::String &target);
+
+ Common::SaveFileManager *getSaveManager(Common::SaveFileManager *realSaveManager);
+ SDL_Surface *getSurface(int width, int height);
+ void RegisterEventSource();
+
+ /** Retrieve game screenshot and compute its checksum for comparison */
+ bool grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]);
+
+ void updateSubsystems();
+ bool switchMode();
+ void switchFastMode();
+
+private:
+ virtual Common::List<Common::Event> mapEvent(const Common::Event &ev, Common::EventSource *source);
+ bool notifyPoll();
+ bool pollEvent(Common::Event &ev);
+ bool _initialized;
+ volatile uint32 _fakeTimer;
+ bool _savedState;
+ bool _needcontinueGame;
+ int _temporarySlot;
+ Common::String _author;
+ Common::String _desc;
+ Common::String _name;
+
+ Common::SaveFileManager *_realSaveManager;
+ SdlMixerManager *_realMixerManager;
+ DefaultTimerManager *_timerManager;
+ RecorderSaveFileManager _fakeSaveManager;
+ NullSdlMixerManager *_fakeMixerManager;
+ GUI::OnScreenDialog *controlPanel;
+ Common::RecorderEvent _nextEvent;
+
+ void setFileHeader();
+ void setGameMd5(const ADGameDescription *gameDesc);
+ void getConfig();
+ void getConfigFromDomain(Common::ConfigManager::Domain *domain);
+ void removeDifferentEntriesInDomain(Common::ConfigManager::Domain *domain);
+ void applyPlaybackSettings();
+
+ void switchMixer();
+ void switchTimerManagers();
+
+ void togglePause();
+
+ void takeScreenshot();
+
+ bool openRecordFile(const Common::String &fileName);
+
+ bool checkGameHash(const ADGameDescription *desc);
+
+ void checkForKeyCode(const Common::Event &event);
+ bool allowMapping() const { return false; }
+
+ volatile uint32 _lastMillis;
+ uint32 _lastScreenshotTime;
+ uint32 _screenshotPeriod;
+ Common::PlaybackFile *_playbackFile;
+
+ void saveScreenShot();
+ void checkRecordedMD5();
+ void deleteTemporarySave();
+ volatile RecordMode _recordMode;
+ Common::String _recordFileName;
+ bool _fastPlayback;
+ bool _needRedraw;
+};
+
+} // End of namespace GUI
+
+#else
+
+#ifdef SDL_BACKEND
+#include "backends/timer/default/default-timer.h"
+#include "backends/mixer/sdl/sdl-mixer.h"
+#endif
+
+#define g_eventRec (GUI::EventRecorder::instance())
+
+namespace GUI {
+
+class EventRecorder : private Common::EventSource, public Common::Singleton<EventRecorder>, private Common::DefaultEventMapper {
+ friend class Common::Singleton<SingletonBaseType>;
+
+ public:
+ EventRecorder() {
+#ifdef SDL_BACKEND
+ _timerManager = NULL;
+ _realMixerManager = NULL;
+#endif
+ }
+ ~EventRecorder() {}
+
+ bool pollEvent(Common::Event &ev) { return false; }
+ void RegisterEventSource() {}
+ void deinit() {}
+ void suspendRecording() {}
+ void resumeRecording() {}
+ void preDrawOverlayGui() {}
+ void postDrawOverlayGui() {}
+ void processGameDescription(const ADGameDescription *desc) {}
+ void updateSubsystems() {}
+ uint32 getRandomSeed(const Common::String &name) { return g_system->getMillis(); }
+ Common::SaveFileManager *getSaveManager(Common::SaveFileManager *realSaveManager) { return realSaveManager; }
+
+#ifdef SDL_BACKEND
+ private:
+ DefaultTimerManager *_timerManager;
+ SdlMixerManager *_realMixerManager;
+
+ public:
+ DefaultTimerManager *getTimerManager() { return _timerManager; }
+ void registerTimerManager(DefaultTimerManager *timerManager) { _timerManager = timerManager; }
+
+ SdlMixerManager *getMixerManager() { return _realMixerManager; }
+ void registerMixerManager(SdlMixerManager *mixerManager) { _realMixerManager = mixerManager; }
+
+ void processMillis(uint32 &millis, bool skipRecord) {}
+ bool processDelayMillis() { return false; }
+#endif
+
+};
+
+} // namespace GUI
+
+#endif // ENABLE_EVENTRECORDER
+
+#endif
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index e2fa2580f5..3ce043cb39 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -50,6 +50,14 @@ const char * const ThemeEngine::kImageEraser = "eraser.bmp";
const char * const ThemeEngine::kImageDelbtn = "delbtn.bmp";
const char * const ThemeEngine::kImageList = "list.bmp";
const char * const ThemeEngine::kImageGrid = "grid.bmp";
+const char * const ThemeEngine::kImageStopbtn = "stopbtn.bmp";
+const char * const ThemeEngine::kImageEditbtn = "editbtn.bmp";
+const char * const ThemeEngine::kImageSwitchModebtn = "switchbtn.bmp";
+const char * const ThemeEngine::kImageFastReplaybtn = "fastreplay.bmp";
+const char * const ThemeEngine::kImageStopSmallbtn = "stopbtn_small.bmp";
+const char * const ThemeEngine::kImageEditSmallbtn = "editbtn_small.bmp";
+const char * const ThemeEngine::kImageSwitchModeSmallbtn = "switchbtn_small.bmp";
+const char * const ThemeEngine::kImageFastReplaySmallbtn = "fastreplay_small.bmp";
struct TextDrawData {
const Graphics::Font *_fontPtr;
@@ -465,11 +473,7 @@ void ThemeEngine::enable() {
if (_enabled)
return;
- if (_useCursor) {
- CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize);
- CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
- CursorMan.showMouse(true);
- }
+ showCursor();
_system->showOverlay();
clearAll();
@@ -482,10 +486,8 @@ void ThemeEngine::disable() {
_system->hideOverlay();
- if (_useCursor) {
- CursorMan.popCursorPalette();
- CursorMan.popCursor();
- }
+ hideCursor();
+
_enabled = false;
}
@@ -1787,5 +1789,20 @@ Common::String ThemeEngine::getThemeId(const Common::String &filename) {
}
}
+void ThemeEngine::showCursor() {
+ if (_useCursor) {
+ CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize);
+ CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
+ CursorMan.showMouse(true);
+ }
+}
+
+void ThemeEngine::hideCursor() {
+ if (_useCursor) {
+ CursorMan.popCursorPalette();
+ CursorMan.popCursor();
+ }
+}
+
} // End of namespace GUI.
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 6e5fd291b7..160ceb3259 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -234,6 +234,14 @@ public:
static const char *const kImageDelbtn; ///< Delete characters in the predictive dialog
static const char *const kImageList; ///< List image used in save/load chooser selection
static const char *const kImageGrid; ///< Grid image used in save/load chooser selection
+ static const char *const kImageStopbtn; ///< Stop recording button in recorder onscreen dialog
+ static const char *const kImageEditbtn; ///< Edit recording metadata in recorder onscreen dialog
+ static const char *const kImageSwitchModebtn; ///< Switch mode button in recorder onscreen dialog
+ static const char *const kImageFastReplaybtn; ///< Fast playback mode button in recorder onscreen dialog
+ static const char *const kImageStopSmallbtn; ///< Stop recording button in recorder onscreen dialog (for 320xY)
+ static const char *const kImageEditSmallbtn; ///< Edit recording metadata in recorder onscreen dialog (for 320xY)
+ static const char *const kImageSwitchModeSmallbtn; ///< Switch mode button in recorder onscreen dialog (for 320xY)
+ static const char *const kImageFastReplaySmallbtn; ///< Fast playback mode button in recorder onscreen dialog (for 320xY)
/**
* Graphics mode enumeration.
@@ -275,8 +283,13 @@ public:
void refresh();
void enable();
+
+ void showCursor();
+ void hideCursor();
+
void disable();
+
/**
* Query the set up pixel format.
*/
diff --git a/gui/credits.h b/gui/credits.h
index 81d46b2b73..70f79ac9a5 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -294,9 +294,6 @@ static const char *credits[] = {
"C0""Andre Heider",
"C0""Angus Lees",
"",
-"C1""BADA",
-"C0""Chris Warren-Smith",
-"",
"C1""Dreamcast",
"C0""Marcus Comstedt",
"",
@@ -352,6 +349,9 @@ static const char *credits[] = {
"C0""Jurgen Braam",
"C0""Lars Persson",
"",
+"C1""Tizen / BADA",
+"C0""Chris Warren-Smith",
+"",
"C1""WebOS",
"C0""Klaus Reimer",
"",
diff --git a/gui/dialog.h b/gui/dialog.h
index 1773c6633e..d269a2f645 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -37,6 +37,8 @@ struct Event;
namespace GUI {
+class EventRecorder;
+
class Widget;
// Some "common" commands sent to handleCommand()
@@ -47,6 +49,7 @@ enum {
class Dialog : public GuiObject {
friend class GuiManager;
+ friend class EventRecorder;
friend class Tooltip;
protected:
Widget *_mouseWidget;
diff --git a/gui/editrecorddialog.cpp b/gui/editrecorddialog.cpp
new file mode 100644
index 0000000000..a6a7a2560e
--- /dev/null
+++ b/gui/editrecorddialog.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "editrecorddialog.h"
+#include "gui/widgets/edittext.h"
+#include "common/translation.h"
+
+
+namespace GUI {
+
+const Common::String EditRecordDialog::getAuthor() {
+ return _authorEdit->getEditString();
+}
+
+void EditRecordDialog::setAuthor(const Common::String &author) {
+ _authorEdit->setEditString(author);
+}
+
+const Common::String EditRecordDialog::getNotes() {
+ return _notesEdit->getEditString();
+}
+
+void EditRecordDialog::setNotes(const Common::String &desc) {
+ _notesEdit->setEditString(desc);
+}
+
+const Common::String EditRecordDialog::getName() {
+ return _nameEdit->getEditString();
+}
+
+void EditRecordDialog::setName(const Common::String &name) {
+ _nameEdit->setEditString(name);
+}
+
+EditRecordDialog::~EditRecordDialog() {
+}
+
+EditRecordDialog::EditRecordDialog(const Common::String author, const Common::String name, const Common::String notes) : Dialog("EditRecordDialog") {
+ new StaticTextWidget(this,"EditRecordDialog.AuthorLabel",_("Author:"));
+ new StaticTextWidget(this,"EditRecordDialog.NameLabel",_("Name:"));
+ new StaticTextWidget(this,"EditRecordDialog.NotesLabel",_("Notes:"));
+ _authorEdit = new EditTextWidget(this, "EditRecordDialog.AuthorEdit","");
+ _notesEdit = new EditTextWidget(this, "EditRecordDialog.NotesEdit","");
+ _nameEdit = new EditTextWidget(this, "EditRecordDialog.NameEdit","");
+ _authorEdit->setEditString(author);
+ _notesEdit->setEditString(notes);
+ _nameEdit->setEditString(name);
+ new GUI::ButtonWidget(this, "EditRecordDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new GUI::ButtonWidget(this, "EditRecordDialog.OK", _("Ok"), 0, kOKCmd);
+}
+
+void EditRecordDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case kCloseCmd:
+ setResult(kCloseCmd);
+ close();
+ break;
+ case kOKCmd:
+ setResult(kOKCmd);
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ break;
+ }
+}
+
+}
diff --git a/backends/platform/bada/application.h b/gui/editrecorddialog.h
index 2b0d37f1ef..c8da4521ca 100644
--- a/backends/platform/bada/application.h
+++ b/gui/editrecorddialog.h
@@ -8,47 +8,49 @@
* 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#ifndef BADA_APPLICATION_H
-#define BADA_APPLICATION_H
+#ifndef GUI_EDITRECORDDIALOG_H
+#define GUI_EDITRECORDDIALOG_H
-#include <FBase.h>
-#include <FApp.h>
-#include <FGraphics.h>
-#include <FUi.h>
-#include <FSystem.h>
+#include "gui/dialog.h"
-#include "backends/platform/bada/system.h"
+namespace GUI {
-class BadaScummVM : public Osp::App::Application {
+class EditTextWidget;
+class StaticTextWidget;
+
+class EditRecordDialog : public Dialog {
+private:
+ EditTextWidget *_notesEdit;
+ EditTextWidget *_nameEdit;
+ EditTextWidget *_authorEdit;
+ EditRecordDialog() : Dialog("EditRecordDialog") {};
public:
- BadaScummVM();
- ~BadaScummVM();
+ EditRecordDialog(const Common::String author, const Common::String name, const Common::String notes);
+ ~EditRecordDialog();
- static Osp::App::Application *createInstance(void);
+ const Common::String getAuthor();
+ const Common::String getNotes();
+ const Common::String getName();
- bool OnAppInitializing(Osp::App::AppRegistry &appRegistry);
- bool OnAppTerminating(Osp::App::AppRegistry &appRegistry, bool forcedTermination = false);
- void OnForeground(void);
- void OnBackground(void);
- void OnLowMemory(void);
- void OnBatteryLevelChanged(Osp::System::BatteryLevel batteryLevel);
- void OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs);
+ void setAuthor(const Common::String &author);
+ void setNotes(const Common::String &desc);
+ void setName(const Common::String &name);
-private:
- void pauseGame(bool pause);
- BadaAppForm *_appForm;
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
};
+}// End of namespace GUI
+
#endif
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index a0ef4216aa..78b40a46ce 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -27,6 +27,7 @@
#include "common/rect.h"
#include "common/textconsole.h"
#include "common/translation.h"
+#include "gui/EventRecorder.h"
#include "backends/keymapper/keymapper.h"
@@ -253,12 +254,13 @@ Dialog *GuiManager::getTopDialog() const {
void GuiManager::runLoop() {
Dialog * const activeDialog = getTopDialog();
bool didSaveState = false;
- int button;
- uint32 time;
if (activeDialog == 0)
return;
+ // Suspend recording while GUI is shown
+ g_eventRec.suspendRecording();
+
if (!_stateIsSaved) {
saveState();
_theme->enable();
@@ -296,10 +298,10 @@ void GuiManager::runLoop() {
// _theme->updateScreen();
// _system->updateScreen();
- if (lastRedraw + waitTime < _system->getMillis()) {
+ if (lastRedraw + waitTime < _system->getMillis(true)) {
_theme->updateScreen();
_system->updateScreen();
- lastRedraw = _system->getMillis();
+ lastRedraw = _system->getMillis(true);
}
Common::Event event;
@@ -314,72 +316,21 @@ void GuiManager::runLoop() {
if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED)
continue;
- Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
-
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- activeDialog->handleKeyDown(event.kbd);
- break;
- case Common::EVENT_KEYUP:
- activeDialog->handleKeyUp(event.kbd);
- break;
- case Common::EVENT_MOUSEMOVE:
- activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
-
- if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
- _lastMousePosition.x = mouse.x;
- _lastMousePosition.y = mouse.y;
- _lastMousePosition.time = _system->getMillis();
- }
+ processEvent(event, activeDialog);
+ if (event.type == Common::EVENT_MOUSEMOVE) {
tooltipCheck = true;
- break;
- // We don't distinguish between mousebuttons (for now at least)
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_RBUTTONDOWN:
- button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
- time = _system->getMillis();
- if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
- && ABS(_lastClick.x - event.mouse.x) < 3
- && ABS(_lastClick.y - event.mouse.y) < 3) {
- _lastClick.count++;
- } else {
- _lastClick.x = event.mouse.x;
- _lastClick.y = event.mouse.y;
- _lastClick.count = 1;
- }
- _lastClick.time = time;
- activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
- break;
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONUP:
- button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
- activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
- break;
- case Common::EVENT_WHEELUP:
- activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
- break;
- case Common::EVENT_WHEELDOWN:
- activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
- break;
- case Common::EVENT_SCREEN_CHANGED:
- screenChange();
- break;
- default:
-#ifdef ENABLE_KEYMAPPER
- activeDialog->handleOtherEvent(event);
-#endif
- break;
}
- if (lastRedraw + waitTime < _system->getMillis()) {
+
+ if (lastRedraw + waitTime < _system->getMillis(true)) {
_theme->updateScreen();
_system->updateScreen();
- lastRedraw = _system->getMillis();
+ lastRedraw = _system->getMillis(true);
}
}
- if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
+ if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) {
Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
Tooltip *tooltip = new Tooltip();
@@ -409,6 +360,9 @@ void GuiManager::runLoop() {
restoreState();
_useStdCursor = false;
}
+
+ // Resume recording once GUI is shown
+ g_eventRec.resumeRecording();
}
#pragma mark -
@@ -492,7 +446,7 @@ void GuiManager::setupCursor() {
// very much. We could plug in a different cursor here if we like to.
void GuiManager::animateCursor() {
- int time = _system->getMillis();
+ int time = _system->getMillis(true);
if (time > _cursorAnimateTimer + kCursorAnimateDelay) {
for (int i = 0; i < 15; i++) {
if ((i < 6) || (i > 8)) {
@@ -537,4 +491,64 @@ void GuiManager::screenChange() {
_system->updateScreen();
}
+void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDialog) {
+ int button;
+ uint32 time;
+ Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ activeDialog->handleKeyDown(event.kbd);
+ break;
+ case Common::EVENT_KEYUP:
+ activeDialog->handleKeyUp(event.kbd);
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
+
+ if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
+ _lastMousePosition.x = mouse.x;
+ _lastMousePosition.y = mouse.y;
+ _lastMousePosition.time = _system->getMillis(true);
+ }
+
+ break;
+ // We don't distinguish between mousebuttons (for now at least)
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
+ time = _system->getMillis(true);
+ if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
+ && ABS(_lastClick.x - event.mouse.x) < 3
+ && ABS(_lastClick.y - event.mouse.y) < 3) {
+ _lastClick.count++;
+ } else {
+ _lastClick.x = event.mouse.x;
+ _lastClick.y = event.mouse.y;
+ _lastClick.count = 1;
+ }
+ _lastClick.time = time;
+ activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
+ activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
+ break;
+ case Common::EVENT_WHEELUP:
+ activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
+ break;
+ case Common::EVENT_WHEELDOWN:
+ activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
+ break;
+ case Common::EVENT_SCREEN_CHANGED:
+ screenChange();
+ break;
+ default:
+ #ifdef ENABLE_KEYMAPPER
+ activeDialog->handleOtherEvent(event);
+ #endif
+ break;
+ }
+}
+
} // End of namespace GUI
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 49542fd001..b52d91ba08 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -35,6 +35,10 @@ namespace Graphics {
class Font;
}
+namespace Common {
+ struct Event;
+}
+
namespace GUI {
class Dialog;
@@ -67,6 +71,8 @@ public:
// until no dialogs are active anymore.
void runLoop();
+ void processEvent(const Common::Event &event, Dialog *const activeDialog);
+
bool isActive() const { return ! _dialogStack.empty(); }
bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled, bool force = false);
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 4e35b54db8..77d4cce794 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -37,6 +37,11 @@
#include "gui/message.h"
#include "gui/gui-manager.h"
#include "gui/options.h"
+#ifdef ENABLE_EVENTRECORDER
+#include "gui/onscreendialog.h"
+#include "gui/recorderdialog.h"
+#include "gui/EventRecorder.h"
+#endif
#include "gui/saveload.h"
#include "gui/widgets/edittext.h"
#include "gui/widgets/list.h"
@@ -596,7 +601,6 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
LauncherDialog::LauncherDialog()
: Dialog(0, 0, 320, 200) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundMain;
-
const int screenW = g_system->getOverlayWidth();
const int screenH = g_system->getOverlayHeight();
@@ -779,10 +783,9 @@ void LauncherDialog::updateListing() {
}
void LauncherDialog::addGame() {
- int modifiers = g_system->getEventManager()->getModifierState();
#ifndef DISABLE_MASS_ADD
- const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
+ const bool massAdd = checkModifier(Common::KBD_SHIFT);
if (massAdd) {
MessageDialog alert(_("Do you really want to run the mass game detector? "
@@ -975,6 +978,49 @@ void LauncherDialog::editGame(int item) {
}
}
+void LauncherDialog::loadGameButtonPressed(int item) {
+#ifdef ENABLE_EVENTRECORDER
+ const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
+ if (shiftPressed) {
+ recordGame(item);
+ } else {
+ loadGame(item);
+ }
+ updateButtons();
+#else
+ loadGame(item);
+#endif
+}
+
+#ifdef ENABLE_EVENTRECORDER
+void LauncherDialog::recordGame(int item) {
+ RecorderDialog recorderDialog;
+ MessageDialog alert(_("Do you want to load savegame?"),
+ _("Yes"), _("No"));
+ switch(recorderDialog.runModal(_domains[item])) {
+ case RecorderDialog::kRecordDialogClose:
+ break;
+ case RecorderDialog::kRecordDialogPlayback:
+ ConfMan.setActiveDomain(_domains[item]);
+ close();
+ ConfMan.set("record_mode", "playback", ConfigManager::kTransientDomain);
+ ConfMan.set("record_file_name", recorderDialog.getFileName(), ConfigManager::kTransientDomain);
+ break;
+ case RecorderDialog::kRecordDialogRecord:
+ ConfMan.setActiveDomain(_domains[item]);
+ if (alert.runModal() == GUI::kMessageOK) {
+ loadGame(item);
+ }
+ close();
+ g_eventRec.setAuthor(recorderDialog._author);
+ g_eventRec.setName(recorderDialog._name);
+ g_eventRec.setNotes(recorderDialog._notes);
+ ConfMan.set("record_mode", "record", ConfigManager::kTransientDomain);
+ break;
+ }
+}
+#endif
+
void LauncherDialog::loadGame(int item) {
String gameId = ConfMan.get("gameid", _domains[item]);
if (gameId.empty())
@@ -1039,7 +1085,7 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
editGame(item);
break;
case kLoadGameCmd:
- loadGame(item);
+ loadGameButtonPressed(item);
break;
case kOptionsCmd: {
GlobalOptionsDialog options;
@@ -1109,20 +1155,28 @@ void LauncherDialog::updateButtons() {
_loadButton->setEnabled(en);
_loadButton->draw();
}
+ switchButtonsText(_addButton, "~A~dd Game...", "Mass Add...");
+#ifdef ENABLE_EVENTRECORDER
+ switchButtonsText(_loadButton, "~L~oad...", "Record...");
+#endif
+}
- // Update the label of the "Add" button depending on whether shift is pressed or not
- int modifiers = g_system->getEventManager()->getModifierState();
- const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
+// Update the label of the button depending on whether shift is pressed or not
+void LauncherDialog::switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText) {
+ const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
const bool lowRes = g_system->getOverlayWidth() <= 320;
- const char *newAddButtonLabel = massAdd
- ? (lowRes ? _c("Mass Add...", "lowres") : _("Mass Add..."))
- : (lowRes ? _c("~A~dd Game...", "lowres") : _("~A~dd Game..."));
+ const char *newAddButtonLabel = shiftPressed
+ ? (lowRes ? _c(shiftedText, "lowres") : _(shiftedText))
+ : (lowRes ? _c(normalText, "lowres") : _(normalText));
- if (_addButton->getLabel() != newAddButtonLabel)
- _addButton->setLabel(newAddButtonLabel);
+ if (button->getLabel() != newAddButtonLabel)
+ button->setLabel(newAddButtonLabel);
}
+
+
+
void LauncherDialog::reflowLayout() {
#ifndef DISABLE_FANCY_THEMES
if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
@@ -1186,4 +1240,9 @@ void LauncherDialog::reflowLayout() {
Dialog::reflowLayout();
}
+bool LauncherDialog::checkModifier(int checkedModifier) {
+ int modifiers = g_system->getEventManager()->getModifierState();
+ return (modifiers & checkedModifier) != 0;
+}
+
} // End of namespace GUI
diff --git a/gui/launcher.h b/gui/launcher.h
index fc0484350a..2ab47be98d 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -56,7 +56,7 @@ protected:
ListWidget *_list;
ButtonWidget *_addButton;
Widget *_startButton;
- Widget *_loadButton;
+ ButtonWidget *_loadButton;
Widget *_editButton;
Widget *_removeButton;
#ifndef DISABLE_FANCY_THEMES
@@ -80,6 +80,7 @@ protected:
void updateListing();
void updateButtons();
+ void switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText);
void open();
void close();
@@ -100,6 +101,16 @@ protected:
void editGame(int item);
/**
+ * Facade for "Load..."/"Record..." buttons.
+ */
+ void loadGameButtonPressed(int item);
+
+ /**
+ * Handle "Record..." button.
+ */
+ void recordGame(int item);
+
+ /**
* Handle "Load..." button.
*/
void loadGame(int item);
@@ -111,6 +122,8 @@ protected:
* @target name of target to select
*/
void selectTarget(const String &target);
+private:
+ bool checkModifier(int modifier);
};
} // End of namespace GUI
diff --git a/gui/module.mk b/gui/module.mk
index bda3c88cd5..338e43c6a4 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
debugger.o \
dialog.o \
error.o \
+ EventRecorder.o \
gui-manager.o \
launcher.o \
massadd.o \
@@ -38,6 +39,13 @@ MODULE_OBJS += \
browser.o
endif
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ editrecorddialog.o \
+ onscreendialog.o \
+ recorderdialog.o
+endif
+
ifdef USE_FLUIDSYNTH
MODULE_OBJS += \
fluidsynth-dialog.o
diff --git a/gui/onscreendialog.cpp b/gui/onscreendialog.cpp
new file mode 100644
index 0000000000..efe8038e68
--- /dev/null
+++ b/gui/onscreendialog.cpp
@@ -0,0 +1,231 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+
+#include "gui/gui-manager.h"
+
+#include "gui/EventRecorder.h"
+
+#include "common/events.h"
+#include "common/rect.h"
+#include "common/translation.h"
+
+#include "graphics/cursorman.h"
+
+#include "gui/editrecorddialog.h"
+#include "gui/ThemeEval.h"
+
+#include "gui/onscreendialog.h"
+
+namespace GUI {
+
+bool OnScreenDialog::isVisible() const {
+ return true;
+}
+
+enum {
+ kStopCmd = 'STOP',
+ kEditCmd = 'EDIT',
+ kSwitchModeCmd = 'MODE',
+ kFastModeCmd = 'FAST'
+};
+
+void OnScreenDialog::reflowLayout() {
+ GuiObject::reflowLayout();
+}
+
+void OnScreenDialog::releaseFocus() {
+}
+
+OnScreenDialog::OnScreenDialog(bool isRecord) : Dialog("OnScreenDialog") {
+ _x = _y = 0;
+
+#ifndef DISABLE_FANCY_THEMES
+ if (g_gui.xmlEval()->getVar("Globals.OnScreenDialog.ShowPics") == 1 && g_gui.theme()->supportsImages()) {
+ GUI::PicButtonWidget *btn;
+ btn = new PicButtonWidget(this, "OnScreenDialog.StopButton", 0, kStopCmd, 0);
+ btn->useThemeTransparency(true);
+
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopbtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopSmallbtn));
+
+ if (isRecord) {
+ btn = new PicButtonWidget(this, "OnScreenDialog.EditButton", 0, kEditCmd, 0);
+ btn->useThemeTransparency(true);
+
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditbtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditSmallbtn));
+ } else {
+ btn = new PicButtonWidget(this, "OnScreenDialog.SwitchModeButton", 0, kSwitchModeCmd, 0);
+ btn->useThemeTransparency(true);
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModebtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModeSmallbtn));
+
+ btn = new PicButtonWidget(this, "OnScreenDialog.FastReplayButton", 0, kFastModeCmd, 0);
+ btn->useThemeTransparency(true);
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaybtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaySmallbtn));
+ }
+ } else
+#endif
+ {
+ GUI::ButtonWidget *btn;
+ if (g_system->getOverlayWidth() > 320)
+ btn = new ButtonWidget(this, "OnScreenDialog.StopButton", "[ ]", _("Stop"), kStopCmd);
+ else
+ btn = new ButtonWidget(this, "OnScreenDialog.StopButton", "[]", _("Stop"), kStopCmd);
+
+ if (isRecord) {
+ btn = new ButtonWidget(this, "OnScreenDialog.EditButton", "E", _("Edit record description"), kEditCmd);
+ } else {
+ btn = new ButtonWidget(this, "OnScreenDialog.SwitchModeButton", "G", _("Switch to Game"), kSwitchModeCmd);
+
+ btn = new ButtonWidget(this, "OnScreenDialog.FastReplayButton", ">>", _("Fast replay"), kFastModeCmd);
+ }
+ }
+
+
+ text = new GUI::StaticTextWidget(this, "OnScreenDialog.TimeLabel", "00:00:00");
+ _enableDrag = false;
+ _mouseOver = false;
+ _editDlgShown = false;
+}
+
+void OnScreenDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ Common::Event eventRTL;
+ switch (cmd) {
+ case kStopCmd:
+ eventRTL.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(eventRTL);
+ close();
+ break;
+ case kEditCmd:
+ dlg = new EditRecordDialog(g_eventRec.getAuthor(), g_eventRec.getName(), g_eventRec.getNotes());
+ CursorMan.lock(false);
+ g_eventRec.setRedraw(false);
+ g_system->showOverlay();
+ _editDlgShown = true;
+ dlg->runModal();
+ _editDlgShown = false;
+ g_system->hideOverlay();
+ g_eventRec.setRedraw(true);
+ CursorMan.lock(true);
+ g_eventRec.setAuthor(((EditRecordDialog *)dlg)->getAuthor());
+ g_eventRec.setName(((EditRecordDialog *)dlg)->getName());
+ g_eventRec.setNotes(((EditRecordDialog *)dlg)->getNotes());
+ delete dlg;
+ break;
+ case kSwitchModeCmd:
+ if (g_eventRec.switchMode()) {
+ close();
+ }
+ break;
+ case kFastModeCmd:
+ g_eventRec.switchFastMode();
+ break;
+ }
+}
+
+void OnScreenDialog::setReplayedTime(uint32 newTime) {
+ if (newTime - lastTime > 1000) {
+ uint32 seconds = newTime / 1000;
+ text->setLabel(Common::String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60));
+ lastTime = newTime;
+ }
+}
+
+OnScreenDialog::~OnScreenDialog() {
+}
+
+void OnScreenDialog::handleMouseMoved(int x, int y, int button) {
+ if (_enableDrag) {
+ _x = _x + x - _dragPoint.x;
+ _y = _y + y - _dragPoint.y;
+ }
+ Dialog::handleMouseMoved(x, y, button);
+ if (isMouseOver(x, y)) {
+ if (_mouseOver == false) {
+ g_gui.theme()->showCursor();
+ CursorMan.lock(true);
+ }
+ _mouseOver = true;
+ } else {
+ if (_mouseOver == true) {
+ CursorMan.lock(false);
+ g_gui.theme()->hideCursor();
+ }
+ _mouseOver = false;
+ }
+}
+
+void OnScreenDialog::handleMouseDown(int x, int y, int button, int clickCount) {
+ if (isMouseOver(x, y)) {
+ _dragPoint.x = x;
+ _dragPoint.y = y;
+ _enableDrag = true;
+ }
+ Dialog::handleMouseDown(x, y, button, clickCount);
+}
+
+void OnScreenDialog::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (isMouseOver(x, y)) {
+
+ }
+ _enableDrag = false;
+ Dialog::handleMouseUp(x, y, button, clickCount);
+}
+
+bool OnScreenDialog::isMouseOver(int x, int y) {
+ return (x >= 0 && x < _w && y >= 0 && y < _h);
+}
+
+bool OnScreenDialog::isMouseOver() {
+ return _mouseOver;
+}
+
+void OnScreenDialog::close() {
+ CursorMan.lock(false);
+ Dialog::close();
+}
+
+Dialog *OnScreenDialog::getActiveDlg() {
+ if (_editDlgShown) {
+ return dlg;
+ } else {
+ return this;
+ }
+}
+
+bool OnScreenDialog::isEditDlgVisible() {
+ return _editDlgShown;
+}
+
+}
diff --git a/gui/onscreendialog.h b/gui/onscreendialog.h
new file mode 100644
index 0000000000..4f3839acb6
--- /dev/null
+++ b/gui/onscreendialog.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_ONSCREENDIALOG_H
+#define GUI_ONSCREENDIALOG_H
+
+#include "gui/dialog.h"
+#include "gui/widget.h"
+
+namespace GUI {
+
+class OnScreenDialog : public Dialog {
+private:
+ uint32 lastTime;
+ bool _enableDrag;
+ bool _mouseOver;
+ bool _editDlgShown;
+ Common::Point _dragPoint;
+ GUI::StaticTextWidget *text;
+ Dialog *dlg;
+ bool isMouseOver(int x, int y);
+public:
+ OnScreenDialog(bool recordingMode);
+ ~OnScreenDialog();
+ virtual void close();
+ virtual bool isVisible() const;
+ virtual void reflowLayout();
+
+ void setReplayedTime(uint32 newTime);
+
+ virtual void handleMouseMoved(int x, int y, int button);
+ virtual void handleMouseDown(int x, int y, int button, int clickCount);
+ virtual void handleMouseUp(int x, int y, int button, int clickCount);
+ void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+ bool isMouseOver();
+ bool isEditDlgVisible();
+ Dialog *getActiveDlg();
+protected:
+ virtual void releaseFocus();
+};
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp
new file mode 100644
index 0000000000..55f342d4a1
--- /dev/null
+++ b/gui/recorderdialog.cpp
@@ -0,0 +1,291 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "common/algorithm.h"
+#include "common/bufferedstream.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "common/translation.h"
+#include "gui/widgets/list.h"
+#include "gui/editrecorddialog.h"
+#include "gui/EventRecorder.h"
+#include "gui/message.h"
+#include "gui/saveload.h"
+#include "common/system.h"
+#include "gui/ThemeEval.h"
+#include "gui/gui-manager.h"
+#include "recorderdialog.h"
+
+#define MAX_RECORDS_NAMES 0xFF
+
+namespace GUI {
+
+enum {
+ kRecordCmd = 'RCRD',
+ kPlaybackCmd = 'PBCK',
+ kDeleteCmd = 'DEL ',
+ kNextScreenshotCmd = 'NEXT',
+ kPrevScreenshotCmd = 'PREV',
+ kEditRecordCmd = 'EDIT'
+};
+
+RecorderDialog::RecorderDialog() : Dialog("RecorderDialog"), _list(0), _currentScreenshot(0) {
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", _("Recorder or Playback Gameplay"));
+
+ _list = new GUI::ListWidget(this, "RecorderDialog.List");
+ _list->setNumberingMode(GUI::kListNumberingOff);
+
+ _deleteButton = new GUI::ButtonWidget(this, "RecorderDialog.Delete", _("Delete"), 0, kDeleteCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.Record", _("Record"), 0, kRecordCmd);
+ _playbackButton = new GUI::ButtonWidget(this, "RecorderDialog.Playback", _("Playback"), 0, kPlaybackCmd);
+
+ _editButton = new GUI::ButtonWidget(this, "RecorderDialog.Edit", _("Edit"), 0, kEditRecordCmd);
+
+ _editButton->setEnabled(false);
+ _deleteButton->setEnabled(false);
+ _playbackButton->setEnabled(false);
+
+ _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
+ _container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) {
+ new GUI::ButtonWidget(this,"RecorderDialog.NextScreenShotButton", "<", 0, kPrevScreenshotCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.PreviousScreenShotButton", ">", 0, kNextScreenshotCmd);
+ _currentScreenshotText = new StaticTextWidget(this, "RecorderDialog.currentScreenshot", "0/0");
+ _authorText = new StaticTextWidget(this, "RecorderDialog.Author", _("Author: "));
+ _notesText = new StaticTextWidget(this, "RecorderDialog.Notes", _("Notes: "));
+ }
+ if (_gfxWidget)
+ _gfxWidget->setGfx(0);
+}
+
+
+void RecorderDialog::reflowLayout() {
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) {
+ int16 x, y;
+ uint16 w, h;
+
+ if (!g_gui.xmlEval()->getWidgetData("RecorderDialog.Thumbnail", x, y, w, h)) {
+ error("Error when loading position data for Recorder Thumbnails");
+ }
+
+ int thumbW = kThumbnailWidth;
+ int thumbH = kThumbnailHeight2;
+ int thumbX = x + (w >> 1) - (thumbW >> 1);
+ int thumbY = y + kLineHeight;
+
+ _container->resize(x, y, w, h);
+ _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
+
+ _container->setVisible(true);
+ _gfxWidget->setVisible(true);
+ updateSelection(false);
+ } else {
+ _container->setVisible(false);
+ _gfxWidget->setVisible(false);
+ }
+ Dialog::reflowLayout();
+}
+
+
+
+void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case kEditRecordCmd: {
+ if (_list->getSelected() >= 0) {
+ EditRecordDialog editDlg(_fileHeaders[_list->getSelected()].author, _fileHeaders[_list->getSelected()].name, _fileHeaders[_list->getSelected()].notes);
+ if (editDlg.runModal() != kOKCmd) {
+ return;
+ }
+ _playbackFile.openRead(_fileHeaders[_list->getSelected()].fileName);
+ _playbackFile.getHeader().author = editDlg.getAuthor();
+ _playbackFile.getHeader().name = editDlg.getName();
+ _playbackFile.getHeader().notes = editDlg.getNotes();
+ _playbackFile.updateHeader();
+ _fileHeaders[_list->getSelected()] = _playbackFile.getHeader();
+ int oldselection = _list->getSelected();
+ updateList();
+ _list->setSelected(oldselection);
+ updateSelection(true);
+ _playbackFile.close();
+ }
+ }
+ break;
+ case kNextScreenshotCmd:
+ ++_currentScreenshot;
+ updateScreenshot();
+ break;
+ case kPrevScreenshotCmd:
+ --_currentScreenshot;
+ updateScreenshot();
+ break;
+ case kDeleteCmd:
+ if (_list->getSelected() >= 0) {
+ MessageDialog alert(_("Do you really want to delete this record?"),
+ _("Delete"), _("Cancel"));
+ if (alert.runModal() == GUI::kMessageOK) {
+ _playbackFile.close();
+ g_eventRec.deleteRecord(_fileHeaders[_list->getSelected()].fileName);
+ _list->setSelected(-1);
+ updateList();
+ }
+ }
+ break;
+ case GUI::kListSelectionChangedCmd:
+ updateSelection(true);
+ break;
+ case kRecordCmd: {
+ TimeDate t;
+ Common::String gameId = ConfMan.get("gameid", _target);
+ const EnginePlugin *plugin = 0;
+ GameDescriptor desc = EngineMan.findGame(gameId, &plugin);
+ g_system->getTimeAndDate(t);
+ EditRecordDialog editDlg("Unknown Author", Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), "");
+ if (editDlg.runModal() != kOKCmd) {
+ return;
+ }
+ _author = editDlg.getAuthor();
+ _name = editDlg.getName();
+ _notes = editDlg.getNotes();
+ _filename = g_eventRec.generateRecordFileName(_target);
+ setResult(kRecordDialogRecord);
+ close();
+ }
+ break;
+ case kPlaybackCmd:
+ if (_list->getSelected() >= 0) {
+ _filename = _fileHeaders[_list->getSelected()].fileName;
+ setResult(kRecordDialogPlayback);
+ close();
+ }
+ break;
+ case kCloseCmd:
+ setResult(kRecordDialogClose);
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+ }
+
+void RecorderDialog::updateList() {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::String pattern(_target+".r??");
+ Common::StringArray files = saveFileMan->listSavefiles(pattern);
+ Common::PlaybackFile file;
+ Common::StringArray namesList;
+ _fileHeaders.clear();
+ for (Common::StringArray::iterator i = files.begin(); i != files.end(); ++i) {
+ if (file.openRead(*i)) {
+ namesList.push_back(file.getHeader().name);
+ _fileHeaders.push_back(file.getHeader());
+ }
+ file.close();
+ }
+ _list->setList(namesList);
+ _list->draw();
+}
+
+int RecorderDialog::runModal(Common::String &target) {
+ _target = target;
+ updateList();
+ return Dialog::runModal();
+}
+
+RecorderDialog::~RecorderDialog() {
+}
+
+void RecorderDialog::updateSelection(bool redraw) {
+ if (_list->getSelected() >= 0) {
+ _editButton->setEnabled(true);
+ _deleteButton->setEnabled(true);
+ _playbackButton->setEnabled(true);
+ }
+
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") != 1)
+ return;
+
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ _screenShotsCount = 0;
+ _currentScreenshot = 0;
+ updateScreenShotsText();
+ if (_list->getSelected() >= 0) {
+ _authorText->setLabel(_("Author: ") + _fileHeaders[_list->getSelected()].author);
+ _notesText->setLabel(_("Notes: ") + _fileHeaders[_list->getSelected()].notes);
+
+ _firstScreenshotUpdate = true;
+ updateScreenshot();
+ if ((_screenShotsCount) > 0) {
+ _currentScreenshot = 1;
+ }
+ updateScreenshot();
+ } else {
+ _authorText->setLabel(_("Author: "));
+ _notesText->setLabel(_("Notes: "));
+ _screenShotsCount = -1;
+ _currentScreenshot = 0;
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ _gfxWidget->draw();
+ updateScreenShotsText();
+ }
+}
+
+void RecorderDialog::updateScreenshot() {
+ if (_list->getSelected() == -1) {
+ return;
+ }
+ if (_currentScreenshot < 1) {
+ _currentScreenshot = _screenShotsCount;
+ }
+ if (_currentScreenshot > _screenShotsCount) {
+ _currentScreenshot = 1;
+ }
+ if (_firstScreenshotUpdate) {
+ _playbackFile.openRead(_fileHeaders[_list->getSelected()].fileName);
+ _screenShotsCount = _playbackFile.getScreensCount();
+ _firstScreenshotUpdate = false;
+ }
+ Graphics::Surface *srcsf = _playbackFile.getScreenShot(_currentScreenshot);
+ if (srcsf != NULL) {
+ Graphics::Surface *destsf = Graphics::scale(*srcsf, _gfxWidget->getWidth(), _gfxWidget->getHeight());
+ _gfxWidget->setGfx(destsf);
+ updateScreenShotsText();
+ delete destsf;
+ delete srcsf;
+ } else {
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ }
+ _gfxWidget->draw();
+}
+
+void RecorderDialog::updateScreenShotsText() {
+ if (_screenShotsCount == -1) {
+ _currentScreenshotText->setLabel(Common::String::format("%d / ?", _currentScreenshot));
+ } else {
+ _currentScreenshotText->setLabel(Common::String::format("%d / %d", _currentScreenshot, _screenShotsCount));
+ }
+}
+
+} // End of namespace GUI
diff --git a/gui/recorderdialog.h b/gui/recorderdialog.h
new file mode 100644
index 0000000000..eb690a4f38
--- /dev/null
+++ b/gui/recorderdialog.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GUI_RECORDER_DIALOG_H
+#define GUI_RECORDER_DIALOG_H
+#include "common/stream.h"
+#include "common/recorderfile.h"
+#include "gui/dialog.h"
+namespace GUI {
+
+class ListWidget;
+class GraphicsWidget;
+class ButtonWidget;
+class CommandSender;
+class ContainerWidget;
+class StaticTextWidget;
+
+class RecorderDialog : public GUI::Dialog {
+private:
+ bool _firstScreenshotUpdate;
+ Common::PlaybackFile _playbackFile;
+ Common::String _target;
+ Common::String _filename;
+ int _currentScreenshot;
+ int _screenShotsCount;
+ Common::Array<Common::PlaybackFile::PlaybackFileHeader> _fileHeaders;
+ GUI::ListWidget *_list;
+ GUI::ContainerWidget *_container;
+ GUI::GraphicsWidget *_gfxWidget;
+ GUI::StaticTextWidget *_currentScreenshotText;
+ GUI::StaticTextWidget *_authorText;
+ GUI::StaticTextWidget *_notesText;
+ GUI::ButtonWidget *_editButton;
+ GUI::ButtonWidget *_deleteButton;
+ GUI::ButtonWidget *_playbackButton;
+
+ void updateList();
+ void updateScreenShotsText();
+ void updateSelection(bool redraw);
+ void updateScreenshot();
+public:
+ Common::String _author;
+ Common::String _name;
+ Common::String _notes;
+ enum DialogResult {
+ kRecordDialogClose,
+ kRecordDialogRecord,
+ kRecordDialogPlayback
+ };
+ RecorderDialog();
+ ~RecorderDialog();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void reflowLayout();
+
+ int runModal(Common::String &target);
+ const Common::String getFileName() {return _filename;}
+};
+
+} // End of namespace GUI
+
+
+#endif
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 6d8e6baac7..1b6ae3ec27 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -610,50 +610,54 @@
"/> "
"</drawdata> "
"</render_info> "
-"<layout_info resolution='y<400'> "
+"<layout_info resolution='y>399'> "
"<globals> "
-"<def var='Line.Height' value='12' /> "
-"<def var='Font.Height' value='10' /> "
-"<def var='About.OuterBorder' value='10'/> "
-"<def var='Layout.Spacing' value='8'/> "
+"<def var='Line.Height' value='16' /> "
+"<def var='Font.Height' value='16' /> "
+"<def var='About.OuterBorder' value='80'/> "
+"<def var='Layout.Spacing' value='8' /> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
"<def var='ShowChooserPics' value='0'/> "
-"<def var='ShowChooserPageDisplay' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
-"<def var='KeyMapper.Spacing' value='5'/> "
-"<def var='KeyMapper.LabelWidth' value='80'/> "
-"<def var='KeyMapper.ButtonWidth' value='60'/> "
-"<def var='Tooltip.MaxWidth' value='70'/> "
-"<def var='Tooltip.XDelta' value='8'/> "
-"<def var='Tooltip.YDelta' value='8'/> "
-"<def var='Predictive.Button.Width' value='45' /> "
-"<def var='Predictive.Button.Height' value='15' /> "
-"<widget name='Button' "
-"size='72,16' "
-"/> "
-"<widget name='Slider' "
-"size='85,12' "
-"/> "
+"<def var='ShowChooserPageDisplay' value='1'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
+"<def var='RecorderDialog.ExtInfo.Visible' value='1'/> "
+"<def var='OnScreenDialog.ShowPics' value='0'/> "
+"<def var='KeyMapper.Spacing' value='10'/> "
+"<def var='KeyMapper.LabelWidth' value='100'/> "
+"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='Tooltip.MaxWidth' value='200'/> "
+"<def var='Tooltip.XDelta' value='16'/> "
+"<def var='Tooltip.YDelta' value='16'/> "
+"<def var='Predictive.Button.Width' value='60' /> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='18,Globals.Line.Height' "
+"size='24,Globals.Line.Height' "
+"/> "
+"<widget name='ShortOptionsLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='Button' "
+"size='108,24' "
+"/> "
+"<widget name='Slider' "
+"size='128,18' "
"/> "
"<widget name='PopUp' "
-"size='-1,15' "
+"size='-1,19' "
"/> "
"<widget name='Checkbox' "
-"size='-1,Globals.Line.Height' "
+"size='-1,14' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,0,0' "
+"padding='5,0,8,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -665,29 +669,35 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='9,0' "
+"size='15,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='45,16' "
-"padding='0,0,2,0' "
+"size='75,27' "
+"padding='0,0,8,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,-8' "
+"padding='0,0,0,0' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='32,18' "
-"padding='0,0,1,0' "
+"size='15,18' "
+"padding='0,3,4,0' "
+"/> "
+"<widget name='EditRecordLabel' "
+"size='60,25' "
+"/> "
+"<widget name='EditRecord' "
+"size='240,25' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='6,6,2,2'> "
+"<layout type='vertical' center='true' padding='16,16,8,8'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"textalign='center' "
"/> "
-"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
"<widget name='SearchDesc' "
-"width='50' "
+"width='60' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -702,38 +712,39 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='LoadGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AddGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='EditGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='RemoveGameButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<space size='4'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='QuitButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AboutButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='OptionsButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='StartButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -741,7 +752,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,8,0'> "
+"<layout type='vertical' padding='0,0,16,0'> "
"<widget name='Hidden' "
"type='Checkbox' "
"/> "
@@ -760,10 +771,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -776,7 +787,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -784,7 +795,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -802,7 +813,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -810,7 +821,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -818,7 +829,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -826,7 +837,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -840,7 +851,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -854,8 +865,9 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -866,7 +878,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -877,7 +889,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -888,8 +900,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,0,24,0' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -897,8 +909,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='6'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -906,7 +918,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -921,7 +933,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -934,14 +946,14 @@
"/> "
"</layout> "
"<widget name='mcFluidSynthSettings' "
-"width='150' "
+"width='200' "
"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -959,7 +971,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -971,7 +983,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -983,7 +995,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -1007,7 +1019,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1015,31 +1027,25 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='RendererPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -1074,10 +1080,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,4'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1089,7 +1095,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1097,7 +1103,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1105,7 +1111,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1113,7 +1119,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1121,7 +1127,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1129,43 +1135,34 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Id' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Name' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<space size='8'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='LangPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PlatformPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -1174,8 +1171,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -1187,7 +1184,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -1199,7 +1196,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -1210,7 +1207,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='vertical' padding='16,16,16,16'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -1235,55 +1232,57 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' center='true'> "
"<widget name='Title' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
"<widget name='Version' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
-"<space size='1'/> "
+"<widget name='Resume' "
+"width='150' "
+"height='Globals.Button.Height' "
+"/> "
+"<space size='10'/> "
"<widget name='Load' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Save' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
-"<space size='1'/> "
+"<space size='10'/> "
"<widget name='Options' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Help' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='About' "
-"width='120' "
-"height='12' "
-"/> "
-"<space size='1'/> "
-"<widget name='Resume' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='10'/> "
"<widget name='RTL' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Quit' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='0,0,0,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1294,7 +1293,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1305,7 +1304,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1316,34 +1315,33 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,24,24,24' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"</layout> "
+"<space size='8' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"</layout> "
-"</layout> "
-"<space size='2' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1354,8 +1352,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='16'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"<space size='60'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -1372,7 +1370,7 @@
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='ResetSettings' "
"type='Button' "
@@ -1387,7 +1385,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1450,7 +1448,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1505,7 +1503,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='InterpolationText' "
"type='OptionsLabel' "
@@ -1517,10 +1515,25 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' height='Globals.Line.Height'/> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<space/> "
+"<widget name='PageDisplay' "
+"width='200' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Thumbnail' "
+"width='180' "
+"height='200' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
@@ -1533,7 +1546,7 @@
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='16'/> "
+"<space size='32'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -1546,7 +1559,7 @@
"<dialog name='SavenameDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='DescriptionText' "
-"width='180' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description' "
@@ -1556,22 +1569,139 @@
"<widget name='Cancel' "
"type='Button' "
"/> "
+"<space size='96'/> "
"<widget name='Ok' "
"type='Button' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='RecorderDialog' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<widget name='List' /> "
+"<layout type='vertical' padding='0,0,0,0'> "
+"<widget name='Thumbnail' "
"width='180' "
+"height='170' "
+"/> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='NextScreenShotButton' "
+"width='25' "
+"height='25' "
+"/> "
+"<widget name='currentScreenshot' "
+"width='125' "
+"height='25' "
+"textalign='center' "
+"/> "
+"<widget name='PreviousScreenShotButton' "
+"width='25' "
+"height='25' "
+"/> "
+"</layout> "
+"<widget name='Author' height='Globals.Line.Height' /> "
+"<widget name='Notes' height='Globals.Line.Height' /> "
+"</layout> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Delete' "
+"type='Button' "
+"/> "
+"<space size='16'/> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<space size='16'/> "
+"<widget name='Edit' "
+"type='Button' "
+"/> "
+"<widget name='Record' "
+"type='Button' "
+"/> "
+"<widget name='Playback' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='OnScreenDialog' overlays='screen_center'> "
+"<layout type='horizontal' spacing='5' padding='5,3,5,3' center='true'> "
+"<widget name='StopButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='EditButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='SwitchModeButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='FastReplayButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='TimeLabel' "
+"width='50' "
+"height='30' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='EditRecordDialog' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' "
+"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='AuthorLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='AuthorEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NameLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NameEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NotesLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NotesEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='OK' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='140' "
+"height='200' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -1588,7 +1718,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='280' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -1606,20 +1736,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' center='true'> "
"<widget name='DirProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='280' "
-"height='100' "
+"width='480' "
+"height='250' "
"/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -1630,20 +1760,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='150' "
+"width='400' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
+"width='600' "
+"height='280' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -1651,142 +1781,144 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='1,1,1,1' center='true'> "
+"<layout type='vertical' padding='5,5,5,5' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='150' "
+"width='210' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='5,5,5,5'> "
"<widget name='Word' "
-"width='120' "
+"width='190' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
+"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,0'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<space size='3' /> "
-"<layout type='horizontal' padding='3,3,0,3'> "
+"<space size='5' /> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='y>399'> "
+"<layout_info resolution='y<400'> "
"<globals> "
-"<def var='Line.Height' value='16' /> "
-"<def var='Font.Height' value='16' /> "
-"<def var='About.OuterBorder' value='80'/> "
-"<def var='Layout.Spacing' value='8' /> "
+"<def var='Line.Height' value='12' /> "
+"<def var='Font.Height' value='10' /> "
+"<def var='About.OuterBorder' value='10'/> "
+"<def var='Layout.Spacing' value='8'/> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
"<def var='ShowChooserPics' value='0'/> "
-"<def var='ShowChooserPageDisplay' value='1'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
-"<def var='KeyMapper.Spacing' value='10'/> "
-"<def var='KeyMapper.LabelWidth' value='100'/> "
-"<def var='KeyMapper.ButtonWidth' value='80'/> "
-"<def var='Tooltip.MaxWidth' value='200'/> "
-"<def var='Tooltip.XDelta' value='16'/> "
-"<def var='Tooltip.YDelta' value='16'/> "
-"<def var='Predictive.Button.Width' value='60' /> "
+"<def var='ShowChooserPageDisplay' value='0'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
+"<def var='RecorderDialog.ExtInfo.Visible' value='0'/> "
+"<def var='OnScreenDialog.ShowPics' value='0'/> "
+"<def var='KeyMapper.Spacing' value='5'/> "
+"<def var='KeyMapper.LabelWidth' value='80'/> "
+"<def var='KeyMapper.ButtonWidth' value='60'/> "
+"<def var='Tooltip.MaxWidth' value='70'/> "
+"<def var='Tooltip.XDelta' value='8'/> "
+"<def var='Tooltip.YDelta' value='8'/> "
+"<def var='Predictive.Button.Width' value='45' /> "
+"<def var='Predictive.Button.Height' value='15' /> "
+"<widget name='Button' "
+"size='72,16' "
+"/> "
+"<widget name='Slider' "
+"size='85,12' "
+"/> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='24,Globals.Line.Height' "
-"/> "
-"<widget name='ShortOptionsLabel' "
-"size='60,Globals.Line.Height' "
-"/> "
-"<widget name='Button' "
-"size='108,24' "
-"/> "
-"<widget name='Slider' "
-"size='128,18' "
+"size='18,Globals.Line.Height' "
"/> "
"<widget name='PopUp' "
-"size='-1,19' "
+"size='-1,15' "
"/> "
"<widget name='Checkbox' "
-"size='-1,14' "
+"size='-1,Globals.Line.Height' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,8,0' "
+"padding='5,0,0,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -1798,29 +1930,35 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='15,0' "
+"size='9,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='75,27' "
-"padding='0,0,8,0' "
+"size='45,16' "
+"padding='0,0,2,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,0' "
+"padding='0,0,0,-8' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='15,18' "
-"padding='0,3,4,0' "
+"size='32,18' "
+"padding='0,0,1,0' "
+"/> "
+"<widget name='EditRecordLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='EditRecord' "
+"size='120,15' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"<layout type='vertical' center='true' padding='6,6,2,2'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"textalign='center' "
"/> "
-"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
"<widget name='SearchDesc' "
-"width='60' "
+"width='50' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -1835,39 +1973,38 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='LoadGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AddGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='EditGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='RemoveGameButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='QuitButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AboutButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='OptionsButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='StartButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,0,4'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -1875,7 +2012,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,16,0'> "
+"<layout type='vertical' padding='0,0,8,0'> "
"<widget name='Hidden' "
"type='Checkbox' "
"/> "
@@ -1894,10 +2031,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1910,7 +2047,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1918,7 +2055,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1936,7 +2073,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1944,7 +2081,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1952,7 +2089,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1960,7 +2097,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -1974,7 +2111,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1988,9 +2125,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -2001,7 +2137,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -2012,7 +2148,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -2023,8 +2159,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -2032,8 +2168,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='6'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -2041,7 +2177,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -2056,7 +2192,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -2069,14 +2205,14 @@
"/> "
"</layout> "
"<widget name='mcFluidSynthSettings' "
-"width='200' "
+"width='150' "
"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -2094,7 +2230,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -2106,7 +2242,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -2118,7 +2254,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -2142,7 +2278,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -2150,25 +2286,31 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='RendererPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -2203,10 +2345,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -2218,7 +2360,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2226,7 +2368,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2234,7 +2376,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2242,7 +2384,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2250,7 +2392,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2258,34 +2400,43 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Id' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Name' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<space size='8'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='LangPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='PlatformPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -2294,8 +2445,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -2307,7 +2458,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -2319,7 +2470,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -2330,7 +2481,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -2355,57 +2506,55 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
"<widget name='Title' "
-"width='210' "
-"height='Globals.Line.Height' "
+"width='160' "
+"height='4' "
"/> "
"<widget name='Version' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Resume' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='160' "
+"height='4' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Load' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Save' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Options' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Help' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='About' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
+"/> "
+"<space size='1'/> "
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Quit' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<layout type='vertical' padding='0,0,0,0' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -2416,7 +2565,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -2427,7 +2576,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -2438,33 +2587,34 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"</layout> "
+"<space size='2' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -2475,8 +2625,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<space size='16'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -2493,7 +2643,7 @@
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='ResetSettings' "
"type='Button' "
@@ -2508,7 +2658,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2571,7 +2721,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2626,7 +2776,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='InterpolationText' "
"type='OptionsLabel' "
@@ -2638,25 +2788,10 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,32' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='Title' "
-"height='Globals.Line.Height' "
-"/> "
-"<space/> "
-"<widget name='PageDisplay' "
-"width='200' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' height='Globals.Line.Height'/> "
"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
@@ -2669,7 +2804,7 @@
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='32'/> "
+"<space size='16'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -2682,7 +2817,7 @@
"<dialog name='SavenameDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='DescriptionText' "
-"width='320' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description' "
@@ -2692,23 +2827,114 @@
"<widget name='Cancel' "
"type='Button' "
"/> "
-"<space size='96'/> "
"<widget name='Ok' "
"type='Button' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen_center'> "
+"<dialog name='RecorderDialog' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,4' center='true'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='List' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='2'> "
+"<widget name='Edit' "
+"type='Button' "
+"/> "
+"<space /> "
+"<widget name='Record' "
+"type='Button' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='2'> "
+"<widget name='Delete' "
+"type='Button' "
+"/> "
+"<space /> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Playback' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='OnScreenDialog' overlays='screen_center'> "
+"<layout type='horizontal' spacing='5' padding='3,2,3,2' center='true'> "
+"<widget name='StopButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='EditButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='SwitchModeButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='FastReplayButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='TimeLabel' "
+"width='50' "
+"height='16' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='EditRecordDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Title' "
-"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='AuthorLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='AuthorEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NameLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NameEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NotesLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NotesEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='OK' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='Title' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='200' "
+"height='140' "
"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -2725,7 +2951,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='320' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -2743,20 +2969,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"<layout type='vertical' padding='4,4,16,4' center='true'> "
"<widget name='DirProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='480' "
-"height='250' "
+"width='280' "
+"height='100' "
"/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='4,4,4,4'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -2767,20 +2993,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='400' "
+"width='150' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
+"width='300' "
+"height='120' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -2788,93 +3014,91 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='5,5,5,5' center='true'> "
+"<layout type='vertical' padding='1,1,1,1' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='210' "
+"width='150' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='5,5,5,5'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Word' "
-"width='190' "
+"width='120' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='3,3,3,0'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<space size='3' /> "
+"<layout type='horizontal' padding='3,3,0,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
-"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"</layout> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 297ff20344..4154c6c33a 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 180e8fba74..5fd2d6f835 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -36,6 +36,9 @@
<def var = 'ShowChooserPageDisplay' value = '1'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
<def var = 'KeyMapper.LabelWidth' value = '100'/>
@@ -101,6 +104,12 @@
size = '15, 18'
padding = '0, 3, 4, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, 25'
+ />
+ <widget name = 'EditRecord'
+ size = '240, 25'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1019,6 +1028,125 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
+ <widget name = 'List' />
+ <layout type = 'vertical' padding = '0, 0, 0, 0'>
+ <widget name = 'Thumbnail'
+ width = '180'
+ height = '170'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'NextScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ <widget name = 'currentScreenshot'
+ width = '125'
+ height = '25'
+ textalign = 'center'
+ />
+ <widget name = 'PreviousScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ </layout>
+ <widget name = 'Author' height = 'Globals.Line.Height' />
+ <widget name = 'Notes' height = 'Globals.Line.Height' />
+ </layout>
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '5, 3, 5, 3' center = 'true'>
+ <widget name = 'StopButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'EditButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'FastReplayButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '30'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 8bb03dea17..802998df3c 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -37,6 +37,9 @@
<def var = 'ShowChooserPageDisplay' value = '0'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '5'/>
<def var = 'KeyMapper.LabelWidth' value = '80'/>
@@ -99,6 +102,12 @@
size = '32, 18'
padding = '0, 0, 1, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, Globals.Line.Height'
+ />
+ <widget name = 'EditRecord'
+ size = '120, 15'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1013,6 +1022,101 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 4' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'List' />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '3, 2, 3, 2' center = 'true'>
+ <widget name = 'StopButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'EditButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'FastReplayButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '16'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index dbd84992e6..0f10003e94 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/editbtn.bmp b/gui/themes/scummmodern/editbtn.bmp
new file mode 100644
index 0000000000..49eb4035b5
--- /dev/null
+++ b/gui/themes/scummmodern/editbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/editbtn_small.bmp b/gui/themes/scummmodern/editbtn_small.bmp
new file mode 100644
index 0000000000..8a0357fc2e
--- /dev/null
+++ b/gui/themes/scummmodern/editbtn_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/fastreplay.bmp b/gui/themes/scummmodern/fastreplay.bmp
new file mode 100644
index 0000000000..35ad2b4444
--- /dev/null
+++ b/gui/themes/scummmodern/fastreplay.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/fastreplay_small.bmp b/gui/themes/scummmodern/fastreplay_small.bmp
new file mode 100644
index 0000000000..8ef004c3bf
--- /dev/null
+++ b/gui/themes/scummmodern/fastreplay_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 4d449f50ec..1b3bcea0d6 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -103,6 +103,14 @@
<bitmap filename = 'delbtn.bmp'/>
<bitmap filename = 'list.bmp'/>
<bitmap filename = 'grid.bmp'/>
+ <bitmap filename = 'stopbtn.bmp'/>
+ <bitmap filename = 'editbtn.bmp'/>
+ <bitmap filename = 'switchbtn.bmp'/>
+ <bitmap filename = 'fastreplay.bmp'/>
+ <bitmap filename = 'stopbtn_small.bmp'/>
+ <bitmap filename = 'editbtn_small.bmp'/>
+ <bitmap filename = 'switchbtn_small.bmp'/>
+ <bitmap filename = 'fastreplay_small.bmp'/>
</bitmaps>
<fonts>
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 49c13cf1b0..b760e15919 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -43,6 +43,9 @@
<def var = 'ShowChooserPageDisplay' value = '1'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
<def var = 'KeyMapper.LabelWidth' value = '100'/>
@@ -106,6 +109,13 @@
size = '15, 18'
padding = '0, 3, 4, 0'
/>
+
+ <widget name = 'EditRecordLabel'
+ size = '60, 25'
+ />
+ <widget name = 'EditRecord'
+ size = '220, 25'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1032,6 +1042,126 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
+ <widget name = 'List' />
+ <layout type = 'vertical' padding = '0, 0, 0, 0'>
+ <widget name = 'Thumbnail'
+ width = '180'
+ height = '170'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'NextScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ <widget name = 'currentScreenshot'
+ width = '125'
+ height = '25'
+ textalign = 'center'
+ />
+ <widget name = 'PreviousScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ </layout>
+ <widget name = 'Author' height = 'Globals.Line.Height' />
+ <widget name = 'Notes' height = 'Globals.Line.Height' />
+ </layout>
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '5, 3, 5, 3' center = 'true'>
+ <widget name = 'StopButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'EditButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'FastReplayButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '30'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 9658402f82..cee1e4af2b 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -35,6 +35,9 @@
<def var = 'ShowChooserPageDisplay' value = '0'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '1'/>
<def var = 'Predictive.Button.Width' value = '45' />
<def var = 'Predictive.Button.Height' value = '15' />
@@ -97,6 +100,12 @@
size = '32, 18'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, Globals.Line.Height'
+ />
+ <widget name = 'EditRecord'
+ size = '120, 15'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1012,6 +1021,122 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 4' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'List' />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '3, 2, 3, 2' center = 'true'>
+ <widget name = 'StopButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'EditButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'FastReplayButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '16'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen' inset = '8'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/stopbtn.bmp b/gui/themes/scummmodern/stopbtn.bmp
new file mode 100644
index 0000000000..3575956694
--- /dev/null
+++ b/gui/themes/scummmodern/stopbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/stopbtn_small.bmp b/gui/themes/scummmodern/stopbtn_small.bmp
new file mode 100644
index 0000000000..ffd5025279
--- /dev/null
+++ b/gui/themes/scummmodern/stopbtn_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/switchbtn.bmp b/gui/themes/scummmodern/switchbtn.bmp
new file mode 100644
index 0000000000..6bafa4a998
--- /dev/null
+++ b/gui/themes/scummmodern/switchbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/switchbtn_small.bmp b/gui/themes/scummmodern/switchbtn_small.bmp
new file mode 100644
index 0000000000..929b128884
--- /dev/null
+++ b/gui/themes/scummmodern/switchbtn_small.bmp
Binary files differ
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 4b266e8194..3677f02e47 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "common/system.h"
#include "gui/widgets/edittext.h"
#include "gui/gui-manager.h"
@@ -79,8 +80,13 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
if (setCaretPos(i))
draw();
-}
+#ifdef TIZEN
+ // Display the virtual keypad to allow text entry. Samsung app-store testers expected
+ // the keypad to be displayed when clicking the filter edit control in the laucher gui.
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+#endif
+}
void EditTextWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundEditText);
diff --git a/po/POTFILES b/po/POTFILES
index c2f67e288b..b812620c25 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -48,6 +48,8 @@ engines/groovie/script.cpp
engines/kyra/detection.cpp
engines/kyra/lol.cpp
engines/kyra/sound_midi.cpp
+engines/neverhood/detection.cpp
+engines/neverhood/menumodule.cpp
engines/queen/queen.cpp
engines/sky/compact.cpp
engines/sky/detection.cpp
diff --git a/test/common/str.h b/test/common/str.h
index 2c563f3132..adc6a099e4 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -243,6 +243,14 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(str, "012345678923456789012345678901");
}
+ void test_erase() {
+ Common::String str("01234567890123456789012345678901");
+ str.erase(18);
+ TS_ASSERT_EQUALS(str, "012345678901234567");
+ str.erase(7, 5);
+ TS_ASSERT_EQUALS(str, "0123456234567");
+ }
+
void test_sharing() {
Common::String str("01234567890123456789012345678901");
Common::String str2(str);
diff --git a/video/codecs/indeo3.cpp b/video/codecs/indeo3.cpp
index 7bf7fc8235..28e1a9c620 100644
--- a/video/codecs/indeo3.cpp
+++ b/video/codecs/indeo3.cpp
@@ -32,8 +32,9 @@
#include "common/endian.h"
#include "common/stream.h"
#include "common/textconsole.h"
+#include "common/util.h"
-#include "graphics/conversion.h"
+#include "graphics/yuv_to_rgb.h"
#include "video/codecs/indeo3.h"
@@ -260,91 +261,61 @@ const Graphics::Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *
delete[] inData;
- // Blit the frame onto the surface
const byte *srcY = _cur_frame->Ybuf;
const byte *srcU = _cur_frame->Ubuf;
const byte *srcV = _cur_frame->Vbuf;
- byte *dest = (byte *)_surface->pixels;
-
- const byte *srcUP = srcU;
- const byte *srcVP = srcV;
- const byte *srcUN = srcU + chromaWidth;
- const byte *srcVN = srcV + chromaWidth;
-
- uint32 scaleWidth = _surface->w / fWidth;
- uint32 scaleHeight = _surface->h / fHeight;
- for (uint32 y = 0; y < fHeight; y++) {
- byte *rowDest = dest;
-
- for (uint32 sH = 0; sH < scaleHeight; sH++) {
- for (uint32 x = 0; x < fWidth; x++) {
- uint32 xP = MAX<int32>((x >> 2) - 1, 0);
- uint32 xN = MIN<int32>((x >> 2) + 1, chromaWidth - 1);
-
- byte cY = srcY[x];
- byte cU = srcU[x >> 2];
- byte cV = srcV[x >> 2];
-
- if (((x % 4) == 0) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xN])) / 2;
- } else if (((x % 4) == 0) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xN])) / 2;
- } else if ( (x % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcU[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xP])) / 2;
- } else if ( (x % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcU[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xN])) / 2;
- } else if ( (y % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcUP[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[x >> 2])) / 2;
- } else if ( (y % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcUN[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[x >> 2])) / 2;
- }
+ // Create buffers for U/V with an extra row/column copied from the second-to-last
+ // row/column.
+ byte *tempU = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
+ byte *tempV = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(cY, cU, cV, r, g, b);
+ for (uint i = 0; i < chromaHeight; i++) {
+ memcpy(tempU + (chromaWidth + 1) * i, srcU + chromaWidth * i, chromaWidth);
+ memcpy(tempV + (chromaWidth + 1) * i, srcV + chromaWidth * i, chromaWidth);
+ tempU[(chromaWidth + 1) * i + chromaWidth] = srcU[chromaWidth * (i + 1) - 1];
+ tempV[(chromaWidth + 1) * i + chromaWidth] = srcV[chromaWidth * (i + 1) - 1];
+ }
- const uint32 color = _pixelFormat.RGBToColor(r, g, b);
+ memcpy(tempU + (chromaWidth + 1) * chromaHeight, tempU + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
+ memcpy(tempV + (chromaWidth + 1) * chromaHeight, tempV + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
- for (uint32 sW = 0; sW < scaleWidth; sW++, rowDest += _surface->format.bytesPerPixel) {
- if (_surface->format.bytesPerPixel == 1)
- *((uint8 *)rowDest) = (uint8)color;
- else if (_surface->format.bytesPerPixel == 2)
- *((uint16 *)rowDest) = (uint16)color;
- }
- }
+ // Blit the frame onto the surface
+ uint32 scaleWidth = _surface->w / fWidth;
+ uint32 scaleHeight = _surface->h / fHeight;
- dest += _surface->pitch;
+ if (scaleWidth == 1 && scaleHeight == 1) {
+ // Shortcut: Don't need to scale so we can decode straight to the surface
+ YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+ } else {
+ // Need to upscale, so decode to a temp surface first
+ Graphics::Surface tempSurface;
+ tempSurface.create(fWidth, fHeight, _surface->format);
+
+ YUVToRGBMan.convert410(&tempSurface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+
+ // Upscale
+ for (int y = 0; y < _surface->h; y++) {
+ for (int x = 0; x < _surface->w; x++) {
+ if (_surface->format.bytesPerPixel == 1)
+ *((byte *)_surface->getBasePtr(x, y)) = *((byte *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 2)
+ *((uint16 *)_surface->getBasePtr(x, y)) = *((uint16 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 4)
+ *((uint32 *)_surface->getBasePtr(x, y)) = *((uint32 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ }
}
- srcY += fWidth;
-
- if ((y & 3) == 3) {
- srcU += chromaWidth;
- srcV += chromaWidth;
-
- if (y > 0) {
- srcUP += chromaWidth;
- srcVP += chromaWidth;
- }
- if (y < (fHeight - 4U)) {
- srcUN += chromaWidth;
- srcVN += chromaWidth;
- }
- }
+ tempSurface.free();
}
+ delete[] tempU;
+ delete[] tempV;
+
return _surface;
}
diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp
index d24a021f3b..4c3b6f8414 100644
--- a/video/coktel_decoder.cpp
+++ b/video/coktel_decoder.cpp
@@ -2426,8 +2426,10 @@ void VMDDecoder::blit16(const Graphics::Surface &srcSurf, Common::Rect &rect) {
if ((r == 0) && (g == 0) && (b == 0))
c = 0;
- if (_surface.format.bytesPerPixel == 2)
+ if (_surface.format.bytesPerPixel == 2)
*((uint16 *)dstRow) = (uint16) c;
+ else if (_surface.format.bytesPerPixel == 4)
+ *((uint32 *)dstRow) = (uint32) c;
}
src += srcSurf .pitch;
@@ -2462,8 +2464,10 @@ void VMDDecoder::blit24(const Graphics::Surface &srcSurf, Common::Rect &rect) {
if ((r == 0) && (g == 0) && (b == 0))
c = 0;
- if (_surface.format.bytesPerPixel == 2)
+ if (_surface.format.bytesPerPixel == 2)
*((uint16 *)dstRow) = (uint16) c;
+ else if (_surface.format.bytesPerPixel == 4)
+ *((uint32 *)dstRow) = (uint32) c;
}
src += srcSurf .pitch;