diff options
555 files changed, 28966 insertions, 24045 deletions
@@ -57,6 +57,7 @@ ScummVM Team Cinematique evo 2: Vincent Hamm - original CruisE engine author + Paul Gilbert FOTAQ: Gregory Montoir @@ -26,6 +26,7 @@ CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder # Enable even more warnings... CXXFLAGS+= -Wpointer-arith -Wcast-qual -Wcast-align CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings +CXXFLAGS+= -Wmissing-format-attribute # Disable RTTI and exceptions, and enabled checking of pointers returned by "new" CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new diff --git a/Makefile.common b/Makefile.common index 522fa7c809..cea30a5f9f 100644 --- a/Makefile.common +++ b/Makefile.common @@ -211,6 +211,8 @@ dist-src: \ @#RPM-src? @#DEB-src? +# Common files +DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.LGPL COPYRIGHT NEWS README) # Themes files DIST_FILES_THEMES:=$(addprefix $(srcdir)/gui/themes/,scummmodern.zip) @@ -240,6 +242,11 @@ DIST_FILES_ENGINEDATA+=sky.cpt endif DIST_FILES_ENGINEDATA:=$(addprefix $(srcdir)/dists/engine-data/,$(DIST_FILES_ENGINEDATA)) +# pred.dic is currently only used for the AGI engine +ifdef ENABLE_AGI +DIST_FILES_ENGINEDATA+=$(srcdir)/dists/pred.dic +endif + # Plugin files DIST_FILES_PLUGINS:=$(addprefix $(srcdir)/,$(PLUGINS)) @@ -4,86 +4,96 @@ For a more comprehensive changelog for the latest experimental SVN code, see: 0.14.0 (2009-??-??) New Games: - Added support for Discworld. - - Added support for Discworld 2 - Missing Presumed ...!? - - Added support for Return to Zork - - Added support for Leather Goddesses of Phobos 2 - - Added support for The Manhole - - Added support for Rodney's Funscreen - + - Added support for Discworld 2 - Missing Presumed ...!?. + - Added support for Return to Zork. + - Added support for Leather Goddesses of Phobos 2. + - Added support for The Manhole. + - Added support for Rodney's Funscreen. + General: - Added experimental AdLib emulator from DOSBox. + - Added quick search to Launcher. + - Improved modern GUI theme look. + - Added per-game GUI options. + - Improved Mass Add dialog. + + AGI: + - Increased compatibility for Sierra games. + - Implemented all 'unknown' commands. Beneath a Steel Sky: - Changed the game speed to match the original game (previously it ran too fast). Broken Sword 1: - - Added support for the original cutscenes. + - Added support for the original cutscenes. - Dropped support for the now obsolete MPEG2 cutscenes. - Added support for the PlayStation version. Broken Sword 2: - - Added support for the original cutscenes. + - Added support for the original cutscenes. - Dropped support for the now obsolete MPEG2 cutscenes. - Dropped support for playing cutscene sound without the video. - Added support for the PlayStation version. KYRA: - Added support for PC Speaker based music and sound effects. + - Added support for 16 color dithering in Kyrandia PC-9801 (Japanese version + only). New Ports: - Added GP2X Wiz port. -0.13.1 (2009-04-27) +0.13.1 (2009-04-27) AGOS: - - Fixed crash after OmniTV video is played in The Feeble Files + - Fixed crash after OmniTV video is played in The Feeble Files. - Fixed crashes when exploring Jack the Ripper scene in the PC version of - the Waxworks - - Fixed palette glitches in the AtariST version of Elvira 2 - - Fixed noise that can occur when sound effects are played, when exploring - Pyramid scene in the Waxworks + the Waxworks. + - Fixed palette glitches in the AtariST version of Elvira 2. + - Fixed noise that can occur when sound effects are played, when exploring + Pyramid scene in the Waxworks. Gob: - - Fixed a crash in the Italian version of Woodruff + - Fixed a crash in the Italian version of Woodruff. Groovie: - - Fixed some issues with music in The 7th Guest + - Fixed some issues with music in The 7th Guest. Parallaction: - - Fixed the sarcophagus puzzle in Nippon Safes + - Fixed the sarcophagus puzzle in Nippon Safes. SAGA: - - Fixed a crash in Inherit the Earth + - Fixed a crash in Inherit the Earth. - Fixed glitches in the save/load dialog. Sword2: - Fixed random sound corruption when using the original sound files. Game launcher: - - Fixed a case where memory could be corrupted - - Fixed the small cursor in the modern theme - - Fixed a bug in the theme engine, which could cause crashes - - Made the file browser bigger in 1x mode + - Fixed a case where memory could be corrupted. + - Fixed the small cursor in the modern theme. + - Fixed a bug in the theme engine, which could cause crashes. + - Made the file browser bigger in 1x mode. iPhone port: - - Fixed backspace handling on the iPhone soft keyboard + - Fixed backspace handling on the iPhone soft keyboard. DS port: - - Added support for the Global Main Menu feature - + - Added support for the Global Main Menu feature. + PS2 port: - - Switched to the new GUI and theme code + - Switched to the new GUI and theme code. - All possible devices are supported to store, play and save games - (CD, HD, USB, MC and remote) - - Optimized cache/read-ahead for every media - - Added support for the Return to Launcher feature + (CD, HD, USB, MC and remote). + - Optimized cache/read-ahead for every media. + - Added support for the Return to Launcher feature. Symbian port: - - Added Bluetooth mouse support - - Added support for the Return to Launcher feature - + - Added Bluetooth mouse support. + - Added support for the Return to Launcher feature. + WinCE port: - - Fixed an issue which could cause random crashes with VGA devices + - Fixed an issue which could cause random crashes with VGA devices. 0.13.0 (2009-02-28) General: @@ -101,17 +111,17 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Added support for The 7th Guest. AGOS: - - Added support for the original cutscenes of The Feeble Files - - Added support for text compression in the AtariST version of Elvira 1 - - Fixed combining items in Waxworks - - Fixed display of spell descriptions in Elvira 2 + - Added support for the original cutscenes of The Feeble Files. + - Added support for text compression in the AtariST version of Elvira 1. + - Fixed combining items in Waxworks. + - Fixed display of spell descriptions in Elvira 2. KYRA: - Added support for Auto-save feature. - Added support for MIDI music. Parallaction: - - Credits of the Nippon Safes Amiga demo are now shown correctly + - Credits of the Nippon Safes Amiga demo are now shown correctly. SCUMM: - Implemented radio-chatter effect in The DIG. @@ -126,13 +136,13 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Added support for the Macintosh version of I Have no Mouth, and I must Scream. - Added support for Drascula: The Vampire Strikes Back. - + General: - Added CAMD MIDI driver for AmigaOS4. - Revived the PS2 port (was already in 0.11.1 but was forgotten in the release notes). - - Plugged numerous memory leaks in all engines (part of GSoC'08 task), - - Added audio double buffering to the SDL backend, which fixes the + - Plugged numerous memory leaks in all engines (part of GSoC'08 task). + - Added audio double buffering to the SDL backend, which fixes the problems with the MT-32 emulator on Mac OS X (for now only enabled on Mac OS X). @@ -433,12 +443,12 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Fixed sound distortion in the Inherit the Earth demo. Simon - - Improved Hebrew support + - Improved Hebrew support. - Lots of long-overdue cleanups and re-structuring were made to accomodate for The Feeble Files. - Fixed a rare MIDI bug that would cause a channel to change volume without adjusting it to the master volume. - - Fixed delay after introduction of Simon the Sorcerer 1 demo (With speech) + - Fixed delay after introduction of Simon the Sorcerer 1 demo (with speech). - Fixed music tempo in DOS versions of Simon the Sorcerer 1. Broken Sword 1: @@ -1089,6 +1089,7 @@ other games. Cmd-q - Quit (Mac OS X) Ctrl-q - Quit (other unices including Linux) Ctrl-z OR Alt-x - Quit (other platforms) + Ctrl-u - Mute all sounds Ctrl-m - Toggle mouse capture Ctrl-Alt 1-8 - Switch between graphics filters Ctrl-Alt + and - - Increase/Decrease the scale factor diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index 9b2c8df287..4fdf96e57e 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -278,7 +278,7 @@ void DefaultEventManager::init() { if (ConfMan.hasKey("vkeybd_pack_name")) { _vk->loadKeyboardPack(ConfMan.get("vkeybd_pack_name")); } else { - _vk->loadKeyboardPack("vkeybd"); + _vk->loadKeyboardPack("vkeybd_default"); } #endif } @@ -553,6 +553,11 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { _shouldRTL = true; break; + case Common::EVENT_MUTE: + if (g_engine) + g_engine->flipMute(); + break; + case Common::EVENT_QUIT: if (ConfMan.getBool("confirm_exit")) { if (_confirmExitDialogActive) { diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index d53ae588f8..0440acdd0a 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -39,16 +39,17 @@ enum { }; RemapDialog::RemapDialog() - : Dialog("KeyRemapper"), _keymapTable(0), _activeRemapAction(0), _topAction(0), _remapTimeout(0) { + : Dialog("KeyMapper"), _keymapTable(0), _activeRemapAction(0), _topAction(0), _remapTimeout(0) { _keymapper = g_system->getEventManager()->getKeymapper(); assert(_keymapper); - _kmPopUp = new GUI::PopUpWidget(this, "KeyRemapper.Popup", "Keymap: "); + _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", "Keymap:"); + _kmPopUp = new GUI::PopUpWidget(this, "KeyMapper.Popup"); _scrollBar = new GUI::ScrollBarWidget(this, 0, 0, 0, 0); - new GUI::ButtonWidget(this, "KeyRemapper.Close", "Close", kCloseCmd); + new GUI::ButtonWidget(this, "KeyMapper.Close", "Close", kCloseCmd); } RemapDialog::~RemapDialog() { @@ -137,12 +138,12 @@ void RemapDialog::reflowLayout() { int16 areaX, areaY; uint16 areaW, areaH; - int spacing = g_gui.xmlEval()->getVar("Globals.KeyRemapper.Spacing"); - int labelWidth = g_gui.xmlEval()->getVar("Globals.KeyRemapper.LabelWidth"); - int buttonWidth = g_gui.xmlEval()->getVar("Globals.KeyRemapper.ButtonWidth"); + int spacing = g_gui.xmlEval()->getVar("Globals.KeyMapper.Spacing"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.KeyMapper.LabelWidth"); + int buttonWidth = g_gui.xmlEval()->getVar("Globals.KeyMapper.ButtonWidth"); int colWidth = labelWidth + buttonWidth + spacing; - g_gui.xmlEval()->getWidgetData((const String&)String("KeyRemapper.KeymapArea"), areaX, areaY, areaW, areaH); + g_gui.xmlEval()->getWidgetData((const String&)String("KeyMapper.KeymapArea"), areaX, areaY, areaW, areaH); _colCount = (areaW - scrollbarWidth) / colWidth; _rowCount = (areaH + spacing) / (buttonHeight + spacing); diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h index abec8a2d5c..88f099520a 100644 --- a/backends/keymapper/remap-dialog.h +++ b/backends/keymapper/remap-dialog.h @@ -76,6 +76,7 @@ protected: Rect _keymapArea; + GUI::StaticTextWidget *_kmPopUpDesc; GUI::PopUpWidget *_kmPopUp; //GUI::ContainerWidget *_container; GUI::ScrollBarWidget *_scrollBar; diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp index 5b7f071fd9..3522975679 100644 --- a/backends/midi/seq.cpp +++ b/backends/midi/seq.cpp @@ -142,7 +142,7 @@ void MidiDriver_SEQ::send(uint32 b) { warning("MidiDriver_SEQ::send: unknown : %08x", (int)b); break; } - write(device, buf, position); + (void)write(device, buf, position); } void MidiDriver_SEQ::sysEx (const byte *msg, uint16 length) { @@ -167,7 +167,7 @@ void MidiDriver_SEQ::sysEx (const byte *msg, uint16 length) { buf[position++] = _device_num; buf[position++] = 0; - write (device, buf, position); + (void)write(device, buf, position); } diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index ecb6dd7e8a..c813441724 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -221,7 +221,7 @@ int MidiDriver_TIMIDITY::open() { * "200 Ready data connection" */ res = timidity_ctl_command(NULL); if (atoi(res) != 200) { - fprintf(stderr, "Can't connect timidity: %s\t(host=%s, port=%d)\n", res, timidity_host, data_port); + warning("Can't connect timidity: %s\t(host=%s, port=%d)", res, timidity_host, data_port); close_all(); return -1; } @@ -334,7 +334,7 @@ char *MidiDriver_TIMIDITY::timidity_ctl_command(const char *fmt, ...) { buff[len++] = '\n'; /* write command to control socket */ - write(_control_fd, buff, len); + (void)write(_control_fd, buff, len); } while (1) { diff --git a/backends/platform/PalmOS/Src/be_os5.cpp b/backends/platform/PalmOS/Src/be_os5.cpp index aa578dad9c..91e9818c02 100644 --- a/backends/platform/PalmOS/Src/be_os5.cpp +++ b/backends/platform/PalmOS/Src/be_os5.cpp @@ -115,6 +115,10 @@ void OSystem_PalmOS5::setFeatureState(Feature f, bool enable) { } void OSystem_PalmOS5::setWindowCaption(const char *caption) { +FIXME/TODO: Convert caption from ISO Latin 1 to "right" encoding ? +If the output encoding is unclear or conversion impossible, +then one could just skip over any chars > 0x7F and display the rest + Err e; Char buf[64]; Coord w, y, h = FntLineHeight() + 2; diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index 0ccd69593e..f86a2c6065 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -232,5 +232,5 @@ class OSystem_Dreamcast : private DCHardware, public BaseBackend, public Filesys extern int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, byte &shiftFlags, Interactive *inter = NULL); -extern bool selectGame(char *&, char *&, class Icon &); +extern bool selectGame(char *&, char *&, Common::Language &, Common::Platform &, class Icon &); diff --git a/backends/platform/dc/dcmain.cpp b/backends/platform/dc/dcmain.cpp index 7a0f71ad1a..795504d243 100644 --- a/backends/platform/dc/dcmain.cpp +++ b/backends/platform/dc/dcmain.cpp @@ -234,8 +234,10 @@ int main() int DCLauncherDialog::runModal() { char *base = NULL, *dir = NULL; + Common::Language language = Common::UNK_LANG; + Common::Platform platform = Common::kPlatformUnknown; - if (!selectGame(base, dir, icon)) + if (!selectGame(base, dir, language, platform, icon)) g_system->quit(); // Set the game path. @@ -243,6 +245,14 @@ int DCLauncherDialog::runModal() if (dir != NULL) ConfMan.set("path", dir, base); + // Set the game language. + if (language != Common::UNK_LANG) + ConfMan.set("language", Common::getLanguageCode(language), base); + + // Set the game platform. + if (platform != Common::kPlatformUnknown) + ConfMan.set("platform", Common::getPlatformCode(platform), base); + // Set the target. ConfMan.setActiveDomain(base); diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 9465769ea3..e2998234c3 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -138,6 +138,8 @@ struct Game char dir[256]; char filename_base[256]; char text[256]; + Common::Language language; + Common::Platform platform; Icon icon; Label label; }; @@ -183,11 +185,15 @@ static void makeDefIcon(Icon &icon) icon.load(scummvm_icon, sizeof(scummvm_icon)); } -static bool uniqueGame(const char *base, const char *dir, Game *games, int cnt) +static bool uniqueGame(const char *base, const char *dir, + Common::Language lang, Common::Platform plf, + Game *games, int cnt) { while (cnt--) if (!strcmp(dir, games->dir) && - !stricmp(base, games->filename_base)) + !stricmp(base, games->filename_base) && + lang == games->language && + plf == games->platform) return false; else games++; @@ -227,14 +233,20 @@ static int findGames(Game *games, int max) if (curr_game < max) { strcpy(games[curr_game].filename_base, ge->gameid().c_str()); strcpy(games[curr_game].dir, dirs[curr_dir-1].name); + games[curr_game].language = ge->language(); + games[curr_game].platform = ge->platform(); if (uniqueGame(games[curr_game].filename_base, - games[curr_game].dir, games, curr_game)) { + games[curr_game].dir, + games[curr_game].language, + games[curr_game].platform, games, curr_game)) { strcpy(games[curr_game].text, ge->description().c_str()); #if 0 - printf("Registered game <%s> in <%s> <%s> because of <%s> <*>\n", - games[curr_game].text, games[curr_game].dir, - games[curr_game].filename_base, + printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n", + games[curr_game].text, + (int)games[curr_game].language, + (int)games[curr_game].platform, + games[curr_game].dir, games[curr_game].filename_base, dirs[curr_dir-1].name); #endif curr_game++; @@ -405,7 +417,7 @@ int gameMenu(Game *games, int num_games) } } -bool selectGame(char *&ret, char *&dir_ret, Icon &icon) +bool selectGame(char *&ret, char *&dir_ret, Common::Language &lang_ret, Common::Platform &plf_ret, Icon &icon) { Game *games = new Game[MAX_GAMES]; int selected, num_games; @@ -449,6 +461,8 @@ bool selectGame(char *&ret, char *&dir_ret, Icon &icon) dir_ret = the_game.dir; #endif ret = the_game.filename_base; + lang_ret = the_game.language; + plf_ret = the_game.platform; icon = the_game.icon; return true; } else diff --git a/backends/platform/ds/arm7/Makefile b/backends/platform/ds/arm7/Makefile index 82637845db..a8dc0efe6e 100644 --- a/backends/platform/ds/arm7/Makefile +++ b/backends/platform/ds/arm7/Makefile @@ -151,13 +151,12 @@ $(OUTPUT).elf : $(OFILES) #--------------------------------------------------------------------------------- %.bin: %.elf @echo built ... $(notdir $@) - @$(OBJCOPY) -O binary $(TARGET).elf $@ + $(OBJCOPY) -O binary $(TARGET).elf $@ #--------------------------------------------------------------------------------- %.elf: echo ELF - @echo $(LD) $(LDFLAGS) -specs=ds_arm7.specs $(OFILES) $(LIBPATHS) $(LIBS) -o $(TARGET).elf - @$(LD) $(LDFLAGS) -specs=ds_arm7.specs $(OFILES) $(LIBPATHS) $(LIBS) -o $(TARGET).elf + $(LD) $(LDFLAGS) -specs=ds_arm7.specs $(OFILES) $(LIBPATHS) $(LIBS) -o $(TARGET).elf diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp index 0e8dd9efeb..7029d96405 100644 --- a/backends/platform/ds/arm7/source/main.cpp +++ b/backends/platform/ds/arm7/source/main.cpp @@ -585,7 +585,7 @@ int main(int argc, char ** argv) { //enable sound // powerOn(POWER_SOUND); - REG_SOUNDCNT = SOUND_ENABLE | SOUND_VOL(0x7F); + SOUND_CR = SOUND_ENABLE | SOUND_VOL(0x7F); IPC->soundData = 0; IPC->reset = false; diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index e35e5edea0..954a33b61d 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -642,12 +642,6 @@ void OSystem_DS::quit() { swiSoftReset();*/ } -void OSystem_DS::setWindowCaption(const char *caption) { -} - -void OSystem_DS::displayMessageOnOSD(const char *msg) { -} - Common::SaveFileManager* OSystem_DS::getSavefileManager() { bool forceSram; diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 5a26a25c8b..3db23a5687 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -134,10 +134,6 @@ public: virtual void quit(); - virtual void setWindowCaption(const char *caption); - - virtual void displayMessageOnOSD(const char *msg); - virtual Common::SaveFileManager *getSavefileManager(); void addEvent(Common::Event& e); diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh index 8d48dcfb06..560f096ed4 100755 --- a/backends/platform/gp2x/build/bundle.sh +++ b/backends/platform/gp2x/build/bundle.sh @@ -12,6 +12,7 @@ export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib echo Collecting files. mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`" mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/saves" +mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/plugins" mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data" echo "Please put your save games in this dir" >> "scummvm-gp2x-`date '+%Y-%m-%d'`/saves/PUT_SAVES_IN_THIS_DIR" @@ -28,8 +29,10 @@ cp ../../../../COPYING ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../gui/themes/scummmodern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/ +cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../dists/engine-data/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data +cp ../../../../plugins/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/plugins echo Making Stripped GPE. arm-open2x-linux-strip ./scummvm-gp2x-`date '+%Y-%m-%d'`/scummvm.gp2x diff --git a/backends/platform/gp2x/build/config-alleng.sh b/backends/platform/gp2x/build/config-alleng.sh new file mode 100755 index 0000000000..5724f39dc5 --- /dev/null +++ b/backends/platform/gp2x/build/config-alleng.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +echo Quick script to make running configure all the time less painful +echo and let all the build work be done from the backend/build folder. + +# Set the paths up here to generate the config. + +PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH +PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH + +# Export the tool names for cross-compiling +export CXX=arm-open2x-linux-g++ +export CXXFLAGS=-march=armv4t +export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include +export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib +export DEFINES=-DNDEBUG + +# Edit the configure line to suit. +cd ../../../.. +./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-all-engines --enable-vkeybd +# --enable-plugins --default-dynamic + +echo Generating config for GP2X complete. Check for errors. diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gp2x/build/config.sh index 17083d1ea4..55954d6231 100755 --- a/backends/platform/gp2x/build/config.sh +++ b/backends/platform/gp2x/build/config.sh @@ -17,7 +17,7 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-made --enable-m4 -#--enable-plugins --default-dynamic +./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd +# --enable-plugins --default-dynamic echo Generating config for GP2X complete. Check for errors. diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp index 1c0fb398db..9a9a59765d 100644 --- a/backends/platform/gp2x/events.cpp +++ b/backends/platform/gp2x/events.cpp @@ -38,33 +38,33 @@ // we should really allow users to map any key to a joystick button #define JOY_DEADZONE 2200 -// #define JOY_INVERT_Y #define JOY_XAXIS 0 #define JOY_YAXIS 1 -// GP2X Stick Buttons (Note: The Stick is read as a set of buttons not a HAT type of setup). -#define JOY_BUT_LMOUSE 0x0D -#define JOY_BUT_RMOUSE 0x0E - -#define JOY_BUT_RETURN 0x08 -#define JOY_BUT_ESCAPE 0x09 -#define JOY_BUT_F5 0x0B -#define JOY_BUT_SPACE 0x0F -#define JOY_BUT_TALKUP 0x10 -#define JOY_BUT_TALKDN 0x11 -#define JOY_BUT_ZERO 0x12 - -#define JOY_BUT_COMB 0x0A -#define JOY_BUT_EXIT 0x12 -#define JOY_BUT_PERIOD 0x0C - - -//TODO: Quick hack 101 ;-) Clean this up, -#define TRUE 1 -#define FALSE 0 - -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) -{ +/* GP2X Wiz: Main Joystick Mappings */ +enum { + GP2X_BUTTON_UP = 0, + GP2X_BUTTON_UPLEFT = 1, + GP2X_BUTTON_LEFT = 2, + GP2X_BUTTON_DOWNLEFT = 3, + GP2X_BUTTON_DOWN = 4, + GP2X_BUTTON_DOWNRIGHT = 5, + GP2X_BUTTON_RIGHT = 6, + GP2X_BUTTON_UPRIGHT = 7, + GP2X_BUTTON_START = 8, + GP2X_BUTTON_SELECT = 9, + GP2X_BUTTON_L = 10, + GP2X_BUTTON_R = 11, + GP2X_BUTTON_A = 12, + GP2X_BUTTON_B = 13, + GP2X_BUTTON_X = 14, + GP2X_BUTTON_Y = 15, + GP2X_BUTTON_VOLUP = 16, + GP2X_BUTTON_VOLDOWN = 17, + GP2X_BUTTON_CLICK = 18 +}; + +static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { if (key >= SDLK_F1 && key <= SDLK_F9) { return key - SDLK_F1 + Common::ASCII_F1; } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { @@ -197,10 +197,9 @@ void OSystem_GP2X::moveStick() { if (_km.x_down_count!=2){ _km.x_vel = 1; _km.x_down_count = 1; - }else + } else _km.x_vel = 4; - } - else{ + } else { _km.x_vel = 0; _km.x_down_count = 0; } @@ -216,36 +215,16 @@ void OSystem_GP2X::moveStick() { if (_km.y_down_count!=2){ _km.y_vel = 1; _km.y_down_count = 1; - }else + } else _km.y_vel = 4; - } - else{ + } else { _km.y_vel = 0; _km.y_down_count = 0; } } - //Quick default button states for modifier. - - //int GP2X_BUTTON_STATE_UP = FALSE; - //int GP2X_BUTTON_STATE_DOWN = FALSE; - //int GP2X_BUTTON_STATE_LEFT = FALSE; - //int GP2X_BUTTON_STATE_RIGHT = FALSE; - //int GP2X_BUTTON_STATE_UPLEFT = FALSE; - //int GP2X_BUTTON_STATE_UPRIGHT = FALSE; - //int GP2X_BUTTON_STATE_DOWNLEFT = FALSE; - //int GP2X_BUTTON_STATE_DOWNRIGHT = FALSE; - //int GP2X_BUTTON_STATE_CLICK = FALSE; - //int GP2X_BUTTON_STATE_A = FALSE; - //int GP2X_BUTTON_STATE_B = FALSE; - //int GP2X_BUTTON_STATE_Y = FALSE; - //int GP2X_BUTTON_STATE_X = FALSE; - int GP2X_BUTTON_STATE_L = FALSE; - //int GP2X_BUTTON_STATE_R = FALSE; - //int GP2X_BUTTON_STATE_START = FALSE; - //int GP2X_BUTTON_STATE_SELECT = FALSE; - //int GP2X_BUTTON_STATE_VOLUP = FALSE; - //int GP2X_BUTTON_STATE_VOLDOWN = FALSE; +/* Quick default button states for modifiers. */ +int GP2X_BUTTON_STATE_L = false; bool OSystem_GP2X::pollEvent(Common::Event &event) { SDL_Event ev; @@ -273,8 +252,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { GP2X_BUTTON_LEFT Cursor Left GP2X_BUTTON_RIGHT Cursor Right - TODO: Add extra directions to cursor mappings. - GP2X_BUTTON_UPLEFT Cursor Up Left GP2X_BUTTON_UPRIGHT Cursor Up Right GP2X_BUTTON_DOWNLEFT Cursor Down Left @@ -288,8 +265,8 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { GP2X_BUTTON_Y Space Bar GP2X_BUTTON_X Right Mouse Click GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R F5 (Right Trigger) - GP2X_BUTTON_START Return + GP2X_BUTTON_R Return (Right Trigger) + GP2X_BUTTON_START F5 (Game Menu) GP2X_BUTTON_SELECT Escape GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down @@ -299,6 +276,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis. + GP2X_BUTTON_L & GP2X_BUTTON_START Common::EVENT_MAINMENU (ScummVM Global Main Menu) GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) */ @@ -357,6 +335,10 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { else if (ev.button.button == SDL_BUTTON_WHEELDOWN) event.type = Common::EVENT_WHEELDOWN; #endif +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONDOWN; +#endif else break; @@ -369,6 +351,10 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { event.type = Common::EVENT_LBUTTONUP; else if (ev.button.button == SDL_BUTTON_RIGHT) event.type = Common::EVENT_RBUTTONUP; +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONUP; +#endif else break; fillMouseEvent(event, ev.button.x, ev.button.y); @@ -379,16 +365,16 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { case SDL_JOYBUTTONDOWN: _stickBtn[ev.jbutton.button] = 1; - if (ev.jbutton.button == JOY_BUT_LMOUSE) { + if (ev.jbutton.button == GP2X_BUTTON_B) { event.type = Common::EVENT_LBUTTONDOWN; fillMouseEvent(event, _km.x, _km.y); } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { event.type = Common::EVENT_LBUTTONDOWN; fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { + } else if (ev.jbutton.button == GP2X_BUTTON_X) { event.type = Common::EVENT_RBUTTONDOWN; fillMouseEvent(event, _km.x, _km.y); - } else if (_stickBtn[JOY_BUT_COMB] && (ev.jbutton.button == JOY_BUT_EXIT)) { + } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { event.type = Common::EVENT_QUIT; } else if (ev.jbutton.button < 8) { moveStick(); @@ -399,19 +385,24 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { event.kbd.flags = 0; switch (ev.jbutton.button) { case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = TRUE; + GP2X_BUTTON_STATE_L = true; break; case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == TRUE) { + if (GP2X_BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else event.kbd.keycode = Common::KEYCODE_0; event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); } break; case GP2X_BUTTON_SELECT: - if (GP2X_BUTTON_STATE_L == TRUE) { + if (GP2X_BUTTON_STATE_L == true) { event.type = Common::EVENT_QUIT; } else { event.kbd.keycode = Common::KEYCODE_ESCAPE; @@ -419,7 +410,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { } break; case GP2X_BUTTON_A: - if (GP2X_BUTTON_STATE_L == TRUE) { + if (GP2X_BUTTON_STATE_L == true) { event.type = Common::EVENT_PREDICTIVE_DIALOG; } else { event.kbd.keycode = Common::KEYCODE_PERIOD; @@ -427,39 +418,21 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { } break; case GP2X_BUTTON_Y: - if (GP2X_BUTTON_STATE_L == TRUE) { + if (GP2X_BUTTON_STATE_L == true) { setZoomOnMouse(); } else { event.kbd.keycode = Common::KEYCODE_SPACE; event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); } break; - case JOY_BUT_RETURN: - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - break; - case JOY_BUT_ZERO: - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); + case GP2X_BUTTON_START: + if (GP2X_BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } break; - - //case GP2X_BUTTON_R: - // if ((ev.jbutton.button == GP2X_BUTTON_L) && (ev.jbutton.button == GP2X_BUTTON_R)) { - // displayMessageOnOSD("Exiting ScummVM"); - // //Sync(); - // event.type = Common::EVENT_QUIT; - // break; - // } else if ((ev.jbutton.button == GP2X_BUTTON_L) && (ev.jbutton.button != GP2X_BUTTON_R)) { - // displayMessageOnOSD("Left Trigger Pressed"); - // break; - // } else if ((ev.jbutton.button == GP2X_BUTTON_R) && (ev.jbutton.button != GP2X_BUTTON_L)) { - // event.kbd.keycode = Common::KEYCODE_F5; - // event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - // break; - // } else { - // break; - // } - // break; case GP2X_BUTTON_VOLUP: //if (GP2X_BUTTON_STATE_L == TRUE) { // displayMessageOnOSD("Setting CPU Speed at 230MHz"); @@ -490,10 +463,13 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { case SDL_JOYBUTTONUP: _stickBtn[ev.jbutton.button] = 0; - if (ev.jbutton.button == JOY_BUT_LMOUSE) { + if (ev.jbutton.button == GP2X_BUTTON_B) { event.type = Common::EVENT_LBUTTONUP; fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { + } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + } else if (ev.jbutton.button == GP2X_BUTTON_X) { event.type = Common::EVENT_RBUTTONUP; fillMouseEvent(event, _km.x, _km.y); } else if (ev.jbutton.button < 8) { @@ -517,15 +493,29 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); break; case GP2X_BUTTON_START: - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + if (GP2X_BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } break; case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = FALSE; + GP2X_BUTTON_STATE_L = false; break; case GP2X_BUTTON_R: - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + if (GP2X_BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } break; case GP2X_BUTTON_VOLUP: break; diff --git a/backends/platform/gp2x/gp2x-hw.h b/backends/platform/gp2x/gp2x-hw.h index 0427698bc4..89ad1093e4 100644 --- a/backends/platform/gp2x/gp2x-hw.h +++ b/backends/platform/gp2x/gp2x-hw.h @@ -31,29 +31,6 @@ #ifndef GP2X_HW_H #define GP2X_HW_H -//GP2X Main Joystick Mappings -//TODO: Use these more standard mappings over the custom ones. - -#define GP2X_BUTTON_UP (0) -#define GP2X_BUTTON_UPLEFT (1) -#define GP2X_BUTTON_LEFT (2) -#define GP2X_BUTTON_DOWNLEFT (3) -#define GP2X_BUTTON_DOWN (4) -#define GP2X_BUTTON_DOWNRIGHT (5) -#define GP2X_BUTTON_RIGHT (6) -#define GP2X_BUTTON_UPRIGHT (7) -#define GP2X_BUTTON_START (8) -#define GP2X_BUTTON_SELECT (9) -#define GP2X_BUTTON_L (10) -#define GP2X_BUTTON_R (11) -#define GP2X_BUTTON_A (12) -#define GP2X_BUTTON_B (13) -#define GP2X_BUTTON_X (14) -#define GP2X_BUTTON_Y (15) -#define GP2X_BUTTON_VOLUP (16) -#define GP2X_BUTTON_VOLDOWN (17) -#define GP2X_BUTTON_CLICK (18) - #define GP2X_MAXVOL 100 // Highest level permitted by GP2X's mixer #define SYS_CLK_FREQ 7372800 // Clock Frequency diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 62c65e8f5e..15b5e19e5d 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -33,15 +33,14 @@ #include "backends/platform/gp2x/gp2x-mem.h" #include "common/archive.h" #include "common/config-manager.h" - +#include "common/debug.h" #include "common/events.h" #include "common/util.h" -#include "common/debug.h" #include "common/file.h" #include "base/main.h" -#include "backends/saves/posix/posix-saves.h" +#include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" #include "backends/plugins/posix/posix-provider.h" @@ -72,15 +71,12 @@ static Uint32 timer_handler(Uint32 interval, void *param) { } int main(int argc, char *argv[]) { - //extern OSystem *OSystem_GP2X_create(); - //g_system = OSystem_GP2X_create(); g_system = new OSystem_GP2X(); assert(g_system); - // Check if Plugins are enabled (Using the hacked up GP2X provider) - #ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new GP2XPluginProvider()); - #endif +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); +#endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); @@ -115,7 +111,8 @@ void OSystem_GP2X::initBackend() { #endif char savePath[PATH_MAX+1]; - char workDirName[PATH_MAX+1]; /* To be passed to getcwd system call. */ + char workDirName[PATH_MAX+1]; + if (getcwd(workDirName, PATH_MAX) == NULL) { error("Could not obtain current working directory."); } else { @@ -133,25 +130,9 @@ void OSystem_GP2X::initBackend() { ConfMan.registerDefault("savepath", savePath); - // Setup default extra data path for engine data files to be workingdir/engine-data - - char enginedataPath[PATH_MAX+1]; - - strcpy(enginedataPath, workDirName); - strcat(enginedataPath, "/engine-data"); - printf("Current engine-data directory: %s\n", enginedataPath); - //struct stat sb; - if (stat(enginedataPath, &sb) == -1) - if (errno == ENOENT) // Create the dir if it does not exist - if (mkdir(enginedataPath, 0755) != 0) - warning("mkdir for '%s' failed", enginedataPath); - - //FIXME: Do not use File::addDefaultDirectory, rather implement OSystem::addSysArchivesToSearchSet() ! - Common::File::addDefaultDirectory(enginedataPath); - - // Note: Review and clean this, it's OTT at the moment. + _savefile = new DefaultSaveFileManager(savePath); - #if defined(DUMP_STDOUT) + #ifdef DUMP_STDOUT // The GP2X has a serial console but most users do not use this so we // output all our STDOUT and STDERR to files for debug purposes. char STDOUT_FILE[PATH_MAX+1]; @@ -168,7 +149,7 @@ void OSystem_GP2X::initBackend() { /* Redirect standard input and standard output */ FILE *newfp = freopen(STDOUT_FILE, "w", stdout); - if (newfp == NULL) { /* This happens on NT */ + if (newfp == NULL) { #if !defined(stdout) stdout = fopen(STDOUT_FILE, "w"); #else @@ -178,8 +159,9 @@ void OSystem_GP2X::initBackend() { } #endif } + newfp = freopen(STDERR_FILE, "w", stderr); - if (newfp == NULL) { /* This happens on NT */ + if (newfp == NULL) { #if !defined(stderr) stderr = fopen(STDERR_FILE, "w"); #else @@ -189,8 +171,10 @@ void OSystem_GP2X::initBackend() { } #endif } - setbuf(stderr, NULL); /* No buffering */ - #endif // DUMP_STDOUT + + setbuf(stderr, NULL); + printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); + #endif /* DUMP_STDOUT */ _graphicsMutex = createMutex(); @@ -199,7 +183,9 @@ void OSystem_GP2X::initBackend() { // Setup other defaults. ConfMan.registerDefault("aspect_ratio", true); - ConfMan.registerDefault("music_volume", 220); // Up default volume as we use a seperate volume system anyway. + + /* Up default volume values as we use a seperate system level volume anyway. */ + ConfMan.registerDefault("music_volume", 220); ConfMan.registerDefault("sfx_volume", 220); ConfMan.registerDefault("speech_volume", 220); ConfMan.registerDefault("autosave_period", 3 * 60); // Trigger autosave every 3 minutes - On low batts 4 mins is about your warning time. @@ -223,12 +209,6 @@ void OSystem_GP2X::initBackend() { _joystick = SDL_JoystickOpen(joystick_num); } - // Create the savefile manager, if none exists yet (we check for this to - // allow subclasses to provide their own). - if (_savefile == 0) { - _savefile = new POSIXSaveFileManager(); - } - // Create and hook up the mixer, if none exists yet (we check for this to // allow subclasses to provide their own). if (_mixer == 0) { @@ -367,32 +347,37 @@ FilesystemFactory *OSystem_GP2X::getFilesystemFactory() { } void OSystem_GP2X::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + /* Setup default extra data paths for engine data files and plugins */ + char workDirName[PATH_MAX+1]; -#ifdef DATA_PATH - // Add the global DATA_PATH to the directory search list - // FIXME: We use depth = 4 for now, to match the old code. May want to change that - Common::FSNode dataNode(DATA_PATH); - if (dataNode.exists() && dataNode.isDirectory()) { - s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority); + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Error: Could not obtain current working directory."); } -#endif -#if defined(MACOSX) || defined(IPHONE) - // Get URL of the Resource directory of the .app bundle - CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); - if (fileUrl) { - // Try to convert the URL to an absolute path - UInt8 buf[MAXPATHLEN]; - if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) { - // Success: Add it to the search path - Common::String bundlePath((const char *)buf); - s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority); - } - CFRelease(fileUrl); + Common::FSNode workdirNode(workDirName); + if (workdirNode.exists() && workdirNode.isDirectory()) { + s.add("__GP2X_WORKDIR__", new Common::FSDirectory(workDirName), priority); } -#endif + char enginedataPath[PATH_MAX+1]; + + strcpy(enginedataPath, workDirName); + strcat(enginedataPath, "/engine-data"); + + Common::FSNode engineNode(enginedataPath); + if (engineNode.exists() && engineNode.isDirectory()) { + s.add("__GP2X_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); + } + + char pluginsPath[PATH_MAX+1]; + + strcpy(pluginsPath, workDirName); + strcat(pluginsPath, "/plugins"); + Common::FSNode pluginsNode(pluginsPath); + if (pluginsNode.exists() && pluginsNode.isDirectory()) { + s.add("__GP2X_PLUGINS__", new Common::FSDirectory(pluginsPath), priority); + } } static Common::String getDefaultConfigFileName() { @@ -479,6 +464,12 @@ void OSystem_GP2X::quit() { delete getEventManager(); + #ifdef DUMP_STDOUT + printf("%s\n", "Debug: STDOUT and STDERR text files closed."); + fclose(stdout); + fclose(stderr); + #endif /* DUMP_STDOUT */ + exit(0); } diff --git a/backends/platform/gp2xwiz/build/bundle.sh b/backends/platform/gp2xwiz/build/bundle.sh index 1dcdb6389e..506dfcb742 100755 --- a/backends/platform/gp2xwiz/build/bundle.sh +++ b/backends/platform/gp2xwiz/build/bundle.sh @@ -22,6 +22,7 @@ cp ../../../../COPYING ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ cp ../../../../COPYRIGHT ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ cp ../../../../NEWS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ cp ../../../../gui/themes/scummmodern.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ +cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ cp ../../../../dists/pred.dic ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ cp ../../../../dists/engine-data/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data cp ../../../../plugins/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins diff --git a/backends/platform/gp2xwiz/build/config-alleng.sh b/backends/platform/gp2xwiz/build/config-alleng.sh index 19ee308908..cfed463edf 100755 --- a/backends/platform/gp2xwiz/build/config-alleng.sh +++ b/backends/platform/gp2xwiz/build/config-alleng.sh @@ -17,6 +17,6 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-all-engines --enable-plugins --default-dynamic +./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gp2xwiz/build/config.sh b/backends/platform/gp2xwiz/build/config.sh index b6889fe3ac..27c1fbf0bf 100755 --- a/backends/platform/gp2xwiz/build/config.sh +++ b/backends/platform/gp2xwiz/build/config.sh @@ -17,6 +17,6 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-plugins --default-dynamic +./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gp2xwiz/gp2xwiz-events.cpp b/backends/platform/gp2xwiz/gp2xwiz-events.cpp index ea1b191213..dfb36742dc 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-events.cpp +++ b/backends/platform/gp2xwiz/gp2xwiz-events.cpp @@ -30,7 +30,7 @@ #include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" #include "backends/platform/gp2xwiz/gp2xwiz-hw.h" -#include "backends/keymapper/keymapper.h" + #include "common/util.h" #include "common/events.h" @@ -41,6 +41,28 @@ #define JOY_XAXIS 0 #define JOY_YAXIS 1 +/* GP2X Wiz: Main Joystick Mappings */ +enum { + GP2X_BUTTON_UP = 0, + GP2X_BUTTON_UPLEFT = 1, + GP2X_BUTTON_LEFT = 2, + GP2X_BUTTON_DOWNLEFT = 3, + GP2X_BUTTON_DOWN = 4, + GP2X_BUTTON_DOWNRIGHT = 5, + GP2X_BUTTON_RIGHT = 6, + GP2X_BUTTON_UPRIGHT = 7, + GP2X_BUTTON_MENU = 8, + GP2X_BUTTON_SELECT = 9, + GP2X_BUTTON_L = 10, + GP2X_BUTTON_R = 11, + GP2X_BUTTON_A = 12, + GP2X_BUTTON_B = 13, + GP2X_BUTTON_X = 14, + GP2X_BUTTON_Y = 15, + GP2X_BUTTON_VOLUP = 16, + GP2X_BUTTON_VOLDOWN = 17 +}; + static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { if (key >= SDLK_F1 && key <= SDLK_F9) { return key - SDLK_F1 + Common::ASCII_F1; @@ -173,8 +195,8 @@ bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) { GP2X_BUTTON_Y Space Bar GP2X_BUTTON_X Right Mouse Click GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R F5 (Right Trigger) - GP2X_BUTTON_MENU Return + GP2X_BUTTON_R Return (Right Trigger) + GP2X_BUTTON_MENU F5 (Game Menu) GP2X_BUTTON_SELECT Escape GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down @@ -291,8 +313,13 @@ bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) { break; case GP2X_BUTTON_R: if (GP2X_BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else event.kbd.keycode = Common::KEYCODE_0; event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif } else { event.kbd.keycode = Common::KEYCODE_RETURN; event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); @@ -388,8 +415,13 @@ bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) { break; case GP2X_BUTTON_R: if (GP2X_BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else event.kbd.keycode = Common::KEYCODE_0; event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif } else { event.kbd.keycode = Common::KEYCODE_RETURN; event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); diff --git a/backends/platform/gp2xwiz/gp2xwiz-hw.cpp b/backends/platform/gp2xwiz/gp2xwiz-hw.cpp index c804b0d819..4d69915e27 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-hw.cpp +++ b/backends/platform/gp2xwiz/gp2xwiz-hw.cpp @@ -42,6 +42,16 @@ namespace WIZ_HW { +enum { + VOLUME_NOCHG = 0, + VOLUME_DOWN = 1, + VOLUME_UP = 2, + VOLUME_CHANGE_RATE = 8, + VOLUME_MIN = 0, + VOLUME_INITIAL = 70, + VOLUME_MAX = 100 +}; + int volumeLevel = VOLUME_INITIAL; void deviceInit() { diff --git a/backends/platform/gp2xwiz/gp2xwiz-hw.h b/backends/platform/gp2xwiz/gp2xwiz-hw.h index 577facc437..507841e902 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-hw.h +++ b/backends/platform/gp2xwiz/gp2xwiz-hw.h @@ -31,37 +31,8 @@ #ifndef GP2XWIZ_HW_H #define GP2XWIZ_HW_H -/* GP2X Wiz: Main Joystick Mappings */ - -#define GP2X_BUTTON_UP (0) -#define GP2X_BUTTON_UPLEFT (1) -#define GP2X_BUTTON_LEFT (2) -#define GP2X_BUTTON_DOWNLEFT (3) -#define GP2X_BUTTON_DOWN (4) -#define GP2X_BUTTON_DOWNRIGHT (5) -#define GP2X_BUTTON_RIGHT (6) -#define GP2X_BUTTON_UPRIGHT (7) -#define GP2X_BUTTON_MENU (8) -#define GP2X_BUTTON_SELECT (9) -#define GP2X_BUTTON_L (10) -#define GP2X_BUTTON_R (11) -#define GP2X_BUTTON_A (12) -#define GP2X_BUTTON_B (13) -#define GP2X_BUTTON_X (14) -#define GP2X_BUTTON_Y (15) -#define GP2X_BUTTON_VOLUP (16) -#define GP2X_BUTTON_VOLDOWN (17) - namespace WIZ_HW { -#define VOLUME_MIN 0 -#define VOLUME_INITIAL 70 /* Default volume if you call mixerMoveVolume(0) without setting the global var. */ -#define VOLUME_MAX 100 -#define VOLUME_CHANGE_RATE 8 -#define VOLUME_NOCHG 0 -#define VOLUME_DOWN 1 -#define VOLUME_UP 2 - extern int volumeLevel; extern void deviceInit(); diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m index 0392172aa2..61770a16c2 100644 --- a/backends/platform/iphone/iphone_video.m +++ b/backends/platform/iphone/iphone_video.m @@ -36,6 +36,9 @@ static int _textureHeight = 0; NSLock* _lock = nil; static int _needsScreenUpdate = 0; +static UITouch* _firstTouch = NULL; +static UITouch* _secondTouch = NULL; + // static long lastTick = 0; // static int frames = 0; @@ -47,14 +50,14 @@ void iPhone_updateScreen() { } void iPhone_updateScreenRect(unsigned short* screen, int x1, int y1, int x2, int y2) { - [_lock lock]; + //[_lock lock]; int y; for (y = y1; y < y2; ++y) { memcpy(&_textureBuffer[(y * _textureWidth + x1 )* 2], &screen[y * _width + x1], (x2 - x1) * 2); } - [_lock unlock]; + //[_lock unlock]; } @@ -192,12 +195,12 @@ uint getSizeNextPOT(uint size) { glVertexPointer(2, GL_FLOAT, 0, vertices); glTexCoordPointer(2, GL_FLOAT, 0, texCoords); - [_lock lock]; + //[_lock lock]; // Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases // due to the iPhone internals having to convert the whole texture back from its internal format when used. // In the future we could use several tiled textures instead. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureWidth, _textureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _textureBuffer); - [_lock unlock]; + //[_lock unlock]; glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); @@ -280,7 +283,7 @@ uint getSizeNextPOT(uint size) { glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); // The color buffer is triple-buffered, so we clear it multiple times right away to avid doing any glClears later. - int clearCount = 3; + int clearCount = 5; while (clearCount-- > 0) { glClear(GL_COLOR_BUFFER_BIT); [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; @@ -366,7 +369,6 @@ uint getSizeNextPOT(uint size) { ]; } - - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouches]; @@ -374,11 +376,12 @@ uint getSizeNextPOT(uint size) { switch ([allTouches count]) { case 1: { - UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; + UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; if (!getLocalMouseCoords(&point)) return; + _firstTouch = touch; [self addEvent: [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:kInputMouseDown], @"type", @@ -391,11 +394,12 @@ uint getSizeNextPOT(uint size) { } case 2: { - UITouch *touch = [[allTouches allObjects] objectAtIndex:1]; + UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; if (!getLocalMouseCoords(&point)) return; + _secondTouch = touch; [self addEvent: [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:kInputMouseSecondDown], @"type", @@ -413,14 +417,13 @@ uint getSizeNextPOT(uint size) { { NSSet *allTouches = [event allTouches]; - switch ([allTouches count]) { - case 1: - { - UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; + for (UITouch* touch in touches) { + if (touch == _firstTouch) { + CGPoint point = [touch locationInView:self]; if (!getLocalMouseCoords(&point)) return; - + [self addEvent: [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:kInputMouseDragged], @"type", @@ -429,15 +432,13 @@ uint getSizeNextPOT(uint size) { nil ] ]; - break; - } - case 2: - { - UITouch *touch = [[allTouches allObjects] objectAtIndex:1]; + + } else if (touch == _secondTouch) { + CGPoint point = [touch locationInView:self]; if (!getLocalMouseCoords(&point)) return; - + [self addEvent: [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:kInputMouseSecondDragged], @"type", @@ -446,7 +447,7 @@ uint getSizeNextPOT(uint size) { nil ] ]; - break; + } } } diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp index b72e8b65d5..7f30c0caaf 100644 --- a/backends/platform/iphone/osys_iphone.cpp +++ b/backends/platform/iphone/osys_iphone.cpp @@ -813,22 +813,22 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, return false; } + static const int kNeededLength = 100; + static const int kMaxDeviation = 20; + int vecX = (x - _gestureStartX); int vecY = (y - _gestureStartY); - int lengthSq = vecX * vecX + vecY * vecY; - //printf("Lengthsq: %u\n", lengthSq); + + int absX = abs(vecX); + int absY = abs(vecY); + + //printf("(%d, %d)\n", vecX, vecY); - if (lengthSq > 15000) { // Long enough gesture to react upon. + if (absX >= kNeededLength || absY >= kNeededLength) { // Long enough gesture to react upon. _gestureStartX = -1; _gestureStartY = -1; - float vecLength = sqrt(lengthSq); - float vecXNorm = vecX / vecLength; - float vecYNorm = vecY / vecLength; - - //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm); - - if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) { + if (absX < kMaxDeviation && vecY >= kNeededLength) { // Swipe down event.type = Common::EVENT_KEYDOWN; _queuedInputEvent.type = Common::EVENT_KEYUP; @@ -837,7 +837,10 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5; event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5; _needEventRestPeriod = true; - } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) { + return true; + } + + if (absX < kMaxDeviation && -vecY >= kNeededLength) { // Swipe up _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled; const char *dialogMsg; @@ -849,8 +852,9 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, GUI::TimedMessageDialog dialog(dialogMsg, 1500); dialog.runModal(); return false; - - } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) { + } + + if (absY < kMaxDeviation && vecX >= kNeededLength) { // Swipe right _touchpadModeEnabled = !_touchpadModeEnabled; const char *dialogMsg; @@ -862,7 +866,9 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, dialog.runModal(); return false; - } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) { + } + + if (absY < kMaxDeviation && -vecX >= kNeededLength) { // Swipe left return false; } @@ -1106,16 +1112,18 @@ void OSystem_IPHONE::AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBuf outQB->mAudioDataByteSize = 4 * s_AudioQueue.frameCount; s_soundCallback(s_soundParam, (byte *)outQB->mAudioData, outQB->mAudioDataByteSize); AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL); - } else + } else { AudioQueueStop(s_AudioQueue.queue, false); + } } void OSystem_IPHONE::mixCallback(void *sys, byte *samples, int len) { OSystem_IPHONE *this_ = (OSystem_IPHONE *)sys; assert(this_); - if (this_->_mixer) + if (this_->_mixer) { this_->_mixer->mixCallback(samples, len); + } } void OSystem_IPHONE::setupMixer() { @@ -1202,9 +1210,6 @@ void OSystem_IPHONE::getTimeAndDate(struct tm &t) const { t = *localtime(&curTime); } -void OSystem_IPHONE::setWindowCaption(const char *caption) { -} - Common::SaveFileManager *OSystem_IPHONE::getSavefileManager() { assert(_savefile); return _savefile; diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h index ceb2102a5f..705f89319a 100644 --- a/backends/platform/iphone/osys_iphone.h +++ b/backends/platform/iphone/osys_iphone.h @@ -171,8 +171,6 @@ public: virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); virtual void getTimeAndDate(struct tm &t) const; - virtual void setWindowCaption(const char *caption); - virtual Common::SaveFileManager *getSavefileManager(); virtual Audio::Mixer *getMixer(); virtual Common::TimerManager *getTimerManager(); diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp index 304b7e80eb..ca4eda9158 100644 --- a/backends/platform/null/null.cpp +++ b/backends/platform/null/null.cpp @@ -113,8 +113,6 @@ public: virtual void quit(); - virtual void setWindowCaption(const char *caption); - virtual Common::SaveFileManager *getSavefileManager(); virtual Audio::Mixer *getMixer(); virtual void getTimeAndDate(struct tm &t) const; @@ -308,9 +306,6 @@ bool OSystem_NULL::setSoundCallback(SoundProc proc, void *param) { void OSystem_NULL::quit() { } -void OSystem_NULL::setWindowCaption(const char *caption) { -} - Common::SaveFileManager *OSystem_NULL::getSavefileManager() { assert(_savefile); return _savefile; diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 29747c0943..ab27d93574 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -73,7 +73,6 @@ public: virtual void unlockScreen(); virtual void updateScreen(); /* TODO : check */ - virtual void fillScreen(unsigned int i) { printf("fillScreen %d\n", i); }; virtual void displayMessageOnOSD(const char *msg) { printf("displayMessageOnOSD: %s\n", msg); }; /* */ diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 63ea5bc0dc..45be0a0cd3 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -635,12 +635,6 @@ void OSystem_PSP::getTimeAndDate(struct tm &t) const { t = *localtime(&curTime); } -void OSystem_PSP::setWindowCaption(const char *caption) { -} - -void OSystem_PSP::displayMessageOnOSD(const char *msg) { -} - #define PSP_CONFIG_FILE "ms0:/scummvm.ini" Common::SeekableReadStream *OSystem_PSP::createConfigReadStream() { diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 7abba332df..34957b293c 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -140,10 +140,6 @@ public: virtual void quit(); - virtual void setWindowCaption(const char *caption); - - virtual void displayMessageOnOSD(const char *msg); - virtual Common::SeekableReadStream *createConfigReadStream(); virtual Common::WriteStream *createConfigWriteStream(); }; diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec index 223bd58098..807b8f93b7 100644 --- a/backends/platform/psp/psp.spec +++ b/backends/platform/psp/psp.spec @@ -1,3 +1,3 @@ %rename lib old_lib *lib: --lg -lm -lstdc++ -lsupc++ -lg -lpsprtc -lpspaudio -lpspuser -lpsputility -lpspdebug -lc -lpspgum -lpspvfpu -lpspgu -lpspctrl -lpspge -lpspdisplay_driver -lpspdisplay -lpsphprm -lpspge_driver -lpspsdk -lpsppower -lpsppower_driver -lpspgum_vfpu -lpspkernel %(old_lib) +%(old_lib) -lpspdebug -lpspgu -lpspctrl -lpspge -lpspdisplay -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lc -lpspuser -lpsputility -lpspkernel -lpspnet_inet -lz -lstdc++ -lc -lpspdisplay -lpspgu -lpspctrl -lpspsdk -lpspnet -lpspnet_inet -lpsputility -lpspsdk -lpspuser diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp index b4fc5e0777..feb2c9a9c5 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/platform/sdl/events.cpp @@ -252,6 +252,11 @@ bool OSystem_SDL::pollEvent(Common::Event &event) { } #endif + if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') { + event.type = Common::EVENT_MUTE; + return true; + } + // Ctrl-Alt-<key> will change the GFX mode if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 3f9b81a912..105206ec07 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -395,13 +395,20 @@ Common::WriteStream *OSystem_SDL::createConfigWriteStream() { } void OSystem_SDL::setWindowCaption(const char *caption) { - Common::String cap(caption); + Common::String cap; + byte c; + + // The string caption is supposed to be in LATIN-1 encoding. + // SDL expects UTF-8. So we perform the conversion here. + while ((c = *(const byte *)caption++)) { + if (c < 0x80) + cap += c; + else { + cap += 0xC0 | (c >> 6); + cap += 0x80 | (c & 0x3F); + } + } - // Filter out any non-ASCII characters, replacing them by question marks. - // At some point, we may wish to allow LATIN 1 or UTF-8. - for (uint i = 0; i < cap.size(); ++i) - if ((byte)cap[i] > 0x7F) - cap.setChar('?', i); SDL_WM_SetCaption(cap.c_str(), cap.c_str()); } @@ -487,7 +494,7 @@ void OSystem_SDL::quit() { void OSystem_SDL::setupIcon() { int x, y, w, h, ncols, nbytes, i; unsigned int rgba[256]; - unsigned int *icon; + unsigned int *icon; sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes); if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) { diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp index c45cef32bd..995b03f200 100644 --- a/backends/platform/symbian/src/SymbianActions.cpp +++ b/backends/platform/symbian/src/SymbianActions.cpp @@ -102,8 +102,15 @@ SymbianActions::SymbianActions() } void SymbianActions::initInstanceMain(OSystem *mainSystem) { + int i; + Actions::initInstanceMain(mainSystem); + // Disable all mappings before setting main mappings again + for (i = 0; i < ACTION_LAST; i++) { + _action_enabled[i] = false; + } + // Mouse Up _action_enabled[ACTION_UP] = true; diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index 452f730110..7af1cade8c 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -471,9 +471,18 @@ bool OSystem_SDL_Symbian::remapKey(SDL_Event &ev, Common::Event &event) { void OSystem_SDL_Symbian::setWindowCaption(const char *caption) { OSystem_SDL::setWindowCaption(caption); +} + +void OSystem_SDL_Symbian::engineInit() { + // Check mappings for the engine just started check_mappings(); } +void OSystem_SDL_Symbian::engineDone() { + // Need to reset engine to basic state after an engine has been running + GUI::Actions::Instance()->initInstanceMain(this); +} + void OSystem_SDL_Symbian::check_mappings() { if (ConfMan.get("gameid").empty() || GUI::Actions::Instance()->initialized()) return; diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h index efca94b706..b873b503be 100644 --- a/backends/platform/symbian/src/SymbianOS.h +++ b/backends/platform/symbian/src/SymbianOS.h @@ -107,6 +107,18 @@ protected: void setWindowCaption(const char *caption); + /** + * Allows the backend to perform engine specific init. + * Called just before the engine is run. + */ + virtual void engineInit(); + + /** + * Allows the backend to perform engine specific de-init. + * Called after the engine finishes. + */ + virtual void engineDone(); + // // Used to intialized special game mappings // diff --git a/backends/platform/wii/wii.mk b/backends/platform/wii/wii.mk index 030cc997eb..f99288c4a6 100644 --- a/backends/platform/wii/wii.mk +++ b/backends/platform/wii/wii.mk @@ -1,61 +1,25 @@ -WII_ELF=scummvm.elf -WII_DOL=scummvm.dol -WII_DISTPATH=$(srcdir)/dists/wii -all: $(WII_DOL) +WII_EXE := scummvm$(EXEEXT) +WII_EXE_STRIPPED := scummvm_stripped$(EXEEXT) -$(WII_DOL): $(WII_ELF) - $(DEVKITPPC)/bin/elf2dol $< $@ +$(WII_EXE_STRIPPED): $(WII_EXE) + $(STRIP) $< -o $@ clean: wiiclean wiiclean: - $(RM) $(WII_DOL) + $(RM) $(WII_EXE_STRIPPED) -wiiload: $(WII_DOL) - $(DEVKITPPC)/bin/wiiload $(WII_DOL) -d3 +wiiload: $(WII_EXE_STRIPPED) + $(DEVKITPPC)/bin/wiiload $< -geckoupload: $(WII_DOL) - $(DEVKITPPC)/bin/geckoupload $(WII_DOL) +geckoupload: $(WII_EXE_STRIPPED) + $(DEVKITPPC)/bin/geckoupload $< wiigdb: - $(DEVKITPPC)/bin/powerpc-gekko-gdb -n $(WII_ELF) + $(DEVKITPPC)/bin/powerpc-gekko-gdb -n $(WII_EXE) wiidebug: - $(DEVKITPPC)/bin/powerpc-gekko-gdb -n $(WII_ELF) -x $(srcdir)/backends/platform/wii/gdb.txt - -wiidist: - $(MKDIR) dist/scummvm - $(CP) $(WII_DOL) dist/scummvm/boot.dol - $(CP) $(WII_DISTPATH)/meta.xml dist/scummvm/ - $(CP) $(WII_DISTPATH)/icon.png dist/scummvm/ - $(CP) $(WII_DISTPATH)/READMII dist/scummvm/ - $(CP) $(srcdir)/AUTHORS dist/scummvm/ - $(CP) $(srcdir)/COPYING dist/scummvm/ - $(CP) $(srcdir)/COPYING.LGPL dist/scummvm/ - $(CP) $(srcdir)/COPYRIGHT dist/scummvm/ - $(CP) $(srcdir)/NEWS dist/scummvm/ - $(CP) $(srcdir)/README dist/scummvm/ - $(CP) $(srcdir)/dists/pred.dic dist/scummvm/ - $(CP) $(DIST_FILES_THEMES) dist/scummvm/ -ifneq ($(DIST_FILES_ENGINEDATA),) - $(CP) $(DIST_FILES_ENGINEDATA) dist/scummvm/ -endif - -gcdist: - $(MKDIR) dist/scummvm - $(CP) $(WII_DOL) dist/scummvm/ - $(CP) $(WII_DISTPATH)/READMII dist/scummvm/ - $(CP) $(srcdir)/AUTHORS dist/scummvm/ - $(CP) $(srcdir)/COPYING dist/scummvm/ - $(CP) $(srcdir)/COPYING.LGPL dist/scummvm/ - $(CP) $(srcdir)/COPYRIGHT dist/scummvm/ - $(CP) $(srcdir)/NEWS dist/scummvm/ - $(CP) $(srcdir)/README dist/scummvm/ - $(CP) $(srcdir)/dists/pred.dic dist/scummvm/ - $(CP) $(DIST_FILES_THEMES) dist/scummvm/ -ifneq ($(DIST_FILES_ENGINEDATA),) - $(CP) $(DIST_FILES_ENGINEDATA) dist/scummvm/ -endif - -.PHONY: wiiclean wiiload geckoupload wiigdb wiidebug wiidist gcdist + $(DEVKITPPC)/bin/powerpc-gekko-gdb -n $(WII_EXE) -x $(srcdir)/backends/platform/wii/gdb.txt + +.PHONY: wiiclean wiiload geckoupload wiigdb wiidebug diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index 344edd7143..b8261d029e 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -916,6 +916,8 @@ void OSystem_WINCE3::setWindowCaption(const char *caption) { compute_sample_rate(); setupMixer(); +FIXME: move check_mappings() etc. calls to engineInit() & engineDone() + // handle the actual event OSystem_SDL::setWindowCaption(caption); } diff --git a/backends/vkeybd/packs/vkeybd_default.zip b/backends/vkeybd/packs/vkeybd_default.zip Binary files differnew file mode 100644 index 0000000000..9311b2a902 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default.zip diff --git a/backends/vkeybd/packs/vkeybd_default/lowercase-symbols320x240.bmp b/backends/vkeybd/packs/vkeybd_default/lowercase-symbols320x240.bmp Binary files differnew file mode 100644 index 0000000000..02254aa3c7 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/lowercase-symbols320x240.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/lowercase-symbols640x480.bmp b/backends/vkeybd/packs/vkeybd_default/lowercase-symbols640x480.bmp Binary files differnew file mode 100644 index 0000000000..98c602acbe --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/lowercase-symbols640x480.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp b/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp Binary files differnew file mode 100644 index 0000000000..3270bf21e4 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/lowercase640x480.bmp b/backends/vkeybd/packs/vkeybd_default/lowercase640x480.bmp Binary files differnew file mode 100644 index 0000000000..610f0844d0 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/lowercase640x480.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/uppercase-symbols320x240.bmp b/backends/vkeybd/packs/vkeybd_default/uppercase-symbols320x240.bmp Binary files differnew file mode 100644 index 0000000000..8fd645eb22 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/uppercase-symbols320x240.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/uppercase-symbols640x480.bmp b/backends/vkeybd/packs/vkeybd_default/uppercase-symbols640x480.bmp Binary files differnew file mode 100644 index 0000000000..cbdfbf19e9 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/uppercase-symbols640x480.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/uppercase320x240.bmp b/backends/vkeybd/packs/vkeybd_default/uppercase320x240.bmp Binary files differnew file mode 100644 index 0000000000..6a1132314a --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/uppercase320x240.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/uppercase640x480.bmp b/backends/vkeybd/packs/vkeybd_default/uppercase640x480.bmp Binary files differnew file mode 100644 index 0000000000..e635a3ccf2 --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/uppercase640x480.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml new file mode 100644 index 0000000000..982c4f45ef --- /dev/null +++ b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml @@ -0,0 +1,920 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<keyboard initial_mode="lowercase" v_align="bottom" h_align="centre"> + + <!-- Lowercase --> + <mode name="lowercase" resolutions="320x240,640x480"> + <layout resolution="320x240" bitmap="lowercase320x240.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="13,8,306,20" target="display_area" /> + <area shape="rect" coords="9,26,25,42" target="esc" /> + <area shape="rect" coords="50,25,67,43" target="f2" /> + <area shape="rect" coords="29,24,46,43" target="f1" /> + <area shape="rect" coords="71,26,88,44" target="f3" /> + <area shape="rect" coords="90,25,107,43" target="f4" /> + <area shape="rect" coords="111,26,128,44" target="f5" /> + <area shape="rect" coords="132,26,149,44" target="f6" /> + <area shape="rect" coords="153,25,170,44" target="f7" /> + <area shape="rect" coords="173,26,190,44" target="f8" /> + <area shape="rect" coords="194,24,211,43" target="f9" /> + <area shape="rect" coords="215,26,231,44" target="f10" /> + <area shape="rect" coords="235,26,253,43" target="f11" /> + <area shape="rect" coords="255,26,272,45" target="f12" /> + <area shape="rect" coords="276,27,310,43" target="del" /> + <area shape="rect" coords="276,47,308,64" target="backspace" /> + <area shape="rect" coords="8,68,32,85" target="tab" /> + <area shape="rect" coords="36,68,53,85" target="q" /> + <area shape="rect" coords="57,68,75,86" target="w" /> + <area shape="rect" coords="78,67,94,85" target="e" /> + <area shape="rect" coords="98,67,115,85" target="r" /> + <area shape="rect" coords="119,67,136,85" target="t" /> + <area shape="rect" coords="141,68,158,86" target="y" /> + <area shape="rect" coords="161,67,179,86" target="u" /> + <area shape="rect" coords="182,67,199,86" target="i" /> + <area shape="rect" coords="202,67,220,85" target="o" /> + <area shape="rect" coords="223,68,240,86" target="p" /> + <area shape="rect" coords="44,88,63,107" target="a" /> + <area shape="rect" coords="65,88,84,106" target="s" /> + <area shape="rect" coords="86,89,104,107" target="d" /> + <area shape="rect" coords="107,89,124,107" target="f" /> + <area shape="rect" coords="128,89,145,107" target="g" /> + <area shape="rect" coords="149,88,165,107" target="h" /> + <area shape="rect" coords="169,89,186,107" target="j" /> + <area shape="rect" coords="189,89,207,107" target="k" /> + <area shape="rect" coords="210,89,228,107" target="l" /> + <area shape="rect" coords="273,89,311,106" target="enter" /> + <area shape="rect" coords="9,110,50,127" target="shift" /> + <area shape="rect" coords="8,89,41,106" target="caps" /> + <area shape="rect" coords="58,110,75,128" target="z" /> + <area shape="rect" coords="79,110,96,128" target="x" /> + <area shape="rect" coords="99,109,116,127" target="c" /> + <area shape="rect" coords="120,110,138,128" target="v" /> + <area shape="rect" coords="141,109,157,127" target="b" /> + <area shape="rect" coords="162,110,179,128" target="n" /> + <area shape="rect" coords="182,110,199,128" target="m" /> + <area shape="rect" coords="271,109,311,128" target="symbols" /> + <area shape="rect" coords="9,130,33,148" target="ctrl" /> + <area shape="rect" coords="38,130,61,147" target="alt" /> + <area shape="rect" coords="67,130,262,148" target="space" /> + <area shape="rect" coords="8,47,26,64" target="|" /> + <area shape="rect" coords="28,47,45,64" target="1" /> + <area shape="rect" coords="50,47,67,65" target="2" /> + <area shape="rect" coords="70,46,87,65" target="3" /> + <area shape="rect" coords="91,46,108,64" target="4" /> + <area shape="rect" coords="111,46,129,65" target="5" /> + <area shape="rect" coords="132,47,149,65" target="6" /> + <area shape="rect" coords="152,47,170,64" target="7" /> + <area shape="rect" coords="174,46,191,63" target="8" /> + <area shape="rect" coords="194,47,211,65" target="9" /> + <area shape="rect" coords="215,46,232,64" target="0" /> + <area shape="rect" coords="235,47,252,65" target="-" /> + <area shape="rect" coords="255,46,272,65" target="=" /> + <area shape="rect" coords="244,68,261,86" target="[" /> + <area shape="rect" coords="264,67,282,86" target="]" /> + <area shape="rect" coords="284,68,309,86" target="#" /> + <area shape="rect" coords="231,88,249,106" target=";" /> + <area shape="rect" coords="251,89,269,107" target="’" /> + <area shape="rect" coords="202,110,219,128" target="," /> + <area shape="rect" coords="223,110,241,128" target="." /> + <area shape="rect" coords="243,110,261,128" target="/" /> + <area shape="rect" coords="277,133,292,148" target="ok" /> + <area shape="rect" coords="292,133,309,148" target="cancel" /> + </map> + </layout> + <layout resolution="640x480" bitmap="lowercase640x480.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="26,23,613,37" target="display_area" /> + <area shape="rect" coords="18,52,51,85" target="esc" /> + <area shape="rect" coords="100,51,135,88" target="f2" /> + <area shape="rect" coords="59,49,94,88" target="f1" /> + <area shape="rect" coords="142,53,176,89" target="f3" /> + <area shape="rect" coords="181,51,216,87" target="f4" /> + <area shape="rect" coords="223,52,258,88" target="f5" /> + <area shape="rect" coords="265,52,299,89" target="f6" /> + <area shape="rect" coords="306,51,341,90" target="f7" /> + <area shape="rect" coords="347,53,382,89" target="f8" /> + <area shape="rect" coords="389,49,424,88" target="f9" /> + <area shape="rect" coords="431,52,464,89" target="f10" /> + <area shape="rect" coords="470,53,506,88" target="f11" /> + <area shape="rect" coords="511,52,546,90" target="f12" /> + <area shape="rect" coords="552,55,620,87" target="del" /> + <area shape="rect" coords="553,94,618,129" target="backspace" /> + <area shape="rect" coords="17,136,66,171" target="tab" /> + <area shape="rect" coords="73,137,108,171" target="q" /> + <area shape="rect" coords="114,136,150,172" target="w" /> + <area shape="rect" coords="157,134,189,171" target="e" /> + <area shape="rect" coords="197,135,232,171" target="r" /> + <area shape="rect" coords="239,135,274,172" target="t" /> + <area shape="rect" coords="282,136,317,173" target="y" /> + <area shape="rect" coords="322,135,359,173" target="u" /> + <area shape="rect" coords="364,134,399,172" target="i" /> + <area shape="rect" coords="404,135,440,171" target="o" /> + <area shape="rect" coords="446,136,480,172" target="p" /> + <area shape="rect" coords="89,177,127,216" target="a" /> + <area shape="rect" coords="131,177,169,214" target="s" /> + <area shape="rect" coords="173,178,209,215" target="d" /> + <area shape="rect" coords="215,178,250,214" target="f" /> + <area shape="rect" coords="256,178,291,214" target="g" /> + <area shape="rect" coords="299,176,332,214" target="h" /> + <area shape="rect" coords="339,178,374,215" target="j" /> + <area shape="rect" coords="379,178,415,215" target="k" /> + <area shape="rect" coords="421,178,457,215" target="l" /> + <area shape="rect" coords="546,179,622,214" target="enter" /> + <area shape="rect" coords="19,221,101,256" target="shift" /> + <area shape="rect" coords="17,179,84,213" target="caps" /> + <area shape="rect" coords="117,220,152,256" target="z" /> + <area shape="rect" coords="158,220,192,256" target="x" /> + <area shape="rect" coords="198,219,233,256" target="c" /> + <area shape="rect" coords="240,220,276,257" target="v" /> + <area shape="rect" coords="283,219,316,255" target="b" /> + <area shape="rect" coords="324,220,359,256" target="n" /> + <area shape="rect" coords="365,220,399,257" target="m" /> + <area shape="rect" coords="542,219,623,257" target="symbols" /> + <area shape="rect" coords="19,260,68,296" target="ctrl" /> + <area shape="rect" coords="76,261,123,295" target="alt" /> + <area shape="rect" coords="135,261,525,297" target="space" /> + <area shape="rect" coords="16,95,53,129" target="|" /> + <area shape="rect" coords="57,95,92,129" target="1" /> + <area shape="rect" coords="100,94,134,130" target="2" /> + <area shape="rect" coords="140,93,174,131" target="3" /> + <area shape="rect" coords="182,93,217,130" target="4" /> + <area shape="rect" coords="222,93,258,132" target="5" /> + <area shape="rect" coords="265,94,299,131" target="6" /> + <area shape="rect" coords="305,94,341,129" target="7" /> + <area shape="rect" coords="348,93,382,128" target="8" /> + <area shape="rect" coords="389,94,423,130" target="9" /> + <area shape="rect" coords="431,93,465,130" target="0" /> + <area shape="rect" coords="471,94,505,131" target="-" /> + <area shape="rect" coords="511,93,546,131" target="=" /> + <area shape="rect" coords="488,136,522,172" target="[" /> + <area shape="rect" coords="529,135,565,173" target="]" /> + <area shape="rect" coords="569,136,620,172" target="#" /> + <area shape="rect" coords="462,177,498,214" target=";" /> + <area shape="rect" coords="503,178,539,214" target="’" /> + <area shape="rect" coords="405,220,440,256" target="," /> + <area shape="rect" coords="447,220,483,256" target="." /> + <area shape="rect" coords="487,220,524,256" target="/" /> + <area shape="rect" coords="555,266,585,298" target="ok" /> + <area shape="rect" coords="585,266,619,298" target="cancel" /> + </map> + </layout> + <event name="esc" type="key" code="27" ascii="27" modifiers="" /> + <event name="f1" type="key" code="282" ascii="315" modifiers="" /> + <event name="f2" type="key" code="283" ascii="316" modifiers="" /> + <event name="f3" type="key" code="284" ascii="317" modifiers="" /> + <event name="f4" type="key" code="285" ascii="318" modifiers="" /> + <event name="f5" type="key" code="286" ascii="319" modifiers="" /> + <event name="f6" type="key" code="287" ascii="320" modifiers="" /> + <event name="f7" type="key" code="288" ascii="321" modifiers="" /> + <event name="f8" type="key" code="289" ascii="322" modifiers="" /> + <event name="f9" type="key" code="290" ascii="323" modifiers="" /> + <event name="f10" type="key" code="291" ascii="324" modifiers="" /> + <event name="f11" type="key" code="292" ascii="325" modifiers="" /> + <event name="f12" type="key" code="293" ascii="326" modifiers="" /> + <event name="del" type="key" code="127" ascii="0" modifiers="" /> + <event name="ctrl" type="modifier" modifiers="ctrl" /> + <event name="alt" type="modifier" modifiers="alt" /> + <event name="shift" type="modifier" modifiers="shift" /> + <event name="caps" type="switch_mode" mode="uppercase" /> + <event name="symbols" type="switch_mode" mode="lowercasesymbols" /> + <event name="backspace" type="key" code="8" ascii="8" modifiers="" /> + <event name="enter" type="key" code="13" ascii="13" modifiers="" /> + <event name="|" type="key" code="124" ascii="124" modifiers="" /> + <event name="-" type="key" code="45" ascii="45" modifiers="" /> + <event name="=" type="key" code="61" ascii="61" modifiers="" /> + <event name="[" type="key" code="91" ascii="91" modifiers="" /> + <event name="]" type="key" code="93" ascii="93" modifiers="" /> + <event name="#" type="key" code="35" ascii="35" modifiers="" /> + <event name=";" type="key" code="59" ascii="59" modifiers="" /> + <event name="'" type="key" code="39" ascii="39" modifiers="" /> + <event name="," type="key" code="44" ascii="44" modifiers="" /> + <event name="." type="key" code="46" ascii="46" modifiers="" /> + <event name="/" type="key" code="47" ascii="47" modifiers="" /> + <event name="space" type="key" code="32" ascii="32" modifiers="" /> + <event name="tab" type="key" code="9" ascii="9" modifiers="" /> + <event name="a" type="key" code="97" ascii="97" modifiers="" /> + <event name="b" type="key" code="98" ascii="98" modifiers="" /> + <event name="c" type="key" code="99" ascii="99" modifiers="" /> + <event name="d" type="key" code="100" ascii="100" modifiers="" /> + <event name="e" type="key" code="101" ascii="101" modifiers="" /> + <event name="f" type="key" code="102" ascii="102" modifiers="" /> + <event name="g" type="key" code="103" ascii="103" modifiers="" /> + <event name="h" type="key" code="104" ascii="104" modifiers="" /> + <event name="i" type="key" code="105" ascii="105" modifiers="" /> + <event name="j" type="key" code="106" ascii="106" modifiers="" /> + <event name="k" type="key" code="107" ascii="107" modifiers="" /> + <event name="l" type="key" code="108" ascii="108" modifiers="" /> + <event name="m" type="key" code="109" ascii="109" modifiers="" /> + <event name="n" type="key" code="110" ascii="110" modifiers="" /> + <event name="o" type="key" code="111" ascii="111" modifiers="" /> + <event name="p" type="key" code="112" ascii="112" modifiers="" /> + <event name="q" type="key" code="113" ascii="113" modifiers="" /> + <event name="r" type="key" code="114" ascii="114" modifiers="" /> + <event name="s" type="key" code="115" ascii="115" modifiers="" /> + <event name="t" type="key" code="116" ascii="116" modifiers="" /> + <event name="u" type="key" code="117" ascii="117" modifiers="" /> + <event name="v" type="key" code="118" ascii="118" modifiers="" /> + <event name="w" type="key" code="119" ascii="119" modifiers="" /> + <event name="x" type="key" code="120" ascii="120" modifiers="" /> + <event name="y" type="key" code="121" ascii="121" modifiers="" /> + <event name="z" type="key" code="122" ascii="122" modifiers="" /> + <event name="0" type="key" code="48" ascii="48" modifiers="" /> + <event name="1" type="key" code="49" ascii="49" modifiers="" /> + <event name="2" type="key" code="50" ascii="50" modifiers="" /> + <event name="3" type="key" code="51" ascii="51" modifiers="" /> + <event name="4" type="key" code="52" ascii="52" modifiers="" /> + <event name="5" type="key" code="53" ascii="53" modifiers="" /> + <event name="6" type="key" code="54" ascii="54" modifiers="" /> + <event name="7" type="key" code="55" ascii="55" modifiers="" /> + <event name="8" type="key" code="56" ascii="56" modifiers="" /> + <event name="9" type="key" code="57" ascii="57" modifiers="" /> + <event name="ok" type="submit" /> + <event name="cancel" type="cancel" /> + <event name="quit" type="submit" /> + </mode> + + <!-- Uppercase --> + <mode name="uppercase" resolutions="320x240,640x480"> + <layout resolution="320x240" bitmap="uppercase320x240.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="13,8,306,20" target="display_area" /> + <area shape="rect" coords="9,26,25,42" target="esc" /> + <area shape="rect" coords="50,25,67,43" target="f2" /> + <area shape="rect" coords="29,24,46,43" target="f1" /> + <area shape="rect" coords="71,26,88,44" target="f3" /> + <area shape="rect" coords="90,25,107,43" target="f4" /> + <area shape="rect" coords="111,26,128,44" target="f5" /> + <area shape="rect" coords="132,26,149,44" target="f6" /> + <area shape="rect" coords="153,25,170,44" target="f7" /> + <area shape="rect" coords="173,26,190,44" target="f8" /> + <area shape="rect" coords="194,24,211,43" target="f9" /> + <area shape="rect" coords="215,26,231,44" target="f10" /> + <area shape="rect" coords="235,26,253,43" target="f11" /> + <area shape="rect" coords="255,26,272,45" target="f12" /> + <area shape="rect" coords="276,27,310,43" target="del" /> + <area shape="rect" coords="276,47,308,64" target="backspace" /> + <area shape="rect" coords="8,68,32,85" target="tab" /> + <area shape="rect" coords="36,68,53,85" target="Q" /> + <area shape="rect" coords="57,68,75,86" target="W" /> + <area shape="rect" coords="78,67,94,85" target="E" /> + <area shape="rect" coords="98,67,115,85" target="R" /> + <area shape="rect" coords="119,67,136,85" target="T" /> + <area shape="rect" coords="141,68,158,86" target="Y" /> + <area shape="rect" coords="161,67,179,86" target="U" /> + <area shape="rect" coords="182,67,199,86" target="I" /> + <area shape="rect" coords="202,67,220,85" target="O" /> + <area shape="rect" coords="223,68,240,86" target="P" /> + <area shape="rect" coords="44,88,63,107" target="A" /> + <area shape="rect" coords="65,88,84,106" target="S" /> + <area shape="rect" coords="86,89,104,107" target="D" /> + <area shape="rect" coords="107,89,124,107" target="F" /> + <area shape="rect" coords="128,89,145,107" target="G" /> + <area shape="rect" coords="149,88,165,107" target="H" /> + <area shape="rect" coords="169,89,186,107" target="J" /> + <area shape="rect" coords="189,89,207,107" target="K" /> + <area shape="rect" coords="210,89,228,107" target="L" /> + <area shape="rect" coords="273,89,311,106" target="enter" /> + <area shape="rect" coords="9,110,50,127" target="shift" /> + <area shape="rect" coords="8,89,41,106" target="caps" /> + <area shape="rect" coords="58,110,75,128" target="Z" /> + <area shape="rect" coords="79,110,96,128" target="X" /> + <area shape="rect" coords="99,109,116,127" target="C" /> + <area shape="rect" coords="120,110,138,128" target="V" /> + <area shape="rect" coords="141,109,157,127" target="B" /> + <area shape="rect" coords="162,110,179,128" target="N" /> + <area shape="rect" coords="182,110,199,128" target="M" /> + <area shape="rect" coords="271,109,311,128" target="symbols" /> + <area shape="rect" coords="9,130,33,148" target="ctrl" /> + <area shape="rect" coords="38,130,61,147" target="alt" /> + <area shape="rect" coords="67,130,262,148" target="space" /> + <area shape="rect" coords="8,47,26,64" target="|" /> + <area shape="rect" coords="28,47,45,64" target="1" /> + <area shape="rect" coords="50,47,67,65" target="2" /> + <area shape="rect" coords="70,46,87,65" target="3" /> + <area shape="rect" coords="91,46,108,64" target="4" /> + <area shape="rect" coords="111,46,129,65" target="5" /> + <area shape="rect" coords="132,47,149,65" target="6" /> + <area shape="rect" coords="152,47,170,64" target="7" /> + <area shape="rect" coords="174,46,191,63" target="8" /> + <area shape="rect" coords="194,47,211,65" target="9" /> + <area shape="rect" coords="215,46,232,64" target="0" /> + <area shape="rect" coords="235,47,252,65" target="-" /> + <area shape="rect" coords="255,46,272,65" target="=" /> + <area shape="rect" coords="244,68,261,86" target="[" /> + <area shape="rect" coords="264,67,282,86" target="]" /> + <area shape="rect" coords="284,68,309,86" target="#" /> + <area shape="rect" coords="231,88,249,106" target=";" /> + <area shape="rect" coords="251,89,269,107" target="’" /> + <area shape="rect" coords="202,110,219,128" target="," /> + <area shape="rect" coords="223,110,241,128" target="." /> + <area shape="rect" coords="243,110,261,128" target="/" /> + </map> + </layout> + <layout resolution="640x480" bitmap="uppercase640x480.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="26,23,613,37" target="display_area" /> + <area shape="rect" coords="18,52,51,85" target="esc" /> + <area shape="rect" coords="100,51,135,88" target="f2" /> + <area shape="rect" coords="59,49,94,88" target="f1" /> + <area shape="rect" coords="142,53,176,89" target="f3" /> + <area shape="rect" coords="181,51,216,87" target="f4" /> + <area shape="rect" coords="223,52,258,88" target="f5" /> + <area shape="rect" coords="265,52,299,89" target="f6" /> + <area shape="rect" coords="306,51,341,90" target="f7" /> + <area shape="rect" coords="347,53,382,89" target="f8" /> + <area shape="rect" coords="389,49,424,88" target="f9" /> + <area shape="rect" coords="431,52,464,89" target="f10" /> + <area shape="rect" coords="470,53,506,88" target="f11" /> + <area shape="rect" coords="511,52,546,90" target="f12" /> + <area shape="rect" coords="552,55,620,87" target="del" /> + <area shape="rect" coords="553,94,618,129" target="backspace" /> + <area shape="rect" coords="17,136,66,171" target="tab" /> + <area shape="rect" coords="73,137,108,171" target="Q" /> + <area shape="rect" coords="114,136,150,172" target="W" /> + <area shape="rect" coords="157,134,189,171" target="E" /> + <area shape="rect" coords="197,135,232,171" target="R" /> + <area shape="rect" coords="239,135,274,172" target="T" /> + <area shape="rect" coords="282,136,317,173" target="Y" /> + <area shape="rect" coords="322,135,359,173" target="U" /> + <area shape="rect" coords="364,134,399,172" target="I" /> + <area shape="rect" coords="404,135,440,171" target="O" /> + <area shape="rect" coords="446,136,480,172" target="P" /> + <area shape="rect" coords="89,177,127,216" target="A" /> + <area shape="rect" coords="131,177,169,214" target="S" /> + <area shape="rect" coords="173,178,209,215" target="D" /> + <area shape="rect" coords="215,178,250,214" target="F" /> + <area shape="rect" coords="256,178,291,214" target="G" /> + <area shape="rect" coords="299,176,332,214" target="H" /> + <area shape="rect" coords="339,178,374,215" target="J" /> + <area shape="rect" coords="379,178,415,215" target="K" /> + <area shape="rect" coords="421,178,457,215" target="L" /> + <area shape="rect" coords="546,179,622,214" target="enter" /> + <area shape="rect" coords="19,221,101,256" target="shift" /> + <area shape="rect" coords="17,179,84,213" target="caps" /> + <area shape="rect" coords="117,220,152,256" target="Z" /> + <area shape="rect" coords="158,220,192,256" target="X" /> + <area shape="rect" coords="198,219,233,256" target="C" /> + <area shape="rect" coords="240,220,276,257" target="V" /> + <area shape="rect" coords="283,219,316,255" target="B" /> + <area shape="rect" coords="324,220,359,256" target="N" /> + <area shape="rect" coords="365,220,399,257" target="M" /> + <area shape="rect" coords="542,219,623,257" target="symbols" /> + <area shape="rect" coords="19,260,68,296" target="ctrl" /> + <area shape="rect" coords="76,261,123,295" target="alt" /> + <area shape="rect" coords="135,261,525,297" target="space" /> + <area shape="rect" coords="16,95,53,129" target="|" /> + <area shape="rect" coords="57,95,92,129" target="1" /> + <area shape="rect" coords="100,94,134,130" target="2" /> + <area shape="rect" coords="140,93,174,131" target="3" /> + <area shape="rect" coords="182,93,217,130" target="4" /> + <area shape="rect" coords="222,93,258,132" target="5" /> + <area shape="rect" coords="265,94,299,131" target="6" /> + <area shape="rect" coords="305,94,341,129" target="7" /> + <area shape="rect" coords="348,93,382,128" target="8" /> + <area shape="rect" coords="389,94,423,130" target="9" /> + <area shape="rect" coords="431,93,465,130" target="0" /> + <area shape="rect" coords="471,94,505,131" target="-" /> + <area shape="rect" coords="511,93,546,131" target="=" /> + <area shape="rect" coords="488,136,522,172" target="[" /> + <area shape="rect" coords="529,135,565,173" target="]" /> + <area shape="rect" coords="569,136,620,172" target="#" /> + <area shape="rect" coords="462,177,498,214" target=";" /> + <area shape="rect" coords="503,178,539,214" target="’" /> + <area shape="rect" coords="405,220,440,256" target="," /> + <area shape="rect" coords="447,220,483,256" target="." /> + <area shape="rect" coords="487,220,524,256" target="/" /> + </map> + </layout> + <event name="esc" type="key" code="27" ascii="27" modifiers="" /> + <event name="f1" type="key" code="282" ascii="315" modifiers="" /> + <event name="f2" type="key" code="283" ascii="316" modifiers="" /> + <event name="f3" type="key" code="284" ascii="317" modifiers="" /> + <event name="f4" type="key" code="285" ascii="318" modifiers="" /> + <event name="f5" type="key" code="286" ascii="319" modifiers="" /> + <event name="f6" type="key" code="287" ascii="320" modifiers="" /> + <event name="f7" type="key" code="288" ascii="321" modifiers="" /> + <event name="f8" type="key" code="289" ascii="322" modifiers="" /> + <event name="f9" type="key" code="290" ascii="323" modifiers="" /> + <event name="f10" type="key" code="291" ascii="324" modifiers="" /> + <event name="f11" type="key" code="292" ascii="325" modifiers="" /> + <event name="f12" type="key" code="293" ascii="326" modifiers="" /> + <event name="del" type="key" code="127" ascii="0" modifiers="" /> + <event name="ctrl" type="modifier" modifiers="ctrl" /> + <event name="alt" type="modifier" modifiers="alt" /> + <event name="shift" type="modifier" modifiers="shift" /> + <event name="caps" type="switch_mode" mode="lowercase" /> + <event name="symbols" type="switch_mode" mode="uppercasesymbols" /> + <event name="backspace" type="key" code="8" ascii="8" modifiers="" /> + <event name="enter" type="key" code="13" ascii="13" modifiers="" /> + <event name="|" type="key" code="124" ascii="124" modifiers="" /> + <event name="-" type="key" code="45" ascii="45" modifiers="" /> + <event name="=" type="key" code="61" ascii="61" modifiers="" /> + <event name="[" type="key" code="91" ascii="91" modifiers="" /> + <event name="]" type="key" code="93" ascii="93" modifiers="" /> + <event name="#" type="key" code="35" ascii="35" modifiers="" /> + <event name=";" type="key" code="59" ascii="59" modifiers="" /> + <event name="'" type="key" code="39" ascii="39" modifiers="" /> + <event name="," type="key" code="44" ascii="44" modifiers="" /> + <event name="." type="key" code="46" ascii="46" modifiers="" /> + <event name="/" type="key" code="47" ascii="47" modifiers="" /> + <event name="space" type="key" code="32" ascii="32" modifiers="" /> + <event name="tab" type="key" code="9" ascii="9" modifiers="" /> + <event name="A" type="key" code="97" ascii="65" modifiers="shift" /> + <event name="B" type="key" code="98" ascii="66" modifiers="shift" /> + <event name="C" type="key" code="99" ascii="67" modifiers="shift" /> + <event name="D" type="key" code="100" ascii="68" modifiers="shift" /> + <event name="E" type="key" code="101" ascii="69" modifiers="shift" /> + <event name="F" type="key" code="102" ascii="70" modifiers="shift" /> + <event name="G" type="key" code="103" ascii="71" modifiers="shift" /> + <event name="H" type="key" code="104" ascii="72" modifiers="shift" /> + <event name="I" type="key" code="105" ascii="73" modifiers="shift" /> + <event name="J" type="key" code="106" ascii="74" modifiers="shift" /> + <event name="K" type="key" code="107" ascii="75" modifiers="shift" /> + <event name="L" type="key" code="108" ascii="76" modifiers="shift" /> + <event name="M" type="key" code="109" ascii="77" modifiers="shift" /> + <event name="N" type="key" code="110" ascii="78" modifiers="shift" /> + <event name="O" type="key" code="111" ascii="79" modifiers="shift" /> + <event name="P" type="key" code="112" ascii="80" modifiers="shift" /> + <event name="Q" type="key" code="113" ascii="81" modifiers="shift" /> + <event name="R" type="key" code="114" ascii="82" modifiers="shift" /> + <event name="S" type="key" code="115" ascii="83" modifiers="shift" /> + <event name="T" type="key" code="116" ascii="84" modifiers="shift" /> + <event name="U" type="key" code="117" ascii="85" modifiers="shift" /> + <event name="V" type="key" code="118" ascii="86" modifiers="shift" /> + <event name="W" type="key" code="119" ascii="87" modifiers="shift" /> + <event name="X" type="key" code="120" ascii="88" modifiers="shift" /> + <event name="Y" type="key" code="121" ascii="89" modifiers="shift" /> + <event name="Z" type="key" code="122" ascii="90" modifiers="shift" /> + <event name="0" type="key" code="48" ascii="48" modifiers="" /> + <event name="1" type="key" code="49" ascii="49" modifiers="" /> + <event name="2" type="key" code="50" ascii="50" modifiers="" /> + <event name="3" type="key" code="51" ascii="51" modifiers="" /> + <event name="4" type="key" code="52" ascii="52" modifiers="" /> + <event name="5" type="key" code="53" ascii="53" modifiers="" /> + <event name="6" type="key" code="54" ascii="54" modifiers="" /> + <event name="7" type="key" code="55" ascii="55" modifiers="" /> + <event name="8" type="key" code="56" ascii="56" modifiers="" /> + <event name="9" type="key" code="57" ascii="57" modifiers="" /> + <event name="quit" type="submit" /> + </mode> + + <!-- Lowercase Symbols --> + <mode name="lowercasesymbols" resolutions="320x240,640x480"> + <layout resolution="320x240" bitmap="lowercase-symbols320x240.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="13,8,306,20" target="display_area" /> + <area shape="rect" coords="9,26,25,42" target="esc" /> + <area shape="rect" coords="50,25,67,43" target="f2" /> + <area shape="rect" coords="29,24,46,43" target="f1" /> + <area shape="rect" coords="71,26,88,44" target="f3" /> + <area shape="rect" coords="90,25,107,43" target="f4" /> + <area shape="rect" coords="111,26,128,44" target="f5" /> + <area shape="rect" coords="132,26,149,44" target="f6" /> + <area shape="rect" coords="153,25,170,44" target="f7" /> + <area shape="rect" coords="173,26,190,44" target="f8" /> + <area shape="rect" coords="194,24,211,43" target="f9" /> + <area shape="rect" coords="215,26,231,44" target="f10" /> + <area shape="rect" coords="235,26,253,43" target="f11" /> + <area shape="rect" coords="255,26,272,45" target="f12" /> + <area shape="rect" coords="276,27,310,43" target="del" /> + <area shape="rect" coords="8,47,26,64" target="¬" /> + <area shape="rect" coords="28,47,45,64" target="!" /> + <area shape="rect" coords="50,47,67,65" target="quote" /> + <area shape="rect" coords="70,46,87,65" target="£" /> + <area shape="rect" coords="91,46,108,64" target="$" /> + <area shape="rect" coords="111,46,129,65" target="%" /> + <area shape="rect" coords="132,47,149,65" target="^" /> + <area shape="rect" coords="152,47,170,64" target="&" /> + <area shape="rect" coords="174,46,191,63" target="*" /> + <area shape="rect" coords="194,47,211,65" target="(" /> + <area shape="rect" coords="215,46,232,64" target=")" /> + <area shape="rect" coords="235,47,252,65" target="_" /> + <area shape="rect" coords="255,46,272,65" target="+" /> + <area shape="rect" coords="276,47,308,64" target="backspace" /> + <area shape="rect" coords="8,68,32,85" target="tab" /> + <area shape="rect" coords="36,68,53,85" target="q" /> + <area shape="rect" coords="57,68,75,86" target="w" /> + <area shape="rect" coords="78,67,94,85" target="e" /> + <area shape="rect" coords="98,67,115,85" target="r" /> + <area shape="rect" coords="119,67,136,85" target="t" /> + <area shape="rect" coords="141,68,158,86" target="y" /> + <area shape="rect" coords="161,67,179,86" target="u" /> + <area shape="rect" coords="182,67,199,86" target="i" /> + <area shape="rect" coords="202,67,220,85" target="o" /> + <area shape="rect" coords="223,68,240,86" target="p" /> + <area shape="rect" coords="244,68,261,86" target="{" /> + <area shape="rect" coords="264,67,282,86" target="}" /> + <area shape="rect" coords="284,68,309,86" target="~" /> + <area shape="rect" coords="8,89,41,106" target="caps" /> + <area shape="rect" coords="44,88,63,107" target="a" /> + <area shape="rect" coords="65,88,84,106" target="s" /> + <area shape="rect" coords="86,89,104,107" target="d" /> + <area shape="rect" coords="107,89,124,107" target="f" /> + <area shape="rect" coords="128,89,145,107" target="g" /> + <area shape="rect" coords="149,88,165,107" target="h" /> + <area shape="rect" coords="169,89,186,107" target="j" /> + <area shape="rect" coords="189,89,207,107" target="k" /> + <area shape="rect" coords="210,89,228,107" target="l" /> + <area shape="rect" coords="231,88,249,106" target=":" /> + <area shape="rect" coords="251,89,269,107" target="@" /> + <area shape="rect" coords="273,89,311,106" target="enter" /> + <area shape="rect" coords="9,110,50,127" target="shift" /> + <area shape="rect" coords="58,110,75,128" target="z" /> + <area shape="rect" coords="79,110,96,128" target="x" /> + <area shape="rect" coords="99,109,116,127" target="c" /> + <area shape="rect" coords="120,110,138,128" target="v" /> + <area shape="rect" coords="141,109,157,127" target="b" /> + <area shape="rect" coords="162,110,179,128" target="n" /> + <area shape="rect" coords="182,110,199,128" target="m" /> + <area shape="rect" coords="202,110,219,128" target="<" /> + <area shape="rect" coords="223,110,241,128" target=">" /> + <area shape="rect" coords="243,110,261,128" target="?" /> + <area shape="rect" coords="271,109,311,128" target="symbols" /> + <area shape="rect" coords="9,130,33,148" target="ctrl" /> + <area shape="rect" coords="38,130,61,147" target="alt" /> + <area shape="rect" coords="67,130,262,148" target="space" /> + </map> + </layout> + <layout resolution="640x480" bitmap="lowercase-symbols640x480.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="26,23,613,37" target="display_area" /> + <area shape="rect" coords="18,52,51,85" target="esc" /> + <area shape="rect" coords="100,51,135,88" target="f2" /> + <area shape="rect" coords="59,49,94,88" target="f1" /> + <area shape="rect" coords="142,53,176,89" target="f3" /> + <area shape="rect" coords="181,51,216,87" target="f4" /> + <area shape="rect" coords="223,52,258,88" target="f5" /> + <area shape="rect" coords="265,52,299,89" target="f6" /> + <area shape="rect" coords="306,51,341,90" target="f7" /> + <area shape="rect" coords="347,53,382,89" target="f8" /> + <area shape="rect" coords="389,49,424,88" target="f9" /> + <area shape="rect" coords="431,52,464,89" target="f10" /> + <area shape="rect" coords="470,53,506,88" target="f11" /> + <area shape="rect" coords="511,52,546,90" target="f12" /> + <area shape="rect" coords="552,55,620,87" target="del" /> + <area shape="rect" coords="16,95,53,129" target="¬" /> + <area shape="rect" coords="57,95,92,129" target="!" /> + <area shape="rect" coords="100,94,134,130" target="quote" /> + <area shape="rect" coords="140,93,174,131" target="£" /> + <area shape="rect" coords="182,93,217,130" target="$" /> + <area shape="rect" coords="222,93,258,132" target="%" /> + <area shape="rect" coords="265,94,299,131" target="^" /> + <area shape="rect" coords="305,94,341,129" target="&" /> + <area shape="rect" coords="348,93,382,128" target="*" /> + <area shape="rect" coords="389,94,423,130" target="(" /> + <area shape="rect" coords="431,93,465,130" target=")" /> + <area shape="rect" coords="471,94,505,131" target="_" /> + <area shape="rect" coords="511,93,546,131" target="+" /> + <area shape="rect" coords="553,94,618,129" target="backspace" /> + <area shape="rect" coords="17,136,66,171" target="tab" /> + <area shape="rect" coords="73,137,108,171" target="q" /> + <area shape="rect" coords="114,136,150,172" target="w" /> + <area shape="rect" coords="157,134,189,171" target="e" /> + <area shape="rect" coords="197,135,232,171" target="r" /> + <area shape="rect" coords="239,135,274,172" target="t" /> + <area shape="rect" coords="282,136,317,173" target="y" /> + <area shape="rect" coords="322,135,359,173" target="u" /> + <area shape="rect" coords="364,134,399,172" target="i" /> + <area shape="rect" coords="404,135,440,171" target="o" /> + <area shape="rect" coords="446,136,480,172" target="p" /> + <area shape="rect" coords="488,136,522,172" target="{" /> + <area shape="rect" coords="529,135,565,173" target="}" /> + <area shape="rect" coords="569,136,620,172" target="~" /> + <area shape="rect" coords="17,179,84,213" target="caps" /> + <area shape="rect" coords="89,177,127,216" target="a" /> + <area shape="rect" coords="131,177,169,214" target="s" /> + <area shape="rect" coords="173,178,209,215" target="d" /> + <area shape="rect" coords="215,178,250,214" target="f" /> + <area shape="rect" coords="256,178,291,214" target="g" /> + <area shape="rect" coords="299,176,332,214" target="h" /> + <area shape="rect" coords="339,178,374,215" target="j" /> + <area shape="rect" coords="379,178,415,215" target="k" /> + <area shape="rect" coords="421,178,457,215" target="l" /> + <area shape="rect" coords="462,177,498,214" target=":" /> + <area shape="rect" coords="503,178,539,214" target="@" /> + <area shape="rect" coords="546,179,622,214" target="enter" /> + <area shape="rect" coords="19,221,101,256" target="shift" /> + <area shape="rect" coords="117,220,152,256" target="z" /> + <area shape="rect" coords="158,220,192,256" target="x" /> + <area shape="rect" coords="198,219,233,256" target="c" /> + <area shape="rect" coords="240,220,276,257" target="v" /> + <area shape="rect" coords="283,219,316,255" target="b" /> + <area shape="rect" coords="324,220,359,256" target="n" /> + <area shape="rect" coords="365,220,399,257" target="m" /> + <area shape="rect" coords="405,220,440,256" target="<" /> + <area shape="rect" coords="447,220,483,256" target=">" /> + <area shape="rect" coords="487,220,524,256" target="?" /> + <area shape="rect" coords="542,219,623,257" target="symbols" /> + <area shape="rect" coords="19,260,68,296" target="ctrl" /> + <area shape="rect" coords="76,261,123,295" target="alt" /> + <area shape="rect" coords="135,261,525,297" target="space" /> + </map> + </layout> + <event name="esc" type="key" code="27" ascii="27" modifiers="" /> + <event name="f1" type="key" code="282" ascii="315" modifiers="" /> + <event name="f2" type="key" code="283" ascii="316" modifiers="" /> + <event name="f3" type="key" code="284" ascii="317" modifiers="" /> + <event name="f4" type="key" code="285" ascii="318" modifiers="" /> + <event name="f5" type="key" code="286" ascii="319" modifiers="" /> + <event name="f6" type="key" code="287" ascii="320" modifiers="" /> + <event name="f7" type="key" code="288" ascii="321" modifiers="" /> + <event name="f8" type="key" code="289" ascii="322" modifiers="" /> + <event name="f9" type="key" code="290" ascii="323" modifiers="" /> + <event name="f10" type="key" code="291" ascii="324" modifiers="" /> + <event name="f11" type="key" code="292" ascii="325" modifiers="" /> + <event name="f12" type="key" code="293" ascii="326" modifiers="" /> + <event name="del" type="key" code="127" ascii="0" modifiers="" /> + <event name="ctrl" type="modifier" modifiers="ctrl" /> + <event name="alt" type="modifier" modifiers="alt" /> + <event name="shift" type="modifier" modifiers="shift" /> + <event name="symbols" type="switch_mode" mode="lowercase" /> + <event name="caps" type="switch_mode" mode="uppercasesymbols" /> + <event name="backspace" type="key" code="8" ascii="8" modifiers="" /> + <event name="enter" type="key" code="13" ascii="13" modifiers="" /> + <event name="quote" type="key" code="34" ascii="34" modifiers="" /> + <event name="£" type="key" code="163" ascii="163" modifiers="" /> + <event name="$" type="key" code="36" ascii="36" modifiers="" /> + <event name="%" type="key" code="37" ascii="37" modifiers="" /> + <event name="^" type="key" code="94" ascii="94" modifiers="" /> + <event name="&" type="key" code="38" ascii="38" modifiers="" /> + <event name="*" type="key" code="42" ascii="42" modifiers="" /> + <event name="(" type="key" code="40" ascii="40" modifiers="" /> + <event name=")" type="key" code="41" ascii="41" modifiers="" /> + <event name="_" type="key" code="95" ascii="95" modifiers="" /> + <event name="+" type="key" code="43" ascii="43" modifiers="" /> + <event name="¬" type="key" code="172" ascii="172" modifiers="" /> + <event name="!" type="key" code="33" ascii="33" modifiers="" /> + <event name="{" type="key" code="123" ascii="123" modifiers="" /> + <event name="}" type="key" code="125" ascii="125" modifiers="" /> + <event name="~" type="key" code="126" ascii="126" modifiers="" /> + <event name=":" type="key" code="58" ascii="58" modifiers="" /> + <event name="@" type="key" code="64" ascii="64" modifiers="" /> + <event name="<" type="key" code="60" ascii="60" modifiers="" /> + <event name=">" type="key" code="62" ascii="62" modifiers="" /> + <event name="?" type="key" code="63" ascii="63" modifiers="" /> + <event name="space" type="key" code="32" ascii="32" modifiers="" /> + <event name="tab" type="key" code="9" ascii="9" modifiers="" /> + <event name="a" type="key" code="97" ascii="97" modifiers="" /> + <event name="b" type="key" code="98" ascii="98" modifiers="" /> + <event name="c" type="key" code="99" ascii="99" modifiers="" /> + <event name="d" type="key" code="100" ascii="100" modifiers="" /> + <event name="e" type="key" code="101" ascii="101" modifiers="" /> + <event name="f" type="key" code="102" ascii="102" modifiers="" /> + <event name="g" type="key" code="103" ascii="103" modifiers="" /> + <event name="h" type="key" code="104" ascii="104" modifiers="" /> + <event name="i" type="key" code="105" ascii="105" modifiers="" /> + <event name="j" type="key" code="106" ascii="106" modifiers="" /> + <event name="k" type="key" code="107" ascii="107" modifiers="" /> + <event name="l" type="key" code="108" ascii="108" modifiers="" /> + <event name="m" type="key" code="109" ascii="109" modifiers="" /> + <event name="n" type="key" code="110" ascii="110" modifiers="" /> + <event name="o" type="key" code="111" ascii="111" modifiers="" /> + <event name="p" type="key" code="112" ascii="112" modifiers="" /> + <event name="q" type="key" code="113" ascii="113" modifiers="" /> + <event name="r" type="key" code="114" ascii="114" modifiers="" /> + <event name="s" type="key" code="115" ascii="115" modifiers="" /> + <event name="t" type="key" code="116" ascii="116" modifiers="" /> + <event name="u" type="key" code="117" ascii="117" modifiers="" /> + <event name="v" type="key" code="118" ascii="118" modifiers="" /> + <event name="w" type="key" code="119" ascii="119" modifiers="" /> + <event name="x" type="key" code="120" ascii="120" modifiers="" /> + <event name="y" type="key" code="121" ascii="121" modifiers="" /> + <event name="z" type="key" code="122" ascii="122" modifiers="" /> + <event name="quit" type="submit" /> + </mode> + + <!-- Uppercase Symbols --> + <mode name="uppercasesymbols" resolutions="320x240,640x480"> + <layout resolution="320x240" bitmap="uppercase-symbols320x240.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="13,8,306,20" target="display_area" /> + <area shape="rect" coords="9,26,25,42" target="esc" /> + <area shape="rect" coords="50,25,67,43" target="f2" /> + <area shape="rect" coords="29,24,46,43" target="f1" /> + <area shape="rect" coords="71,26,88,44" target="f3" /> + <area shape="rect" coords="90,25,107,43" target="f4" /> + <area shape="rect" coords="111,26,128,44" target="f5" /> + <area shape="rect" coords="132,26,149,44" target="f6" /> + <area shape="rect" coords="153,25,170,44" target="f7" /> + <area shape="rect" coords="173,26,190,44" target="f8" /> + <area shape="rect" coords="194,24,211,43" target="f9" /> + <area shape="rect" coords="215,26,231,44" target="f10" /> + <area shape="rect" coords="235,26,253,43" target="f11" /> + <area shape="rect" coords="255,26,272,45" target="f12" /> + <area shape="rect" coords="276,27,310,43" target="del" /> + <area shape="rect" coords="8,47,26,64" target="¬" /> + <area shape="rect" coords="28,47,45,64" target="!" /> + <area shape="rect" coords="50,47,67,65" target="quote" /> + <area shape="rect" coords="70,46,87,65" target="£" /> + <area shape="rect" coords="91,46,108,64" target="$" /> + <area shape="rect" coords="111,46,129,65" target="%" /> + <area shape="rect" coords="132,47,149,65" target="^" /> + <area shape="rect" coords="152,47,170,64" target="&" /> + <area shape="rect" coords="174,46,191,63" target="*" /> + <area shape="rect" coords="194,47,211,65" target="(" /> + <area shape="rect" coords="215,46,232,64" target=")" /> + <area shape="rect" coords="235,47,252,65" target="_" /> + <area shape="rect" coords="255,46,272,65" target="+" /> + <area shape="rect" coords="276,47,308,64" target="backspace" /> + <area shape="rect" coords="8,68,32,85" target="tab" /> + <area shape="rect" coords="36,68,53,85" target="Q" /> + <area shape="rect" coords="57,68,75,86" target="W" /> + <area shape="rect" coords="78,67,94,85" target="E" /> + <area shape="rect" coords="98,67,115,85" target="R" /> + <area shape="rect" coords="119,67,136,85" target="T" /> + <area shape="rect" coords="141,68,158,86" target="Y" /> + <area shape="rect" coords="161,67,179,86" target="U" /> + <area shape="rect" coords="182,67,199,86" target="I" /> + <area shape="rect" coords="202,67,220,85" target="O" /> + <area shape="rect" coords="223,68,240,86" target="P" /> + <area shape="rect" coords="244,68,261,86" target="{" /> + <area shape="rect" coords="264,67,282,86" target="}" /> + <area shape="rect" coords="284,68,309,86" target="~" /> + <area shape="rect" coords="8,89,41,106" target="caps" /> + <area shape="rect" coords="44,88,63,107" target="A" /> + <area shape="rect" coords="65,88,84,106" target="S" /> + <area shape="rect" coords="86,89,104,107" target="D" /> + <area shape="rect" coords="107,89,124,107" target="F" /> + <area shape="rect" coords="128,89,145,107" target="G" /> + <area shape="rect" coords="149,88,165,107" target="H" /> + <area shape="rect" coords="169,89,186,107" target="J" /> + <area shape="rect" coords="189,89,207,107" target="K" /> + <area shape="rect" coords="210,89,228,107" target="L" /> + <area shape="rect" coords="231,88,249,106" target=":" /> + <area shape="rect" coords="251,89,269,107" target="@" /> + <area shape="rect" coords="273,89,311,106" target="enter" /> + <area shape="rect" coords="9,110,50,127" target="shift" /> + <area shape="rect" coords="58,110,75,128" target="z" /> + <area shape="rect" coords="79,110,96,128" target="x" /> + <area shape="rect" coords="99,109,116,127" target="c" /> + <area shape="rect" coords="120,110,138,128" target="v" /> + <area shape="rect" coords="141,109,157,127" target="b" /> + <area shape="rect" coords="162,110,179,128" target="n" /> + <area shape="rect" coords="182,110,199,128" target="m" /> + <area shape="rect" coords="202,110,219,128" target="<" /> + <area shape="rect" coords="223,110,241,128" target=">" /> + <area shape="rect" coords="243,110,261,128" target="?" /> + <area shape="rect" coords="271,109,311,128" target="symbols" /> + <area shape="rect" coords="9,130,33,148" target="ctrl" /> + <area shape="rect" coords="38,130,61,147" target="alt" /> + <area shape="rect" coords="67,130,262,148" target="space" /> + </map> + </layout> + <layout resolution="640x480" bitmap="uppercase-symbols640x480.bmp" transparent_color="255,0,255"> + <map> + <area shape="rect" coords="26,23,613,37" target="display_area" /> + <area shape="rect" coords="18,52,51,85" target="esc" /> + <area shape="rect" coords="100,51,135,88" target="f2" /> + <area shape="rect" coords="59,49,94,88" target="f1" /> + <area shape="rect" coords="142,53,176,89" target="f3" /> + <area shape="rect" coords="181,51,216,87" target="f4" /> + <area shape="rect" coords="223,52,258,88" target="f5" /> + <area shape="rect" coords="265,52,299,89" target="f6" /> + <area shape="rect" coords="306,51,341,90" target="f7" /> + <area shape="rect" coords="347,53,382,89" target="f8" /> + <area shape="rect" coords="389,49,424,88" target="f9" /> + <area shape="rect" coords="431,52,464,89" target="f10" /> + <area shape="rect" coords="470,53,506,88" target="f11" /> + <area shape="rect" coords="511,52,546,90" target="f12" /> + <area shape="rect" coords="552,55,620,87" target="del" /> + <area shape="rect" coords="16,95,53,129" target="¬" /> + <area shape="rect" coords="57,95,92,129" target="!" /> + <area shape="rect" coords="100,94,134,130" target="quote" /> + <area shape="rect" coords="140,93,174,131" target="£" /> + <area shape="rect" coords="182,93,217,130" target="$" /> + <area shape="rect" coords="222,93,258,132" target="%" /> + <area shape="rect" coords="265,94,299,131" target="^" /> + <area shape="rect" coords="305,94,341,129" target="&" /> + <area shape="rect" coords="348,93,382,128" target="*" /> + <area shape="rect" coords="389,94,423,130" target="(" /> + <area shape="rect" coords="431,93,465,130" target=")" /> + <area shape="rect" coords="471,94,505,131" target="_" /> + <area shape="rect" coords="511,93,546,131" target="+" /> + <area shape="rect" coords="553,94,618,129" target="backspace" /> + <area shape="rect" coords="17,136,66,171" target="tab" /> + <area shape="rect" coords="73,137,108,171" target="Q" /> + <area shape="rect" coords="114,136,150,172" target="W" /> + <area shape="rect" coords="157,134,189,171" target="E" /> + <area shape="rect" coords="197,135,232,171" target="R" /> + <area shape="rect" coords="239,135,274,172" target="T" /> + <area shape="rect" coords="282,136,317,173" target="Y" /> + <area shape="rect" coords="322,135,359,173" target="U" /> + <area shape="rect" coords="364,134,399,172" target="I" /> + <area shape="rect" coords="404,135,440,171" target="O" /> + <area shape="rect" coords="446,136,480,172" target="P" /> + <area shape="rect" coords="488,136,522,172" target="{" /> + <area shape="rect" coords="529,135,565,173" target="}" /> + <area shape="rect" coords="569,136,620,172" target="~" /> + <area shape="rect" coords="17,179,84,213" target="caps" /> + <area shape="rect" coords="89,177,127,216" target="A" /> + <area shape="rect" coords="131,177,169,214" target="S" /> + <area shape="rect" coords="173,178,209,215" target="D" /> + <area shape="rect" coords="215,178,250,214" target="F" /> + <area shape="rect" coords="256,178,291,214" target="G" /> + <area shape="rect" coords="299,176,332,214" target="H" /> + <area shape="rect" coords="339,178,374,215" target="J" /> + <area shape="rect" coords="379,178,415,215" target="K" /> + <area shape="rect" coords="421,178,457,215" target="L" /> + <area shape="rect" coords="462,177,498,214" target=":" /> + <area shape="rect" coords="503,178,539,214" target="@" /> + <area shape="rect" coords="546,179,622,214" target="enter" /> + <area shape="rect" coords="19,221,101,256" target="shift" /> + <area shape="rect" coords="117,220,152,256" target="z" /> + <area shape="rect" coords="158,220,192,256" target="x" /> + <area shape="rect" coords="198,219,233,256" target="c" /> + <area shape="rect" coords="240,220,276,257" target="v" /> + <area shape="rect" coords="283,219,316,255" target="b" /> + <area shape="rect" coords="324,220,359,256" target="n" /> + <area shape="rect" coords="365,220,399,257" target="m" /> + <area shape="rect" coords="405,220,440,256" target="<" /> + <area shape="rect" coords="447,220,483,256" target=">" /> + <area shape="rect" coords="487,220,524,256" target="?" /> + <area shape="rect" coords="542,219,623,257" target="symbols" /> + <area shape="rect" coords="19,260,68,296" target="ctrl" /> + <area shape="rect" coords="76,261,123,295" target="alt" /> + <area shape="rect" coords="135,261,525,297" target="space" /> + </map> + </layout> + <event name="esc" type="key" code="27" ascii="27" modifiers="" /> + <event name="f1" type="key" code="282" ascii="315" modifiers="" /> + <event name="f2" type="key" code="283" ascii="316" modifiers="" /> + <event name="f3" type="key" code="284" ascii="317" modifiers="" /> + <event name="f4" type="key" code="285" ascii="318" modifiers="" /> + <event name="f5" type="key" code="286" ascii="319" modifiers="" /> + <event name="f6" type="key" code="287" ascii="320" modifiers="" /> + <event name="f7" type="key" code="288" ascii="321" modifiers="" /> + <event name="f8" type="key" code="289" ascii="322" modifiers="" /> + <event name="f9" type="key" code="290" ascii="323" modifiers="" /> + <event name="f10" type="key" code="291" ascii="324" modifiers="" /> + <event name="f11" type="key" code="292" ascii="325" modifiers="" /> + <event name="f12" type="key" code="293" ascii="326" modifiers="" /> + <event name="del" type="key" code="127" ascii="0" modifiers="" /> + <event name="ctrl" type="modifier" modifiers="ctrl" /> + <event name="alt" type="modifier" modifiers="alt" /> + <event name="shift" type="switch_mode" mode="shiftlowercase" /> + <event name="caps" type="switch_mode" mode="lowercasesymbols" /> + <event name="symbols" type="switch_mode" mode="uppercase" /> + <event name="backspace" type="key" code="8" ascii="8" modifiers="" /> + <event name="enter" type="key" code="13" ascii="13" modifiers="" /> + <event name="quote" type="key" code="34" ascii="34" modifiers="" /> + <event name="£" type="key" code="163" ascii="163" modifiers="" /> + <event name="$" type="key" code="36" ascii="36" modifiers="" /> + <event name="%" type="key" code="37" ascii="37" modifiers="" /> + <event name="^" type="key" code="94" ascii="94" modifiers="" /> + <event name="&" type="key" code="38" ascii="38" modifiers="" /> + <event name="*" type="key" code="42" ascii="42" modifiers="" /> + <event name="(" type="key" code="40" ascii="40" modifiers="" /> + <event name=")" type="key" code="41" ascii="41" modifiers="" /> + <event name="_" type="key" code="95" ascii="95" modifiers="" /> + <event name="+" type="key" code="43" ascii="43" modifiers="" /> + <event name="¬" type="key" code="172" ascii="172" modifiers="" /> + <event name="!" type="key" code="33" ascii="33" modifiers="" /> + <event name="{" type="key" code="123" ascii="123" modifiers="" /> + <event name="}" type="key" code="125" ascii="125" modifiers="" /> + <event name="~" type="key" code="126" ascii="126" modifiers="" /> + <event name=":" type="key" code="58" ascii="58" modifiers="" /> + <event name="@" type="key" code="64" ascii="64" modifiers="" /> + <event name="<" type="key" code="60" ascii="60" modifiers="" /> + <event name=">" type="key" code="62" ascii="62" modifiers="" /> + <event name="?" type="key" code="63" ascii="63" modifiers="" /> + <event name="space" type="key" code="32" ascii="32" modifiers="" /> + <event name="tab" type="key" code="9" ascii="9" modifiers="" /> + <event name="A" type="key" code="97" ascii="65" modifiers="shift" /> + <event name="B" type="key" code="98" ascii="66" modifiers="shift" /> + <event name="C" type="key" code="99" ascii="67" modifiers="shift" /> + <event name="D" type="key" code="100" ascii="68" modifiers="shift" /> + <event name="E" type="key" code="101" ascii="69" modifiers="shift" /> + <event name="F" type="key" code="102" ascii="70" modifiers="shift" /> + <event name="G" type="key" code="103" ascii="71" modifiers="shift" /> + <event name="H" type="key" code="104" ascii="72" modifiers="shift" /> + <event name="I" type="key" code="105" ascii="73" modifiers="shift" /> + <event name="J" type="key" code="106" ascii="74" modifiers="shift" /> + <event name="K" type="key" code="107" ascii="75" modifiers="shift" /> + <event name="L" type="key" code="108" ascii="76" modifiers="shift" /> + <event name="M" type="key" code="109" ascii="77" modifiers="shift" /> + <event name="N" type="key" code="110" ascii="78" modifiers="shift" /> + <event name="O" type="key" code="111" ascii="79" modifiers="shift" /> + <event name="P" type="key" code="112" ascii="80" modifiers="shift" /> + <event name="Q" type="key" code="113" ascii="81" modifiers="shift" /> + <event name="R" type="key" code="114" ascii="82" modifiers="shift" /> + <event name="S" type="key" code="115" ascii="83" modifiers="shift" /> + <event name="T" type="key" code="116" ascii="84" modifiers="shift" /> + <event name="U" type="key" code="117" ascii="85" modifiers="shift" /> + <event name="V" type="key" code="118" ascii="86" modifiers="shift" /> + <event name="W" type="key" code="119" ascii="87" modifiers="shift" /> + <event name="X" type="key" code="120" ascii="88" modifiers="shift" /> + <event name="Y" type="key" code="121" ascii="89" modifiers="shift" /> + <event name="Z" type="key" code="122" ascii="90" modifiers="shift" /> + <event name="0" type="key" code="48" ascii="48" modifiers="" /> + <event name="1" type="key" code="49" ascii="49" modifiers="" /> + <event name="2" type="key" code="50" ascii="50" modifiers="" /> + <event name="3" type="key" code="51" ascii="51" modifiers="" /> + <event name="4" type="key" code="52" ascii="52" modifiers="" /> + <event name="5" type="key" code="53" ascii="53" modifiers="" /> + <event name="6" type="key" code="54" ascii="54" modifiers="" /> + <event name="7" type="key" code="55" ascii="55" modifiers="" /> + <event name="8" type="key" code="56" ascii="56" modifiers="" /> + <event name="9" type="key" code="57" ascii="57" modifiers="" /> + <event name="quit" type="submit" /> + </mode> + +</keyboard> diff --git a/backends/vkeybd/packs/vkeybdpack.py b/backends/vkeybd/packs/vkeybdpack.py new file mode 100755 index 0000000000..130e4b737b --- /dev/null +++ b/backends/vkeybd/packs/vkeybdpack.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# encoding: utf-8 +import sys +import re +import os +import zipfile +try: + import zlib + compression = zipfile.ZIP_DEFLATED +except: + compression = zipfile.ZIP_STORED + +PACK_FILE_EXTENSIONS = ('.xml', '.bmp') + +def buildPack(packName): + if not os.path.isdir(packName): + print ("Invalid pack name: " + packName) + return + + zf = zipfile.ZipFile(packName + ".zip", 'w') + + zf.compress_type = zipfile.ZIP_DEFLATED + + print ("Building '" + packName + "' pack:") + os.chdir(packName) + + for filename in os.listdir('.'): + if os.path.isfile(filename) and not filename[0] == '.' and filename.endswith(PACK_FILE_EXTENSIONS): + zf.write(filename, './' + filename, compress_type=compression) + print (" Adding file: " + filename) + + os.chdir('../') + + zf.close() + +def buildAllPacks(): + for f in os.listdir('.'): + if os.path.isdir(os.path.join('.', f)) and not f[0] == '.': + buildPack(f) + +def printUsage(): + print ("===============================================") + print ("ScummVM Virtual Keyboard Pack Generation Script") + print ("===============================================") + print ("Usage:") + print ("vkeybdpack.py makeall") + print (" Builds all the available pack.\n") + print ("vkeybdpack.py make [packname]") + print (" Builds the pack called 'packname'.\n") + +def main(): + + if len(sys.argv) == 2 and sys.argv[1] == "makeall": + buildAllPacks() + + elif len(sys.argv) == 3 and sys.argv[1] == "make": + buildPack(sys.argv[2]) + + else: + printUsage() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp index 54b9b3d43d..e1c076ad24 100644 --- a/backends/vkeybd/virtual-keyboard-gui.cpp +++ b/backends/vkeybd/virtual-keyboard-gui.cpp @@ -117,8 +117,12 @@ void VirtualKeyboardGUI::setupDisplayArea(Rect& r, OverlayColor forecolor) { if (!fontIsSuitable(_dispFont, r)) { _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); if (!fontIsSuitable(_dispFont, r)) { - _displayEnabled = false; - return; + /* FIXME: We 'ab'use the kConsoleFont to get a font that fits in a small display_area on 320*240 keyboard images */ + _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont); + if (!fontIsSuitable(_dispFont, r)) { + _displayEnabled = false; + return; + } } } _dispX = _kbdBound.left + r.left; diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp index 3e40ffc1fa..5ae53f08ec 100644 --- a/backends/vkeybd/virtual-keyboard-parser.cpp +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -87,7 +87,7 @@ bool VirtualKeyboardParser::parserCallback_keyboard(ParserNode *node) { } if (node->values.contains("v_align")) { - String v = node->values["h_align"]; + String v = node->values["v_align"]; if (v.equalsIgnoreCase("top")) _keyboard->_vAlignment = VirtualKeyboard::kAlignTop; else if (v.equalsIgnoreCase("middle") || v.equalsIgnoreCase("center")) diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp index a95b79d213..4ca4a5f586 100644 --- a/backends/vkeybd/virtual-keyboard.cpp +++ b/backends/vkeybd/virtual-keyboard.cpp @@ -31,7 +31,6 @@ #include "backends/vkeybd/virtual-keyboard-parser.h" #include "backends/vkeybd/keycode-descriptions.h" #include "common/config-manager.h" -#include "common/fs.h" #include "common/unzip.h" #define KEY_START_CHAR ('[') @@ -77,51 +76,77 @@ void VirtualKeyboard::reset() { _kbdGUI->reset(); } -bool VirtualKeyboard::loadKeyboardPack(String packName) { - _kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight()); - - delete _fileArchive; - _fileArchive = 0; - - FSNode vkDir; - if (ConfMan.hasKey("vkeybdpath")) - vkDir = FSNode(ConfMan.get("vkeybdpath")); - else if (ConfMan.hasKey("extrapath")) - vkDir = FSNode(ConfMan.get("extrapath")); - else // use current directory - vkDir = FSNode("."); - - if (vkDir.getChild(packName + ".xml").exists()) { - _fileArchive = new FSDirectory(vkDir, 1); +bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) { + if (node.getChild(packName + ".xml").exists()) { + _fileArchive = new FSDirectory(node, 1); // uncompressed keyboard pack - if (!_parser->loadFile(vkDir.getChild(packName + ".xml"))) + if (!_parser->loadFile(node.getChild(packName + ".xml"))) { + delete _fileArchive; + _fileArchive = 0; return false; + } + + return true; + } - } else if (vkDir.getChild(packName + ".zip").exists()) { - // compressed keyboard pack #ifdef USE_ZLIB - _fileArchive = new ZipArchive(vkDir.getChild(packName + ".zip")); + if (node.getChild(packName + ".zip").exists()) { + // compressed keyboard pack + _fileArchive = new ZipArchive(node.getChild(packName + ".zip")); if (_fileArchive->hasFile(packName + ".xml")) { - if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) + if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) { + delete _fileArchive; + _fileArchive = 0; return false; + } } else { warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str()); + delete _fileArchive; + _fileArchive = 0; return false; } -#else - return false; + + return true; + } #endif + + return false; +} + +bool VirtualKeyboard::loadKeyboardPack(const String &packName) { + _kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight()); + + delete _fileArchive; + _fileArchive = 0; + _loaded = false; + + bool opened = false; + if (ConfMan.hasKey("vkeybdpath")) + opened = openPack(packName, FSNode(ConfMan.get("vkeybdpath"))); + else if (ConfMan.hasKey("extrapath")) + opened = openPack(packName, FSNode(ConfMan.get("extrapath"))); + + // fallback to the current dir + if (!opened) + opened = openPack(packName, FSNode(".")); + + if (opened) { + _parser->setParseMode(VirtualKeyboardParser::kParseFull); + _loaded = _parser->parse(); + + if (_loaded) { + printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str()); + } else { + warning("Error parsing the keyboard pack '%s'", packName.c_str()); + + delete _fileArchive; + _fileArchive = 0; + } } else { warning("Keyboard pack not found"); - return false; } - _parser->setParseMode(VirtualKeyboardParser::kParseFull); - _loaded = _parser->parse(); - if (_loaded) - printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str()); - return _loaded; } diff --git a/backends/vkeybd/virtual-keyboard.h b/backends/vkeybd/virtual-keyboard.h index e3a9cd3600..2c31afcb35 100644 --- a/backends/vkeybd/virtual-keyboard.h +++ b/backends/vkeybd/virtual-keyboard.h @@ -37,6 +37,7 @@ class OSystem; #include "common/keyboard.h" #include "common/list.h" #include "common/str.h" +#include "common/fs.h" #include "backends/vkeybd/image-map.h" #include "graphics/surface.h" @@ -190,7 +191,7 @@ public: * searches for a compressed keyboard pack by looking for packName.zip. * @param packName name of the keyboard pack */ - bool loadKeyboardPack(String packName); + bool loadKeyboardPack(const String &packName); /** * Shows the keyboard, starting an event loop that will intercept all @@ -232,6 +233,7 @@ protected: VirtualKeyboardParser *_parser; void reset(); + bool openPack(const String &packName, const FSNode &node); void deleteEvents(); bool checkModeResolutions(); void switchMode(Mode *newMode); diff --git a/backends/vkeybd/vkeybd.zip b/backends/vkeybd/vkeybd.zip Binary files differdeleted file mode 100644 index 70f84ad0ce..0000000000 --- a/backends/vkeybd/vkeybd.zip +++ /dev/null diff --git a/base/commandLine.cpp b/base/commandLine.cpp index b58c3d320d..890d14db92 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -37,6 +37,7 @@ #include "gui/ThemeEngine.h" #define DETECTOR_TESTING_HACK +#define UPGRADE_ALL_TARGETS_HACK namespace Base { @@ -322,9 +323,17 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha DO_COMMAND('z', "list-games") END_OPTION +#ifdef DETECTOR_TESTING_HACK // HACK FIXME TODO: This command is intentionally *not* documented! DO_LONG_COMMAND("test-detector") END_OPTION +#endif + +#ifdef UPGRADE_ALL_TARGETS_HACK + // HACK FIXME TODO: This command is intentionally *not* documented! + DO_LONG_COMMAND("upgrade-targets") + END_OPTION +#endif DO_LONG_OPTION("list-saves") // FIXME: Need to document this. @@ -685,7 +694,7 @@ static void runDetectorTest() { if (gameidDiffers) { printf(" WARNING: Multiple games detected, some/all with wrong gameid\n"); } else { - printf(" WARNING: Multiple games detected, but all have the same gameid\n"); + printf(" WARNING: Multiple games detected, but all have matching gameid\n"); } failure++; } else if (gameidDiffers) { @@ -710,6 +719,121 @@ static void runDetectorTest() { } #endif +#ifdef UPGRADE_ALL_TARGETS_HACK +void upgradeTargets() { + // HACK: The following upgrades all your targets to the latest and + // greatest. Right now that means updating the guioptions and (optionally) + // also the game descriptions. + // Basically, it loops over all targets, and calls the detector for the + // given path. It then compares the result with the settings of the target. + // If the basics seem to match, it updates the guioptions. + + printf("Upgrading all your existing targets\n"); + + Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); + Common::ConfigManager::DomainMap::iterator iter = domains.begin(); + for (iter = domains.begin(); iter != domains.end(); ++iter) { + Common::ConfigManager::Domain &dom = iter->_value; + Common::String name(iter->_key); + Common::String gameid(dom.get("gameid")); + Common::String path(dom.get("path")); + printf("Looking at target '%s', gameid '%s' ...\n", + name.c_str(), gameid.c_str()); + if (path.empty()) { + printf(" ... no path specified, skipping\n"); + continue; + } + if (gameid.empty()) { + gameid = name; + } + gameid.toLowercase(); // TODO: Is this paranoia? Maybe we should just assume all lowercase, always? + + Common::FSNode dir(path); + Common::FSList files; + if (!dir.getChildren(files, Common::FSNode::kListAll)) { + printf(" ... invalid path, skipping\n"); + continue; + } + + Common::Language lang = Common::parseLanguage(dom.get("language")); + Common::Platform plat = Common::parsePlatform(dom.get("platform")); + Common::String desc(dom.get("description")); + + GameList candidates(EngineMan.detectGames(files)); + GameDescriptor *g = 0; + + // We proceed as follows: + // * If detection failed to produce candidates, skip. + // * If there is a unique detector match, trust it. + // * If there are multiple match, run over them comparing gameid, language and platform. + // If we end up with a unique match, use it. Otherwise, skip. + if (candidates.size() == 0) { + printf(" ... failed to detect game, skipping\n"); + continue; + } + if (candidates.size() > 1) { + // Scan over all candidates, check if there is a unique match for gameid, language and platform + GameList::iterator x; + int matchesFound = 0; + for (x = candidates.begin(); x != candidates.end(); ++x) { + if (x->gameid() == gameid && x->language() == lang && x->platform() == plat) { + matchesFound++; + g = &(*x); + } + } + if (matchesFound != 1) { + printf(" ... detected multiple games, could not establish unique match, skipping\n"); + continue; + } + } else { + // Unique match -> use it + g = &candidates[0]; + } + + // At this point, g points to a GameDescriptor which we can use to update + // the target referred to by dom. We update several things + + // Always set the gameid explicitly (in case of legacy targets) + dom["gameid"] = g->gameid(); + + // Always set the GUI options. The user should not modify them, and engines might + // gain more features over time, so we want to keep this list up-to-date. + if (g->contains("guioptions")) { + printf(" -> update guioptions to '%s'\n", (*g)["guioptions"].c_str()); + dom["guioptions"] = (*g)["guioptions"]; + } else if (dom.contains("guioptions")) { + dom.erase("guioptions"); + } + + // Update the language setting but only if none has been set yet. + if (lang == Common::UNK_LANG && g->language() != Common::UNK_LANG) { + printf(" -> set language to '%s'\n", Common::getLanguageCode(g->language())); + dom["language"] = (*g)["language"]; + } + + // Update the platform setting but only if none has been set yet. + if (plat == Common::kPlatformUnknown && g->platform() != Common::kPlatformUnknown) { + printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform())); + dom["platform"] = (*g)["platform"]; + } + + // TODO: We could also update the description. But not everybody will want that. + // Esp. because for some games (e.g. the combined Zak/Loom FM-TOWNS demo etc.) + // ScummVM still generates an incorrect description string. So, the description + // should only be updated if the user explicitly requests this. +#if 0 + if (desc != g->description()) { + printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description().c_str()); + dom["description"] = (*g)["description"]; + } +#endif + } + + // Finally, save our changes to disk + ConfMan.flushToDisk(); +} +#endif + #else // DISABLE_COMMAND_LINE @@ -754,6 +878,12 @@ bool processSettings(Common::String &command, Common::StringMap &settings) { return false; } #endif +#ifdef UPGRADE_ALL_TARGETS_HACK + else if (command == "upgrade-targets") { + upgradeTargets(); + return false; + } +#endif #endif // DISABLE_COMMAND_LINE diff --git a/base/main.cpp b/base/main.cpp index dba4aeccaa..a091c5885a 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -81,8 +81,15 @@ static const EnginePlugin *detectPlugin() { // Make sure the gameid is set in the config manager, and that it is lowercase. Common::String gameid(ConfMan.getActiveDomainName()); assert(!gameid.empty()); - if (ConfMan.hasKey("gameid")) + if (ConfMan.hasKey("gameid")) { gameid = ConfMan.get("gameid"); + + // Set last selected game, that the game will be highlighted + // on RTL + ConfMan.set("lastselectedgame", ConfMan.getActiveDomainName(), Common::ConfigManager::kApplicationDomain); + ConfMan.flushToDisk(); + } + gameid.toLowercase(); ConfMan.set("gameid", gameid); diff --git a/common/config-manager.h b/common/config-manager.h index d86431be2f..bc734dbdc3 100644 --- a/common/config-manager.h +++ b/common/config-manager.h @@ -155,6 +155,7 @@ public: void renameGameDomain(const String &oldName, const String &newName); bool hasGameDomain(const String &domName) const; const DomainMap & getGameDomains() const { return _gameDomains; } + DomainMap & getGameDomains() { return _gameDomains; } private: friend class Singleton<SingletonBaseType>; diff --git a/common/debug.cpp b/common/debug.cpp index cc358596f7..ff17959cbf 100644 --- a/common/debug.cpp +++ b/common/debug.cpp @@ -227,6 +227,19 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) { va_end(va); } +void debugCN(int level, uint32 debugChannels, const char *s, ...) { + va_list va; + + // Debug level 11 turns on all special debug level messages + if (gDebugLevel != 11) + if (level > gDebugLevel || !(Common::gDebugLevelsEnabled & debugChannels)) + return; + + va_start(va, s); + debugHelper(s, va, false); + va_end(va); +} + void debugC(uint32 debugChannels, const char *s, ...) { va_list va; @@ -240,4 +253,17 @@ void debugC(uint32 debugChannels, const char *s, ...) { va_end(va); } +void debugCN(uint32 debugChannels, const char *s, ...) { + va_list va; + + // Debug level 11 turns on all special debug level messages + if (gDebugLevel != 11) + if (!(Common::gDebugLevelsEnabled & debugChannels)) + return; + + va_start(va, s); + debugHelper(s, va, false); + va_end(va); +} + #endif diff --git a/common/debug.h b/common/debug.h index 43fe297859..95779af617 100644 --- a/common/debug.h +++ b/common/debug.h @@ -106,6 +106,8 @@ inline void debug(int level, const char *s, ...) {} inline void debugN(int level, const char *s, ...) {} inline void debugC(int level, uint32 engine_level, const char *s, ...) {} inline void debugC(uint32 engine_level, const char *s, ...) {} +inline void debugCN(int level, uint32 engine_level, const char *s, ...) {} +inline void debugCN(uint32 engine_level, const char *s, ...) {} #else @@ -135,7 +137,7 @@ void debugN(int level, const char *s, ...) GCC_PRINTF(2, 3); /** * Print a debug message to the text console (stdout), but only if - * the specified level does not exceed the value of gDebugLevel OR + * the specified level does not exceed the value of gDebugLevel AND * if the specified special debug level is active. * As a rule of thumb, the more important the message, the lower the level. * Automatically appends a newline. @@ -146,6 +148,17 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4 /** * Print a debug message to the text console (stdout), but only if + * the specified level does not exceed the value of gDebugLevel AND + * if the specified special debug level is active. + * As a rule of thumb, the more important the message, the lower the level. + * Does not append a newline automatically. + * + * @see enableDebugChannel + */ +void debugCN(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4); + +/** + * Print a debug message to the text console (stdout), but only if * the specified special debug level is active. * Automatically appends a newline. * @@ -153,6 +166,14 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4 */ void debugC(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); +/** + * Print a debug message to the text console (stdout), but only if + * the specified special debug level is active. + * Does not append a newline automatically. + * + * @see enableDebugChannel + */ +void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); #endif diff --git a/common/events.h b/common/events.h index f6a07e3341..e13d95cf47 100644 --- a/common/events.h +++ b/common/events.h @@ -61,6 +61,7 @@ enum EventType { EVENT_MAINMENU = 15, EVENT_RTL = 16, + EVENT_MUTE = 17, EVENT_QUIT = 10, EVENT_SCREEN_CHANGED = 11, diff --git a/common/hashmap.cpp b/common/hashmap.cpp index 0fb03ec3f8..d8b84f61a5 100644 --- a/common/hashmap.cpp +++ b/common/hashmap.cpp @@ -58,6 +58,7 @@ uint hashit_lower(const char *p) { #ifdef DEBUG_HASH_COLLISIONS static double g_collisions = 0, + g_dummyHits = 0, g_lookups = 0, g_collPerLook = 0, g_capacity = 0, @@ -66,9 +67,10 @@ static int g_max_capacity = 0, g_max_size = 0; static int g_totalHashmaps = 0; static int g_stats[4] = {0,0,0,0}; -void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) { +void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int arrsize, int nele) { g_collisions += collisions; g_lookups += lookups; + g_dummyHits += dummyHits; if (lookups) g_collPerLook += (double)collisions / (double)lookups; g_capacity += arrsize; @@ -87,9 +89,10 @@ void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele g_max_capacity = MAX(g_max_capacity, arrsize); g_max_size = MAX(g_max_size, nele); - fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", + fprintf(stdout, "%d hashmaps: colls %.1f; dummies hit %.1f, lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", g_totalHashmaps, g_collisions / g_totalHashmaps, + g_dummyHits / g_totalHashmaps, g_lookups / g_totalHashmaps, 100 * g_collPerLook / g_totalHashmaps, g_size / g_totalHashmaps, g_max_size, diff --git a/common/hashmap.h b/common/hashmap.h index 16de7cdf54..f5059a4bcf 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -24,8 +24,7 @@ */ // The hash map (associative array) implementation in this file is -// based on the PyDict implementation of CPython. The erase() method -// is based on example code in the Wikipedia article on Hash tables. +// based on the PyDict implementation of CPython. #ifndef COMMON_HASHMAP_H #define COMMON_HASHMAP_H @@ -72,7 +71,8 @@ public: struct Node { const Key _key; Val _value; - Node(const Key &key) : _key(key), _value() {} + explicit Node(const Key &key) : _key(key), _value() {} + Node() : _key(), _value() {} }; enum { @@ -98,12 +98,14 @@ public: } void freeNode(Node *node) { - _nodePool.deleteChunk(node); + if (node && node != &_dummyNode) + _nodePool.deleteChunk(node); } Node **_storage; // hashtable of size arrsize. uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */ uint _size; + uint _deleted; ///< Number of deleted elements (_dummyNodes) HashFunc _hash; EqualFunc _equal; @@ -111,8 +113,11 @@ public: // Default value, returned by the const getVal. const Val _defaultVal; + // Dummy node, used as marker for erased objects. + Node _dummyNode; + #ifdef DEBUG_HASH_COLLISIONS - mutable int _collisions, _lookups; + mutable int _collisions, _lookups, _dummyHits; #endif void assign(const HM_t &map); @@ -269,7 +274,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() #ifdef __PLAYSTATION2__ { #else - : _defaultVal() { + : _defaultVal(), _dummyNode() { #endif _mask = HASHMAP_MIN_CAPACITY - 1; _storage = new Node *[HASHMAP_MIN_CAPACITY]; @@ -277,10 +282,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *)); _size = 0; + _deleted = 0; #ifdef DEBUG_HASH_COLLISIONS _collisions = 0; _lookups = 0; + _dummyHits = 0; #endif } @@ -291,7 +298,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() */ template<class Key, class Val, class HashFunc, class EqualFunc> HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : - _defaultVal() { + _defaultVal(), _dummyNode() { +#ifdef DEBUG_HASH_COLLISIONS + _collisions = 0; + _lookups = 0; + _dummyHits = 0; +#endif assign(map); } @@ -301,13 +313,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : template<class Key, class Val, class HashFunc, class EqualFunc> HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { for (uint ctr = 0; ctr <= _mask; ++ctr) - if (_storage[ctr] != NULL) - freeNode(_storage[ctr]); + freeNode(_storage[ctr]); delete[] _storage; #ifdef DEBUG_HASH_COLLISIONS - extern void updateHashCollisionStats(int, int, int, int); - updateHashCollisionStats(_collisions, _lookups, _mask+1, _size); + extern void updateHashCollisionStats(int, int, int, int, int); + updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size); #endif } @@ -327,8 +338,12 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { // Simply clone the map given to us, one by one. _size = 0; + _deleted = 0; for (uint ctr = 0; ctr <= _mask; ++ctr) { - if (map._storage[ctr] != NULL) { + if (map._storage[ctr] == &map._dummyNode) { + _storage[ctr] = &_dummyNode; + _deleted++; + } else if (map._storage[ctr] != NULL) { _storage[ctr] = allocNode(map._storage[ctr]->_key); _storage[ctr]->_value = map._storage[ctr]->_value; _size++; @@ -336,16 +351,15 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { } // Perform a sanity check (to help track down hashmap corruption) assert(_size == map._size); + assert(_deleted == map._deleted); } template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { for (uint ctr = 0; ctr <= _mask; ++ctr) { - if (_storage[ctr] != NULL) { - freeNode(_storage[ctr]); - _storage[ctr] = NULL; - } + freeNode(_storage[ctr]); + _storage[ctr] = NULL; } #ifdef USE_HASHMAP_MEMORY_POOL @@ -362,18 +376,22 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { } _size = 0; + _deleted = 0; } template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { assert(newCapacity > _mask+1); +#ifndef NDEBUG const uint old_size = _size; +#endif const uint old_mask = _mask; Node **old_storage = _storage; // allocate a new array _size = 0; + _deleted = 0; _mask = newCapacity - 1; _storage = new Node *[newCapacity]; assert(_storage != NULL); @@ -381,7 +399,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // rehash all the old elements for (uint ctr = 0; ctr <= old_mask; ++ctr) { - if (old_storage[ctr] == NULL) + if (old_storage[ctr] == NULL || old_storage[ctr] == &_dummyNode) continue; // Insert the element from the old table into the new table. @@ -390,7 +408,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // don't have to call _equal(). const uint hash = _hash(old_storage[ctr]->_key); uint idx = hash & _mask; - for (uint perturb = hash; _storage[idx] != NULL; perturb >>= HASHMAP_PERTURB_SHIFT) { + for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != &_dummyNode; perturb >>= HASHMAP_PERTURB_SHIFT) { idx = (5 * idx + perturb + 1) & _mask; } @@ -412,7 +430,13 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { const uint hash = _hash(key); uint ctr = hash & _mask; for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { - if (_storage[ctr] == NULL || _equal(_storage[ctr]->_key, key)) + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == &_dummyNode) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + } else if (_equal(_storage[ctr]->_key, key)) break; ctr = (5 * ctr + perturb + 1) & _mask; @@ -424,8 +448,8 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { #ifdef DEBUG_HASH_COLLISIONS _lookups++; - fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", - _collisions, _lookups, ((double) _collisions / (double)_lookups), + fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), (const void *)this, _mask+1, _size); #endif @@ -434,16 +458,54 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { template<class Key, class Val, class HashFunc, class EqualFunc> int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { - uint ctr = lookup(key); + const uint hash = _hash(key); + uint ctr = hash & _mask; + const uint NONE_FOUND = _mask + 1; + uint first_free = NONE_FOUND; + bool found = false; + for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { + if (_storage[ctr] == NULL) + break; + if (_storage[ctr] == &_dummyNode) { +#ifdef DEBUG_HASH_COLLISIONS + _dummyHits++; +#endif + if (first_free != _mask + 1) + first_free = ctr; + } else if (_equal(_storage[ctr]->_key, key)) { + found = true; + break; + } + + ctr = (5 * ctr + perturb + 1) & _mask; - if (_storage[ctr] == NULL) { +#ifdef DEBUG_HASH_COLLISIONS + _collisions++; +#endif + } + +#ifdef DEBUG_HASH_COLLISIONS + _lookups++; + fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", + _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups), + (const void *)this, _mask+1, _size); +#endif + + if (!found && first_free != _mask + 1) + ctr = first_free; + + if (!found) { + if (_storage[ctr]) + _deleted--; _storage[ctr] = allocNode(key); assert(_storage[ctr] != NULL); _size++; // Keep the load factor below a certain threshold. + // Deleted nodes are also counted uint capacity = _mask + 1; - if (_size * HASHMAP_LOADFACTOR_DENOMINATOR > capacity * HASHMAP_LOADFACTOR_NUMERATOR) { + if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR > + capacity * HASHMAP_LOADFACTOR_NUMERATOR) { capacity = capacity < 500 ? (capacity * 4) : (capacity * 2); expandStorage(capacity); ctr = lookup(key); @@ -496,44 +558,16 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &v template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { - // This is based on code in the Wikipedia article on Hash tables. - - const uint hash = _hash(key); - uint i = hash & _mask; - uint perturb; - - for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { - if (_storage[i] == NULL || _equal(_storage[i]->_key, key)) - break; - i = (5 * i + perturb + 1) & _mask; - } + uint ctr = lookup(key); + if (_storage[ctr] == NULL) + return; - if (_storage[i] == NULL) - return; // key wasn't present, so no work has to be done - - // If we remove a key, we must check all subsequent keys and possibly - // reinsert them. - uint j = i; - freeNode(_storage[i]); - _storage[i] = NULL; - for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { - // Look at the next table slot - j = (5 * j + perturb + 1) & _mask; - // If the next slot is empty, we are done - if (_storage[j] == NULL) - break; - // Compute the slot where the content of the next slot should normally be, - // assuming an empty table, and check whether we have to move it. - uint k = _hash(_storage[j]->_key) & _mask; - if ((j > i && (k <= i || k > j)) || - (j < i && (k <= i && k > j)) ) { - _storage[i] = _storage[j]; - i = j; - } - } - _storage[i] = NULL; + // If we remove a key, we replace it with a dummy node. + freeNode(_storage[ctr]); + _storage[ctr] = &_dummyNode; _size--; + _deleted++; return; } diff --git a/common/iff_container.h b/common/iff_container.h index 617bdde690..ebcf9ba803 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -27,6 +27,7 @@ #include "common/scummsys.h" #include "common/endian.h" +#include "common/func.h" #include "common/stream.h" #include "common/util.h" @@ -145,90 +146,159 @@ page 376) */ char * ID2string(Common::IFF_ID id); -class IFFChunk : public Common::ReadStream { - -protected: - Common::ReadStream *_input; - uint32 bytesRead; - -public: - IFF_ID id; - uint32 size; - - IFFChunk(Common::ReadStream *input): _input(input) { - size = bytesRead = 0; - } - - void incBytesRead(uint32 inc) { - bytesRead += inc; - if (bytesRead > size) { - error("Chunk '%s' overread", ID2string(id)); - } - } +/** + * Represents a IFF chunk available to client code. + * + * Client code must *not* deallocate _stream when done. + */ +struct IFFChunk { + Common::IFF_ID _type; + uint32 _size; + Common::ReadStream *_stream; - void readHeader() { - id = _input->readUint32BE(); - size = _input->readUint32BE(); - bytesRead = 0; + IFFChunk(Common::IFF_ID type, uint32 size, Common::ReadStream *stream) : _type(type), _size(size), _stream(stream) { + assert(_stream); } +}; - bool hasReadAll() const { - return (size - bytesRead) == 0; - } +/** + * Parser for IFF containers. + */ +class IFFParser { - void feed() { - if (size % 2) { - size++; + /** + * This private class implements IFF chunk navigation. + */ + class IFFChunkNav : public Common::ReadStream { + protected: + Common::ReadStream *_input; + uint32 _bytesRead; + public: + Common::IFF_ID id; + uint32 size; + + IFFChunkNav() : _input(0) { } - while (!hasReadAll()) { - readByte(); + void setInputStream(Common::ReadStream *input) { + _input = input; + size = _bytesRead = 0; } - } + void incBytesRead(uint32 inc) { + _bytesRead += inc; + if (_bytesRead > size) { + error("Chunk overread"); + } + } + void readHeader() { + id = _input->readUint32BE(); + size = _input->readUint32BE(); + _bytesRead = 0; + } + bool hasReadAll() const { + return (size - _bytesRead) == 0; + } + void feed() { + if (size % 2) { + size++; + } + while (!hasReadAll()) { + readByte(); + } + } + // Common::ReadStream implementation + bool eos() const { return _input->eos(); } + bool err() const { return _input->err(); } + void clearErr() { _input->clearErr(); } + + uint32 read(void *dataPtr, uint32 dataSize) { + incBytesRead(dataSize); + return _input->read(dataPtr, dataSize); + } + }; - // Common::ReadStream implementation - bool eos() const { return _input->eos(); } - bool err() const { return _input->err(); } - void clearErr() { _input->clearErr(); } +protected: + IFFChunkNav _formChunk; //!< The root chunk of the file. + IFFChunkNav _chunk; //!< The current chunk. - uint32 read(void *dataPtr, uint32 dataSize) { - incBytesRead(dataSize); - return _input->read(dataPtr, dataSize); - } + uint32 _formSize; + Common::IFF_ID _formType; -}; + Common::ReadStream *_stream; + bool _disposeStream; + + void setInputStream(Common::ReadStream *stream) { + assert(stream); + _formChunk.setInputStream(stream); + _chunk.setInputStream(stream); -class IFFParser { -public: - IFFParser(Common::ReadStream &input) : _formChunk(&input), _chunk(&input) { _formChunk.readHeader(); if (_formChunk.id != ID_FORM) { error("IFFParser input is not a FORM type IFF file"); } - _typeId = _formChunk.readUint32BE(); + _formSize = _formChunk.size; + _formType = _formChunk.readUint32BE(); } - virtual ~IFFParser() {} - - IFFChunk *nextChunk() { - _chunk.feed(); - _formChunk.incBytesRead(_chunk.size); - - if (_formChunk.hasReadAll()) - return 0; - - _formChunk.incBytesRead(8); - _chunk.readHeader(); - - return &_chunk; +public: + IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(disposeStream) { + setInputStream(stream); + } + ~IFFParser() { + if (_disposeStream) { + delete _stream; + } + _stream = 0; } - IFF_ID _typeId; - -protected: - IFFChunk _formChunk; - IFFChunk _chunk; + /** + * Returns the IFF FORM type. + * @return the IFF FORM type of the stream, or 0 if FORM header is not found. + */ + Common::IFF_ID getFORMType() const; + + /** + * Returns the size of the data. + * @return the size of the data in file, or -1 if FORM header is not found. + */ + uint32 getFORMSize() const; + + /** + * Callback type for the parser. + */ + typedef Common::Functor1< IFFChunk&, bool > IFFCallback; + + /** + * Parse the IFF container, invoking the callback on each chunk encountered. + * The callback can interrupt the parsing by returning 'true'. + */ + void parse(IFFCallback &callback) { + bool stop; + do { + _chunk.feed(); + _formChunk.incBytesRead(_chunk.size); + + if (_formChunk.hasReadAll()) { + break; + } + + _formChunk.incBytesRead(8); + _chunk.readHeader(); + + // invoke the callback + Common::SubReadStream stream(&_chunk, _chunk.size); + IFFChunk chunk(_chunk.id, _chunk.size, &stream); + stop = callback(chunk); + + // eats up all the remaining data in the chunk + while (!stream.eos()) { + stream.readByte(); + } + + } while (!stop); + } }; + } // namespace Common #endif diff --git a/common/str.cpp b/common/str.cpp index 3a3b1e610c..0d24f2edac 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -264,6 +264,9 @@ String& String::operator =(char c) { } String &String::operator +=(const char *str) { + if (_str <= str && str <= _str + _size) + return operator+=(Common::String(str)); + int len = strlen(str); if (len > 0) { ensureCapacity(_size + len, true); @@ -275,6 +278,9 @@ String &String::operator +=(const char *str) { } String &String::operator +=(const String &str) { + if (&str == this) + return operator+=(Common::String(str)); + int len = str._size; if (len > 0) { ensureCapacity(_size + len, true); @@ -294,6 +300,10 @@ String &String::operator +=(char c) { return *this; } +bool String::hasPrefix(const String &x) const { + return hasPrefix(x.c_str()); +} + bool String::hasPrefix(const char *x) const { assert(x != 0); // Compare x with the start of _str. @@ -307,6 +317,10 @@ bool String::hasPrefix(const char *x) const { return *x == 0; } +bool String::hasSuffix(const String &x) const { + return hasSuffix(x.c_str()); +} + bool String::hasSuffix(const char *x) const { assert(x != 0); // Compare x with the end of _str. @@ -323,6 +337,10 @@ bool String::hasSuffix(const char *x) const { return *x == 0; } +bool String::contains(const String &x) const { + return strstr(c_str(), x.c_str()) != NULL; +} + bool String::contains(const char *x) const { assert(x != 0); return strstr(c_str(), x) != NULL; diff --git a/common/str.h b/common/str.h index 4dc0f1be92..b7dbd6535a 100644 --- a/common/str.h +++ b/common/str.h @@ -143,9 +143,13 @@ public: int compareTo(const char *x) const; // strcmp clone int compareToIgnoreCase(const char *x) const; // stricmp clone + bool hasSuffix(const String &x) const; bool hasSuffix(const char *x) const; + + bool hasPrefix(const String &x) const; bool hasPrefix(const char *x) const; + bool contains(const String &x) const; bool contains(const char *x) const; bool contains(char x) const; diff --git a/common/system.h b/common/system.h index 46e14589ab..6f3dc6b6c8 100644 --- a/common/system.h +++ b/common/system.h @@ -151,6 +151,10 @@ public: * It is currently used only by some Macintosh versions of Humongous * Entertainment games. If the backend doesn't implement this feature then * the engine switches to b/w versions of cursors. + * The GUI also relies on this feature for mouse cursors. + * + * To enable the cursor palette call "disableCursorPalette" with false. + * @see disableCursorPalette */ kFeatureCursorHasPalette, @@ -721,10 +725,25 @@ public: - /** @name Mouse */ + /** @name Mouse + * This is the lower level implementation as provided by the + * backends. The engines should use the Graphics::CursorManager + * class instead of using it directly. + */ //@{ - /** Show or hide the mouse cursor. */ + /** + * Show or hide the mouse cursor. + * + * Currently the backend is not required to immediately draw the + * mouse cursor on showMouse(true). + * + * TODO: We might want to reconsider this fact, + * check Graphics::CursorManager::showMouse for some details about + * this. + * + * @see Graphics::CursorManager::showMouse + */ virtual bool showMouse(bool visible) = 0; /** @@ -890,6 +909,9 @@ public: * @name Audio CD * The methods in this group deal with Audio CD playback. * The default implementation simply does nothing. + * This is the lower level implementation as provided by the + * backends. The engines should use the Audio::AudioCDManager + * class instead of using it directly. */ //@{ @@ -935,13 +957,11 @@ public: /** * Set a window caption or any other comparable status display to the - * given value. The caption must be a pure ASCII string. Passing a - * non-ASCII string may lead to unexpected behavior, even crashes. + * given value. The caption must be a pure ISO LATIN 1 string. Passing a + * string with a different encoding may lead to unexpected behavior, + * even crashes. * - * In a future revision of this API, this may be changed to allowing - * UTF-8 or UTF-16 encoded data, or maybe ISO LATIN 1. - * - * @param caption the window caption to use, as an ASCII string + * @param caption the window caption to use, as an ISO LATIN 1 string */ virtual void setWindowCaption(const char *caption) {} @@ -951,6 +971,8 @@ public: * rectangle over the regular screen content; or in a message box beneath * it; etc.). * + * Currently, only pure ASCII messages can be expected to show correctly. + * * @note There is a default implementation which uses a TimedMessageDialog * to display the message. Hence implementing this is optional. * diff --git a/common/util.cpp b/common/util.cpp index f6c89fc4a5..e99bbeb12d 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -211,6 +211,7 @@ const LanguageDescription g_languages[] = { {"ru", "Russian", RU_RUS}, {"es", "Spanish", ES_ESP}, {"se", "Swedish", SE_SWE}, + {"hu", "Hungarian", HU_HUN}, {0, 0, UNK_LANG} }; @@ -259,6 +260,7 @@ const PlatformDescription g_platforms[] = { {"pc", "dos", "ibm", "DOS", kPlatformPC}, {"pc98", "pc98", "pc98", "PC-98", kPlatformPC98}, {"wii", "wii", "wii", "Nintendo Wii", kPlatformWii}, + {"coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3}, // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). // However, on the net many variations can be seen, like "FMTOWNS", @@ -371,6 +373,52 @@ const char *getRenderModeDescription(RenderMode id) { return 0; } +const struct GameOpt { + uint32 option; + const char *desc; +} g_gameOptions[] = { + { GUIO_NOSUBTITLES, "sndNoSubs" }, + { GUIO_NOMUSIC, "sndNoMusic" }, + { GUIO_NOSPEECH, "sndNoSpeech" }, + { GUIO_NOSFX, "sndNoSFX" }, + { GUIO_NOMIDI, "sndNoMIDI" }, + { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, + { GUIO_NONE, 0 } +}; + +bool checkGameGUIOption(GameGUIOption option, const String &str) { + for (int i = 0; g_gameOptions[i].desc; i++) { + if (g_gameOptions[i].option & option) { + if (str.contains(g_gameOptions[i].desc)) + return true; + else + return false; + } + } + return false; +} + +uint32 parseGameGUIOptions(const String &str) { + uint32 res = 0; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (str.contains(g_gameOptions[i].desc)) + res |= g_gameOptions[i].option; + + return res; +} + +String getGameGUIOptionsDescription(uint32 options) { + String res = ""; + + for (int i = 0; g_gameOptions[i].desc; i++) + if (options & g_gameOptions[i].option) + res += String(g_gameOptions[i].desc) + " "; + + res.trim(); + + return res; +} } // End of namespace Common diff --git a/common/util.h b/common/util.h index a7d6260583..e50dcebff0 100644 --- a/common/util.h +++ b/common/util.h @@ -172,6 +172,7 @@ enum Language { RU_RUS, ES_ESP, SE_SWE, + HU_HUN, UNK_LANG = -1 // Use default language (i.e. none specified) }; @@ -205,6 +206,7 @@ enum Platform { kPlatformWindows, kPlatformNES, kPlatformC64, + kPlatformCoCo3, kPlatformLinux, kPlatformAcorn, kPlatformSegaCD, @@ -268,6 +270,19 @@ extern RenderMode parseRenderMode(const String &str); extern const char *getRenderModeCode(RenderMode id); extern const char *getRenderModeDescription(RenderMode id); +enum GameGUIOption { + GUIO_NONE = 0, + GUIO_NOSUBTITLES = (1 << 0), + GUIO_NOMUSIC = (1 << 1), + GUIO_NOSPEECH = (1 << 2), + GUIO_NOSFX = (1 << 3), + GUIO_NOMIDI = (1 << 4), + GUIO_NOLAUNCHLOAD = (1 << 5) +}; + +bool checkGameGUIOption(GameGUIOption option, const String &str); +uint32 parseGameGUIOptions(const String &str); +String getGameGUIOptionsDescription(uint32 options); } // End of namespace Common @@ -293,7 +293,7 @@ get_system_exe_extension() { # Show the configure help line for an option option_help() { - tmpopt=`echo $1 | sed 's/_/-/g'` + tmpopt=`echo $1 | sed 's/_/-/g'` option=`echo "--${tmpopt} " | sed "s/\(.\{23\}\).*/\1/"` echo " ${option} ${2}" } @@ -1118,6 +1118,10 @@ case $_host_os in LIBS="$LIBS -lmingw32 -lwinmm" OBJS="$OBJS scummvmico.o" ;; + cygwin*) + echo ERROR: Cygwin building is not supported by ScummVM anymore. Consider using MinGW. + exit 0 + ;; os2-emx*) DEFINES="$DEFINES -DUNIX" ;; @@ -1310,8 +1314,10 @@ if test -n "$_host"; then type_4_byte='int' _ar="$_host_alias-ar cru" _ranlib=$_host_alias-ranlib + _strip=$_host_alias-strip _backend="wii" _build_hq_scalers="no" + add_line_to_config_mk 'GAMECUBE = 0' add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk' add_line_to_config_h "#define DEBUG_WII_USBGECKO" add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */" @@ -1328,10 +1334,13 @@ if test -n "$_host"; then type_4_byte='int' _ar="$_host_alias-ar cru" _ranlib=$_host_alias-ranlib + _strip=$_host_alias-strip _backend="wii" _build_hq_scalers="no" _mt32emu="no" + add_line_to_config_mk 'GAMECUBE = 1' add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk' + add_line_to_config_h '#define GAMECUBE' add_line_to_config_h "/* #define DEBUG_WII_USBGECKO */" add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */" add_line_to_config_h "/* #define DEBUG_WII_GDB */" @@ -1937,7 +1946,6 @@ case $_backend in DEFINES="$DEFINES -D__WII__ -DGEKKO" case $_host_os in gamecube) - DEFINES="$DEFINES -DGAMECUBE" LIBS="$LIBS -lfat -logc -ldb" ;; *) diff --git a/dists/iphone/scummvm.xcodeproj/project.pbxproj b/dists/iphone/scummvm.xcodeproj/project.pbxproj index a840fb031a..9d8b74628a 100755 --- a/dists/iphone/scummvm.xcodeproj/project.pbxproj +++ b/dists/iphone/scummvm.xcodeproj/project.pbxproj @@ -264,7 +264,6 @@ DF093F6B0F63CB26002D821E /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421120E7BA6A700F5680E /* sound.cpp */; }; DF093F6C0F63CB26002D821E /* talk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421130E7BA6A700F5680E /* talk.cpp */; }; DF093F6D0F63CB26002D821E /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421140E7BA6A700F5680E /* engine.cpp */; }; - DF093F6E0F63CB26002D821E /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421190E7BA6A700F5680E /* coktelvideo.cpp */; }; DF093F6F0F63CB26002D821E /* dataio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211B0E7BA6A700F5680E /* dataio.cpp */; }; DF093F700F63CB26002D821E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211D0E7BA6A700F5680E /* detection.cpp */; }; DF093F710F63CB26002D821E /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211E0E7BA6A700F5680E /* draw.cpp */; }; @@ -303,12 +302,6 @@ DF093F920F63CB26002D821E /* mult_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214A0E7BA6A700F5680E /* mult_v2.cpp */; }; DF093F930F63CB26002D821E /* palanim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214C0E7BA6A700F5680E /* palanim.cpp */; }; DF093F940F63CB26002D821E /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214E0E7BA6A700F5680E /* parse.cpp */; }; - DF093F950F63CB26002D821E /* parse_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421500E7BA6A700F5680E /* parse_v1.cpp */; }; - DF093F960F63CB26002D821E /* parse_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421510E7BA6A700F5680E /* parse_v2.cpp */; }; - DF093F970F63CB26002D821E /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421520E7BA6A700F5680E /* saveload.cpp */; }; - DF093F980F63CB26002D821E /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421540E7BA6A700F5680E /* saveload_v2.cpp */; }; - DF093F990F63CB26002D821E /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421550E7BA6A700F5680E /* saveload_v3.cpp */; }; - DF093F9A0F63CB26002D821E /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421560E7BA6A700F5680E /* saveload_v4.cpp */; }; DF093F9B0F63CB26002D821E /* scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421570E7BA6A700F5680E /* scenery.cpp */; }; DF093F9C0F63CB26002D821E /* scenery_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421590E7BA6A700F5680E /* scenery_v1.cpp */; }; DF093F9D0F63CB26002D821E /* scenery_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84215A0E7BA6A700F5680E /* scenery_v2.cpp */; }; @@ -805,10 +798,7 @@ DF09418A0F63CB26002D821E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; }; DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; }; DF09418C0F63CB26002D821E /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; }; - DF09418D0F63CB26002D821E /* dxa_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9B0F485D950006E566 /* dxa_player.cpp */; }; - DF09418E0F63CB26002D821E /* flic_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9E0F485D950006E566 /* flic_player.cpp */; }; DF09418F0F63CB26002D821E /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA10F485D950006E566 /* mpeg_player.cpp */; }; - DF0941900F63CB26002D821E /* smk_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA40F485D950006E566 /* smk_player.cpp */; }; DF0941910F63CB26002D821E /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; }; DF0941920F63CB26002D821E /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; }; DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; }; @@ -824,8 +814,6 @@ DF09419D0F63CB26002D821E /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC330F48628A0006E566 /* sound_midi.cpp */; }; DF09419E0F63CB26002D821E /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC360F48628A0006E566 /* util.cpp */; }; DF09419F0F63CB26002D821E /* game_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC400F4862D90006E566 /* game_v6.cpp */; }; - DF0941A00F63CB26002D821E /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC410F4862D90006E566 /* indeo3.cpp */; }; - DF0941A10F63CB26002D821E /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC440F4862D90006E566 /* saveload_v6.cpp */; }; DF0941A20F63CB26002D821E /* scene_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC490F4863100006E566 /* scene_lol.cpp */; }; DF0941A30F63CB26002D821E /* advancedDetector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC4C0F4863560006E566 /* advancedDetector.cpp */; }; DF0941A40F63CB26002D821E /* base-backend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC5B0F4866E70006E566 /* base-backend.cpp */; }; @@ -878,7 +866,6 @@ DF0941D40F63CB26002D821E /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830310F48AF18005EF03C /* message.cpp */; }; DF0941D50F63CB26002D821E /* said.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830330F48AF18005EF03C /* said.cpp */; }; DF0941D60F63CB26002D821E /* savegame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830360F48AF18005EF03C /* savegame.cpp */; }; - DF0941D70F63CB26002D821E /* scriptconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830380F48AF18005EF03C /* scriptconsole.cpp */; }; DF0941D80F63CB26002D821E /* scriptdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830390F48AF18005EF03C /* scriptdebug.cpp */; }; DF0941D90F63CB26002D821E /* seg_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303A0F48AF18005EF03C /* seg_manager.cpp */; }; DF0941DA0F63CB26002D821E /* vm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303C0F48AF18005EF03C /* vm.cpp */; }; @@ -891,36 +878,22 @@ DF0941E10F63CB26002D821E /* menubar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304C0F48AF18005EF03C /* menubar.cpp */; }; DF0941E20F63CB26002D821E /* operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304D0F48AF18005EF03C /* operations.cpp */; }; DF0941EC0F63CB26002D821E /* sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830960F48AF18005EF03C /* sci.cpp */; }; - DF0941F10F63CB26002D821E /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830B00F48AF19005EF03C /* resource.cpp */; }; - DF0941F20F63CB26002D821E /* versions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BA0F48AF19005EF03C /* versions.cpp */; }; - DF0941F30F63CB26002D821E /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BB0F48AF19005EF03C /* vocabulary.cpp */; }; - DF0941F40F63CB26002D821E /* vocab_debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BC0F48AF19005EF03C /* vocab_debug.cpp */; }; DF0941F60F63CB26002D821E /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C00F48AF19005EF03C /* core.cpp */; }; - DF0941F70F63CB26002D821E /* devices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C40F48AF19005EF03C /* devices.cpp */; }; DF0941F80F63CB26002D821E /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830CB0F48AF19005EF03C /* iterator.cpp */; }; - DF0941F90F63CB26002D821E /* players.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830E90F48AF19005EF03C /* players.cpp */; }; - DF0941FA0F63CB26002D821E /* realtime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EB0F48AF19005EF03C /* realtime.cpp */; }; DF0941FB0F63CB26002D821E /* sequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F30F48AF19005EF03C /* sequencers.cpp */; }; DF0941FC0F63CB26002D821E /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F60F48AF19005EF03C /* amiga.cpp */; }; - DF0941FD0F63CB26002D821E /* opl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FA0F48AF19005EF03C /* opl2.cpp */; }; - DF0941FE0F63CB26002D821E /* pcspeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FB0F48AF19005EF03C /* pcspeaker.cpp */; }; - DF0941FF0F63CB26002D821E /* SN76496.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FC0F48AF19005EF03C /* SN76496.cpp */; }; - DF0942000F63CB26002D821E /* softsequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FD0F48AF19005EF03C /* softsequencers.cpp */; }; DF0942010F63CB26002D821E /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FF0F48AF19005EF03C /* songlib.cpp */; }; DF0942020F63CB26002D821E /* unzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFE473C10D81F4E800B6D1FB /* unzip.cpp */; }; DF0942030F63CB26002D821E /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD2390F50120E00C3A4E2 /* console.cpp */; }; DF0942040F63CB26002D821E /* exereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD23B0F50120E00C3A4E2 /* exereader.cpp */; }; DF0942070F63CB26002D821E /* intmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFA0F5A81EA00961A72 /* intmap.cpp */; }; - DF0942080F63CB26002D821E /* kdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFC0F5A81EA00961A72 /* kdebug.cpp */; }; DF0942090F63CB26002D821E /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C010F5A81EA00961A72 /* state.cpp */; }; DF09420A0F63CB26002D821E /* gfx_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C130F5A820E00961A72 /* gfx_widgets.cpp */; }; - DF09420B0F63CB26002D821E /* sciconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C210F5A822D00961A72 /* sciconsole.cpp */; }; DF09420C0F63CB26002D821E /* exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBA0F5A85B300961A72 /* exec.cpp */; }; DF09420D0F63CB26002D821E /* timer_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBD0F5A85E100961A72 /* timer_lol.cpp */; }; DF09420F0F63CB26002D821E /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CC40F5A863100961A72 /* tools.cpp */; }; DF0942100F63CB26002D821E /* sprites_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */; }; DF0942110F63CB26002D821E /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2A30F62D79E00D756B6 /* script.cpp */; }; - DF0942120F63CB26002D821E /* polled.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EA0F48AF19005EF03C /* polled.cpp */; }; DF0942130F63CB26002D821E /* shorten.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B60F62D91000D756B6 /* shorten.cpp */; }; DF0942140F63CB26002D821E /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B80F62D91000D756B6 /* timestamp.cpp */; }; DF0942150F63CB26002D821E /* pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5C0F63CAD4002D821E /* pn.cpp */; }; @@ -962,14 +935,10 @@ DF09CC290FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */; }; DF09CC2A0FAC4EAB00A5AFD7 /* script_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */; }; DF09CC2B0FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */; }; - DF224E030FB23BC500C8E453 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF224E020FB23BC500C8E453 /* OpenGLES.framework */; }; DF224E040FB23BC500C8E453 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF224E020FB23BC500C8E453 /* OpenGLES.framework */; }; DF224E050FB23BC500C8E453 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF224E020FB23BC500C8E453 /* OpenGLES.framework */; }; DF2FFB930F485D890006E566 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; }; - DF2FFBAF0F485D950006E566 /* dxa_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9B0F485D950006E566 /* dxa_player.cpp */; }; - DF2FFBB10F485D950006E566 /* flic_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9E0F485D950006E566 /* flic_player.cpp */; }; DF2FFBB30F485D950006E566 /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA10F485D950006E566 /* mpeg_player.cpp */; }; - DF2FFBB50F485D950006E566 /* smk_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA40F485D950006E566 /* smk_player.cpp */; }; DF2FFBB70F485D950006E566 /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; }; DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; }; DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; }; @@ -985,8 +954,6 @@ DF2FFC3C0F48628A0006E566 /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC330F48628A0006E566 /* sound_midi.cpp */; }; DF2FFC3E0F48628A0006E566 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC360F48628A0006E566 /* util.cpp */; }; DF2FFC450F4862D90006E566 /* game_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC400F4862D90006E566 /* game_v6.cpp */; }; - DF2FFC460F4862D90006E566 /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC410F4862D90006E566 /* indeo3.cpp */; }; - DF2FFC470F4862D90006E566 /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC440F4862D90006E566 /* saveload_v6.cpp */; }; DF2FFC4A0F4863100006E566 /* scene_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC490F4863100006E566 /* scene_lol.cpp */; }; DF2FFC4E0F4863560006E566 /* advancedDetector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC4C0F4863560006E566 /* advancedDetector.cpp */; }; DF2FFC5D0F4866E70006E566 /* base-backend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC5B0F4866E70006E566 /* base-backend.cpp */; }; @@ -1024,15 +991,11 @@ DF2FFD2C0F48717F0006E566 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = DF2FFD2A0F48717F0006E566 /* icon.png */; }; DF2FFD2D0F48719E0006E566 /* scummclassic.zip in Resources */ = {isa = PBXBuildFile; fileRef = DF2FFBDB0F485E480006E566 /* scummclassic.zip */; }; DF573C060F5A81EA00961A72 /* intmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFA0F5A81EA00961A72 /* intmap.cpp */; }; - DF573C070F5A81EA00961A72 /* kdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFC0F5A81EA00961A72 /* kdebug.cpp */; }; DF573C080F5A81EA00961A72 /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C010F5A81EA00961A72 /* state.cpp */; }; DF573C1B0F5A820E00961A72 /* gfx_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C130F5A820E00961A72 /* gfx_widgets.cpp */; }; - DF573C250F5A822D00961A72 /* sciconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C210F5A822D00961A72 /* sciconsole.cpp */; }; DF573CBB0F5A85B300961A72 /* exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBA0F5A85B300961A72 /* exec.cpp */; }; DF573CBE0F5A85E100961A72 /* timer_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBD0F5A85E100961A72 /* timer_lol.cpp */; }; DF573CC60F5A863100961A72 /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CC40F5A863100961A72 /* tools.cpp */; }; - DF5CEAFA0F75529B00DEA624 /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAF80F75529B00DEA624 /* decompressor.cpp */; }; - DF5CEAFB0F75529B00DEA624 /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAF80F75529B00DEA624 /* decompressor.cpp */; }; DF5CEB0B0F7552C700DEA624 /* gfx_resmgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAFF0F7552C700DEA624 /* gfx_resmgr.cpp */; }; DF5CEB0D0F7552C700DEA624 /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB010F7552C700DEA624 /* palette.cpp */; }; DF5CEB0E0F7552C700DEA624 /* picfill.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB030F7552C700DEA624 /* picfill.cpp */; }; @@ -1040,8 +1003,6 @@ DF5CEB100F7552C700DEA624 /* res_font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB050F7552C700DEA624 /* res_font.cpp */; }; DF5CEB110F7552C700DEA624 /* res_pal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB060F7552C700DEA624 /* res_pal.cpp */; }; DF5CEB120F7552C700DEA624 /* res_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB070F7552C700DEA624 /* res_pic.cpp */; }; - DF5CEB130F7552C700DEA624 /* res_view0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB080F7552C700DEA624 /* res_view0.cpp */; }; - DF5CEB140F7552C700DEA624 /* res_view1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB090F7552C700DEA624 /* res_view1.cpp */; }; DF5CEB160F7552C700DEA624 /* gfx_resmgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAFF0F7552C700DEA624 /* gfx_resmgr.cpp */; }; DF5CEB180F7552C700DEA624 /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB010F7552C700DEA624 /* palette.cpp */; }; DF5CEB190F7552C700DEA624 /* picfill.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB030F7552C700DEA624 /* picfill.cpp */; }; @@ -1049,12 +1010,8 @@ DF5CEB1B0F7552C700DEA624 /* res_font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB050F7552C700DEA624 /* res_font.cpp */; }; DF5CEB1C0F7552C700DEA624 /* res_pal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB060F7552C700DEA624 /* res_pal.cpp */; }; DF5CEB1D0F7552C700DEA624 /* res_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB070F7552C700DEA624 /* res_pic.cpp */; }; - DF5CEB1E0F7552C700DEA624 /* res_view0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB080F7552C700DEA624 /* res_view0.cpp */; }; - DF5CEB1F0F7552C700DEA624 /* res_view1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB090F7552C700DEA624 /* res_view1.cpp */; }; - DF5CEB280F75535000DEA624 /* iff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB240F75535000DEA624 /* iff.cpp */; }; DF5CEB290F75535000DEA624 /* sound_br.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB260F75535000DEA624 /* sound_br.cpp */; }; DF5CEB2A0F75535000DEA624 /* sound_ns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB270F75535000DEA624 /* sound_ns.cpp */; }; - DF5CEB2B0F75535000DEA624 /* iff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB240F75535000DEA624 /* iff.cpp */; }; DF5CEB2C0F75535000DEA624 /* sound_br.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB260F75535000DEA624 /* sound_br.cpp */; }; DF5CEB2D0F75535000DEA624 /* sound_ns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB270F75535000DEA624 /* sound_ns.cpp */; }; DF5CEB310F75538000DEA624 /* protracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB2F0F75538000DEA624 /* protracker.cpp */; }; @@ -1063,6 +1020,103 @@ DF5CEB380F7553E000DEA624 /* vag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB350F7553E000DEA624 /* vag.cpp */; }; DF5CEB3B0F75540700DEA624 /* stringfrag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB3A0F75540700DEA624 /* stringfrag.cpp */; }; DF5CEB3C0F75540700DEA624 /* stringfrag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB3A0F75540700DEA624 /* stringfrag.cpp */; }; + DF6118320FE3A7D20042AD3F /* res_view.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61182F0FE3A7D20042AD3F /* res_view.cpp */; }; + DF6118330FE3A7D20042AD3F /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */; }; + DF6118340FE3A7D20042AD3F /* res_view.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61182F0FE3A7D20042AD3F /* res_view.cpp */; }; + DF6118350FE3A7D20042AD3F /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */; }; + DF6118360FE3A7D20042AD3F /* res_view.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61182F0FE3A7D20042AD3F /* res_view.cpp */; }; + DF6118370FE3A7D20042AD3F /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */; }; + DF61183C0FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; }; + DF61183D0FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; }; + DF61183E0FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; }; + DF61183F0FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; }; + DF6118400FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; }; + DF6118410FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; }; + DF6118490FE3A8250042AD3F /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118430FE3A8250042AD3F /* decompressor.cpp */; }; + DF61184A0FE3A8250042AD3F /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118450FE3A8250042AD3F /* resource.cpp */; }; + DF61184B0FE3A8250042AD3F /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118470FE3A8250042AD3F /* vocabulary.cpp */; }; + DF61184C0FE3A8250042AD3F /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118430FE3A8250042AD3F /* decompressor.cpp */; }; + DF61184D0FE3A8250042AD3F /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118450FE3A8250042AD3F /* resource.cpp */; }; + DF61184E0FE3A8250042AD3F /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118470FE3A8250042AD3F /* vocabulary.cpp */; }; + DF61184F0FE3A8250042AD3F /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118430FE3A8250042AD3F /* decompressor.cpp */; }; + DF6118500FE3A8250042AD3F /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118450FE3A8250042AD3F /* resource.cpp */; }; + DF6118510FE3A8250042AD3F /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118470FE3A8250042AD3F /* vocabulary.cpp */; }; + DF6118550FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; + DF6118560FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; + DF6118570FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; + DF6118660FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; + DF6118670FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; + DF6118680FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; + DF6118690FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; + DF61186A0FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; + DF61186B0FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; + DF61186C0FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; + DF61186D0FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; + DF61186E0FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; + DF61186F0FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; + DF6118700FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; + DF6118710FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; + DF6118720FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; + DF6118730FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; + DF6118740FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; + DF6118890FE3A9AA0042AD3F /* saveconverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118790FE3A9AA0042AD3F /* saveconverter.cpp */; }; + DF61188A0FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187B0FE3A9AA0042AD3F /* saveconverter_v2.cpp */; }; + DF61188B0FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187C0FE3A9AA0042AD3F /* saveconverter_v3.cpp */; }; + DF61188C0FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187D0FE3A9AA0042AD3F /* saveconverter_v4.cpp */; }; + DF61188D0FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187E0FE3A9AA0042AD3F /* saveconverter_v6.cpp */; }; + DF61188E0FE3A9AA0042AD3F /* savefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187F0FE3A9AA0042AD3F /* savefile.cpp */; }; + DF61188F0FE3A9AA0042AD3F /* savehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118810FE3A9AA0042AD3F /* savehandler.cpp */; }; + DF6118900FE3A9AA0042AD3F /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118830FE3A9AA0042AD3F /* saveload.cpp */; }; + DF6118910FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118850FE3A9AA0042AD3F /* saveload_v2.cpp */; }; + DF6118920FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118860FE3A9AA0042AD3F /* saveload_v3.cpp */; }; + DF6118930FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118870FE3A9AA0042AD3F /* saveload_v4.cpp */; }; + DF6118940FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118880FE3A9AA0042AD3F /* saveload_v6.cpp */; }; + DF6118950FE3A9AA0042AD3F /* saveconverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118790FE3A9AA0042AD3F /* saveconverter.cpp */; }; + DF6118960FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187B0FE3A9AA0042AD3F /* saveconverter_v2.cpp */; }; + DF6118970FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187C0FE3A9AA0042AD3F /* saveconverter_v3.cpp */; }; + DF6118980FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187D0FE3A9AA0042AD3F /* saveconverter_v4.cpp */; }; + DF6118990FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187E0FE3A9AA0042AD3F /* saveconverter_v6.cpp */; }; + DF61189A0FE3A9AA0042AD3F /* savefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187F0FE3A9AA0042AD3F /* savefile.cpp */; }; + DF61189B0FE3A9AA0042AD3F /* savehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118810FE3A9AA0042AD3F /* savehandler.cpp */; }; + DF61189C0FE3A9AA0042AD3F /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118830FE3A9AA0042AD3F /* saveload.cpp */; }; + DF61189D0FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118850FE3A9AA0042AD3F /* saveload_v2.cpp */; }; + DF61189E0FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118860FE3A9AA0042AD3F /* saveload_v3.cpp */; }; + DF61189F0FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118870FE3A9AA0042AD3F /* saveload_v4.cpp */; }; + DF6118A00FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118880FE3A9AA0042AD3F /* saveload_v6.cpp */; }; + DF6118A10FE3A9AA0042AD3F /* saveconverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118790FE3A9AA0042AD3F /* saveconverter.cpp */; }; + DF6118A20FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187B0FE3A9AA0042AD3F /* saveconverter_v2.cpp */; }; + DF6118A30FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187C0FE3A9AA0042AD3F /* saveconverter_v3.cpp */; }; + DF6118A40FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187D0FE3A9AA0042AD3F /* saveconverter_v4.cpp */; }; + DF6118A50FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187E0FE3A9AA0042AD3F /* saveconverter_v6.cpp */; }; + DF6118A60FE3A9AA0042AD3F /* savefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61187F0FE3A9AA0042AD3F /* savefile.cpp */; }; + DF6118A70FE3A9AA0042AD3F /* savehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118810FE3A9AA0042AD3F /* savehandler.cpp */; }; + DF6118A80FE3A9AA0042AD3F /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118830FE3A9AA0042AD3F /* saveload.cpp */; }; + DF6118A90FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118850FE3A9AA0042AD3F /* saveload_v2.cpp */; }; + DF6118AA0FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118860FE3A9AA0042AD3F /* saveload_v3.cpp */; }; + DF6118AB0FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118870FE3A9AA0042AD3F /* saveload_v4.cpp */; }; + DF6118AC0FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118880FE3A9AA0042AD3F /* saveload_v6.cpp */; }; + DF6118AF0FE3A9EA0042AD3F /* feeble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */; }; + DF6118B00FE3A9EA0042AD3F /* feeble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */; }; + DF6118B10FE3A9EA0042AD3F /* feeble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */; }; + DF6118B80FE3AA280042AD3F /* saveload_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */; }; + DF6118B90FE3AA280042AD3F /* sound_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B40FE3AA280042AD3F /* sound_lol.cpp */; }; + DF6118BA0FE3AA280042AD3F /* sound_pcspk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */; }; + DF6118BB0FE3AA280042AD3F /* text_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B60FE3AA280042AD3F /* text_lol.cpp */; }; + DF6118BC0FE3AA280042AD3F /* saveload_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */; }; + DF6118BD0FE3AA280042AD3F /* sound_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B40FE3AA280042AD3F /* sound_lol.cpp */; }; + DF6118BE0FE3AA280042AD3F /* sound_pcspk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */; }; + DF6118BF0FE3AA280042AD3F /* text_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B60FE3AA280042AD3F /* text_lol.cpp */; }; + DF6118C00FE3AA280042AD3F /* saveload_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */; }; + DF6118C10FE3AA280042AD3F /* sound_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B40FE3AA280042AD3F /* sound_lol.cpp */; }; + DF6118C20FE3AA280042AD3F /* sound_pcspk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */; }; + DF6118C30FE3AA280042AD3F /* text_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118B60FE3AA280042AD3F /* text_lol.cpp */; }; + DF6118C70FE3AABD0042AD3F /* player_v2cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */; }; + DF6118C80FE3AABD0042AD3F /* player_v2cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */; }; + DF6118C90FE3AABD0042AD3F /* player_v2cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */; }; + DF6118CC0FE3AAFD0042AD3F /* hardwarekeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118CB0FE3AAFD0042AD3F /* hardwarekeys.cpp */; }; + DF6118D10FE3AB560042AD3F /* mame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118CF0FE3AB560042AD3F /* mame.cpp */; }; + DF6118D20FE3AB560042AD3F /* mame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118CF0FE3AB560042AD3F /* mame.cpp */; }; + DF6118D30FE3AB560042AD3F /* mame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118CF0FE3AB560042AD3F /* mame.cpp */; }; DF7A40330FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7A40320FB6E8960094E50F /* gfx_pixmap_scale.cpp */; }; DF7A40340FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7A40320FB6E8960094E50F /* gfx_pixmap_scale.cpp */; }; DF7A40350FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7A40320FB6E8960094E50F /* gfx_pixmap_scale.cpp */; }; @@ -1219,7 +1273,6 @@ DF8425D70E7BA6AC00F5680E /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421120E7BA6A700F5680E /* sound.cpp */; }; DF8425D80E7BA6AC00F5680E /* talk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421130E7BA6A700F5680E /* talk.cpp */; }; DF8425D90E7BA6AC00F5680E /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421140E7BA6A700F5680E /* engine.cpp */; }; - DF8425DC0E7BA6AC00F5680E /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421190E7BA6A700F5680E /* coktelvideo.cpp */; }; DF8425DD0E7BA6AC00F5680E /* dataio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211B0E7BA6A700F5680E /* dataio.cpp */; }; DF8425DE0E7BA6AC00F5680E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211D0E7BA6A700F5680E /* detection.cpp */; }; DF8425DF0E7BA6AC00F5680E /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211E0E7BA6A700F5680E /* draw.cpp */; }; @@ -1258,12 +1311,6 @@ DF8426010E7BA6AC00F5680E /* mult_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214A0E7BA6A700F5680E /* mult_v2.cpp */; }; DF8426030E7BA6AC00F5680E /* palanim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214C0E7BA6A700F5680E /* palanim.cpp */; }; DF8426040E7BA6AC00F5680E /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214E0E7BA6A700F5680E /* parse.cpp */; }; - DF8426050E7BA6AC00F5680E /* parse_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421500E7BA6A700F5680E /* parse_v1.cpp */; }; - DF8426060E7BA6AC00F5680E /* parse_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421510E7BA6A700F5680E /* parse_v2.cpp */; }; - DF8426070E7BA6AC00F5680E /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421520E7BA6A700F5680E /* saveload.cpp */; }; - DF8426080E7BA6AC00F5680E /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421540E7BA6A700F5680E /* saveload_v2.cpp */; }; - DF8426090E7BA6AC00F5680E /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421550E7BA6A700F5680E /* saveload_v3.cpp */; }; - DF84260A0E7BA6AC00F5680E /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421560E7BA6A700F5680E /* saveload_v4.cpp */; }; DF84260B0E7BA6AC00F5680E /* scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421570E7BA6A700F5680E /* scenery.cpp */; }; DF84260C0E7BA6AC00F5680E /* scenery_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421590E7BA6A700F5680E /* scenery_v1.cpp */; }; DF84260D0E7BA6AC00F5680E /* scenery_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84215A0E7BA6A700F5680E /* scenery_v2.cpp */; }; @@ -1754,7 +1801,6 @@ DF842A710E7BBDB200F5680E /* musicplugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF842A6F0E7BBDB200F5680E /* musicplugin.cpp */; }; DF89C2880F62D55C00D756B6 /* sprites_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */; }; DF89C2A40F62D79E00D756B6 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2A30F62D79E00D756B6 /* script.cpp */; }; - DF89C2B40F62D89600D756B6 /* polled.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EA0F48AF19005EF03C /* polled.cpp */; }; DF89C2BA0F62D91000D756B6 /* shorten.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B60F62D91000D756B6 /* shorten.cpp */; }; DF89C2BB0F62D91000D756B6 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B80F62D91000D756B6 /* timestamp.cpp */; }; DFAAAFF70F0112AD003E9390 /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFF50F0112AD003E9390 /* saveload.cpp */; }; @@ -1782,7 +1828,6 @@ DFC831330F48AF19005EF03C /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830310F48AF18005EF03C /* message.cpp */; }; DFC831340F48AF19005EF03C /* said.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830330F48AF18005EF03C /* said.cpp */; }; DFC831370F48AF19005EF03C /* savegame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830360F48AF18005EF03C /* savegame.cpp */; }; - DFC831380F48AF19005EF03C /* scriptconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830380F48AF18005EF03C /* scriptconsole.cpp */; }; DFC831390F48AF19005EF03C /* scriptdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830390F48AF18005EF03C /* scriptdebug.cpp */; }; DFC8313A0F48AF19005EF03C /* seg_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303A0F48AF18005EF03C /* seg_manager.cpp */; }; DFC8313C0F48AF19005EF03C /* vm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303C0F48AF18005EF03C /* vm.cpp */; }; @@ -1795,21 +1840,10 @@ DFC8314B0F48AF19005EF03C /* menubar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304C0F48AF18005EF03C /* menubar.cpp */; }; DFC8314C0F48AF19005EF03C /* operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304D0F48AF18005EF03C /* operations.cpp */; }; DFC8315C0F48AF19005EF03C /* sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830960F48AF18005EF03C /* sci.cpp */; }; - DFC831710F48AF19005EF03C /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830B00F48AF19005EF03C /* resource.cpp */; }; - DFC8317B0F48AF19005EF03C /* versions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BA0F48AF19005EF03C /* versions.cpp */; }; - DFC8317C0F48AF19005EF03C /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BB0F48AF19005EF03C /* vocabulary.cpp */; }; - DFC8317D0F48AF19005EF03C /* vocab_debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BC0F48AF19005EF03C /* vocab_debug.cpp */; }; DFC8317F0F48AF19005EF03C /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C00F48AF19005EF03C /* core.cpp */; }; - DFC831820F48AF19005EF03C /* devices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C40F48AF19005EF03C /* devices.cpp */; }; DFC831870F48AF19005EF03C /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830CB0F48AF19005EF03C /* iterator.cpp */; }; - DFC8319E0F48AF19005EF03C /* players.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830E90F48AF19005EF03C /* players.cpp */; }; - DFC831A00F48AF19005EF03C /* realtime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EB0F48AF19005EF03C /* realtime.cpp */; }; DFC831A60F48AF19005EF03C /* sequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F30F48AF19005EF03C /* sequencers.cpp */; }; DFC831A70F48AF19005EF03C /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F60F48AF19005EF03C /* amiga.cpp */; }; - DFC831AA0F48AF19005EF03C /* opl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FA0F48AF19005EF03C /* opl2.cpp */; }; - DFC831AB0F48AF19005EF03C /* pcspeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FB0F48AF19005EF03C /* pcspeaker.cpp */; }; - DFC831AC0F48AF19005EF03C /* SN76496.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FC0F48AF19005EF03C /* SN76496.cpp */; }; - DFC831AD0F48AF19005EF03C /* softsequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FD0F48AF19005EF03C /* softsequencers.cpp */; }; DFC831AE0F48AF19005EF03C /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FF0F48AF19005EF03C /* songlib.cpp */; }; DFD511480DF3383500854012 /* memorypool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD511460DF3383500854012 /* memorypool.cpp */; }; DFD517E20DF33CAC00854012 /* seq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD517E10DF33CAC00854012 /* seq.cpp */; }; @@ -1916,12 +1950,8 @@ DFE88C470F874A1100C555C5 /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFE88C440F874A1100C555C5 /* sound.cpp */; }; DFE88C4D0F874A6600C555C5 /* gfx_gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFE88C4B0F874A6600C555C5 /* gfx_gui.cpp */; }; DFE88C4E0F874A6600C555C5 /* gfx_gui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFE88C4B0F874A6600C555C5 /* gfx_gui.cpp */; }; - DFF958A50FB222AF00A3EC78 /* adlib_sbi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A30FB222AF00A3EC78 /* adlib_sbi.cpp */; }; - DFF958A60FB222AF00A3EC78 /* adlib_sbi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A30FB222AF00A3EC78 /* adlib_sbi.cpp */; }; DFF958AF0FB222F300A3EC78 /* dosbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A90FB222F300A3EC78 /* dosbox.cpp */; }; DFF958B20FB222F300A3EC78 /* dosbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A90FB222F300A3EC78 /* dosbox.cpp */; }; - DFF958C00FB223B300A3EC78 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958BF0FB223B300A3EC78 /* player.cpp */; }; - DFF958C10FB223B300A3EC78 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958BF0FB223B300A3EC78 /* player.cpp */; }; DFF958C80FB223F000A3EC78 /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958C40FB223F000A3EC78 /* adlib.cpp */; }; DFF958C90FB223F000A3EC78 /* pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958C60FB223F000A3EC78 /* pcjr.cpp */; }; DFF958CA0FB223F000A3EC78 /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958C40FB223F000A3EC78 /* adlib.cpp */; }; @@ -2175,7 +2205,6 @@ DFF95A010FB22D5700A3EC78 /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421120E7BA6A700F5680E /* sound.cpp */; }; DFF95A020FB22D5700A3EC78 /* talk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421130E7BA6A700F5680E /* talk.cpp */; }; DFF95A030FB22D5700A3EC78 /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421140E7BA6A700F5680E /* engine.cpp */; }; - DFF95A040FB22D5700A3EC78 /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421190E7BA6A700F5680E /* coktelvideo.cpp */; }; DFF95A050FB22D5700A3EC78 /* dataio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211B0E7BA6A700F5680E /* dataio.cpp */; }; DFF95A060FB22D5700A3EC78 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211D0E7BA6A700F5680E /* detection.cpp */; }; DFF95A070FB22D5700A3EC78 /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84211E0E7BA6A700F5680E /* draw.cpp */; }; @@ -2214,12 +2243,6 @@ DFF95A280FB22D5700A3EC78 /* mult_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214A0E7BA6A700F5680E /* mult_v2.cpp */; }; DFF95A290FB22D5700A3EC78 /* palanim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214C0E7BA6A700F5680E /* palanim.cpp */; }; DFF95A2A0FB22D5700A3EC78 /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84214E0E7BA6A700F5680E /* parse.cpp */; }; - DFF95A2B0FB22D5700A3EC78 /* parse_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421500E7BA6A700F5680E /* parse_v1.cpp */; }; - DFF95A2C0FB22D5700A3EC78 /* parse_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421510E7BA6A700F5680E /* parse_v2.cpp */; }; - DFF95A2D0FB22D5700A3EC78 /* saveload.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421520E7BA6A700F5680E /* saveload.cpp */; }; - DFF95A2E0FB22D5700A3EC78 /* saveload_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421540E7BA6A700F5680E /* saveload_v2.cpp */; }; - DFF95A2F0FB22D5700A3EC78 /* saveload_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421550E7BA6A700F5680E /* saveload_v3.cpp */; }; - DFF95A300FB22D5700A3EC78 /* saveload_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421560E7BA6A700F5680E /* saveload_v4.cpp */; }; DFF95A310FB22D5700A3EC78 /* scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421570E7BA6A700F5680E /* scenery.cpp */; }; DFF95A320FB22D5700A3EC78 /* scenery_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421590E7BA6A700F5680E /* scenery_v1.cpp */; }; DFF95A330FB22D5700A3EC78 /* scenery_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84215A0E7BA6A700F5680E /* scenery_v2.cpp */; }; @@ -2717,10 +2740,7 @@ DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; }; DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; }; DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; }; - DFF95C220FB22D5700A3EC78 /* dxa_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9B0F485D950006E566 /* dxa_player.cpp */; }; - DFF95C230FB22D5700A3EC78 /* flic_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB9E0F485D950006E566 /* flic_player.cpp */; }; DFF95C240FB22D5700A3EC78 /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA10F485D950006E566 /* mpeg_player.cpp */; }; - DFF95C250FB22D5700A3EC78 /* smk_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA40F485D950006E566 /* smk_player.cpp */; }; DFF95C260FB22D5700A3EC78 /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; }; DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; }; DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; }; @@ -2736,8 +2756,6 @@ DFF95C320FB22D5700A3EC78 /* sound_midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC330F48628A0006E566 /* sound_midi.cpp */; }; DFF95C330FB22D5700A3EC78 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC360F48628A0006E566 /* util.cpp */; }; DFF95C340FB22D5700A3EC78 /* game_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC400F4862D90006E566 /* game_v6.cpp */; }; - DFF95C350FB22D5700A3EC78 /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC410F4862D90006E566 /* indeo3.cpp */; }; - DFF95C360FB22D5700A3EC78 /* saveload_v6.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC440F4862D90006E566 /* saveload_v6.cpp */; }; DFF95C370FB22D5700A3EC78 /* scene_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC490F4863100006E566 /* scene_lol.cpp */; }; DFF95C380FB22D5700A3EC78 /* advancedDetector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC4C0F4863560006E566 /* advancedDetector.cpp */; }; DFF95C390FB22D5700A3EC78 /* base-backend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFC5B0F4866E70006E566 /* base-backend.cpp */; }; @@ -2790,7 +2808,6 @@ DFF95C680FB22D5700A3EC78 /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830310F48AF18005EF03C /* message.cpp */; }; DFF95C690FB22D5700A3EC78 /* said.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830330F48AF18005EF03C /* said.cpp */; }; DFF95C6A0FB22D5700A3EC78 /* savegame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830360F48AF18005EF03C /* savegame.cpp */; }; - DFF95C6B0FB22D5700A3EC78 /* scriptconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830380F48AF18005EF03C /* scriptconsole.cpp */; }; DFF95C6C0FB22D5700A3EC78 /* scriptdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830390F48AF18005EF03C /* scriptdebug.cpp */; }; DFF95C6D0FB22D5700A3EC78 /* seg_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303A0F48AF18005EF03C /* seg_manager.cpp */; }; DFF95C6E0FB22D5700A3EC78 /* vm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8303C0F48AF18005EF03C /* vm.cpp */; }; @@ -2803,42 +2820,27 @@ DFF95C750FB22D5700A3EC78 /* menubar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304C0F48AF18005EF03C /* menubar.cpp */; }; DFF95C760FB22D5700A3EC78 /* operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8304D0F48AF18005EF03C /* operations.cpp */; }; DFF95C770FB22D5700A3EC78 /* sci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830960F48AF18005EF03C /* sci.cpp */; }; - DFF95C780FB22D5700A3EC78 /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830B00F48AF19005EF03C /* resource.cpp */; }; - DFF95C790FB22D5700A3EC78 /* versions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BA0F48AF19005EF03C /* versions.cpp */; }; - DFF95C7A0FB22D5700A3EC78 /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BB0F48AF19005EF03C /* vocabulary.cpp */; }; - DFF95C7B0FB22D5700A3EC78 /* vocab_debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830BC0F48AF19005EF03C /* vocab_debug.cpp */; }; DFF95C7C0FB22D5700A3EC78 /* core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C00F48AF19005EF03C /* core.cpp */; }; - DFF95C7D0FB22D5700A3EC78 /* devices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830C40F48AF19005EF03C /* devices.cpp */; }; DFF95C7E0FB22D5700A3EC78 /* iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830CB0F48AF19005EF03C /* iterator.cpp */; }; - DFF95C7F0FB22D5700A3EC78 /* players.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830E90F48AF19005EF03C /* players.cpp */; }; - DFF95C800FB22D5700A3EC78 /* realtime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EB0F48AF19005EF03C /* realtime.cpp */; }; DFF95C810FB22D5700A3EC78 /* sequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F30F48AF19005EF03C /* sequencers.cpp */; }; DFF95C820FB22D5700A3EC78 /* amiga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830F60F48AF19005EF03C /* amiga.cpp */; }; - DFF95C830FB22D5700A3EC78 /* opl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FA0F48AF19005EF03C /* opl2.cpp */; }; - DFF95C840FB22D5700A3EC78 /* pcspeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FB0F48AF19005EF03C /* pcspeaker.cpp */; }; - DFF95C850FB22D5700A3EC78 /* SN76496.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FC0F48AF19005EF03C /* SN76496.cpp */; }; - DFF95C860FB22D5700A3EC78 /* softsequencers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FD0F48AF19005EF03C /* softsequencers.cpp */; }; DFF95C870FB22D5700A3EC78 /* songlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830FF0F48AF19005EF03C /* songlib.cpp */; }; DFF95C880FB22D5700A3EC78 /* unzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFE473C10D81F4E800B6D1FB /* unzip.cpp */; }; DFF95C890FB22D5700A3EC78 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD2390F50120E00C3A4E2 /* console.cpp */; }; DFF95C8A0FB22D5700A3EC78 /* exereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD23B0F50120E00C3A4E2 /* exereader.cpp */; }; DFF95C8C0FB22D5700A3EC78 /* intmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFA0F5A81EA00961A72 /* intmap.cpp */; }; - DFF95C8D0FB22D5700A3EC78 /* kdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573BFC0F5A81EA00961A72 /* kdebug.cpp */; }; DFF95C8E0FB22D5700A3EC78 /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C010F5A81EA00961A72 /* state.cpp */; }; DFF95C8F0FB22D5700A3EC78 /* gfx_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C130F5A820E00961A72 /* gfx_widgets.cpp */; }; - DFF95C900FB22D5700A3EC78 /* sciconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C210F5A822D00961A72 /* sciconsole.cpp */; }; DFF95C910FB22D5700A3EC78 /* exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBA0F5A85B300961A72 /* exec.cpp */; }; DFF95C920FB22D5700A3EC78 /* timer_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBD0F5A85E100961A72 /* timer_lol.cpp */; }; DFF95C930FB22D5700A3EC78 /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CC40F5A863100961A72 /* tools.cpp */; }; DFF95C940FB22D5700A3EC78 /* sprites_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */; }; DFF95C950FB22D5700A3EC78 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2A30F62D79E00D756B6 /* script.cpp */; }; - DFF95C960FB22D5700A3EC78 /* polled.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC830EA0F48AF19005EF03C /* polled.cpp */; }; DFF95C970FB22D5700A3EC78 /* shorten.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B60F62D91000D756B6 /* shorten.cpp */; }; DFF95C980FB22D5700A3EC78 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B80F62D91000D756B6 /* timestamp.cpp */; }; DFF95C990FB22D5700A3EC78 /* pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5C0F63CAD4002D821E /* pn.cpp */; }; DFF95C9A0FB22D5700A3EC78 /* script_pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5D0F63CAD4002D821E /* script_pn.cpp */; }; DFF95C9B0FB22D5700A3EC78 /* vga_pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5E0F63CAD4002D821E /* vga_pn.cpp */; }; - DFF95C9C0FB22D5700A3EC78 /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAF80F75529B00DEA624 /* decompressor.cpp */; }; DFF95C9D0FB22D5700A3EC78 /* gfx_resmgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEAFF0F7552C700DEA624 /* gfx_resmgr.cpp */; }; DFF95C9E0FB22D5700A3EC78 /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB010F7552C700DEA624 /* palette.cpp */; }; DFF95C9F0FB22D5700A3EC78 /* picfill.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB030F7552C700DEA624 /* picfill.cpp */; }; @@ -2846,9 +2848,6 @@ DFF95CA10FB22D5700A3EC78 /* res_font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB050F7552C700DEA624 /* res_font.cpp */; }; DFF95CA20FB22D5700A3EC78 /* res_pal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB060F7552C700DEA624 /* res_pal.cpp */; }; DFF95CA30FB22D5700A3EC78 /* res_pic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB070F7552C700DEA624 /* res_pic.cpp */; }; - DFF95CA40FB22D5700A3EC78 /* res_view0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB080F7552C700DEA624 /* res_view0.cpp */; }; - DFF95CA50FB22D5700A3EC78 /* res_view1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB090F7552C700DEA624 /* res_view1.cpp */; }; - DFF95CA60FB22D5700A3EC78 /* iff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB240F75535000DEA624 /* iff.cpp */; }; DFF95CA70FB22D5700A3EC78 /* sound_br.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB260F75535000DEA624 /* sound_br.cpp */; }; DFF95CA80FB22D5700A3EC78 /* sound_ns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB270F75535000DEA624 /* sound_ns.cpp */; }; DFF95CA90FB22D5700A3EC78 /* protracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5CEB2F0F75538000DEA624 /* protracker.cpp */; }; @@ -2864,9 +2863,7 @@ DFF95CB30FB22D5700A3EC78 /* inter_fascin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC0F0FAC4E1900A5AFD7 /* inter_fascin.cpp */; }; DFF95CB40FB22D5700A3EC78 /* script_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */; }; DFF95CB50FB22D5700A3EC78 /* script_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */; }; - DFF95CB60FB22D5700A3EC78 /* adlib_sbi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A30FB222AF00A3EC78 /* adlib_sbi.cpp */; }; DFF95CB70FB22D5700A3EC78 /* dosbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958A90FB222F300A3EC78 /* dosbox.cpp */; }; - DFF95CB80FB22D5700A3EC78 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958BF0FB223B300A3EC78 /* player.cpp */; }; DFF95CB90FB22D5700A3EC78 /* adlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958C40FB223F000A3EC78 /* adlib.cpp */; }; DFF95CBA0FB22D5700A3EC78 /* pcjr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF958C60FB223F000A3EC78 /* pcjr.cpp */; }; DFF95CBC0FB22D5700A3EC78 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF842A160E7BB34E00F5680E /* CoreAudio.framework */; }; @@ -2978,19 +2975,8 @@ DF2FFB900F485D890006E566 /* dither.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dither.cpp; sourceTree = "<group>"; }; DF2FFB910F485D890006E566 /* dither.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dither.h; sourceTree = "<group>"; }; DF2FFB920F485D890006E566 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = "<group>"; }; - DF2FFB960F485D950006E566 /* dxa_player.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = dxa_player.d; sourceTree = "<group>"; }; - DF2FFB970F485D950006E566 /* flic_player.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = flic_player.d; sourceTree = "<group>"; }; - DF2FFB980F485D950006E566 /* mpeg_player.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = mpeg_player.d; sourceTree = "<group>"; }; - DF2FFB990F485D950006E566 /* smk_player.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = smk_player.d; sourceTree = "<group>"; }; - DF2FFB9A0F485D950006E566 /* video_player.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = video_player.d; sourceTree = "<group>"; }; - DF2FFB9B0F485D950006E566 /* dxa_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dxa_player.cpp; sourceTree = "<group>"; }; - DF2FFB9C0F485D950006E566 /* dxa_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxa_player.h; sourceTree = "<group>"; }; - DF2FFB9E0F485D950006E566 /* flic_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flic_player.cpp; sourceTree = "<group>"; }; - DF2FFB9F0F485D950006E566 /* flic_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flic_player.h; sourceTree = "<group>"; }; DF2FFBA10F485D950006E566 /* mpeg_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mpeg_player.cpp; sourceTree = "<group>"; }; DF2FFBA20F485D950006E566 /* mpeg_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpeg_player.h; sourceTree = "<group>"; }; - DF2FFBA40F485D950006E566 /* smk_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = smk_player.cpp; sourceTree = "<group>"; }; - DF2FFBA50F485D950006E566 /* smk_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smk_player.h; sourceTree = "<group>"; }; DF2FFBA70F485D950006E566 /* video_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_player.cpp; sourceTree = "<group>"; }; DF2FFBA80F485D950006E566 /* video_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = video_player.h; sourceTree = "<group>"; }; DF2FFBD10F485DFB0006E566 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; }; @@ -3019,10 +3005,6 @@ DF2FFC360F48628A0006E566 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = "<group>"; }; DF2FFC370F48628A0006E566 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; }; DF2FFC400F4862D90006E566 /* game_v6.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game_v6.cpp; sourceTree = "<group>"; }; - DF2FFC410F4862D90006E566 /* indeo3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indeo3.cpp; sourceTree = "<group>"; }; - DF2FFC420F4862D90006E566 /* indeo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indeo3.h; sourceTree = "<group>"; }; - DF2FFC430F4862D90006E566 /* indeo3data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indeo3data.h; sourceTree = "<group>"; }; - DF2FFC440F4862D90006E566 /* saveload_v6.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v6.cpp; sourceTree = "<group>"; }; DF2FFC490F4863100006E566 /* scene_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scene_lol.cpp; sourceTree = "<group>"; }; DF2FFC4C0F4863560006E566 /* advancedDetector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = advancedDetector.cpp; sourceTree = "<group>"; }; DF2FFC4D0F4863560006E566 /* advancedDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advancedDetector.h; sourceTree = "<group>"; }; @@ -3080,12 +3062,8 @@ DF2FFD290F48717F0006E566 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; }; DF2FFD2A0F48717F0006E566 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; }; DF573BF50F5A81D400961A72 /* uinput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uinput.h; sourceTree = "<group>"; }; - DF573BF80F5A81EA00961A72 /* aatree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aatree.h; sourceTree = "<group>"; }; - DF573BF90F5A81EA00961A72 /* heapmgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heapmgr.h; sourceTree = "<group>"; }; DF573BFA0F5A81EA00961A72 /* intmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intmap.cpp; sourceTree = "<group>"; }; DF573BFB0F5A81EA00961A72 /* intmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intmap.h; sourceTree = "<group>"; }; - DF573BFC0F5A81EA00961A72 /* kdebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kdebug.cpp; sourceTree = "<group>"; }; - DF573BFD0F5A81EA00961A72 /* kdebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kdebug.h; sourceTree = "<group>"; }; DF573BFE0F5A81EA00961A72 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = "<group>"; }; DF573BFF0F5A81EA00961A72 /* script.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = script.h; sourceTree = "<group>"; }; DF573C000F5A81EA00961A72 /* seg_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seg_manager.h; sourceTree = "<group>"; }; @@ -3105,25 +3083,16 @@ DF573C140F5A820E00961A72 /* gfx_widgets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gfx_widgets.h; sourceTree = "<group>"; }; DF573C160F5A820E00961A72 /* menubar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menubar.h; sourceTree = "<group>"; }; DF573C170F5A820E00961A72 /* operations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = operations.h; sourceTree = "<group>"; }; - DF573C200F5A822D00961A72 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = "<group>"; }; - DF573C210F5A822D00961A72 /* sciconsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sciconsole.cpp; sourceTree = "<group>"; }; - DF573C220F5A822D00961A72 /* sciconsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sciconsole.h; sourceTree = "<group>"; }; - DF573C230F5A822D00961A72 /* versions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = versions.h; sourceTree = "<group>"; }; - DF573C240F5A822D00961A72 /* vocabulary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vocabulary.h; sourceTree = "<group>"; }; DF573C260F5A824700961A72 /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; }; DF573C270F5A824700961A72 /* iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = "<group>"; }; DF573C280F5A824700961A72 /* iterator_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iterator_internal.h; sourceTree = "<group>"; }; - DF573C2A0F5A824700961A72 /* player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = player.h; sourceTree = "<group>"; }; DF573C2B0F5A824700961A72 /* sci_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sci_midi.h; sourceTree = "<group>"; }; - DF573C2C0F5A824700961A72 /* sfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sfx.h; sourceTree = "<group>"; }; DF573C2D0F5A824700961A72 /* sfx_pcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sfx_pcm.h; sourceTree = "<group>"; }; DF573C2F0F5A824700961A72 /* songlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = songlib.h; sourceTree = "<group>"; }; DF573CBA0F5A85B300961A72 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = "<group>"; }; DF573CBD0F5A85E100961A72 /* timer_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timer_lol.cpp; sourceTree = "<group>"; }; DF573CC40F5A863100961A72 /* tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tools.cpp; sourceTree = "<group>"; }; DF573CC50F5A863100961A72 /* tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tools.h; sourceTree = "<group>"; }; - DF5CEAF80F75529B00DEA624 /* decompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decompressor.cpp; sourceTree = "<group>"; }; - DF5CEAF90F75529B00DEA624 /* decompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decompressor.h; sourceTree = "<group>"; }; DF5CEAFD0F7552C700DEA624 /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = "<group>"; }; DF5CEAFF0F7552C700DEA624 /* gfx_resmgr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gfx_resmgr.cpp; sourceTree = "<group>"; }; DF5CEB010F7552C700DEA624 /* palette.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = palette.cpp; sourceTree = "<group>"; }; @@ -3133,10 +3102,6 @@ DF5CEB050F7552C700DEA624 /* res_font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_font.cpp; sourceTree = "<group>"; }; DF5CEB060F7552C700DEA624 /* res_pal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_pal.cpp; sourceTree = "<group>"; }; DF5CEB070F7552C700DEA624 /* res_pic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_pic.cpp; sourceTree = "<group>"; }; - DF5CEB080F7552C700DEA624 /* res_view0.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_view0.cpp; sourceTree = "<group>"; }; - DF5CEB090F7552C700DEA624 /* res_view1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_view1.cpp; sourceTree = "<group>"; }; - DF5CEB240F75535000DEA624 /* iff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iff.cpp; sourceTree = "<group>"; }; - DF5CEB250F75535000DEA624 /* iff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iff.h; sourceTree = "<group>"; }; DF5CEB260F75535000DEA624 /* sound_br.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_br.cpp; sourceTree = "<group>"; }; DF5CEB270F75535000DEA624 /* sound_ns.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_ns.cpp; sourceTree = "<group>"; }; DF5CEB2F0F75538000DEA624 /* protracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = protracker.cpp; sourceTree = "<group>"; }; @@ -3144,6 +3109,59 @@ DF5CEB350F7553E000DEA624 /* vag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vag.cpp; sourceTree = "<group>"; }; DF5CEB360F7553E000DEA624 /* vag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vag.h; sourceTree = "<group>"; }; DF5CEB3A0F75540700DEA624 /* stringfrag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stringfrag.cpp; sourceTree = "<group>"; }; + DF61182E0FE3A7AF0042AD3F /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = "<group>"; }; + DF61182F0FE3A7D20042AD3F /* res_view.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = res_view.cpp; sourceTree = "<group>"; }; + DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = seq_decoder.cpp; sourceTree = "<group>"; }; + DF6118310FE3A7D20042AD3F /* seq_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seq_decoder.h; sourceTree = "<group>"; }; + DF6118380FE3A8080042AD3F /* kmisc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kmisc.cpp; sourceTree = "<group>"; }; + DF6118390FE3A8080042AD3F /* memobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memobj.cpp; sourceTree = "<group>"; }; + DF61183A0FE3A8080042AD3F /* memobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memobj.h; sourceTree = "<group>"; }; + DF61183B0FE3A8080042AD3F /* savegame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = savegame.h; sourceTree = "<group>"; }; + DF6118420FE3A8250042AD3F /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; }; + DF6118430FE3A8250042AD3F /* decompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decompressor.cpp; sourceTree = "<group>"; }; + DF6118440FE3A8250042AD3F /* decompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decompressor.h; sourceTree = "<group>"; }; + DF6118450FE3A8250042AD3F /* resource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource.cpp; sourceTree = "<group>"; }; + DF6118460FE3A8250042AD3F /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = "<group>"; }; + DF6118470FE3A8250042AD3F /* vocabulary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vocabulary.cpp; sourceTree = "<group>"; }; + DF6118480FE3A8250042AD3F /* vocabulary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vocabulary.h; sourceTree = "<group>"; }; + DF6118540FE3A8990042AD3F /* disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = disk.cpp; sourceTree = "<group>"; }; + DF6118590FE3A9020042AD3F /* helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = "<group>"; }; + DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coktelvideo.cpp; sourceTree = "<group>"; }; + DF61185D0FE3A9410042AD3F /* coktelvideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coktelvideo.h; sourceTree = "<group>"; }; + DF61185E0FE3A9410042AD3F /* indeo3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indeo3.cpp; sourceTree = "<group>"; }; + DF61185F0FE3A9410042AD3F /* indeo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indeo3.h; sourceTree = "<group>"; }; + DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dxa_decoder.cpp; sourceTree = "<group>"; }; + DF6118610FE3A9410042AD3F /* dxa_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxa_decoder.h; sourceTree = "<group>"; }; + DF6118620FE3A9410042AD3F /* flic_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flic_decoder.cpp; sourceTree = "<group>"; }; + DF6118630FE3A9410042AD3F /* flic_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flic_decoder.h; sourceTree = "<group>"; }; + DF6118640FE3A9410042AD3F /* smk_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = smk_decoder.cpp; sourceTree = "<group>"; }; + DF6118650FE3A9410042AD3F /* smk_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smk_decoder.h; sourceTree = "<group>"; }; + DF6118790FE3A9AA0042AD3F /* saveconverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveconverter.cpp; sourceTree = "<group>"; }; + DF61187A0FE3A9AA0042AD3F /* saveconverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = saveconverter.h; sourceTree = "<group>"; }; + DF61187B0FE3A9AA0042AD3F /* saveconverter_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveconverter_v2.cpp; sourceTree = "<group>"; }; + DF61187C0FE3A9AA0042AD3F /* saveconverter_v3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveconverter_v3.cpp; sourceTree = "<group>"; }; + DF61187D0FE3A9AA0042AD3F /* saveconverter_v4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveconverter_v4.cpp; sourceTree = "<group>"; }; + DF61187E0FE3A9AA0042AD3F /* saveconverter_v6.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveconverter_v6.cpp; sourceTree = "<group>"; }; + DF61187F0FE3A9AA0042AD3F /* savefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = savefile.cpp; sourceTree = "<group>"; }; + DF6118800FE3A9AA0042AD3F /* savefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = savefile.h; sourceTree = "<group>"; }; + DF6118810FE3A9AA0042AD3F /* savehandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = savehandler.cpp; sourceTree = "<group>"; }; + DF6118820FE3A9AA0042AD3F /* savehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = savehandler.h; sourceTree = "<group>"; }; + DF6118830FE3A9AA0042AD3F /* saveload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload.cpp; sourceTree = "<group>"; }; + DF6118840FE3A9AA0042AD3F /* saveload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = saveload.h; sourceTree = "<group>"; }; + DF6118850FE3A9AA0042AD3F /* saveload_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v2.cpp; sourceTree = "<group>"; }; + DF6118860FE3A9AA0042AD3F /* saveload_v3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v3.cpp; sourceTree = "<group>"; }; + DF6118870FE3A9AA0042AD3F /* saveload_v4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v4.cpp; sourceTree = "<group>"; }; + DF6118880FE3A9AA0042AD3F /* saveload_v6.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v6.cpp; sourceTree = "<group>"; }; + DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = feeble.cpp; sourceTree = "<group>"; }; + DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_lol.cpp; sourceTree = "<group>"; }; + DF6118B40FE3AA280042AD3F /* sound_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_lol.cpp; sourceTree = "<group>"; }; + DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound_pcspk.cpp; sourceTree = "<group>"; }; + DF6118B60FE3AA280042AD3F /* text_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = text_lol.cpp; sourceTree = "<group>"; }; + DF6118B70FE3AA280042AD3F /* text_lol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = text_lol.h; sourceTree = "<group>"; }; + DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = player_v2cms.cpp; sourceTree = "<group>"; }; + DF6118CB0FE3AAFD0042AD3F /* hardwarekeys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hardwarekeys.cpp; sourceTree = "<group>"; }; + DF6118CF0FE3AB560042AD3F /* mame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mame.cpp; sourceTree = "<group>"; }; + DF6118D00FE3AB560042AD3F /* mame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mame.h; sourceTree = "<group>"; }; DF7A40320FB6E8960094E50F /* gfx_pixmap_scale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gfx_pixmap_scale.cpp; sourceTree = "<group>"; }; DF7E8BF00ED5FC77001CB19F /* saveload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload.cpp; sourceTree = "<group>"; }; DF7E8BF10ED5FC77001CB19F /* saveload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = saveload.h; sourceTree = "<group>"; }; @@ -3382,8 +3400,6 @@ DF8421130E7BA6A700F5680E /* talk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talk.cpp; sourceTree = "<group>"; }; DF8421140E7BA6A700F5680E /* engine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = engine.cpp; sourceTree = "<group>"; }; DF8421150E7BA6A700F5680E /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = engine.h; sourceTree = "<group>"; }; - DF8421190E7BA6A700F5680E /* coktelvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coktelvideo.cpp; sourceTree = "<group>"; }; - DF84211A0E7BA6A700F5680E /* coktelvideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coktelvideo.h; sourceTree = "<group>"; }; DF84211B0E7BA6A700F5680E /* dataio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dataio.cpp; sourceTree = "<group>"; }; DF84211C0E7BA6A700F5680E /* dataio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dataio.h; sourceTree = "<group>"; }; DF84211D0E7BA6A700F5680E /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = "<group>"; }; @@ -3435,13 +3451,6 @@ DF84214D0E7BA6A700F5680E /* palanim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = palanim.h; sourceTree = "<group>"; }; DF84214E0E7BA6A700F5680E /* parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse.cpp; sourceTree = "<group>"; }; DF84214F0E7BA6A700F5680E /* parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse.h; sourceTree = "<group>"; }; - DF8421500E7BA6A700F5680E /* parse_v1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_v1.cpp; sourceTree = "<group>"; }; - DF8421510E7BA6A700F5680E /* parse_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_v2.cpp; sourceTree = "<group>"; }; - DF8421520E7BA6A700F5680E /* saveload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload.cpp; sourceTree = "<group>"; }; - DF8421530E7BA6A700F5680E /* saveload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = saveload.h; sourceTree = "<group>"; }; - DF8421540E7BA6A700F5680E /* saveload_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v2.cpp; sourceTree = "<group>"; }; - DF8421550E7BA6A700F5680E /* saveload_v3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v3.cpp; sourceTree = "<group>"; }; - DF8421560E7BA6A700F5680E /* saveload_v4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveload_v4.cpp; sourceTree = "<group>"; }; DF8421570E7BA6A700F5680E /* scenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scenery.cpp; sourceTree = "<group>"; }; DF8421580E7BA6A700F5680E /* scenery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scenery.h; sourceTree = "<group>"; }; DF8421590E7BA6A700F5680E /* scenery_v1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scenery_v1.cpp; sourceTree = "<group>"; }; @@ -4332,7 +4341,6 @@ DFC830320F48AF18005EF03C /* message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message.h; sourceTree = "<group>"; }; DFC830330F48AF18005EF03C /* said.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = said.cpp; sourceTree = "<group>"; }; DFC830360F48AF18005EF03C /* savegame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = savegame.cpp; sourceTree = "<group>"; }; - DFC830380F48AF18005EF03C /* scriptconsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptconsole.cpp; sourceTree = "<group>"; }; DFC830390F48AF18005EF03C /* scriptdebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptdebug.cpp; sourceTree = "<group>"; }; DFC8303A0F48AF18005EF03C /* seg_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = seg_manager.cpp; sourceTree = "<group>"; }; DFC8303C0F48AF18005EF03C /* vm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vm.cpp; sourceTree = "<group>"; }; @@ -4346,24 +4354,12 @@ DFC8304D0F48AF18005EF03C /* operations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = operations.cpp; sourceTree = "<group>"; }; DFC830960F48AF18005EF03C /* sci.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sci.cpp; sourceTree = "<group>"; }; DFC830970F48AF18005EF03C /* sci.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sci.h; sourceTree = "<group>"; }; - DFC830B00F48AF19005EF03C /* resource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource.cpp; sourceTree = "<group>"; }; - DFC830BA0F48AF19005EF03C /* versions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = versions.cpp; sourceTree = "<group>"; }; - DFC830BB0F48AF19005EF03C /* vocabulary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vocabulary.cpp; sourceTree = "<group>"; }; - DFC830BC0F48AF19005EF03C /* vocab_debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vocab_debug.cpp; sourceTree = "<group>"; }; DFC830C00F48AF19005EF03C /* core.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core.cpp; sourceTree = "<group>"; }; - DFC830C40F48AF19005EF03C /* devices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = devices.cpp; sourceTree = "<group>"; }; DFC830C60F48AF19005EF03C /* device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = device.h; sourceTree = "<group>"; }; DFC830CB0F48AF19005EF03C /* iterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iterator.cpp; sourceTree = "<group>"; }; - DFC830E90F48AF19005EF03C /* players.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = players.cpp; sourceTree = "<group>"; }; - DFC830EA0F48AF19005EF03C /* polled.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polled.cpp; sourceTree = "<group>"; }; - DFC830EB0F48AF19005EF03C /* realtime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = realtime.cpp; sourceTree = "<group>"; }; DFC830F30F48AF19005EF03C /* sequencers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sequencers.cpp; sourceTree = "<group>"; }; DFC830F40F48AF19005EF03C /* sequencer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sequencer.h; sourceTree = "<group>"; }; DFC830F60F48AF19005EF03C /* amiga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = amiga.cpp; sourceTree = "<group>"; }; - DFC830FA0F48AF19005EF03C /* opl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opl2.cpp; sourceTree = "<group>"; }; - DFC830FB0F48AF19005EF03C /* pcspeaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcspeaker.cpp; sourceTree = "<group>"; }; - DFC830FC0F48AF19005EF03C /* SN76496.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SN76496.cpp; sourceTree = "<group>"; }; - DFC830FD0F48AF19005EF03C /* softsequencers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = softsequencers.cpp; sourceTree = "<group>"; }; DFC830FE0F48AF19005EF03C /* softseq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = softseq.h; sourceTree = "<group>"; }; DFC830FF0F48AF19005EF03C /* songlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = songlib.cpp; sourceTree = "<group>"; }; DFD511460DF3383500854012 /* memorypool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memorypool.cpp; sourceTree = "<group>"; }; @@ -4588,11 +4584,8 @@ DFE88C4B0F874A6600C555C5 /* gfx_gui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gfx_gui.cpp; sourceTree = "<group>"; }; DFE88C4C0F874A6600C555C5 /* gfx_gui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gfx_gui.h; sourceTree = "<group>"; }; DFF4DFFC0F4B449F00C50BC7 /* Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist.in; sourceTree = "<group>"; }; - DFF958A30FB222AF00A3EC78 /* adlib_sbi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adlib_sbi.cpp; sourceTree = "<group>"; }; - DFF958A40FB222AF00A3EC78 /* adlib_sbi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adlib_sbi.h; sourceTree = "<group>"; }; DFF958A90FB222F300A3EC78 /* dosbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dosbox.cpp; sourceTree = "<group>"; }; DFF958AA0FB222F300A3EC78 /* dosbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dosbox.h; sourceTree = "<group>"; }; - DFF958BF0FB223B300A3EC78 /* player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = player.cpp; sourceTree = "<group>"; }; DFF958C40FB223F000A3EC78 /* adlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adlib.cpp; sourceTree = "<group>"; }; DFF958C50FB223F000A3EC78 /* adlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adlib.h; sourceTree = "<group>"; }; DFF958C60FB223F000A3EC78 /* pcjr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcjr.cpp; sourceTree = "<group>"; }; @@ -4636,7 +4629,6 @@ DF0944700F63FCCB002D821E /* IOKit.framework in Frameworks */, DF0944780F63FD10002D821E /* Cocoa.framework in Frameworks */, DF0944800F63FD67002D821E /* AudioUnit.framework in Frameworks */, - DF224E030FB23BC500C8E453 /* OpenGLES.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4743,6 +4735,7 @@ DF09422F0F63CB9A002D821E /* sdl */ = { isa = PBXGroup; children = ( + DF6118CB0FE3AAFD0042AD3F /* hardwarekeys.cpp */, DF0942350F63CB9A002D821E /* events.cpp */, DF0942370F63CB9A002D821E /* graphics.cpp */, DF0942390F63CB9A002D821E /* main.cpp */, @@ -4768,33 +4761,21 @@ DF2FFB940F485D950006E566 /* video */ = { isa = PBXGroup; children = ( - DF2FFB950F485D950006E566 /* .deps */, - DF2FFB9B0F485D950006E566 /* dxa_player.cpp */, - DF2FFB9C0F485D950006E566 /* dxa_player.h */, - DF2FFB9E0F485D950006E566 /* flic_player.cpp */, - DF2FFB9F0F485D950006E566 /* flic_player.h */, + DF61185B0FE3A9410042AD3F /* coktelvideo */, + DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */, + DF6118610FE3A9410042AD3F /* dxa_decoder.h */, + DF6118620FE3A9410042AD3F /* flic_decoder.cpp */, + DF6118630FE3A9410042AD3F /* flic_decoder.h */, + DF6118640FE3A9410042AD3F /* smk_decoder.cpp */, + DF6118650FE3A9410042AD3F /* smk_decoder.h */, DF2FFBA10F485D950006E566 /* mpeg_player.cpp */, DF2FFBA20F485D950006E566 /* mpeg_player.h */, - DF2FFBA40F485D950006E566 /* smk_player.cpp */, - DF2FFBA50F485D950006E566 /* smk_player.h */, DF2FFBA70F485D950006E566 /* video_player.cpp */, DF2FFBA80F485D950006E566 /* video_player.h */, ); path = video; sourceTree = "<group>"; }; - DF2FFB950F485D950006E566 /* .deps */ = { - isa = PBXGroup; - children = ( - DF2FFB960F485D950006E566 /* dxa_player.d */, - DF2FFB970F485D950006E566 /* flic_player.d */, - DF2FFB980F485D950006E566 /* mpeg_player.d */, - DF2FFB990F485D950006E566 /* smk_player.d */, - DF2FFB9A0F485D950006E566 /* video_player.d */, - ); - path = .deps; - sourceTree = "<group>"; - }; DF2FFBF50F4860A60006E566 /* posix */ = { isa = PBXGroup; children = ( @@ -4857,6 +4838,40 @@ path = tucker; sourceTree = "<group>"; }; + DF61185B0FE3A9410042AD3F /* coktelvideo */ = { + isa = PBXGroup; + children = ( + DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */, + DF61185D0FE3A9410042AD3F /* coktelvideo.h */, + DF61185E0FE3A9410042AD3F /* indeo3.cpp */, + DF61185F0FE3A9410042AD3F /* indeo3.h */, + ); + path = coktelvideo; + sourceTree = "<group>"; + }; + DF6118780FE3A9AA0042AD3F /* save */ = { + isa = PBXGroup; + children = ( + DF6118790FE3A9AA0042AD3F /* saveconverter.cpp */, + DF61187A0FE3A9AA0042AD3F /* saveconverter.h */, + DF61187B0FE3A9AA0042AD3F /* saveconverter_v2.cpp */, + DF61187C0FE3A9AA0042AD3F /* saveconverter_v3.cpp */, + DF61187D0FE3A9AA0042AD3F /* saveconverter_v4.cpp */, + DF61187E0FE3A9AA0042AD3F /* saveconverter_v6.cpp */, + DF61187F0FE3A9AA0042AD3F /* savefile.cpp */, + DF6118800FE3A9AA0042AD3F /* savefile.h */, + DF6118810FE3A9AA0042AD3F /* savehandler.cpp */, + DF6118820FE3A9AA0042AD3F /* savehandler.h */, + DF6118830FE3A9AA0042AD3F /* saveload.cpp */, + DF6118840FE3A9AA0042AD3F /* saveload.h */, + DF6118850FE3A9AA0042AD3F /* saveload_v2.cpp */, + DF6118860FE3A9AA0042AD3F /* saveload_v3.cpp */, + DF6118870FE3A9AA0042AD3F /* saveload_v4.cpp */, + DF6118880FE3A9AA0042AD3F /* saveload_v6.cpp */, + ); + path = save; + sourceTree = "<group>"; + }; DF841FF50E7BA6A600F5680E /* engines */ = { isa = PBXGroup; children = ( @@ -4960,6 +4975,7 @@ DF84202D0E7BA6A600F5680E /* agos */ = { isa = PBXGroup; children = ( + DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */, DF093E5C0F63CAD4002D821E /* pn.cpp */, DF093E5D0F63CAD4002D821E /* script_pn.cpp */, DF093E5E0F63CAD4002D821E /* vga_pn.cpp */, @@ -5155,17 +5171,13 @@ DF8421170E7BA6A700F5680E /* gob */ = { isa = PBXGroup; children = ( + DF6118780FE3A9AA0042AD3F /* save */, + DF6118590FE3A9020042AD3F /* helper.h */, DF09CC060FAC4E1900A5AFD7 /* demos */, DF09CC0D0FAC4E1900A5AFD7 /* draw_fascin.cpp */, DF09CC0E0FAC4E1900A5AFD7 /* game_fascin.cpp */, DF09CC0F0FAC4E1900A5AFD7 /* inter_fascin.cpp */, DF2FFC400F4862D90006E566 /* game_v6.cpp */, - DF2FFC410F4862D90006E566 /* indeo3.cpp */, - DF2FFC420F4862D90006E566 /* indeo3.h */, - DF2FFC430F4862D90006E566 /* indeo3data.h */, - DF2FFC440F4862D90006E566 /* saveload_v6.cpp */, - DF8421190E7BA6A700F5680E /* coktelvideo.cpp */, - DF84211A0E7BA6A700F5680E /* coktelvideo.h */, DF84211B0E7BA6A700F5680E /* dataio.cpp */, DF84211C0E7BA6A700F5680E /* dataio.h */, DF84211D0E7BA6A700F5680E /* detection.cpp */, @@ -5217,13 +5229,6 @@ DF84214D0E7BA6A700F5680E /* palanim.h */, DF84214E0E7BA6A700F5680E /* parse.cpp */, DF84214F0E7BA6A700F5680E /* parse.h */, - DF8421500E7BA6A700F5680E /* parse_v1.cpp */, - DF8421510E7BA6A700F5680E /* parse_v2.cpp */, - DF8421520E7BA6A700F5680E /* saveload.cpp */, - DF8421530E7BA6A700F5680E /* saveload.h */, - DF8421540E7BA6A700F5680E /* saveload_v2.cpp */, - DF8421550E7BA6A700F5680E /* saveload_v3.cpp */, - DF8421560E7BA6A700F5680E /* saveload_v4.cpp */, DF8421570E7BA6A700F5680E /* scenery.cpp */, DF8421580E7BA6A700F5680E /* scenery.h */, DF8421590E7BA6A700F5680E /* scenery_v1.cpp */, @@ -5327,6 +5332,11 @@ DF8421A30E7BA6A800F5680E /* kyra */ = { isa = PBXGroup; children = ( + DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */, + DF6118B40FE3AA280042AD3F /* sound_lol.cpp */, + DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */, + DF6118B60FE3AA280042AD3F /* text_lol.cpp */, + DF6118B70FE3AA280042AD3F /* text_lol.h */, DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */, DF573CBD0F5A85E100961A72 /* timer_lol.cpp */, DF2FFC490F4863100006E566 /* scene_lol.cpp */, @@ -5631,8 +5641,7 @@ DF8422E60E7BA6A900F5680E /* parallaction */ = { isa = PBXGroup; children = ( - DF5CEB240F75535000DEA624 /* iff.cpp */, - DF5CEB250F75535000DEA624 /* iff.h */, + DF6118540FE3A8990042AD3F /* disk.cpp */, DF5CEB260F75535000DEA624 /* sound_br.cpp */, DF5CEB270F75535000DEA624 /* sound_ns.cpp */, DF573CBA0F5A85B300961A72 /* exec.cpp */, @@ -5799,6 +5808,7 @@ DF84237B0E7BA6AA00F5680E /* scumm */ = { isa = PBXGroup; children = ( + DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */, DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */, DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */, DF09CC1D0FAC4E6200A5AFD7 /* scumm_v0.h */, @@ -6280,6 +6290,13 @@ DFC830190F48AF18005EF03C /* sci */ = { isa = PBXGroup; children = ( + DF6118420FE3A8250042AD3F /* debug.h */, + DF6118430FE3A8250042AD3F /* decompressor.cpp */, + DF6118440FE3A8250042AD3F /* decompressor.h */, + DF6118450FE3A8250042AD3F /* resource.cpp */, + DF6118460FE3A8250042AD3F /* resource.h */, + DF6118470FE3A8250042AD3F /* vocabulary.cpp */, + DF6118480FE3A8250042AD3F /* vocabulary.h */, DF573CC40F5A863100961A72 /* tools.cpp */, DF573CC50F5A863100961A72 /* tools.h */, DF573BF50F5A81D400961A72 /* uinput.h */, @@ -6292,7 +6309,6 @@ DFC8303D0F48AF18005EF03C /* gfx */, DFC830960F48AF18005EF03C /* sci.cpp */, DFC830970F48AF18005EF03C /* sci.h */, - DFC830980F48AF18005EF03C /* scicore */, DFC830BD0F48AF19005EF03C /* sfx */, ); path = sci; @@ -6301,14 +6317,14 @@ DFC8301B0F48AF18005EF03C /* engine */ = { isa = PBXGroup; children = ( + DF6118380FE3A8080042AD3F /* kmisc.cpp */, + DF6118390FE3A8080042AD3F /* memobj.cpp */, + DF61183A0FE3A8080042AD3F /* memobj.h */, + DF61183B0FE3A8080042AD3F /* savegame.h */, DF5CEB3A0F75540700DEA624 /* stringfrag.cpp */, DF89C2A30F62D79E00D756B6 /* script.cpp */, - DF573BF80F5A81EA00961A72 /* aatree.h */, - DF573BF90F5A81EA00961A72 /* heapmgr.h */, DF573BFA0F5A81EA00961A72 /* intmap.cpp */, DF573BFB0F5A81EA00961A72 /* intmap.h */, - DF573BFC0F5A81EA00961A72 /* kdebug.cpp */, - DF573BFD0F5A81EA00961A72 /* kdebug.h */, DF573BFE0F5A81EA00961A72 /* kernel.h */, DF573BFF0F5A81EA00961A72 /* script.h */, DF573C000F5A81EA00961A72 /* seg_manager.h */, @@ -6337,7 +6353,6 @@ DFC830320F48AF18005EF03C /* message.h */, DFC830330F48AF18005EF03C /* said.cpp */, DFC830360F48AF18005EF03C /* savegame.cpp */, - DFC830380F48AF18005EF03C /* scriptconsole.cpp */, DFC830390F48AF18005EF03C /* scriptdebug.cpp */, DFC8303A0F48AF18005EF03C /* seg_manager.cpp */, DFC8303C0F48AF18005EF03C /* vm.cpp */, @@ -6348,6 +6363,9 @@ DFC8303D0F48AF18005EF03C /* gfx */ = { isa = PBXGroup; children = ( + DF61182F0FE3A7D20042AD3F /* res_view.cpp */, + DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */, + DF6118310FE3A7D20042AD3F /* seq_decoder.h */, DF7A40320FB6E8960094E50F /* gfx_pixmap_scale.cpp */, DFE88C4B0F874A6600C555C5 /* gfx_gui.cpp */, DFE88C4C0F874A6600C555C5 /* gfx_gui.h */, @@ -6360,8 +6378,6 @@ DF5CEB050F7552C700DEA624 /* res_font.cpp */, DF5CEB060F7552C700DEA624 /* res_pal.cpp */, DF5CEB070F7552C700DEA624 /* res_pic.cpp */, - DF5CEB080F7552C700DEA624 /* res_view0.cpp */, - DF5CEB090F7552C700DEA624 /* res_view1.cpp */, DF573C0A0F5A820E00961A72 /* gfx_driver.h */, DF573C0B0F5A820E00961A72 /* gfx_options.h */, DF573C0D0F5A820E00961A72 /* gfx_res_options.h */, @@ -6386,42 +6402,19 @@ path = gfx; sourceTree = "<group>"; }; - DFC830980F48AF18005EF03C /* scicore */ = { - isa = PBXGroup; - children = ( - DF5CEAF80F75529B00DEA624 /* decompressor.cpp */, - DF5CEAF90F75529B00DEA624 /* decompressor.h */, - DF573C200F5A822D00961A72 /* resource.h */, - DF573C210F5A822D00961A72 /* sciconsole.cpp */, - DF573C220F5A822D00961A72 /* sciconsole.h */, - DF573C230F5A822D00961A72 /* versions.h */, - DF573C240F5A822D00961A72 /* vocabulary.h */, - DFC830B00F48AF19005EF03C /* resource.cpp */, - DFC830BA0F48AF19005EF03C /* versions.cpp */, - DFC830BB0F48AF19005EF03C /* vocabulary.cpp */, - DFC830BC0F48AF19005EF03C /* vocab_debug.cpp */, - ); - path = scicore; - sourceTree = "<group>"; - }; DFC830BD0F48AF19005EF03C /* sfx */ = { isa = PBXGroup; children = ( - DFF958A30FB222AF00A3EC78 /* adlib_sbi.cpp */, - DFF958A40FB222AF00A3EC78 /* adlib_sbi.h */, + DF61182E0FE3A7AF0042AD3F /* misc.h */, DF573C260F5A824700961A72 /* core.h */, DF573C270F5A824700961A72 /* iterator.h */, DF573C280F5A824700961A72 /* iterator_internal.h */, - DF573C2A0F5A824700961A72 /* player.h */, DF573C2B0F5A824700961A72 /* sci_midi.h */, - DF573C2C0F5A824700961A72 /* sfx.h */, DF573C2D0F5A824700961A72 /* sfx_pcm.h */, DF573C2F0F5A824700961A72 /* songlib.h */, DFC830C00F48AF19005EF03C /* core.cpp */, - DFC830C10F48AF19005EF03C /* device */, DFC830C60F48AF19005EF03C /* device.h */, DFC830CB0F48AF19005EF03C /* iterator.cpp */, - DFC830E80F48AF19005EF03C /* player */, DFC830EC0F48AF19005EF03C /* seq */, DFC830F40F48AF19005EF03C /* sequencer.h */, DFC830F50F48AF19005EF03C /* softseq */, @@ -6431,25 +6424,6 @@ path = sfx; sourceTree = "<group>"; }; - DFC830C10F48AF19005EF03C /* device */ = { - isa = PBXGroup; - children = ( - DFC830C40F48AF19005EF03C /* devices.cpp */, - ); - path = device; - sourceTree = "<group>"; - }; - DFC830E80F48AF19005EF03C /* player */ = { - isa = PBXGroup; - children = ( - DFF958BF0FB223B300A3EC78 /* player.cpp */, - DFC830E90F48AF19005EF03C /* players.cpp */, - DFC830EA0F48AF19005EF03C /* polled.cpp */, - DFC830EB0F48AF19005EF03C /* realtime.cpp */, - ); - path = player; - sourceTree = "<group>"; - }; DFC830EC0F48AF19005EF03C /* seq */ = { isa = PBXGroup; children = ( @@ -6466,10 +6440,6 @@ DFF958C60FB223F000A3EC78 /* pcjr.cpp */, DFF958C70FB223F000A3EC78 /* pcjr.h */, DFC830F60F48AF19005EF03C /* amiga.cpp */, - DFC830FA0F48AF19005EF03C /* opl2.cpp */, - DFC830FB0F48AF19005EF03C /* pcspeaker.cpp */, - DFC830FC0F48AF19005EF03C /* SN76496.cpp */, - DFC830FD0F48AF19005EF03C /* softsequencers.cpp */, ); path = softseq; sourceTree = "<group>"; @@ -6947,6 +6917,8 @@ DFF958A80FB222F300A3EC78 /* opl */ = { isa = PBXGroup; children = ( + DF6118CF0FE3AB560042AD3F /* mame.cpp */, + DF6118D00FE3AB560042AD3F /* mame.h */, DFF958A90FB222F300A3EC78 /* dosbox.cpp */, DFF958AA0FB222F300A3EC78 /* dosbox.h */, ); @@ -7345,7 +7317,6 @@ DF8425D70E7BA6AC00F5680E /* sound.cpp in Sources */, DF8425D80E7BA6AC00F5680E /* talk.cpp in Sources */, DF8425D90E7BA6AC00F5680E /* engine.cpp in Sources */, - DF8425DC0E7BA6AC00F5680E /* coktelvideo.cpp in Sources */, DF8425DD0E7BA6AC00F5680E /* dataio.cpp in Sources */, DF8425DE0E7BA6AC00F5680E /* detection.cpp in Sources */, DF8425DF0E7BA6AC00F5680E /* draw.cpp in Sources */, @@ -7384,12 +7355,6 @@ DF8426010E7BA6AC00F5680E /* mult_v2.cpp in Sources */, DF8426030E7BA6AC00F5680E /* palanim.cpp in Sources */, DF8426040E7BA6AC00F5680E /* parse.cpp in Sources */, - DF8426050E7BA6AC00F5680E /* parse_v1.cpp in Sources */, - DF8426060E7BA6AC00F5680E /* parse_v2.cpp in Sources */, - DF8426070E7BA6AC00F5680E /* saveload.cpp in Sources */, - DF8426080E7BA6AC00F5680E /* saveload_v2.cpp in Sources */, - DF8426090E7BA6AC00F5680E /* saveload_v3.cpp in Sources */, - DF84260A0E7BA6AC00F5680E /* saveload_v4.cpp in Sources */, DF84260B0E7BA6AC00F5680E /* scenery.cpp in Sources */, DF84260C0E7BA6AC00F5680E /* scenery_v1.cpp in Sources */, DF84260D0E7BA6AC00F5680E /* scenery_v2.cpp in Sources */, @@ -7887,10 +7852,7 @@ DFAAAFFC0F0112DF003E9390 /* detection.cpp in Sources */, DFAAB0020F011392003E9390 /* thumbnail_intern.cpp in Sources */, DF2FFB930F485D890006E566 /* dither.cpp in Sources */, - DF2FFBAF0F485D950006E566 /* dxa_player.cpp in Sources */, - DF2FFBB10F485D950006E566 /* flic_player.cpp in Sources */, DF2FFBB30F485D950006E566 /* mpeg_player.cpp in Sources */, - DF2FFBB50F485D950006E566 /* smk_player.cpp in Sources */, DF2FFBB70F485D950006E566 /* video_player.cpp in Sources */, DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */, DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */, @@ -7906,8 +7868,6 @@ DF2FFC3C0F48628A0006E566 /* sound_midi.cpp in Sources */, DF2FFC3E0F48628A0006E566 /* util.cpp in Sources */, DF2FFC450F4862D90006E566 /* game_v6.cpp in Sources */, - DF2FFC460F4862D90006E566 /* indeo3.cpp in Sources */, - DF2FFC470F4862D90006E566 /* saveload_v6.cpp in Sources */, DF2FFC4A0F4863100006E566 /* scene_lol.cpp in Sources */, DF2FFC4E0F4863560006E566 /* advancedDetector.cpp in Sources */, DF2FFC5D0F4866E70006E566 /* base-backend.cpp in Sources */, @@ -7960,7 +7920,6 @@ DFC831330F48AF19005EF03C /* message.cpp in Sources */, DFC831340F48AF19005EF03C /* said.cpp in Sources */, DFC831370F48AF19005EF03C /* savegame.cpp in Sources */, - DFC831380F48AF19005EF03C /* scriptconsole.cpp in Sources */, DFC831390F48AF19005EF03C /* scriptdebug.cpp in Sources */, DFC8313A0F48AF19005EF03C /* seg_manager.cpp in Sources */, DFC8313C0F48AF19005EF03C /* vm.cpp in Sources */, @@ -7973,42 +7932,27 @@ DFC8314B0F48AF19005EF03C /* menubar.cpp in Sources */, DFC8314C0F48AF19005EF03C /* operations.cpp in Sources */, DFC8315C0F48AF19005EF03C /* sci.cpp in Sources */, - DFC831710F48AF19005EF03C /* resource.cpp in Sources */, - DFC8317B0F48AF19005EF03C /* versions.cpp in Sources */, - DFC8317C0F48AF19005EF03C /* vocabulary.cpp in Sources */, - DFC8317D0F48AF19005EF03C /* vocab_debug.cpp in Sources */, DFC8317F0F48AF19005EF03C /* core.cpp in Sources */, - DFC831820F48AF19005EF03C /* devices.cpp in Sources */, DFC831870F48AF19005EF03C /* iterator.cpp in Sources */, - DFC8319E0F48AF19005EF03C /* players.cpp in Sources */, - DFC831A00F48AF19005EF03C /* realtime.cpp in Sources */, DFC831A60F48AF19005EF03C /* sequencers.cpp in Sources */, DFC831A70F48AF19005EF03C /* amiga.cpp in Sources */, - DFC831AA0F48AF19005EF03C /* opl2.cpp in Sources */, - DFC831AB0F48AF19005EF03C /* pcspeaker.cpp in Sources */, - DFC831AC0F48AF19005EF03C /* SN76496.cpp in Sources */, - DFC831AD0F48AF19005EF03C /* softsequencers.cpp in Sources */, DFC831AE0F48AF19005EF03C /* songlib.cpp in Sources */, DFD6470C0F495B51008E18EF /* unzip.cpp in Sources */, DFAAD23D0F50120E00C3A4E2 /* console.cpp in Sources */, DFAAD23E0F50120E00C3A4E2 /* exereader.cpp in Sources */, DF573C060F5A81EA00961A72 /* intmap.cpp in Sources */, - DF573C070F5A81EA00961A72 /* kdebug.cpp in Sources */, DF573C080F5A81EA00961A72 /* state.cpp in Sources */, DF573C1B0F5A820E00961A72 /* gfx_widgets.cpp in Sources */, - DF573C250F5A822D00961A72 /* sciconsole.cpp in Sources */, DF573CBB0F5A85B300961A72 /* exec.cpp in Sources */, DF573CBE0F5A85E100961A72 /* timer_lol.cpp in Sources */, DF573CC60F5A863100961A72 /* tools.cpp in Sources */, DF89C2880F62D55C00D756B6 /* sprites_lol.cpp in Sources */, DF89C2A40F62D79E00D756B6 /* script.cpp in Sources */, - DF89C2B40F62D89600D756B6 /* polled.cpp in Sources */, DF89C2BA0F62D91000D756B6 /* shorten.cpp in Sources */, DF89C2BB0F62D91000D756B6 /* timestamp.cpp in Sources */, DF093E5F0F63CAD4002D821E /* pn.cpp in Sources */, DF093E600F63CAD4002D821E /* script_pn.cpp in Sources */, DF093E610F63CAD4002D821E /* vga_pn.cpp in Sources */, - DF5CEAFB0F75529B00DEA624 /* decompressor.cpp in Sources */, DF5CEB160F7552C700DEA624 /* gfx_resmgr.cpp in Sources */, DF5CEB180F7552C700DEA624 /* palette.cpp in Sources */, DF5CEB190F7552C700DEA624 /* picfill.cpp in Sources */, @@ -8016,9 +7960,6 @@ DF5CEB1B0F7552C700DEA624 /* res_font.cpp in Sources */, DF5CEB1C0F7552C700DEA624 /* res_pal.cpp in Sources */, DF5CEB1D0F7552C700DEA624 /* res_pic.cpp in Sources */, - DF5CEB1E0F7552C700DEA624 /* res_view0.cpp in Sources */, - DF5CEB1F0F7552C700DEA624 /* res_view1.cpp in Sources */, - DF5CEB2B0F75535000DEA624 /* iff.cpp in Sources */, DF5CEB2C0F75535000DEA624 /* sound_br.cpp in Sources */, DF5CEB2D0F75535000DEA624 /* sound_ns.cpp in Sources */, DF5CEB320F75538000DEA624 /* protracker.cpp in Sources */, @@ -8034,12 +7975,42 @@ DF09CC1B0FAC4E1900A5AFD7 /* inter_fascin.cpp in Sources */, DF09CC2A0FAC4EAB00A5AFD7 /* script_v3.cpp in Sources */, DF09CC2B0FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */, - DFF958A60FB222AF00A3EC78 /* adlib_sbi.cpp in Sources */, DFF958B20FB222F300A3EC78 /* dosbox.cpp in Sources */, - DFF958C10FB223B300A3EC78 /* player.cpp in Sources */, DFF958CA0FB223F000A3EC78 /* adlib.cpp in Sources */, DFF958CB0FB223F000A3EC78 /* pcjr.cpp in Sources */, DF7A40340FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */, + DF6118340FE3A7D20042AD3F /* res_view.cpp in Sources */, + DF6118350FE3A7D20042AD3F /* seq_decoder.cpp in Sources */, + DF61183E0FE3A8080042AD3F /* kmisc.cpp in Sources */, + DF61183F0FE3A8080042AD3F /* memobj.cpp in Sources */, + DF61184C0FE3A8250042AD3F /* decompressor.cpp in Sources */, + DF61184D0FE3A8250042AD3F /* resource.cpp in Sources */, + DF61184E0FE3A8250042AD3F /* vocabulary.cpp in Sources */, + DF6118560FE3A8990042AD3F /* disk.cpp in Sources */, + DF61186B0FE3A9410042AD3F /* coktelvideo.cpp in Sources */, + DF61186C0FE3A9410042AD3F /* indeo3.cpp in Sources */, + DF61186D0FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, + DF61186E0FE3A9410042AD3F /* flic_decoder.cpp in Sources */, + DF61186F0FE3A9410042AD3F /* smk_decoder.cpp in Sources */, + DF6118950FE3A9AA0042AD3F /* saveconverter.cpp in Sources */, + DF6118960FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */, + DF6118970FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */, + DF6118980FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */, + DF6118990FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */, + DF61189A0FE3A9AA0042AD3F /* savefile.cpp in Sources */, + DF61189B0FE3A9AA0042AD3F /* savehandler.cpp in Sources */, + DF61189C0FE3A9AA0042AD3F /* saveload.cpp in Sources */, + DF61189D0FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */, + DF61189E0FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */, + DF61189F0FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */, + DF6118A00FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */, + DF6118B00FE3A9EA0042AD3F /* feeble.cpp in Sources */, + DF6118BC0FE3AA280042AD3F /* saveload_lol.cpp in Sources */, + DF6118BD0FE3AA280042AD3F /* sound_lol.cpp in Sources */, + DF6118BE0FE3AA280042AD3F /* sound_pcspk.cpp in Sources */, + DF6118BF0FE3AA280042AD3F /* text_lol.cpp in Sources */, + DF6118C80FE3AABD0042AD3F /* player_v2cms.cpp in Sources */, + DF6118D30FE3AB560042AD3F /* mame.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -8280,7 +8251,6 @@ DF093F6B0F63CB26002D821E /* sound.cpp in Sources */, DF093F6C0F63CB26002D821E /* talk.cpp in Sources */, DF093F6D0F63CB26002D821E /* engine.cpp in Sources */, - DF093F6E0F63CB26002D821E /* coktelvideo.cpp in Sources */, DF093F6F0F63CB26002D821E /* dataio.cpp in Sources */, DF093F700F63CB26002D821E /* detection.cpp in Sources */, DF093F710F63CB26002D821E /* draw.cpp in Sources */, @@ -8319,12 +8289,6 @@ DF093F920F63CB26002D821E /* mult_v2.cpp in Sources */, DF093F930F63CB26002D821E /* palanim.cpp in Sources */, DF093F940F63CB26002D821E /* parse.cpp in Sources */, - DF093F950F63CB26002D821E /* parse_v1.cpp in Sources */, - DF093F960F63CB26002D821E /* parse_v2.cpp in Sources */, - DF093F970F63CB26002D821E /* saveload.cpp in Sources */, - DF093F980F63CB26002D821E /* saveload_v2.cpp in Sources */, - DF093F990F63CB26002D821E /* saveload_v3.cpp in Sources */, - DF093F9A0F63CB26002D821E /* saveload_v4.cpp in Sources */, DF093F9B0F63CB26002D821E /* scenery.cpp in Sources */, DF093F9C0F63CB26002D821E /* scenery_v1.cpp in Sources */, DF093F9D0F63CB26002D821E /* scenery_v2.cpp in Sources */, @@ -8821,10 +8785,7 @@ DF09418A0F63CB26002D821E /* detection.cpp in Sources */, DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */, DF09418C0F63CB26002D821E /* dither.cpp in Sources */, - DF09418D0F63CB26002D821E /* dxa_player.cpp in Sources */, - DF09418E0F63CB26002D821E /* flic_player.cpp in Sources */, DF09418F0F63CB26002D821E /* mpeg_player.cpp in Sources */, - DF0941900F63CB26002D821E /* smk_player.cpp in Sources */, DF0941910F63CB26002D821E /* video_player.cpp in Sources */, DF0941920F63CB26002D821E /* debug.cpp in Sources */, DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */, @@ -8840,8 +8801,6 @@ DF09419D0F63CB26002D821E /* sound_midi.cpp in Sources */, DF09419E0F63CB26002D821E /* util.cpp in Sources */, DF09419F0F63CB26002D821E /* game_v6.cpp in Sources */, - DF0941A00F63CB26002D821E /* indeo3.cpp in Sources */, - DF0941A10F63CB26002D821E /* saveload_v6.cpp in Sources */, DF0941A20F63CB26002D821E /* scene_lol.cpp in Sources */, DF0941A30F63CB26002D821E /* advancedDetector.cpp in Sources */, DF0941A40F63CB26002D821E /* base-backend.cpp in Sources */, @@ -8894,7 +8853,6 @@ DF0941D40F63CB26002D821E /* message.cpp in Sources */, DF0941D50F63CB26002D821E /* said.cpp in Sources */, DF0941D60F63CB26002D821E /* savegame.cpp in Sources */, - DF0941D70F63CB26002D821E /* scriptconsole.cpp in Sources */, DF0941D80F63CB26002D821E /* scriptdebug.cpp in Sources */, DF0941D90F63CB26002D821E /* seg_manager.cpp in Sources */, DF0941DA0F63CB26002D821E /* vm.cpp in Sources */, @@ -8907,36 +8865,22 @@ DF0941E10F63CB26002D821E /* menubar.cpp in Sources */, DF0941E20F63CB26002D821E /* operations.cpp in Sources */, DF0941EC0F63CB26002D821E /* sci.cpp in Sources */, - DF0941F10F63CB26002D821E /* resource.cpp in Sources */, - DF0941F20F63CB26002D821E /* versions.cpp in Sources */, - DF0941F30F63CB26002D821E /* vocabulary.cpp in Sources */, - DF0941F40F63CB26002D821E /* vocab_debug.cpp in Sources */, DF0941F60F63CB26002D821E /* core.cpp in Sources */, - DF0941F70F63CB26002D821E /* devices.cpp in Sources */, DF0941F80F63CB26002D821E /* iterator.cpp in Sources */, - DF0941F90F63CB26002D821E /* players.cpp in Sources */, - DF0941FA0F63CB26002D821E /* realtime.cpp in Sources */, DF0941FB0F63CB26002D821E /* sequencers.cpp in Sources */, DF0941FC0F63CB26002D821E /* amiga.cpp in Sources */, - DF0941FD0F63CB26002D821E /* opl2.cpp in Sources */, - DF0941FE0F63CB26002D821E /* pcspeaker.cpp in Sources */, - DF0941FF0F63CB26002D821E /* SN76496.cpp in Sources */, - DF0942000F63CB26002D821E /* softsequencers.cpp in Sources */, DF0942010F63CB26002D821E /* songlib.cpp in Sources */, DF0942020F63CB26002D821E /* unzip.cpp in Sources */, DF0942030F63CB26002D821E /* console.cpp in Sources */, DF0942040F63CB26002D821E /* exereader.cpp in Sources */, DF0942070F63CB26002D821E /* intmap.cpp in Sources */, - DF0942080F63CB26002D821E /* kdebug.cpp in Sources */, DF0942090F63CB26002D821E /* state.cpp in Sources */, DF09420A0F63CB26002D821E /* gfx_widgets.cpp in Sources */, - DF09420B0F63CB26002D821E /* sciconsole.cpp in Sources */, DF09420C0F63CB26002D821E /* exec.cpp in Sources */, DF09420D0F63CB26002D821E /* timer_lol.cpp in Sources */, DF09420F0F63CB26002D821E /* tools.cpp in Sources */, DF0942100F63CB26002D821E /* sprites_lol.cpp in Sources */, DF0942110F63CB26002D821E /* script.cpp in Sources */, - DF0942120F63CB26002D821E /* polled.cpp in Sources */, DF0942130F63CB26002D821E /* shorten.cpp in Sources */, DF0942140F63CB26002D821E /* timestamp.cpp in Sources */, DF0942150F63CB26002D821E /* pn.cpp in Sources */, @@ -8949,7 +8893,6 @@ DF0944330F63FBB3002D821E /* coreaudio.cpp in Sources */, DF0944340F63FBB3002D821E /* coremidi.cpp in Sources */, DF0944350F63FBB3002D821E /* quicktime.cpp in Sources */, - DF5CEAFA0F75529B00DEA624 /* decompressor.cpp in Sources */, DF5CEB0B0F7552C700DEA624 /* gfx_resmgr.cpp in Sources */, DF5CEB0D0F7552C700DEA624 /* palette.cpp in Sources */, DF5CEB0E0F7552C700DEA624 /* picfill.cpp in Sources */, @@ -8957,9 +8900,6 @@ DF5CEB100F7552C700DEA624 /* res_font.cpp in Sources */, DF5CEB110F7552C700DEA624 /* res_pal.cpp in Sources */, DF5CEB120F7552C700DEA624 /* res_pic.cpp in Sources */, - DF5CEB130F7552C700DEA624 /* res_view0.cpp in Sources */, - DF5CEB140F7552C700DEA624 /* res_view1.cpp in Sources */, - DF5CEB280F75535000DEA624 /* iff.cpp in Sources */, DF5CEB290F75535000DEA624 /* sound_br.cpp in Sources */, DF5CEB2A0F75535000DEA624 /* sound_ns.cpp in Sources */, DF5CEB310F75538000DEA624 /* protracker.cpp in Sources */, @@ -8975,12 +8915,43 @@ DF09CC150FAC4E1900A5AFD7 /* inter_fascin.cpp in Sources */, DF09CC280FAC4EAB00A5AFD7 /* script_v3.cpp in Sources */, DF09CC290FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */, - DFF958A50FB222AF00A3EC78 /* adlib_sbi.cpp in Sources */, DFF958AF0FB222F300A3EC78 /* dosbox.cpp in Sources */, - DFF958C00FB223B300A3EC78 /* player.cpp in Sources */, DFF958C80FB223F000A3EC78 /* adlib.cpp in Sources */, DFF958C90FB223F000A3EC78 /* pcjr.cpp in Sources */, DF7A40330FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */, + DF6118320FE3A7D20042AD3F /* res_view.cpp in Sources */, + DF6118330FE3A7D20042AD3F /* seq_decoder.cpp in Sources */, + DF61183C0FE3A8080042AD3F /* kmisc.cpp in Sources */, + DF61183D0FE3A8080042AD3F /* memobj.cpp in Sources */, + DF6118490FE3A8250042AD3F /* decompressor.cpp in Sources */, + DF61184A0FE3A8250042AD3F /* resource.cpp in Sources */, + DF61184B0FE3A8250042AD3F /* vocabulary.cpp in Sources */, + DF6118550FE3A8990042AD3F /* disk.cpp in Sources */, + DF6118660FE3A9410042AD3F /* coktelvideo.cpp in Sources */, + DF6118670FE3A9410042AD3F /* indeo3.cpp in Sources */, + DF6118680FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, + DF6118690FE3A9410042AD3F /* flic_decoder.cpp in Sources */, + DF61186A0FE3A9410042AD3F /* smk_decoder.cpp in Sources */, + DF6118890FE3A9AA0042AD3F /* saveconverter.cpp in Sources */, + DF61188A0FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */, + DF61188B0FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */, + DF61188C0FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */, + DF61188D0FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */, + DF61188E0FE3A9AA0042AD3F /* savefile.cpp in Sources */, + DF61188F0FE3A9AA0042AD3F /* savehandler.cpp in Sources */, + DF6118900FE3A9AA0042AD3F /* saveload.cpp in Sources */, + DF6118910FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */, + DF6118920FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */, + DF6118930FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */, + DF6118940FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */, + DF6118AF0FE3A9EA0042AD3F /* feeble.cpp in Sources */, + DF6118B80FE3AA280042AD3F /* saveload_lol.cpp in Sources */, + DF6118B90FE3AA280042AD3F /* sound_lol.cpp in Sources */, + DF6118BA0FE3AA280042AD3F /* sound_pcspk.cpp in Sources */, + DF6118BB0FE3AA280042AD3F /* text_lol.cpp in Sources */, + DF6118C70FE3AABD0042AD3F /* player_v2cms.cpp in Sources */, + DF6118CC0FE3AAFD0042AD3F /* hardwarekeys.cpp in Sources */, + DF6118D10FE3AB560042AD3F /* mame.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -9225,7 +9196,6 @@ DFF95A010FB22D5700A3EC78 /* sound.cpp in Sources */, DFF95A020FB22D5700A3EC78 /* talk.cpp in Sources */, DFF95A030FB22D5700A3EC78 /* engine.cpp in Sources */, - DFF95A040FB22D5700A3EC78 /* coktelvideo.cpp in Sources */, DFF95A050FB22D5700A3EC78 /* dataio.cpp in Sources */, DFF95A060FB22D5700A3EC78 /* detection.cpp in Sources */, DFF95A070FB22D5700A3EC78 /* draw.cpp in Sources */, @@ -9264,12 +9234,6 @@ DFF95A280FB22D5700A3EC78 /* mult_v2.cpp in Sources */, DFF95A290FB22D5700A3EC78 /* palanim.cpp in Sources */, DFF95A2A0FB22D5700A3EC78 /* parse.cpp in Sources */, - DFF95A2B0FB22D5700A3EC78 /* parse_v1.cpp in Sources */, - DFF95A2C0FB22D5700A3EC78 /* parse_v2.cpp in Sources */, - DFF95A2D0FB22D5700A3EC78 /* saveload.cpp in Sources */, - DFF95A2E0FB22D5700A3EC78 /* saveload_v2.cpp in Sources */, - DFF95A2F0FB22D5700A3EC78 /* saveload_v3.cpp in Sources */, - DFF95A300FB22D5700A3EC78 /* saveload_v4.cpp in Sources */, DFF95A310FB22D5700A3EC78 /* scenery.cpp in Sources */, DFF95A320FB22D5700A3EC78 /* scenery_v1.cpp in Sources */, DFF95A330FB22D5700A3EC78 /* scenery_v2.cpp in Sources */, @@ -9767,10 +9731,7 @@ DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */, DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */, DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */, - DFF95C220FB22D5700A3EC78 /* dxa_player.cpp in Sources */, - DFF95C230FB22D5700A3EC78 /* flic_player.cpp in Sources */, DFF95C240FB22D5700A3EC78 /* mpeg_player.cpp in Sources */, - DFF95C250FB22D5700A3EC78 /* smk_player.cpp in Sources */, DFF95C260FB22D5700A3EC78 /* video_player.cpp in Sources */, DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */, DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */, @@ -9786,8 +9747,6 @@ DFF95C320FB22D5700A3EC78 /* sound_midi.cpp in Sources */, DFF95C330FB22D5700A3EC78 /* util.cpp in Sources */, DFF95C340FB22D5700A3EC78 /* game_v6.cpp in Sources */, - DFF95C350FB22D5700A3EC78 /* indeo3.cpp in Sources */, - DFF95C360FB22D5700A3EC78 /* saveload_v6.cpp in Sources */, DFF95C370FB22D5700A3EC78 /* scene_lol.cpp in Sources */, DFF95C380FB22D5700A3EC78 /* advancedDetector.cpp in Sources */, DFF95C390FB22D5700A3EC78 /* base-backend.cpp in Sources */, @@ -9840,7 +9799,6 @@ DFF95C680FB22D5700A3EC78 /* message.cpp in Sources */, DFF95C690FB22D5700A3EC78 /* said.cpp in Sources */, DFF95C6A0FB22D5700A3EC78 /* savegame.cpp in Sources */, - DFF95C6B0FB22D5700A3EC78 /* scriptconsole.cpp in Sources */, DFF95C6C0FB22D5700A3EC78 /* scriptdebug.cpp in Sources */, DFF95C6D0FB22D5700A3EC78 /* seg_manager.cpp in Sources */, DFF95C6E0FB22D5700A3EC78 /* vm.cpp in Sources */, @@ -9853,42 +9811,27 @@ DFF95C750FB22D5700A3EC78 /* menubar.cpp in Sources */, DFF95C760FB22D5700A3EC78 /* operations.cpp in Sources */, DFF95C770FB22D5700A3EC78 /* sci.cpp in Sources */, - DFF95C780FB22D5700A3EC78 /* resource.cpp in Sources */, - DFF95C790FB22D5700A3EC78 /* versions.cpp in Sources */, - DFF95C7A0FB22D5700A3EC78 /* vocabulary.cpp in Sources */, - DFF95C7B0FB22D5700A3EC78 /* vocab_debug.cpp in Sources */, DFF95C7C0FB22D5700A3EC78 /* core.cpp in Sources */, - DFF95C7D0FB22D5700A3EC78 /* devices.cpp in Sources */, DFF95C7E0FB22D5700A3EC78 /* iterator.cpp in Sources */, - DFF95C7F0FB22D5700A3EC78 /* players.cpp in Sources */, - DFF95C800FB22D5700A3EC78 /* realtime.cpp in Sources */, DFF95C810FB22D5700A3EC78 /* sequencers.cpp in Sources */, DFF95C820FB22D5700A3EC78 /* amiga.cpp in Sources */, - DFF95C830FB22D5700A3EC78 /* opl2.cpp in Sources */, - DFF95C840FB22D5700A3EC78 /* pcspeaker.cpp in Sources */, - DFF95C850FB22D5700A3EC78 /* SN76496.cpp in Sources */, - DFF95C860FB22D5700A3EC78 /* softsequencers.cpp in Sources */, DFF95C870FB22D5700A3EC78 /* songlib.cpp in Sources */, DFF95C880FB22D5700A3EC78 /* unzip.cpp in Sources */, DFF95C890FB22D5700A3EC78 /* console.cpp in Sources */, DFF95C8A0FB22D5700A3EC78 /* exereader.cpp in Sources */, DFF95C8C0FB22D5700A3EC78 /* intmap.cpp in Sources */, - DFF95C8D0FB22D5700A3EC78 /* kdebug.cpp in Sources */, DFF95C8E0FB22D5700A3EC78 /* state.cpp in Sources */, DFF95C8F0FB22D5700A3EC78 /* gfx_widgets.cpp in Sources */, - DFF95C900FB22D5700A3EC78 /* sciconsole.cpp in Sources */, DFF95C910FB22D5700A3EC78 /* exec.cpp in Sources */, DFF95C920FB22D5700A3EC78 /* timer_lol.cpp in Sources */, DFF95C930FB22D5700A3EC78 /* tools.cpp in Sources */, DFF95C940FB22D5700A3EC78 /* sprites_lol.cpp in Sources */, DFF95C950FB22D5700A3EC78 /* script.cpp in Sources */, - DFF95C960FB22D5700A3EC78 /* polled.cpp in Sources */, DFF95C970FB22D5700A3EC78 /* shorten.cpp in Sources */, DFF95C980FB22D5700A3EC78 /* timestamp.cpp in Sources */, DFF95C990FB22D5700A3EC78 /* pn.cpp in Sources */, DFF95C9A0FB22D5700A3EC78 /* script_pn.cpp in Sources */, DFF95C9B0FB22D5700A3EC78 /* vga_pn.cpp in Sources */, - DFF95C9C0FB22D5700A3EC78 /* decompressor.cpp in Sources */, DFF95C9D0FB22D5700A3EC78 /* gfx_resmgr.cpp in Sources */, DFF95C9E0FB22D5700A3EC78 /* palette.cpp in Sources */, DFF95C9F0FB22D5700A3EC78 /* picfill.cpp in Sources */, @@ -9896,9 +9839,6 @@ DFF95CA10FB22D5700A3EC78 /* res_font.cpp in Sources */, DFF95CA20FB22D5700A3EC78 /* res_pal.cpp in Sources */, DFF95CA30FB22D5700A3EC78 /* res_pic.cpp in Sources */, - DFF95CA40FB22D5700A3EC78 /* res_view0.cpp in Sources */, - DFF95CA50FB22D5700A3EC78 /* res_view1.cpp in Sources */, - DFF95CA60FB22D5700A3EC78 /* iff.cpp in Sources */, DFF95CA70FB22D5700A3EC78 /* sound_br.cpp in Sources */, DFF95CA80FB22D5700A3EC78 /* sound_ns.cpp in Sources */, DFF95CA90FB22D5700A3EC78 /* protracker.cpp in Sources */, @@ -9914,12 +9854,42 @@ DFF95CB30FB22D5700A3EC78 /* inter_fascin.cpp in Sources */, DFF95CB40FB22D5700A3EC78 /* script_v3.cpp in Sources */, DFF95CB50FB22D5700A3EC78 /* script_v4.cpp in Sources */, - DFF95CB60FB22D5700A3EC78 /* adlib_sbi.cpp in Sources */, DFF95CB70FB22D5700A3EC78 /* dosbox.cpp in Sources */, - DFF95CB80FB22D5700A3EC78 /* player.cpp in Sources */, DFF95CB90FB22D5700A3EC78 /* adlib.cpp in Sources */, DFF95CBA0FB22D5700A3EC78 /* pcjr.cpp in Sources */, DF7A40350FB6E8960094E50F /* gfx_pixmap_scale.cpp in Sources */, + DF6118360FE3A7D20042AD3F /* res_view.cpp in Sources */, + DF6118370FE3A7D20042AD3F /* seq_decoder.cpp in Sources */, + DF6118400FE3A8080042AD3F /* kmisc.cpp in Sources */, + DF6118410FE3A8080042AD3F /* memobj.cpp in Sources */, + DF61184F0FE3A8250042AD3F /* decompressor.cpp in Sources */, + DF6118500FE3A8250042AD3F /* resource.cpp in Sources */, + DF6118510FE3A8250042AD3F /* vocabulary.cpp in Sources */, + DF6118570FE3A8990042AD3F /* disk.cpp in Sources */, + DF6118700FE3A9410042AD3F /* coktelvideo.cpp in Sources */, + DF6118710FE3A9410042AD3F /* indeo3.cpp in Sources */, + DF6118720FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, + DF6118730FE3A9410042AD3F /* flic_decoder.cpp in Sources */, + DF6118740FE3A9410042AD3F /* smk_decoder.cpp in Sources */, + DF6118A10FE3A9AA0042AD3F /* saveconverter.cpp in Sources */, + DF6118A20FE3A9AA0042AD3F /* saveconverter_v2.cpp in Sources */, + DF6118A30FE3A9AA0042AD3F /* saveconverter_v3.cpp in Sources */, + DF6118A40FE3A9AA0042AD3F /* saveconverter_v4.cpp in Sources */, + DF6118A50FE3A9AA0042AD3F /* saveconverter_v6.cpp in Sources */, + DF6118A60FE3A9AA0042AD3F /* savefile.cpp in Sources */, + DF6118A70FE3A9AA0042AD3F /* savehandler.cpp in Sources */, + DF6118A80FE3A9AA0042AD3F /* saveload.cpp in Sources */, + DF6118A90FE3A9AA0042AD3F /* saveload_v2.cpp in Sources */, + DF6118AA0FE3A9AA0042AD3F /* saveload_v3.cpp in Sources */, + DF6118AB0FE3A9AA0042AD3F /* saveload_v4.cpp in Sources */, + DF6118AC0FE3A9AA0042AD3F /* saveload_v6.cpp in Sources */, + DF6118B10FE3A9EA0042AD3F /* feeble.cpp in Sources */, + DF6118C00FE3AA280042AD3F /* saveload_lol.cpp in Sources */, + DF6118C10FE3AA280042AD3F /* sound_lol.cpp in Sources */, + DF6118C20FE3AA280042AD3F /* sound_pcspk.cpp in Sources */, + DF6118C30FE3AA280042AD3F /* text_lol.cpp in Sources */, + DF6118C90FE3AABD0042AD3F /* player_v2cms.cpp in Sources */, + DF6118D20FE3AB560042AD3F /* mame.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/dists/msvc7/gob.vcproj b/dists/msvc7/gob.vcproj index 144f1c6590..1f74676279 100644 --- a/dists/msvc7/gob.vcproj +++ b/dists/msvc7/gob.vcproj @@ -173,6 +173,24 @@ RelativePath="..\..\engines\gob\demos\batplayer.h"> </File> <File + RelativePath="..\..\engines\gob\resources.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\resources.h"> + </File> + <File + RelativePath="..\..\engines\gob\totfile.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\totfile.h"> + </File> + <File + RelativePath="..\..\engines\gob\script.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\script.h"> + </File> + <File RelativePath="..\..\engines\gob\dataio.cpp"> </File> <File @@ -341,16 +359,10 @@ RelativePath="..\..\engines\gob\palanim.h"> </File> <File - RelativePath="..\..\engines\gob\parse.cpp"> - </File> - <File - RelativePath="..\..\engines\gob\parse.h"> - </File> - <File - RelativePath="..\..\engines\gob\parse_v1.cpp"> + RelativePath="..\..\engines\gob\expression.cpp"> </File> <File - RelativePath="..\..\engines\gob\parse_v2.cpp"> + RelativePath="..\..\engines\gob\expression.h"> </File> <File RelativePath="..\..\engines\gob\save\savefile.h"> diff --git a/dists/msvc7/parallaction.vcproj b/dists/msvc7/parallaction.vcproj index c35daed8fa..a5ded11e4f 100644 --- a/dists/msvc7/parallaction.vcproj +++ b/dists/msvc7/parallaction.vcproj @@ -125,6 +125,9 @@ RelativePath="..\..\engines\parallaction\dialogue.cpp"> </File> <File + RelativePath="..\..\engines\parallaction\disk.cpp"> + </File> + <File RelativePath="..\..\engines\parallaction\disk.h"> </File> <File @@ -170,12 +173,6 @@ RelativePath="..\..\engines\parallaction\gui_ns.cpp"> </File> <File - RelativePath="..\..\engines\parallaction\iff.cpp"> - </File> - <File - RelativePath="..\..\engines\parallaction\iff.h"> - </File> - <File RelativePath="..\..\engines\parallaction\input.cpp"> </File> <File diff --git a/dists/msvc7/scumm.vcproj b/dists/msvc7/scumm.vcproj index c4e0881427..9d8e22eff6 100644 --- a/dists/msvc7/scumm.vcproj +++ b/dists/msvc7/scumm.vcproj @@ -485,6 +485,9 @@ RelativePath="..\..\engines\scumm\player_v2a.h"> </File> <File + RelativePath="..\..\engines\scumm\player_v2cms.cpp"> + </File> + <File RelativePath="..\..\engines\scumm\player_v3a.cpp"> </File> <File diff --git a/dists/msvc7/scummvm.vcproj b/dists/msvc7/scummvm.vcproj index 6a5c03f884..def73f7e59 100644 --- a/dists/msvc7/scummvm.vcproj +++ b/dists/msvc7/scummvm.vcproj @@ -1094,6 +1094,9 @@ RelativePath="..\..\graphics\jpeg.h"> </File> <File + RelativePath="..\..\graphics\pixelformat.h"> + </File> + <File RelativePath="..\..\graphics\primitives.cpp"> </File> <File diff --git a/dists/msvc71/gob.vcproj b/dists/msvc71/gob.vcproj index ba112515a2..bbeef85109 100644 --- a/dists/msvc71/gob.vcproj +++ b/dists/msvc71/gob.vcproj @@ -187,6 +187,24 @@ RelativePath="..\..\engines\gob\demos\batplayer.h"> </File> <File + RelativePath="..\..\engines\gob\resources.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\resources.h"> + </File> + <File + RelativePath="..\..\engines\gob\totfile.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\totfile.h"> + </File> + <File + RelativePath="..\..\engines\gob\script.cpp"> + </File> + <File + RelativePath="..\..\engines\gob\script.h"> + </File> + <File RelativePath="..\..\engines\gob\dataio.cpp"> </File> <File @@ -355,16 +373,10 @@ RelativePath="..\..\engines\gob\palanim.h"> </File> <File - RelativePath="..\..\engines\gob\parse.cpp"> - </File> - <File - RelativePath="..\..\engines\gob\parse.h"> - </File> - <File - RelativePath="..\..\engines\gob\parse_v1.cpp"> + RelativePath="..\..\engines\gob\expression.cpp"> </File> <File - RelativePath="..\..\engines\gob\parse_v2.cpp"> + RelativePath="..\..\engines\gob\expression.h"> </File> <File RelativePath="..\..\engines\gob\save\savefile.h"> diff --git a/dists/msvc71/parallaction.vcproj b/dists/msvc71/parallaction.vcproj index 7e550dfae3..5e57f5e581 100644 --- a/dists/msvc71/parallaction.vcproj +++ b/dists/msvc71/parallaction.vcproj @@ -139,6 +139,9 @@ RelativePath="..\..\engines\parallaction\dialogue.cpp"> </File> <File + RelativePath="..\..\engines\parallaction\disk.cpp"> + </File> + <File RelativePath="..\..\engines\parallaction\disk.h"> </File> <File @@ -184,12 +187,6 @@ RelativePath="..\..\engines\parallaction\gui_ns.cpp"> </File> <File - RelativePath="..\..\engines\parallaction\iff.cpp"> - </File> - <File - RelativePath="..\..\engines\parallaction\iff.h"> - </File> - <File RelativePath="..\..\engines\parallaction\input.cpp"> </File> <File diff --git a/dists/msvc71/scumm.vcproj b/dists/msvc71/scumm.vcproj index 999bab170a..d6b7555c1f 100644 --- a/dists/msvc71/scumm.vcproj +++ b/dists/msvc71/scumm.vcproj @@ -499,6 +499,9 @@ RelativePath="..\..\engines\scumm\player_v2a.h"> </File> <File + RelativePath="..\..\engines\scumm\player_v2cms.cpp"> + </File> + <File RelativePath="..\..\engines\scumm\player_v3a.cpp"> </File> <File diff --git a/dists/msvc71/scummvm.vcproj b/dists/msvc71/scummvm.vcproj index b448d3579e..24f486f7e3 100644 --- a/dists/msvc71/scummvm.vcproj +++ b/dists/msvc71/scummvm.vcproj @@ -1108,6 +1108,9 @@ RelativePath="..\..\graphics\jpeg.h"> </File> <File + RelativePath="..\..\graphics\pixelformat.h"> + </File> + <File RelativePath="..\..\graphics\primitives.cpp"> </File> <File diff --git a/dists/msvc8/gob.vcproj b/dists/msvc8/gob.vcproj index 2b2fca62fc..13bdeb9384 100644 --- a/dists/msvc8/gob.vcproj +++ b/dists/msvc8/gob.vcproj @@ -259,6 +259,30 @@ > </File> <File + RelativePath="..\..\engines\gob\resources.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\resources.h" + > + </File> + <File + RelativePath="..\..\engines\gob\totfile.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\totfile.h" + > + </File> + <File + RelativePath="..\..\engines\gob\script.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\script.h" + > + </File> + <File RelativePath="..\..\engines\gob\dataio.cpp" > </File> @@ -483,19 +507,11 @@ > </File> <File - RelativePath="..\..\engines\gob\parse.cpp" - > - </File> - <File - RelativePath="..\..\engines\gob\parse.h" - > - </File> - <File - RelativePath="..\..\engines\gob\parse_v1.cpp" + RelativePath="..\..\engines\gob\expression.cpp" > </File> <File - RelativePath="..\..\engines\gob\parse_v2.cpp" + RelativePath="..\..\engines\gob\expression.h" > </File> <File diff --git a/dists/msvc8/parallaction.vcproj b/dists/msvc8/parallaction.vcproj index 70cf27bc5a..75b32bbf6e 100644 --- a/dists/msvc8/parallaction.vcproj +++ b/dists/msvc8/parallaction.vcproj @@ -195,6 +195,10 @@ > </File> <File + RelativePath="..\..\engines\parallaction\disk.cpp" + > + </File> + <File RelativePath="..\..\engines\parallaction\disk.h" > </File> @@ -255,14 +259,6 @@ > </File> <File - RelativePath="..\..\engines\parallaction\iff.cpp" - > - </File> - <File - RelativePath="..\..\engines\parallaction\iff.h" - > - </File> - <File RelativePath="..\..\engines\parallaction\input.cpp" > </File> diff --git a/dists/msvc8/scumm.vcproj b/dists/msvc8/scumm.vcproj index 63d7e5ddf3..8cc0ab9719 100644 --- a/dists/msvc8/scumm.vcproj +++ b/dists/msvc8/scumm.vcproj @@ -675,6 +675,10 @@ > </File> <File + RelativePath="..\..\engines\scumm\player_v2cms.cpp" + > + </File> + <File RelativePath="..\..\engines\scumm\player_v3a.cpp" > </File> diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj index 5b75747cbf..d60a904dd6 100644 --- a/dists/msvc8/scummvm.vcproj +++ b/dists/msvc8/scummvm.vcproj @@ -1495,6 +1495,10 @@ > </File> <File + RelativePath="..\..\graphics\pixelformat.h" + > + </File> + <File RelativePath="..\..\graphics\primitives.cpp" > </File> diff --git a/dists/msvc9/gob.vcproj b/dists/msvc9/gob.vcproj index c0c681ed1a..98bc1a935f 100644 --- a/dists/msvc9/gob.vcproj +++ b/dists/msvc9/gob.vcproj @@ -260,6 +260,30 @@ > </File> <File + RelativePath="..\..\engines\gob\resources.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\resources.h" + > + </File> + <File + RelativePath="..\..\engines\gob\totfile.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\totfile.h" + > + </File> + <File + RelativePath="..\..\engines\gob\script.cpp" + > + </File> + <File + RelativePath="..\..\engines\gob\script.h" + > + </File> + <File RelativePath="..\..\engines\gob\dataio.cpp" > </File> @@ -484,19 +508,11 @@ > </File> <File - RelativePath="..\..\engines\gob\parse.cpp" - > - </File> - <File - RelativePath="..\..\engines\gob\parse.h" - > - </File> - <File - RelativePath="..\..\engines\gob\parse_v1.cpp" + RelativePath="..\..\engines\gob\expression.cpp" > </File> <File - RelativePath="..\..\engines\gob\parse_v2.cpp" + RelativePath="..\..\engines\gob\expression.h" > </File> <File diff --git a/dists/msvc9/parallaction.vcproj b/dists/msvc9/parallaction.vcproj index 2f3c921de2..f5fc1cee79 100644 --- a/dists/msvc9/parallaction.vcproj +++ b/dists/msvc9/parallaction.vcproj @@ -196,6 +196,10 @@ > </File> <File + RelativePath="..\..\engines\parallaction\disk.cpp" + > + </File> + <File RelativePath="..\..\engines\parallaction\disk.h" > </File> @@ -256,14 +260,6 @@ > </File> <File - RelativePath="..\..\engines\parallaction\iff.cpp" - > - </File> - <File - RelativePath="..\..\engines\parallaction\iff.h" - > - </File> - <File RelativePath="..\..\engines\parallaction\input.cpp" > </File> diff --git a/dists/msvc9/scumm.vcproj b/dists/msvc9/scumm.vcproj index b41f842412..d9214f7ff0 100644 --- a/dists/msvc9/scumm.vcproj +++ b/dists/msvc9/scumm.vcproj @@ -676,6 +676,10 @@ > </File> <File + RelativePath="..\..\engines\scumm\player_v2cms.cpp" + > + </File> + <File RelativePath="..\..\engines\scumm\player_v3a.cpp" > </File> diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 47e9e842a5..bec6f97ce4 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1494,6 +1494,10 @@ > </File> <File + RelativePath="..\..\graphics\pixelformat.h" + > + </File> + <File RelativePath="..\..\graphics\primitives.cpp" > </File> diff --git a/dists/wii/READMII b/dists/wii/READMII index c0c67eafd7..b9460a9863 100644 --- a/dists/wii/READMII +++ b/dists/wii/READMII @@ -1,9 +1,6 @@ Wii/Gamecube port of ScummVM README ----------------------------------- -features not compiled in: -- the AGI game engine - REQUIREMENTS wii: diff --git a/dists/wii/meta.xml b/dists/wii/meta.xml index fb53474052..f8ccbde5e8 100644 --- a/dists/wii/meta.xml +++ b/dists/wii/meta.xml @@ -2,8 +2,8 @@ <app version="1"> <name>ScummVM</name> <coder>The ScummVM Team</coder> - <version>rev FIXME</version> - <release_date>FIXME</release_date> + <version>0.14.0svn@REVISION@</version> + <release_date>@TIMESTAMP@</release_date> <short_description>Point & Click Adventures</short_description> <long_description>ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed! diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 8b752cac85..c127faec28 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -197,6 +197,8 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription * if (params.flags & kADFlagUseExtraAsHint) desc["extra"] = realDesc->extra; + + desc.setGUIOptions(realDesc->guioptions | params.guioptions); } GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index a33b385d46..c024d560b6 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -63,6 +63,8 @@ struct ADGameDescription { * code. */ uint32 flags; + + uint32 guioptions; }; /** @@ -70,7 +72,7 @@ struct ADGameDescription { * terminate a list to be passed to the AdvancedDetector API. */ #define AD_TABLE_END_MARKER \ - { NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS } + { NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS, Common::GUIO_NONE } struct ADObsoleteGameID { @@ -171,6 +173,13 @@ struct ADParams { * that can be ORed together and passed here. */ uint32 flags; + + /** + * A bitmask of game GUI options which will be added to each + * entry in addition to per-game options. Refer to GameGUIOption + * enum for the list. + */ + uint32 guioptions; }; diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 79ea2a079a..e373dd3e6d 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -23,7 +23,6 @@ * */ - #include "common/md5.h" #include "common/events.h" #include "common/file.h" @@ -104,6 +103,20 @@ void AgiEngine::processEvents() { case Common::EVENT_MOUSEMOVE: g_mouse.x = event.mouse.x; g_mouse.y = event.mouse.y; + + if (!_game.mouseFence.isEmpty()) { + if (g_mouse.x < _game.mouseFence.left) + g_mouse.x = _game.mouseFence.left; + if (g_mouse.x > _game.mouseFence.right) + g_mouse.x = _game.mouseFence.right; + if (g_mouse.y < _game.mouseFence.top) + g_mouse.y = _game.mouseFence.top; + if (g_mouse.y > _game.mouseFence.bottom) + g_mouse.y = _game.mouseFence.bottom; + + g_system->warpMouse(g_mouse.x, g_mouse.y); + } + break; case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONUP: @@ -247,6 +260,11 @@ void AgiEngine::processEvents() { if (key) keyEnqueue(key); break; + + case Common::EVENT_KEYUP: + if (_egoHoldKey) + _game.viewTable[0].direction = 0; + default: break; } @@ -266,12 +284,7 @@ void AgiEngine::checkQuickLoad() { } } -int AgiEngine::agiIsKeypressLow() { - processEvents(); - return _keyQueueStart != _keyQueueEnd; -} - -void AgiEngine::agiTimerLow() { +void AgiEngine::pollTimer(void) { static uint32 m = 0; uint32 dm; @@ -288,16 +301,28 @@ void AgiEngine::agiTimerLow() { m = g_tickTimer; } -int AgiEngine::agiGetKeypressLow() { +bool AgiEngine::isKeypress(void) { + processEvents(); + return _keyQueueStart != _keyQueueEnd; +} + +int AgiEngine::getKeypress(void) { int k; - while (_keyQueueStart == _keyQueueEnd) /* block */ - agiTimerLow(); + while (_keyQueueStart == _keyQueueEnd) // block + pollTimer(); + keyDequeue(k); return k; } +void AgiEngine::clearKeyQueue(void) { + while (isKeypress()) { + getKeypress(); + } +} + void AgiEngine::agiTimerFunctionLow(void *refCon) { g_tickTimer++; } @@ -310,6 +335,19 @@ void AgiEngine::releaseImageStack(void) { _imageStack.clear(); } +void AgiEngine::pause(uint32 msec) { + uint32 endTime = _system->getMillis() + msec; + + _gfx->setCursor(_renderMode == Common::kRenderAmiga, true); + + while (_system->getMillis() < endTime) { + processEvents(); + _system->updateScreen(); + _system->delayMillis(10); + } + _gfx->setCursor(_renderMode == Common::kRenderAmiga); +} + void AgiEngine::recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3, int16 p4, int16 p5, int16 p6, int16 p7) { ImageStackElement pnew; @@ -356,18 +394,18 @@ int AgiEngine::agiInit() { int ec, i; debug(2, "initializing"); - debug(2, "game.ver = 0x%x", _game.ver); + debug(2, "game version = 0x%x", getVersion()); - /* initialize with adj.ego.move.to.x.y(0, 0) so to speak */ + // initialize with adj.ego.move.to.x.y(0, 0) so to speak _game.adjMouseX = _game.adjMouseY = 0; - /* reset all flags to false and all variables to 0 */ + // reset all flags to false and all variables to 0 for (i = 0; i < MAX_FLAGS; i++) _game.flags[i] = 0; for (i = 0; i < MAX_VARS; i++) _game.vars[i] = 0; - /* clear all resources and events */ + // clear all resources and events for (i = 0; i < MAX_DIRS; i++) { memset(&_game.views[i], 0, sizeof(struct AgiView)); memset(&_game.pictures[i], 0, sizeof(struct AgiPicture)); @@ -379,35 +417,33 @@ int AgiEngine::agiInit() { memset(&_game.dirSound[i], 0, sizeof(struct AgiDir)); } - /* clear view table */ + // clear view table for (i = 0; i < MAX_VIEWTABLE; i++) memset(&_game.viewTable[i], 0, sizeof(VtEntry)); initWords(); - restartGame = false; - if (!_menu) _menu = new Menu(this, _gfx, _picture); initPriTable(); - /* clear string buffer */ + // clear string buffer for (i = 0; i < MAX_STRINGS; i++) _game.strings[i][0] = 0; - /* setup emulation */ + // setup emulation - switch (_loader->getIntVersion() >> 12) { + switch (getVersion() >> 12) { case 2: report("Emulating Sierra AGI v%x.%03x\n", - (int)(agiGetRelease() >> 12) & 0xF, - (int)(agiGetRelease()) & 0xFFF); + (int)(getVersion() >> 12) & 0xF, + (int)(getVersion()) & 0xFFF); break; case 3: report("Emulating Sierra AGI v%x.002.%03x\n", - (int)(agiGetRelease() >> 12) & 0xF, - (int)(agiGetRelease()) & 0xFFF); + (int)(getVersion() >> 12) & 0xF, + (int)(getVersion()) & 0xFFF); break; } @@ -427,19 +463,19 @@ int AgiEngine::agiInit() { if (_game.gameFlags & ID_AGDS) report("AGDS mode enabled.\n"); - ec = _loader->init(); /* load vol files, etc */ + ec = _loader->init(); // load vol files, etc if (ec == errOK) ec = _loader->loadObjects(OBJECTS); - /* note: demogs has no words.tok */ + // note: demogs has no words.tok if (ec == errOK) ec = _loader->loadWords(WORDS); - /* FIXME: load IIgs instruments and samples */ - /* load_instruments("kq.sys16"); */ + // FIXME: load IIgs instruments and samples + // load_instruments("kq.sys16"); - /* Load logic 0 into memory */ + // Load logic 0 into memory if (ec == errOK) ec = _loader->loadResource(rLOGIC, 0); @@ -449,6 +485,15 @@ int AgiEngine::agiInit() { loadDict(); #endif + _egoHoldKey = false; + + _game.mouseFence.setWidth(0); // Reset + + _game.lastController = 0; + for (i = 0; i < MAX_DIRS; i++) + _game.controllerOccured[i] = false; + + return ec; } @@ -459,7 +504,7 @@ int AgiEngine::agiInit() { void AgiEngine::agiUnloadResources() { int i; - /* Make sure logic 0 is always loaded */ + // Make sure logic 0 is always loaded for (i = 1; i < MAX_DIRS; i++) { _loader->unloadResource(rLOGIC, i); } @@ -473,8 +518,8 @@ void AgiEngine::agiUnloadResources() { int AgiEngine::agiDeinit() { int ec; - cleanInput(); /* remove all words from memory */ - agiUnloadResources(); /* unload resources in memory */ + cleanInput(); // remove all words from memory + agiUnloadResources(); // unload resources in memory _loader->unloadResource(rLOGIC, 0); ec = _loader->deinit(); unloadObjects(); @@ -500,18 +545,6 @@ int AgiEngine::agiDetectGame() { return ec; } -int AgiEngine::agiVersion() { - return _loader->version(); -} - -int AgiEngine::agiGetRelease() { - return _loader->getIntVersion(); -} - -void AgiEngine::agiSetRelease(int n) { - _loader->setIntVersion(n); -} - int AgiEngine::agiLoadResource(int r, int n) { int i; @@ -616,7 +649,10 @@ AgiButtonStyle::AgiButtonStyle(Common::RenderMode renderMode) { } AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + _noSaveLoadAllowed = false; + initFeatures(); + initVersion(); } AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) { @@ -632,6 +668,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas if (!scumm_stricmp(g->gameid, gameid)) _gameId = g->id; + parseFeatures(); + _rnd = new Common::RandomSource(); syst->getEventManager()->registerRandomSource(*_rnd, "agi"); @@ -664,12 +702,15 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _intobj = NULL; _menu = NULL; + _menuSelected = false; _lastSentence[0] = 0; memset(&_stringdata, 0, sizeof(struct StringData)); _objects = NULL; + _restartGame = false; + _oldMode = -1; _predictiveDialogRunning = false; @@ -688,6 +729,8 @@ void AgiEngine::initialize() { // because Apple IIGS AGI games use only Apple IIGS specific sound resources. if (getPlatform() == Common::kPlatformApple2GS) { _soundemu = SOUND_EMU_APPLE2GS; + } else if (getPlatform() == Common::kPlatformCoCo3) { + _soundemu = SOUND_EMU_COCO3; } else { switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) { case MD_PCSPK: @@ -744,8 +787,6 @@ void AgiEngine::initialize() { _timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL); - _game.ver = -1; /* Don't display the conf file warning */ - debugC(2, kDebugLevelMain, "Detect game"); @@ -804,8 +845,6 @@ Common::Error AgiEngine::go() { do { mainCycle(); } while (_game.state < STATE_RUNNING); - if (_game.ver < 0) - _game.ver = 0; /* Enable conf file warning */ } runGame(); @@ -825,4 +864,45 @@ void AgiEngine::syncSoundSettings() { _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech); } +void AgiEngine::parseFeatures(void) { + if (!ConfMan.hasKey("features")) + return; + + char *features = strdup(ConfMan.get("features").c_str()); + const char *feature[100]; + int numFeatures = 0; + + char *tok = strtok(features, " "); + if (tok) { + do { + feature[numFeatures++] = tok; + } while ((tok = strtok(NULL, " ")) != NULL); + } else { + feature[numFeatures++] = features; + } + + const struct Flags { + const char *name; + uint32 flag; + } flags[] = { + { "agimouse", GF_AGIMOUSE }, + { "agds", GF_AGDS }, + { "agi256", GF_AGI256 }, + { "agi256-2", GF_AGI256_2 }, + { "agipal", GF_AGIPAL }, + { 0, 0 } + }; + + for (int i = 0; i < numFeatures; i++) { + for (const Flags *flag = flags; flag->name; flag++) { + if (!scumm_stricmp(feature[i], flag->name)) { + debug(0, "Added feature: %s", flag->name); + + setFeature(flag->flag); + break; + } + } + } +} + } // End of namespace Agi diff --git a/engines/agi/agi.h b/engines/agi/agi.h index e4461904ed..14e1fd448b 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -42,9 +42,9 @@ namespace Agi { typedef signed int Err; -/* - * Version and other definitions - */ +// +// Version and other definitions +// #define TITLE "AGI engine" @@ -59,13 +59,11 @@ typedef signed int Err; #define MAX_DIRS 256 #define MAX_VARS 256 #define MAX_FLAGS (256 >> 3) -#define MAX_VIEWTABLE 255 /* KQ3 uses o255! */ +#define MAX_VIEWTABLE 255 // KQ3 uses o255! #define MAX_WORDS 20 -#define MAX_STRINGS 24 /* MAX_STRINGS + 1 used for get.num */ +#define MAX_STRINGS 24 // MAX_STRINGS + 1 used for get.num #define MAX_STRINGLEN 40 -#ifndef MAX_PATH -#define MAX_PATH 260 -#endif +#define MAX_CONTROLLERS 39 #define _EMPTY 0xfffff #define EGO_OWNED 0xff @@ -73,20 +71,18 @@ typedef signed int Err; #define CRYPT_KEY_SIERRA "Avis Durgan" #define CRYPT_KEY_AGDS "Alex Simkin" -#ifndef INLINE -#define INLINE -#endif - -#define MSG_BOX_COLOUR 0x0f /* White */ -#define MSG_BOX_TEXT 0x00 /* Black */ -#define MSG_BOX_LINE 0x04 /* Red */ -#define BUTTON_BORDER 0x00 /* Black */ -#define STATUS_FG 0x00 /* Black */ -#define STATUS_BG 0x0f /* White */ +#define MSG_BOX_COLOUR 0x0f // White +#define MSG_BOX_TEXT 0x00 // Black +#define MSG_BOX_LINE 0x04 // Red +#define BUTTON_BORDER 0x00 // Black +#define STATUS_FG 0x00 // Black +#define STATUS_BG 0x0f // White #define ADD_PIC 1 #define ADD_VIEW 2 +#define CMD_BSIZE 12 + enum AgiGameID { GID_AGIDEMO, GID_BC, @@ -113,7 +109,7 @@ enum AgiGameID { } // End of namespace Agi -/* AGI resources */ +// AGI resources #include "agi/console.h" #include "agi/view.h" #include "agi/picture.h" @@ -128,13 +124,13 @@ enum AgiGameType { GType_V3 = 2 }; -/* - * GF_OLDAMIGAV20 means that the interpreter is an old Amiga AGI interpreter that - * uses value 20 for the computer type (v20 i.e. vComputer) rather than the usual value 5. - * - * GF_CLIPCOORDS means that views' coordinates must be clipped at least in commands - * position and position.v. - */ +// +// GF_OLDAMIGAV20 means that the interpreter is an old Amiga AGI interpreter that +// uses value 20 for the computer type (v20 i.e. vComputer) rather than the usual value 5. +// +// GF_CLIPCOORDS means that views' coordinates must be clipped at least in commands +// position and position.v. +// enum AgiGameFeatures { GF_AGIMOUSE = (1 << 0), GF_AGDS = (1 << 1), @@ -216,8 +212,8 @@ struct gameIdList { struct Mouse { int button; - unsigned int x; - unsigned int y; + int x; + int y; }; // Used by AGI Mouse protocol 1.0 for v27 (i.e. button pressed -variable). @@ -241,32 +237,32 @@ enum GameId { * AGI variables. */ enum { - vCurRoom = 0, /* 0 */ + vCurRoom = 0, // 0 vPrevRoom, vBorderTouchEgo, vScore, vBorderCode, - vBorderTouchObj, /* 5 */ + vBorderTouchObj, // 5 vEgoDir, vMaxScore, vFreePages, vWordNotFound, - vTimeDelay, /* 10 */ + vTimeDelay, // 10 vSeconds, vMinutes, vHours, vDays, - vJoystickSensitivity, /* 15 */ + vJoystickSensitivity, // 15 vEgoViewResource, vAgiErrCode, vAgiErrCodeInfo, vKey, - vComputer, /* 20 */ + vComputer, // 20 vWindowReset, vSoundgen, vVolume, vMaxInputChars, - vSelItem, /* 25 */ + vSelItem, // 25 vMonitor }; @@ -315,29 +311,33 @@ enum AgiComputerType { * AGI flags */ enum { - fEgoWater = 0, /* 0 */ + fEgoWater = 0, // 0 fEgoInvisible, fEnteredCli, fEgoTouchedP2, fSaidAcceptedInput, - fNewRoomExec, /* 5 */ + fNewRoomExec, // 5 fRestartGame, fScriptBlocked, fJoySensitivity, fSoundOn, - fDebuggerOn, /* 10 */ + fDebuggerOn, // 10 fLogicZeroFirsttime, fRestoreJustRan, fStatusSelectsItems, fMenusWork, - fOutputMode, /* 15 */ - fAutoRestart, - fNoSaveLoadAllowed + fOutputMode, // 15 + fAutoRestart +}; + +enum AgiSlowliness { + kPauseRoom = 1500, + kPausePicture = 500 }; -struct AgiEvent { - uint16 data; - uint8 occured; +struct AgiController { + uint16 keycode; + uint8 controller; }; struct AgiObject { @@ -355,20 +355,20 @@ struct AgiDir { uint32 offset; uint32 len; uint32 clen; + + // 0 = not in mem, can be freed + // 1 = in mem, can be released + // 2 = not in mem, cant be released + // 3 = in mem, cant be released + // 0x40 = was compressed uint8 flags; - /* 0 = not in mem, can be freed - * 1 = in mem, can be released - * 2 = not in mem, cant be released - * 3 = in mem, cant be released - * 0x40 = was compressed - */ }; struct AgiBlock { int active; int x1, y1; int x2, y2; - uint8 *buffer; /* used for window background */ + uint8 *buffer; // used for window background }; /** AGI text color (Background and foreground color). */ @@ -483,6 +483,11 @@ private: bool _authenticAmiga; ///< Don't use border around buttons in Amiga-style mode. }; +struct ScriptPos { + int script; + int curIP; +}; + #define EGO_VIEW_TABLE 0 #define HORIZON 36 #define _WIDTH 160 @@ -508,11 +513,11 @@ struct AgiGame { char id[8]; /**< game id */ uint32 crc; /**< game CRC */ - /* game flags and variables */ + // game flags and variables uint8 flags[MAX_FLAGS]; /**< 256 1-bit flags */ uint8 vars[MAX_VARS]; /**< 256 variables */ - /* internal variables */ + // internal variables int horizon; /**< horizon y coordinate */ int lineStatus; /**< line number to put status on */ int lineUserInput; /**< line to put user input on */ @@ -528,8 +533,9 @@ struct AgiGame { int inputMode; /**< keyboard input mode */ int inputEnabled; /**< keyboard input enabled */ int lognum; /**< current logic number */ + Common::Array<ScriptPos> execStack; - /* internal flags */ + // internal flags int playerControl; /**< player is in control */ int statusLine; /**< status line on/off */ int clockEnabled; /**< clock is on/off */ @@ -542,13 +548,13 @@ struct AgiGame { uint8 priTable[_HEIGHT];/**< priority table */ - /* windows */ + // windows uint32 msgBoxTicks; /**< timed message box tick counter */ AgiBlock block; AgiBlock window; int hasWindow; - /* graphics & text */ + // graphics & text int gfxMode; char cursorChar; unsigned int colorFg; @@ -562,33 +568,38 @@ struct AgiGame { uint8 *sbuf256c; /**< 160x168 256 color AGI screen buffer (For AGI256 and AGI256-2 support). Points at sbufOrig + SBUF256_OFFSET. */ uint8 *sbuf; /**< Currently chosen AGI screen buffer (sbuf256c if AGI256 or AGI256-2 is used, otherwise sbuf16c). */ - /* player command line */ + // player command line AgiWord egoWords[MAX_WORDS]; int numEgoWords; unsigned int numObjects; - AgiEvent evKeyp[MAX_DIRS]; /**< keyboard keypress events */ + bool controllerOccured[MAX_DIRS]; /**< keyboard keypress events */ + AgiController controllers[MAX_CONTROLLERS]; + int lastController; + char strings[MAX_STRINGS + 1][MAX_STRINGLEN]; /**< strings */ - /* directory entries for resources */ + // directory entries for resources AgiDir dirLogic[MAX_DIRS]; AgiDir dirPic[MAX_DIRS]; AgiDir dirView[MAX_DIRS]; AgiDir dirSound[MAX_DIRS]; - /* resources */ + // resources AgiPicture pictures[MAX_DIRS]; /**< AGI picture resources */ AgiLogic logics[MAX_DIRS]; /**< AGI logic resources */ AgiView views[MAX_DIRS]; /**< AGI view resources */ AgiSound *sounds[MAX_DIRS]; /**< Pointers to AGI sound resources */ - /* view table */ + // view table VtEntry viewTable[MAX_VIEWTABLE]; - int32 ver; /**< detected game version */ + int32 ver; /**< detected game version */ + + int simpleSave; /**< select simple savegames */ - int simpleSave; /**< select simple savegames */ + Common::Rect mouseFence; /**< rectangle set by fence.mouse command */ }; class AgiLoader { @@ -604,14 +615,10 @@ public: virtual int unloadResource(int, int) = 0; virtual int loadObjects(const char *) = 0; virtual int loadWords(const char *) = 0; - virtual int version() = 0; - virtual void setIntVersion(int) = 0; - virtual int getIntVersion() = 0; }; class AgiLoader_v2 : public AgiLoader { private: - int _intVersion; AgiEngine *_vm; int loadDir(AgiDir *agid, const char *fname); @@ -621,7 +628,6 @@ public: AgiLoader_v2(AgiEngine *vm) { _vm = vm; - _intVersion = 0; } virtual int init(); @@ -631,14 +637,10 @@ public: virtual int unloadResource(int, int); virtual int loadObjects(const char *); virtual int loadWords(const char *); - virtual int version(); - virtual void setIntVersion(int); - virtual int getIntVersion(); }; class AgiLoader_v3 : public AgiLoader { private: - int _intVersion; AgiEngine *_vm; int loadDir(AgiDir *agid, Common::File *fp, uint32 offs, uint32 len); @@ -648,7 +650,6 @@ public: AgiLoader_v3(AgiEngine *vm) { _vm = vm; - _intVersion = 0; } virtual int init(); @@ -658,9 +659,6 @@ public: virtual int unloadResource(int, int); virtual int loadObjects(const char *); virtual int loadWords(const char *); - virtual int version(); - virtual void setIntVersion(int); - virtual int getIntVersion(); }; class GfxMgr; @@ -670,7 +668,7 @@ class SearchTree; extern struct Mouse g_mouse; -/* Image stack support */ +// Image stack support struct ImageStackElement { uint8 type; uint8 pad; @@ -721,9 +719,12 @@ public: AgiGame _game; Common::RandomSource *_rnd; - virtual void agiTimerLow() = 0; - virtual int agiGetKeypressLow() = 0; - virtual int agiIsKeypressLow() = 0; + bool _noSaveLoadAllowed; + + virtual void pollTimer(void) = 0; + virtual int getKeypress(void) = 0; + virtual bool isKeypress(void) = 0; + virtual void clearKeyQueue(void) = 0; AgiBase(OSystem *syst, const AGIGameDescription *gameDesc); @@ -743,12 +744,22 @@ public: void flipflag(int); const AGIGameDescription *_gameDescription; + + uint32 _gameFeatures; + uint16 _gameVersion; + uint32 getGameID() const; uint32 getFeatures() const; uint16 getVersion() const; uint16 getGameType() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; + const char *getGameMD5() const; + void initFeatures(void); + void setFeature(uint32 feature); + void initVersion(void); + void setVersion(uint16 version); + Common::Error loadGameState(int slot); Common::Error saveGameState(int slot, const char *desc); bool canLoadGameStateCurrently(); @@ -787,12 +798,12 @@ private: int checkCollision(VtEntry *v); int checkPosition(VtEntry *v); - uint32 matchVersion(uint32 crc); + void parseFeatures(void); int _firstSlot; public: - AgiObject *_objects; /* objects in the game */ + AgiObject *_objects; // objects in the game StringData _stringdata; @@ -808,16 +819,17 @@ public: uint8 *_intobj; int _oldMode; - bool restartGame; + bool _restartGame; Menu* _menu; + bool _menuSelected; char _lastSentence[40]; SpritesMgr *_sprites; SoundMgr *_sound; PictureMgr *_picture; - AgiLoader *_loader; /* loader */ + AgiLoader *_loader; // loader Common::Stack<ImageStackElement> _imageStack; @@ -828,21 +840,22 @@ public: int16 p4, int16 p5, int16 p6, int16 p7); void releaseImageStack(); + void pause(uint32 msec); + Console *_console; int agiInit(); int agiDeinit(); - int agiVersion(); - int agiGetRelease(); - void agiSetRelease(int); int agiDetectGame(); int agiLoadResource(int, int); int agiUnloadResource(int, int); void agiUnloadResources(); - virtual void agiTimerLow(); - virtual int agiGetKeypressLow(); - virtual int agiIsKeypressLow(); + virtual void pollTimer(void); + virtual int getKeypress(void); + virtual bool isKeypress(void); + virtual void clearKeyQueue(void); + static void agiTimerFunctionLow(void *refCon); void initPriTable(); @@ -851,23 +864,17 @@ public: int getvar(int); void setvar(int, int); - void decrypt(uint8 * mem, int len); + void decrypt(uint8 *mem, int len); void releaseSprites(); int mainCycle(); int viewPictures(); - int parseCli(int, char **); int runGame(); void inventory(); - void listGames(); - uint32 matchCrc(uint32, char *, int); - int v2IdGame(); - int v3IdGame(); - int v4IdGame(uint32 ver); void updateTimer(); int getAppDir(char *appDir, unsigned int size); - int setupV2Game(int ver, uint32 crc); - int setupV3Game(int ver, uint32 crc); + int setupV2Game(int ver); + int setupV3Game(int ver); void newRoom(int n); void resetControllers(); @@ -939,6 +946,7 @@ private: void motionFollowEgo(VtEntry *v); void motionMoveObj(VtEntry *v); void checkMotion(VtEntry *v); + public: void checkAllMotions(); void moveObj(VtEntry *); @@ -947,6 +955,8 @@ public: void updatePosition(); int getDirection(int x0, int y0, int x, int y, int s); + bool _egoHoldKey; + // Keyboard void initWords(); void cleanInput(); @@ -977,12 +987,13 @@ public: char *agiSprintf(const char *); void writeStatus(void); void writePrompt(void); + void clearPrompt(void); void clearLines(int, int, int); void flushLines(int, int); bool predictiveDialog(void); private: - void printStatus(const char *message, ...); + void printStatus(const char *message, ...) GCC_PRINTF(2, 3); void printText2(int l, const char *msg, int foff, int xoff, int yoff, int len, int fg, int bg, bool checkerboard = false); void blitTextbox(const char *p, int y, int x, int len); void eraseTextbox(); diff --git a/engines/agi/checks.cpp b/engines/agi/checks.cpp index 38bffca355..afede0b836 100644 --- a/engines/agi/checks.cpp +++ b/engines/agi/checks.cpp @@ -23,7 +23,6 @@ * */ - #include "agi/agi.h" namespace Agi { @@ -41,8 +40,8 @@ int AgiEngine::checkPosition(VtEntry *v) { return 0; } - /* MH1 needs this, but it breaks LSL1 */ - if (agiGetRelease() >= 0x3000) { + // MH1 needs this, but it breaks LSL1 + if (getVersion() >= 0x3000) { if (v->yPos < v->ySize) return 0; } @@ -66,21 +65,21 @@ int AgiEngine::checkCollision(VtEntry *v) { if (u->flags & IGNORE_OBJECTS) continue; - /* Same object, check next */ + // Same object, check next if (v->entry == u->entry) continue; - /* No horizontal overlap, check next */ + // No horizontal overlap, check next if (v->xPos + v->xSize < u->xPos || v->xPos > u->xPos + u->xSize) continue; - /* Same y, return error! */ + // Same y, return error! if (v->yPos == u->yPos) { debugC(4, kDebugLevelSprites, "check returns 1 (object %d)", v->entry); return 1; } - /* Crossed the baseline, return error! */ + // Crossed the baseline, return error! if ((v->yPos > u->yPos && v->yPos2 < u->yPos2) || (v->yPos < u->yPos && v->yPos2 > u->yPos2)) { debugC(4, kDebugLevelSprites, "check returns 1 (object %d)", v->entry); @@ -97,7 +96,7 @@ int AgiEngine::checkPriority(VtEntry *v) { uint8 *p0; if (~v->flags & FIXED_PRIORITY) { - /* Priority bands */ + // Priority bands v->priority = _game.priTable[v->yPos]; } @@ -122,17 +121,17 @@ int AgiEngine::checkPriority(VtEntry *v) { for (i = 0; i < v->xSize; i++, p0++) { pri = *p0 >> 4; - if (pri == 0) { /* unconditional black. no go at all! */ + if (pri == 0) { // unconditional black. no go at all! pass = 0; break; } - if (pri == 3) /* water surface */ + if (pri == 3) // water surface continue; water = 0; - if (pri == 1) { /* conditional blue */ + if (pri == 1) { // conditional blue if (v->flags & IGNORE_BLOCKS) continue; @@ -141,7 +140,7 @@ int AgiEngine::checkPriority(VtEntry *v) { break; } - if (pri == 2) { /* trigger */ + if (pri == 2) { // trigger debugC(4, kDebugLevelSprites, "stepped on trigger"); if (!_debug.ignoretriggers) trigger = 1; @@ -198,7 +197,7 @@ void AgiEngine::updatePosition() { x = oldX = v->xPos; y = oldY = v->yPos; - /* If object has moved, update its position */ + // If object has moved, update its position if (~v->flags & UPDATE_POS) { int dx[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; int dy[9] = { 0, -1, -1, 0, 1, 1, 1, 0, -1 }; @@ -206,18 +205,18 @@ void AgiEngine::updatePosition() { y += v->stepSize * dy[v->direction]; } - /* Now check if it touched the borders */ + // Now check if it touched the borders border = 0; - /* Check left/right borders */ + // Check left/right borders if (x < 0) { x = 0; border = 4; - } else if (x <= 0 && agiGetRelease() == 0x3086) { /* KQ4 */ - x = 0; /* See Sarien bug #590462 */ + } else if (x <= 0 && getVersion() == 0x3086) { // KQ4 + x = 0; // See Sarien bug #590462 border = 4; } else if (v->entry == 0 && x == 0 && v->flags & ADJ_EGO_XY) { - /* Extra test to walk west clicking the mouse */ + // Extra test to walk west clicking the mouse x = 0; border = 4; } else if (x + v->xSize > _WIDTH) { @@ -225,7 +224,7 @@ void AgiEngine::updatePosition() { border = 2; } - /* Check top/bottom borders. */ + // Check top/bottom borders. if (y - v->ySize + 1 < 0) { y = v->ySize - 1; border = 1; @@ -238,7 +237,7 @@ void AgiEngine::updatePosition() { border = 1; } - /* Test new position. rollback if test fails */ + // Test new position. rollback if test fails v->xPos = x; v->yPos = y; if (checkCollision(v) || !checkPriority(v)) { @@ -279,7 +278,7 @@ void AgiEngine::fixPosition(int n) { debugC(4, kDebugLevelSprites, "adjusting view table entry #%d (%d,%d)", n, v->xPos, v->yPos); - /* test horizon */ + // test horizon if ((~v->flags & IGNORE_HORIZON) && v->yPos <= _game.horizon) v->yPos = _game.horizon + 1; @@ -288,26 +287,26 @@ void AgiEngine::fixPosition(int n) { while (!checkPosition(v) || checkCollision(v) || !checkPriority(v)) { switch (dir) { - case 0: /* west */ + case 0: // west v->xPos--; if (--count) continue; dir = 1; break; - case 1: /* south */ + case 1: // south v->yPos++; if (--count) continue; dir = 2; size++; break; - case 2: /* east */ + case 2: // east v->xPos++; if (--count) continue; dir = 3; break; - case 3: /* north */ + case 3: // north v->yPos--; if (--count) continue; diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index 6548772f51..d14a4a13bf 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -52,6 +52,8 @@ Console::Console(AgiEngine *vm) : GUI::Debugger() { DCmd_Register("setvar", WRAP_METHOD(Console, Cmd_SetVar)); DCmd_Register("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); DCmd_Register("setobj", WRAP_METHOD(Console, Cmd_SetObj)); + DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); + DCmd_Register("bt", WRAP_METHOD(Console, Cmd_BT)); } Console::~Console() { @@ -133,7 +135,7 @@ bool Console::Cmd_Crc(int argc, const char **argv) { bool Console::Cmd_Agiver(int argc, const char **argv) { int ver, maj, min; - ver = _vm->agiGetRelease(); + ver = _vm->getVersion(); maj = (ver >> 12) & 0xf; min = ver & 0xfff; @@ -243,6 +245,39 @@ bool Console::Cmd_Cont(int argc, const char **argv) { return true; } +bool Console::Cmd_Room(int argc, const char **argv) { + DebugPrintf("Current room: %d\n", _vm->getvar(0)); + + return true; +} + +bool Console::Cmd_BT(int argc, const char **argv) { + DebugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size()); + + uint8 *code = NULL; + uint8 op = 0; + uint8 p[CMD_BSIZE] = { 0 }; + int num; + Common::Array<ScriptPos>::iterator it; + + for (it = _vm->_game.execStack.begin(); it != _vm->_game.execStack.end(); it++) { + code = _vm->_game.logics[it->script].data; + op = code[it->curIP]; + num = logicNamesCmd[op].numArgs; + memmove(p, &code[it->curIP], num); + memset(p + num, 0, CMD_BSIZE - num); + + DebugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name); + + for (int i = 0; i < num; i++) + DebugPrintf("%d, ", p[i]); + + DebugPrintf(")\n"); + } + + return true; +} + PreAGI_Console::PreAGI_Console(PreAgiEngine *vm) { _vm = vm; } @@ -288,7 +323,7 @@ bool Mickey_Console::Cmd_DrawObj(int argc, const char **argv) { Winnie_Console::Winnie_Console(PreAgiEngine *vm, Winnie *winnie) : PreAGI_Console(vm) { _winnie = winnie; - DCmd_Register("curRoom", WRAP_METHOD(Winnie_Console, Cmd_CurRoom)); + DCmd_Register("curRoom", WRAP_METHOD(Winnie_Console, Cmd_CurRoom)); } bool Winnie_Console::Cmd_CurRoom(int argc, const char **argv) { diff --git a/engines/agi/console.h b/engines/agi/console.h index c435a70188..b75abe2ccd 100644 --- a/engines/agi/console.h +++ b/engines/agi/console.h @@ -71,6 +71,8 @@ private: bool Cmd_Step(int argc, const char **argv); bool Cmd_Debug(int argc, const char **argv); bool Cmd_Cont(int argc, const char **argv); + bool Cmd_Room(int argc, const char **argv); + bool Cmd_BT(int argc, const char **argv); private: AgiEngine *_vm; diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index f3828e00d2..bf4622bc08 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -23,7 +23,6 @@ * */ - #include "agi/agi.h" #include "agi/sprite.h" #include "agi/graphics.h" @@ -41,6 +40,10 @@ void AgiEngine::newRoom(int n) { VtEntry *v; int i; + // Simulate slowww computer. + // Many effects rely on it. + pause(kPauseRoom); + debugC(4, kDebugLevelMain, "*** room %d ***", n); _sound->stopSound(); @@ -68,7 +71,7 @@ void AgiEngine::newRoom(int n) { agiLoadResource(rLOGIC, n); - /* Reposition ego in the new room */ + // Reposition ego in the new room switch (_game.vars[vBorderTouchEgo]) { case 1: _game.viewTable[0].yPos = _HEIGHT - 1; @@ -97,7 +100,7 @@ void AgiEngine::resetControllers() { int i; for (i = 0; i < MAX_DIRS; i++) { - _game.evKeyp[i].occured = false; + _game.controllerOccured[i] = false; } } @@ -115,7 +118,7 @@ void AgiEngine::interpretCycle() { oldSound = getflag(fSoundOn); _game.exitAllLogics = false; - while (runLogic(0) == 0 && !(shouldQuit() || restartGame)) { + while (runLogic(0) == 0 && !(shouldQuit() || _restartGame)) { _game.vars[vWordNotFound] = 0; _game.vars[vBorderTouchObj] = 0; _game.vars[vBorderCode] = 0; @@ -183,25 +186,21 @@ void AgiEngine::oldInputMode() { _game.inputMode = _oldMode; } -/* If main_cycle returns false, don't process more events! */ +// If main_cycle returns false, don't process more events! int AgiEngine::mainCycle() { unsigned int key, kascii; VtEntry *v = &_game.viewTable[0]; - _gfx->pollTimer(); /* msdos driver -> does nothing */ + pollTimer(); updateTimer(); - if (_game.ver == 0) { - messageBox("Warning: game CRC not listed, assuming AGI version 2.917."); - _game.ver = -1; - } - key = doPollKeyboard(); - /* In AGI Mouse emulation mode we must update the mouse-related - * vars in every interpreter cycle. - */ - if (getFeatures() & GF_AGIMOUSE) { + // In AGI Mouse emulation mode we must update the mouse-related + // vars in every interpreter cycle. + // + // We run AGIMOUSE always as a side effect + if (getFeatures() & GF_AGIMOUSE || 1) { _game.vars[28] = g_mouse.x / 2; _game.vars[29] = g_mouse.y; } @@ -220,7 +219,7 @@ int AgiEngine::mainCycle() { key = 0; } - /* Click-to-walk mouse interface */ + // Click-to-walk mouse interface if (_game.playerControl && v->flags & ADJ_EGO_XY) { int toX = v->parm1; int toY = v->parm2; @@ -257,25 +256,24 @@ process_key: break; handleKeys(key); - /* if ESC pressed, activate menu before - * accept.input from the interpreter cycle - * sets the input mode to normal again - * (closes: #540856) - */ + // if ESC pressed, activate menu before + // accept.input from the interpreter cycle + // sets the input mode to normal again + // (closes: #540856) if (key == KEY_ESCAPE) { key = 0; goto process_key; } - /* commented out to close Sarien bug #438872 - * if (key) game.keypress = key; - */ + // commented out to close Sarien bug #438872 + if (key) + _game.keypress = key; } break; case INPUT_GETSTRING: handleController(key); handleGetstring(key); - setvar(vKey, 0); /* clear ENTER key */ + setvar(vKey, 0); // clear ENTER key break; case INPUT_MENU: _menu->keyhandler(key); @@ -299,7 +297,7 @@ int AgiEngine::playGame() { int ec = errOK; debugC(2, kDebugLevelMain, "initializing..."); - debugC(2, kDebugLevelMain, "game.ver = 0x%x", _game.ver); + debugC(2, kDebugLevelMain, "game version = 0x%x", getVersion()); _sound->stopSound(); _gfx->clearScreen(0); @@ -307,10 +305,10 @@ int AgiEngine::playGame() { _game.horizon = HORIZON; _game.playerControl = false; - setflag(fLogicZeroFirsttime, true); /* not in 2.917 */ - setflag(fNewRoomExec, true); /* needed for MUMG and SQ2! */ - setflag(fSoundOn, true); /* enable sound */ - setvar(vTimeDelay, 2); /* "normal" speed */ + setflag(fLogicZeroFirsttime, true); // not in 2.917 + setflag(fNewRoomExec, true); // needed for MUMG and SQ2! + setflag(fSoundOn, true); // enable sound + setvar(vTimeDelay, 2); // "normal" speed _game.gfxMode = true; _game.clockEnabled = true; @@ -365,7 +363,7 @@ int AgiEngine::playGame() { saveGame(getSavegameFilename(0), "Autosave"); } - } while (!(shouldQuit() || restartGame)); + } while (!(shouldQuit() || _restartGame)); _sound->stopSound(); @@ -373,22 +371,19 @@ int AgiEngine::playGame() { } int AgiEngine::runGame() { - int i, ec = errOK; - - for (i = 0; i < MAX_DIRS; i++) - memset(&_game.evKeyp[i], 0, sizeof(struct AgiEvent)); + int ec = errOK; - /* Execute the game */ + // Execute the game do { debugC(2, kDebugLevelMain, "game loop"); - debugC(2, kDebugLevelMain, "game.ver = 0x%x", _game.ver); + debugC(2, kDebugLevelMain, "game version = 0x%x", getVersion()); if (agiInit() != errOK) break; - if (restartGame) { + if (_restartGame) { setflag(fRestartGame, true); - restartGame = false; + _restartGame = false; } // Set computer type (v20 i.e. vComputer) @@ -411,7 +406,7 @@ int AgiEngine::runGame() { break; } - setvar(vSoundgen, 1); /* IBM PC SOUND */ + setvar(vSoundgen, 1); // IBM PC SOUND // Set monitor type (v26 i.e. vMonitor) switch (_renderMode) { @@ -432,7 +427,7 @@ int AgiEngine::runGame() { break; } - setvar(vFreePages, 255); // Set amount of free memory to the maximum value + setvar(vFreePages, 180); // Set amount of free memory to realistic value setvar(vMaxInputChars, 38); _game.inputMode = INPUT_NONE; _game.inputEnabled = 0; @@ -442,7 +437,7 @@ int AgiEngine::runGame() { ec = playGame(); _game.state = STATE_LOADED; agiDeinit(); - } while (restartGame); + } while (_restartGame); delete _menu; _menu = NULL; diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index fd81fc0ca0..910f6e0e55 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -51,7 +51,7 @@ uint32 AgiBase::getGameID() const { } uint32 AgiBase::getFeatures() const { - return _gameDescription->features; + return _gameFeatures; } Common::Platform AgiBase::getPlatform() const { @@ -63,13 +63,33 @@ Common::Language AgiBase::getLanguage() const { } uint16 AgiBase::getVersion() const { - return _gameDescription->version; + return _gameVersion; } uint16 AgiBase::getGameType() const { return _gameDescription->gameType; } +const char *AgiBase::getGameMD5() const { + return _gameDescription->desc.filesDescriptions[0].md5; +} + +void AgiBase::initFeatures(void) { + _gameFeatures = _gameDescription->features; +} + +void AgiBase::setFeature(uint32 feature) { + _gameFeatures |= feature; +} + +void AgiBase::setVersion(uint16 version) { + _gameVersion = version; +} + +void AgiBase::initVersion(void) { + _gameVersion = _gameDescription->version; +} + } static const PlainGameDescriptor agiGames[] = { @@ -107,6 +127,8 @@ static const PlainGameDescriptor agiGames[] = { namespace Agi { +using Common::GUIO_NONE; + #define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ { \ id, \ @@ -114,7 +136,8 @@ namespace Agi { AD_ENTRY1s(fname,md5,size), \ lang, \ platform, \ - ADGF_NO_FLAGS \ + ADGF_NO_FLAGS, \ + GUIO_NONE \ }, \ gid, \ interp, \ @@ -145,6 +168,9 @@ namespace Agi { #define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPN(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) +#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) + #define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) #define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) @@ -199,6 +225,12 @@ static const AGIGameDescription gameDescriptions[] = { // Black Cauldron (PC) 2.10 [AGI 3.002.097] GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC), + // Black Cauldron (CoCo3 360k) [AGI 2.023] + GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + + // Black Cauldron (CoCo3 360k) [AGI 2.072] + GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + // TODO // These aren't supposed to work now as they require unsupported agi engine 2.01 #if 0 @@ -246,7 +278,8 @@ static const AGIGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_GOLDRUSH, GType_V3, @@ -255,6 +288,12 @@ static const AGIGameDescription gameDescriptions[] = { }, + // Gold Rush! (CoCo3 720k) [AGI 2.023] + GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + + // Gold Rush! (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + // King's Quest 1 (Amiga) 1.0U # 2.082 // The original game did not have menus, they are enabled under ScummVM GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga), @@ -273,6 +312,15 @@ static const AGIGameDescription gameDescriptions[] = { // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917] GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1), + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE) GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS), @@ -292,6 +340,15 @@ static const AGIGameDescription gameDescriptions[] = { // King's Quest 2 (Russian) GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC), + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + // King's Quest 3 (Amiga) 1.01 11/8/86 // The original game did not have menus, they are enabled under ScummVM GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga), @@ -326,6 +383,9 @@ static const AGIGameDescription gameDescriptions[] = { // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936] GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3), + // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023] + GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3), + // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086] GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4), @@ -347,6 +407,12 @@ static const AGIGameDescription gameDescriptions[] = { // Menus not tested GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4), + // King's Quest 4 (CoCo3 720k) [AGI 2.023] + GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + + // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440] GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1), @@ -368,6 +434,9 @@ static const AGIGameDescription gameDescriptions[] = { // Leisure Suit Larry 1 (Mac) 1.05 6/26/87 GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh), + // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072] + GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3), + // Manhunter NY (ST) 1.03 10/20/88 GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), @@ -384,6 +453,12 @@ static const AGIGameDescription gameDescriptions[] = { // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102] GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC), + // Manhunter NY (CoCo3 720k) [AGI 2.023] + GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + + // Manhunter NY (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + // Manhunter SF (ST) 1.0 7/29/89 GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), @@ -396,6 +471,12 @@ static const AGIGameDescription gameDescriptions[] = { // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149] GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2), + // Manhunter SF (CoCo3 720k) [AGI 2.023] + GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + + // Manhunter SF (CoCo3 720k) [AGI 2.072] + GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + // Mickey's Space Adventure // Preagi game GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC), @@ -413,11 +494,8 @@ static const AGIGameDescription gameDescriptions[] = { // Mixed-Up Mother Goose (PC) [AGI 2.915] GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), -#if 0 - // Mixed Up Mother Goose (PC) [AGI 2.915] (Broken) - // Menus not tested - GAME("mixedup", "[corrupt/OBJECT from disk 1]", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), -#endif + // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072] + GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3), // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915] GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1), @@ -447,6 +525,12 @@ static const AGIGameDescription gameDescriptions[] = { // not sure about disk format -- dsymonds GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1), + // Police Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + + // Police Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + // Space Quest 1 (ST) 1.1A // The original game did not have menus, they are enabled under ScummVM GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST), @@ -475,6 +559,15 @@ static const AGIGameDescription gameDescriptions[] = { // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917] GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1), + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936] GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2), @@ -493,7 +586,8 @@ static const AGIGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_SQ2, GType_V2, @@ -522,6 +616,12 @@ static const AGIGameDescription gameDescriptions[] = { // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936] GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2), + // Space Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + + // Space Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + // Troll's Tale GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC), @@ -540,6 +640,9 @@ static const AGIGameDescription gameDescriptions[] = { // Xmas Card 1986 (PC) [AGI 2.272] GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD), + // Xmas Card 1986 (CoCo3 360k) [AGI 2.072] + GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3), + FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE), FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"), FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"), @@ -580,6 +683,7 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"), FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"), FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), + FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA), FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"), @@ -601,6 +705,7 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"), FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"), FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"), + FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3), FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"), FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"), FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"), @@ -621,7 +726,8 @@ static const AGIGameDescription gameDescriptions[] = { AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"), Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_FANMADE, GType_V2, @@ -637,7 +743,8 @@ static const AGIGameDescription gameDescriptions[] = { AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_GETOUTTASQ, GType_V2, @@ -734,7 +841,7 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), - FANMADE_IF("serguei1", "(v1.0)", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE), @@ -746,8 +853,10 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"), FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"), + FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3), FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), + FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), @@ -774,11 +883,30 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"), FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"), FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"), + FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3), FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"), FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"), FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"), FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"), FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"), + { + // V - The Graphical Adventure + { + "agi-fanmade", + "V - The Graphical Adventure (Demo 2)", + AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_FANMADE, + GType_V3, + GF_FANMADE, + 0x3149, + }, + FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3), + FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"), FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"), FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"), @@ -797,7 +925,8 @@ static AGIGameDescription g_fallbackDesc = { AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor Common::UNK_LANG, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_FANMADE, GType_V2, @@ -821,7 +950,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI }; } // End of namespace Agi @@ -924,14 +1055,14 @@ SaveStateList AgiMetaEngine::listSaves(const char *target) const { int AgiMetaEngine::getMaximumSaveSlot() const { return 999; } void AgiMetaEngine::removeSaveState(const char *target, int slot) const { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; sprintf(fileName, "%s.%03d", target, slot); g_system->getSavefileManager()->removeSavefile(fileName); } SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const { const uint32 AGIflag = MKID_BE('AGI:'); - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; sprintf(fileName, "%s.%03d", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); @@ -1174,11 +1305,11 @@ Common::Error AgiBase::saveGameState(int slot, const char *desc) { } bool AgiBase::canLoadGameStateCurrently() { - return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !getflag(fNoSaveLoadAllowed)); + return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed); } bool AgiBase::canSaveGameStateCurrently() { - return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !getflag(fNoSaveLoadAllowed)); + return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed && _game.inputEnabled); } } // End of namespace Agi diff --git a/engines/agi/font.h b/engines/agi/font.h index 8d99aa41b5..e24db80bbf 100644 --- a/engines/agi/font.h +++ b/engines/agi/font.h @@ -26,25 +26,23 @@ #ifndef AGI_FONT_H #define AGI_FONT_H - - #include "agi/agi.h" namespace Agi { -/* 8x8 font patterns */ +// 8x8 font patterns static const uint8 curFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, /* cursor hollow */ - 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, /* cursor solid */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cursor empty */ + 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, // cursor hollow + 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, // cursor solid + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cursor empty 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x3C, 0x3C, 0x18, 0xFF, 0xE7, 0x18, 0x3C, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0xEE, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* \n */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // \n 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x08, 0x0C, 0x0A, 0x0A, 0x08, 0x78, 0xF0, 0x00, @@ -161,8 +159,8 @@ static const uint8 curFont[] = { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xE0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xE0, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /*0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, */ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*replacement 0x7F */ + //0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //replacement 0x7F 0x1E, 0x36, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00, 0x7C, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, diff --git a/engines/agi/global.cpp b/engines/agi/global.cpp index 9f38b5d775..ed8e9e8dbe 100644 --- a/engines/agi/global.cpp +++ b/engines/agi/global.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" namespace Agi { @@ -41,16 +39,16 @@ void AgiBase::setflag(int n, int v) { set += n >> 3; if (v) - *set |= 1 << (n & 0x07); /* set bit */ + *set |= 1 << (n & 0x07); // set bit else - *set &= ~(1 << (n & 0x07)); /* clear bit */ + *set &= ~(1 << (n & 0x07)); // clear bit } void AgiBase::flipflag(int n) { uint8 *set = (uint8 *)&_game.flags; set += n >> 3; - *set ^= 1 << (n & 0x07); /* flip bit */ + *set ^= 1 << (n & 0x07); // flip bit } void AgiEngine::setvar(int var, int val) { diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp index a4554919de..ad2c264184 100644 --- a/engines/agi/graphics.cpp +++ b/engines/agi/graphics.cpp @@ -505,22 +505,22 @@ static const uint8 vgaPalette[256 * 3] = { }; static const uint16 cgaMap[16] = { - 0x0000, /* 0 - black */ - 0x0d00, /* 1 - blue */ - 0x0b00, /* 2 - green */ - 0x0f00, /* 3 - cyan */ - 0x000b, /* 4 - red */ - 0x0b0d, /* 5 - magenta */ - 0x000d, /* 6 - brown */ - 0x0b0b, /* 7 - gray */ - 0x0d0d, /* 8 - dark gray */ - 0x0b0f, /* 9 - light blue */ - 0x0b0d, /* 10 - light green */ - 0x0f0d, /* 11 - light cyan */ - 0x0f0d, /* 12 - light red */ - 0x0f00, /* 13 - light magenta */ - 0x0f0b, /* 14 - yellow */ - 0x0f0f /* 15 - white */ + 0x0000, // 0 - black + 0x0d00, // 1 - blue + 0x0b00, // 2 - green + 0x0f00, // 3 - cyan + 0x000b, // 4 - red + 0x0b0d, // 5 - magenta + 0x000d, // 6 - brown + 0x0b0b, // 7 - gray + 0x0d0d, // 8 - dark gray + 0x0b0f, // 9 - light blue + 0x0b0d, // 10 - light green + 0x0f0d, // 11 - light cyan + 0x0f0d, // 12 - light red + 0x0f00, // 13 - light magenta + 0x0f0b, // 14 - yellow + 0x0f0f // 15 - white }; struct UpdateBlock { @@ -540,22 +540,22 @@ GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) { } -/* - * Layer 4: 640x480? ================== User display - * ^ - * | do_update(), put_block() - * | - * Layer 3: 640x480? ================== Framebuffer - * ^ - * | flush_block(), put_pixels() - * | - * Layer 2: 320x200 ================== AGI engine screen (console), put_pixel() - * | - * Layer 1: 160x336 ================== AGI screen - * - * Upper half (160x168) of Layer 1 is for the normal 16 color & control line/priority info. - * Lower half (160x168) of Layer 1 is for the 256 color information (Used with AGI256 & AGI256-2). - */ +// +// Layer 4: 640x480? ================== User display +// ^ +// | do_update(), put_block() +// | +// Layer 3: 640x480? ================== Framebuffer +// ^ +// | flush_block(), put_pixels() +// | +// Layer 2: 320x200 ================== AGI engine screen (console), put_pixel() +// | +// Layer 1: 160x336 ================== AGI screen +// +// Upper half (160x168) of Layer 1 is for the normal 16 color & control line/priority info. +// Lower half (160x168) of Layer 1 is for the 256 color information (Used with AGI256 & AGI256-2). +// #define SHAKE_MAG 3 @@ -638,9 +638,8 @@ void GfxMgr::putTextCharacter(int l, int x, int y, unsigned char c, int fg, int _agiScreen[xx + yy * GFX_WIDTH] = 15; } - /* FIXME: we don't want this when we're writing on the - * console! - */ + // FIXME: we don't want this when we're writing on the + // console! flushBlock(x, y, x + CHAR_COLS - 1, y + CHAR_LINES - 1); } @@ -670,16 +669,16 @@ void GfxMgr::drawFrame(int x1, int y1, int x2, int y2, int c1, int c2) { int y, w; uint8 *p0; - /* top line */ + // top line w = x2 - x1 + 1; p0 = &_agiScreen[x1 + y1 * GFX_WIDTH]; memset(p0, c1, w); - /* bottom line */ + // bottom line p0 = &_agiScreen[x1 + y2 * GFX_WIDTH]; memset(p0, c2, w); - /* side lines */ + // side lines for (y = y1; y <= y2; y++) { _agiScreen[x1 + y * GFX_WIDTH] = c1; _agiScreen[x2 + y * GFX_WIDTH] = c2; @@ -791,18 +790,6 @@ void GfxMgr::putScreen() { putBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); } -void GfxMgr::pollTimer() { - _vm->agiTimerLow(); -} - -int GfxMgr::getKey() { - return _vm->agiGetKeypressLow(); -} - -int GfxMgr::keypress() { - return _vm->agiIsKeypressLow(); -} - /* * Public functions */ @@ -890,7 +877,7 @@ int GfxMgr::getAGIPalFileNum() { return _agipalFileNum; } -/* put a block onto the screen */ +// put a block onto the screen void GfxMgr::gfxPutBlock(int x1, int y1, int x2, int y2) { if (x1 >= GFX_WIDTH) x1 = GFX_WIDTH - 1; @@ -1014,7 +1001,14 @@ static const byte busyAmigaMouseCursor[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1 }; -void GfxMgr::setCursor(bool amigaStyleCursor) { +void GfxMgr::setCursor(bool amigaStyleCursor, bool busy) { + if (busy) { + CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4); + CursorMan.replaceCursor(busyAmigaMouseCursor, 13, 16, 7, 8, 0); + + return; + } + if (!amigaStyleCursor) { CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4); CursorMan.replaceCursor(sciMouseCursor, 11, 16, 1, 1, 0); @@ -1151,11 +1145,13 @@ void GfxMgr::doUpdate() { gfxPutBlock(update.x1, update.y1, update.x2, update.y2); } - /* reset update block variables */ + // reset update block variables update.x1 = MAX_INT; update.y1 = MAX_INT; update.x2 = 0; update.y2 = 0; + + g_system->updateScreen(); } /** @@ -1206,6 +1202,9 @@ void GfxMgr::flushBlockA(int x1, int y1, int x2, int y2) { */ void GfxMgr::flushScreen() { flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); + + doUpdate(); + g_system->updateScreen(); } /** diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h index 2965dd0da3..05e59c8851 100644 --- a/engines/agi/graphics.h +++ b/engines/agi/graphics.h @@ -92,13 +92,10 @@ public: void putBlock(int x1, int y1, int x2, int y2); void gfxSetPalette(); - void setCursor(bool amigaStyleCursor = false); + void setCursor(bool amigaStyleCursor = false, bool busy = false); void setCursorPalette(bool amigaStylePalette = false); - int keypress(); - int getKey(); void printCharacter(int, int, char, int, int); - void pollTimer(); int initMachine(); int deinitMachine(); }; diff --git a/engines/agi/id.cpp b/engines/agi/id.cpp index 1ce665d900..a3ab335441 100644 --- a/engines/agi/id.cpp +++ b/engines/agi/id.cpp @@ -30,51 +30,24 @@ namespace Agi { -int AgiEngine::v2IdGame() { - int ver; - - ver = getVersion(); - _game.ver = ver; - debugC(2, kDebugLevelMain, "game.ver = 0x%x", _game.ver); - agiSetRelease(ver); - - return setupV2Game(ver, 0); -} - -/* - * Currently, there is no known difference between v3.002.098 -> v3.002.149 - * So version emulated; - * - * 0x0086, - * 0x0149 - */ - -int AgiEngine::v3IdGame() { - int ver; - - ver = getVersion(); - _game.ver = ver; - debugC(2, kDebugLevelMain, "game.ver = 0x%x", _game.ver); - agiSetRelease(ver); - - return setupV3Game(ver, 0); -} +// +// Currently, there is no known difference between v3.002.098 -> v3.002.149 +// So version emulated; +// +// 0x0086, +// 0x0149 +// /** * */ -int AgiEngine::setupV2Game(int ver, uint32 crc) { +int AgiEngine::setupV2Game(int ver) { int ec = errOK; - if (ver == 0) { - report("Unknown v2 Sierra game: %08x\n\n", crc); - agiSetRelease(ver = 0x2917); - } - // Should this go above the previous lines, so we can force emulation versions // even for AGDS games? -- dsymonds if (getFeatures() & GF_AGDS) - agiSetRelease(ver = 0x2440); /* ALL AGDS games built for 2.440 */ + setVersion(ver = 0x2440); // ALL AGDS games built for 2.440 report("Setting up for version 0x%04X\n", ver); @@ -96,14 +69,9 @@ int AgiEngine::setupV2Game(int ver, uint32 crc) { /** * */ -int AgiEngine::setupV3Game(int ver, uint32 crc) { +int AgiEngine::setupV3Game(int ver) { int ec = errOK; - if (ver == 0) { - report("Unknown v3 Sierra game: %08x\n\n", crc); - agiSetRelease(ver = 0x3149); - } - report("Setting up for version 0x%04X\n", ver); // 'unknown176' takes 1 arg for 3.002.086, not 0 args. diff --git a/engines/agi/inv.cpp b/engines/agi/inv.cpp index e1b864c2b5..dad1548cd9 100644 --- a/engines/agi/inv.cpp +++ b/engines/agi/inv.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" #include "agi/sprite.h" #include "agi/graphics.h" @@ -32,9 +30,9 @@ namespace Agi { -/* - * Messages and coordinates - */ +// +// Messages and coordinates +// #define NOTHING_X 16 #define NOTHING_Y 3 @@ -92,7 +90,7 @@ int AgiEngine::showItems() { for (x = i = 0; x < _game.numObjects; x++) { if (objectGetLocation(x) == EGO_OWNED) { - /* add object to our list! */ + // add object to our list! _intobj[i] = x; printItem(i, STATUS_FG, STATUS_BG); i++; @@ -182,7 +180,7 @@ void AgiEngine::inventory() { int oldFg, oldBg; int n; - /* screen is white with black text */ + // screen is white with black text oldFg = _game.colorFg; oldBg = _game.colorBg; _game.colorFg = 0; @@ -198,7 +196,7 @@ void AgiEngine::inventory() { break; } - /* FIXME: doesn't check if objects overflow off screen... */ + // FIXME: doesn't check if objects overflow off screen... _intobj = (uint8 *)malloc(4 + _game.numObjects); memset(_intobj, 0, (4 + _game.numObjects)); @@ -224,10 +222,9 @@ void AgiEngine::inventory() { _gfx->flushScreen(); - /* If flag 13 is set, we want to highlight & select an item. - * opon selection, put objnum in var 25. Then on esc put in - * var 25 = 0xff. - */ + // If flag 13 is set, we want to highlight & select an item. + // opon selection, put objnum in var 25. Then on esc put in + // var 25 = 0xff. if (getflag(fStatusSelectsItems)) selectItems(n); diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 3bbdc95192..6604587051 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -35,36 +35,36 @@ namespace Agi { -/* - * IBM-PC keyboard scancodes - */ +// +// IBM-PC keyboard scancodes +// uint8 scancodeTable[26] = { - 30, /* A */ - 48, /* B */ - 46, /* C */ - 32, /* D */ - 18, /* E */ - 33, /* F */ - 34, /* G */ - 35, /* H */ - 23, /* I */ - 36, /* J */ - 37, /* K */ - 38, /* L */ - 50, /* M */ - 49, /* N */ - 24, /* O */ - 25, /* P */ - 16, /* Q */ - 19, /* R */ - 31, /* S */ - 20, /* T */ - 22, /* U */ - 47, /* V */ - 17, /* W */ - 45, /* X */ - 21, /* Y */ - 44 /* Z */ + 30, // A + 48, // B + 46, // C + 32, // D + 18, // E + 33, // F + 34, // G + 35, // H + 23, // I + 36, // J + 37, // K + 38, // L + 50, // M + 49, // N + 24, // O + 25, // P + 16, // Q + 19, // R + 31, // S + 20, // T + 22, // U + 47, // V + 17, // W + 45, // X + 21, // Y + 44 // Z }; void AgiEngine::initWords() { @@ -93,9 +93,9 @@ void AgiEngine::getString(int x, int y, int len, int str) { int AgiEngine::doPollKeyboard() { int key = 0; - /* If a key is ready, rip it */ - if (_gfx->keypress()) { - key = _gfx->getKey(); + // If a key is ready, rip it + if (isKeypress()) { + key = getKeypress(); debugC(3, kDebugLevelInput, "key %02x pressed", key); } @@ -110,20 +110,21 @@ int AgiEngine::handleController(int key) { // AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus // Games with the GF_ESCPAUSE flag need KEY_ESCAPE to pause the game if (key == 0 || - (key == KEY_ESCAPE && agiGetRelease() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) ) + (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) ) return false; if ((getGameID() == GID_MH1 || getGameID() == GID_MH2) && (key == KEY_ENTER) && - (_game.inputMode == INPUT_NONE)) + (_game.inputMode == INPUT_NONE)) { key = 0x20; // Set Enter key to Space in Manhunter when there's no text input + } debugC(3, kDebugLevelInput, "key = %04x", key); - for (i = 0; i < MAX_DIRS; i++) { - if (_game.evKeyp[i].data == key) { - debugC(3, kDebugLevelInput, "event %d: key press", i); - _game.evKeyp[i].occured = true; - report("event AC:%i occured\n", i); + for (i = 0; i < _game.lastController; i++) { + if (_game.controllers[i].keycode == key) { + debugC(3, kDebugLevelInput, "event %d: key press", _game.controllers[i].controller); + _game.controllerOccured[_game.controllers[i].controller] = true; + report("event AC:%i occured\n", _game.controllers[i].controller); return true; } } @@ -184,7 +185,7 @@ int AgiEngine::handleController(int key) { } if (!(getFeatures() & GF_AGIMOUSE)) { - /* Handle mouse button events */ + // Handle mouse button events if (key == BUTTON_LEFT) { v->flags |= ADJ_EGO_XY; v->parm1 = WIN_TO_PIC_X(g_mouse.x); @@ -205,7 +206,7 @@ int AgiEngine::handleController(int key) { } void AgiEngine::handleGetstring(int key) { - static int pos = 0; /* Cursor position */ + static int pos = 0; // Cursor position static char buf[40]; if (KEY_ASCII(key) == 0) @@ -230,9 +231,11 @@ void AgiEngine::handleGetstring(int key) { debugC(3, kDebugLevelInput, "KEY_ENTER"); _game.hasPrompt = 0; buf[pos] = 0; + strcpy(_game.strings[_stringdata.str], buf); debugC(3, kDebugLevelInput, "buffer=[%s]", buf); buf[pos = 0] = 0; + newInputMode(INPUT_NORMAL); _gfx->printCharacter(_stringdata.x + strlen(_game.strings[_stringdata.str]) + 1, _stringdata.y, ' ', _game.colorFg, _game.colorBg); @@ -241,11 +244,13 @@ void AgiEngine::handleGetstring(int key) { debugC(3, kDebugLevelInput, "KEY_ESCAPE"); _game.hasPrompt = 0; buf[pos = 0] = 0; + strcpy(_game.strings[_stringdata.str], buf); newInputMode(INPUT_NORMAL); - /* newInputMode(INPUT_MENU); */ + + // newInputMode(INPUT_MENU); break; - case KEY_BACKSPACE: /*0x08: */ + case KEY_BACKSPACE: // 0x08 if (!pos) break; @@ -264,14 +269,14 @@ void AgiEngine::handleGetstring(int key) { buf[pos++] = key; buf[pos] = 0; - /* Echo */ + // Echo _gfx->printCharacter(_stringdata.x + pos, _stringdata.y, buf[pos - 1], _game.colorFg, _game.colorBg); break; } - /* print cursor */ + // print cursor _gfx->printCharacter(_stringdata.x + pos + 1, _stringdata.y, (char)_game.cursorChar, _game.colorFg, _game.colorBg); } @@ -293,13 +298,13 @@ void AgiEngine::handleKeys(int key) { debugC(3, kDebugLevelInput, "KEY_ENTER"); _game.keypress = 0; - /* Remove all leading spaces */ + // Remove all leading spaces for (p = _game.inputBuffer; *p && *p == 0x20; p++) ; - /* Copy to internal buffer */ + // Copy to internal buffer for (; *p; p++) { - /* Squash spaces */ + // Squash spaces if (*p == 0x20 && *(p + 1) == 0x20) { p++; continue; @@ -308,14 +313,14 @@ void AgiEngine::handleKeys(int key) { } formattedEntry[c++] = 0; - /* Handle string only if it's not empty */ + // Handle string only if it's not empty if (formattedEntry[0]) { strcpy((char *)_game.echoBuffer, (const char *)_game.inputBuffer); strcpy(_lastSentence, (const char *)formattedEntry); dictionaryWords(_lastSentence); } - /* Clear to start a new line */ + // Clear to start a new line _game.hasPrompt = 0; _game.inputBuffer[_game.cursorPos = 0] = 0; debugC(3, kDebugLevelInput, "clear lines"); @@ -331,14 +336,15 @@ void AgiEngine::handleKeys(int key) { newInputMode(INPUT_MENU); break; case KEY_BACKSPACE: - /* Ignore backspace at start of line */ + // Ignore backspace at start of line if (_game.cursorPos == 0) break; - /* erase cursor */ + // erase cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, ' ', fg, bg); _game.inputBuffer[--_game.cursorPos] = 0; - /* Print cursor */ + + // Print cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, _game.cursorChar, fg, bg); #ifdef __DS__ @@ -346,11 +352,11 @@ void AgiEngine::handleKeys(int key) { #endif break; default: - /* Ignore invalid keystrokes */ + // Ignore invalid keystrokes if (key < 0x20 || key > 0x7f) break; - /* Maximum input size reached */ + // Maximum input size reached if (_game.cursorPos >= getvar(vMaxInputChars)) break; @@ -361,10 +367,10 @@ void AgiEngine::handleKeys(int key) { DS::findWordCompletions((char *) _game.inputBuffer); #endif - /* echo */ + // echo _gfx->printCharacter(_game.cursorPos + promptLength - 1, l, _game.inputBuffer[_game.cursorPos - 1], fg, bg); - /* Print cursor */ + // Print cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, _game.cursorChar, fg, bg); break; } @@ -373,19 +379,16 @@ void AgiEngine::handleKeys(int key) { int AgiEngine::waitKey() { int key = 0; - /* clear key queue */ - while (_gfx->keypress()) { - _gfx->getKey(); - } + clearKeyQueue(); debugC(3, kDebugLevelInput, "waiting..."); - while (!(shouldQuit() || restartGame || getflag(fRestoreJustRan))) { - _gfx->pollTimer(); /* msdos driver -> does nothing */ + while (!(shouldQuit() || _restartGame || getflag(fRestoreJustRan))) { + pollTimer(); key = doPollKeyboard(); if (key == KEY_ENTER || key == KEY_ESCAPE || key == BUTTON_LEFT) break; - _gfx->pollTimer(); + pollTimer(); updateTimer(); _gfx->doUpdate(); @@ -396,14 +399,11 @@ int AgiEngine::waitKey() { int AgiEngine::waitAnyKey() { int key = 0; - /* clear key queue */ - while (_gfx->keypress()) { - _gfx->getKey(); - } + clearKeyQueue(); debugC(3, kDebugLevelInput, "waiting... (any key)"); - while (!(shouldQuit() || restartGame)) { - _gfx->pollTimer(); /* msdos driver -> does nothing */ + while (!(shouldQuit() || _restartGame)) { + pollTimer(); key = doPollKeyboard(); if (key) break; diff --git a/engines/agi/keyboard.h b/engines/agi/keyboard.h index 5a96364acd..bc1706b280 100644 --- a/engines/agi/keyboard.h +++ b/engines/agi/keyboard.h @@ -26,8 +26,6 @@ #ifndef AGI_KEYBOARD_H #define AGI_KEYBOARD_H - - namespace Agi { #define keyEnqueue(k) do { _keyQueue[_keyQueueEnd++] = (k); \ @@ -51,10 +49,10 @@ public: } }; -/* QNX4 has a KEY_DOWN defined which we don't need to care about */ +// QNX4 has a KEY_DOWN defined which we don't need to care about #undef KEY_DOWN -/* Allegro defines these */ +// Allegro defines these #undef KEY_BACKSPACE #undef KEY_ENTER #undef KEY_LEFT @@ -79,24 +77,24 @@ public: #define KEY_UP_LEFT 0x4700 #define KEY_UP_RIGHT 0x4900 -#define KEY_STATUSLN 0xd900 /* F11 */ -#define KEY_PRIORITY 0xda00 /* F12 */ +#define KEY_STATUSLN 0xd900 // F11 +#define KEY_PRIORITY 0xda00 // F12 -#define KEY_PGUP 0x4900 /* Page Up (fixed by Ziv Barber) */ -#define KEY_PGDN 0x5100 /* Page Down */ -#define KEY_HOME 0x4700 /* Home */ -#define KEY_END 0x4f00 /* End * */ +#define KEY_PGUP 0x4900 // Page Up (fixed by Ziv Barber) +#define KEY_PGDN 0x5100 // Page Down +#define KEY_HOME 0x4700 // Home +#define KEY_END 0x4f00 // End * -#define BUTTON_LEFT 0xF101 /* Left mouse button */ -#define BUTTON_RIGHT 0xF202 /* Right mouse button */ -#define WHEEL_UP 0xF203 /* Mouse wheel up */ -#define WHEEL_DOWN 0xF204 /* Mouse wheel down */ +#define BUTTON_LEFT 0xF101 // Left mouse button +#define BUTTON_RIGHT 0xF202 // Right mouse button +#define WHEEL_UP 0xF203 // Mouse wheel up +#define WHEEL_DOWN 0xF204 // Mouse wheel down #define KEY_SCAN(k) (k >> 8) #define KEY_ASCII(k) (k & 0xff) extern uint8 scancodeTable[]; -} // End of namespace Agi +} // End of namespace Agi #endif /* AGI_KEYBOARD_H */ diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index 2ace4e7e6b..4ad1c6bf93 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -29,18 +29,6 @@ namespace Agi { -int AgiLoader_v2::version() { - return 2; -} - -void AgiLoader_v2::setIntVersion(int ver) { - _intVersion = ver; -} - -int AgiLoader_v2::getIntVersion() { - return _intVersion; -} - int AgiLoader_v2::detectGame() { if (!Common::File::exists(LOGDIR) || !Common::File::exists(PICDIR) || @@ -48,8 +36,7 @@ int AgiLoader_v2::detectGame() { !Common::File::exists(VIEWDIR)) return errInvalidAGIFile; - _intVersion = 0x2917; /* setup for 2.917 */ - return _vm->v2IdGame(); + return _vm->setupV2Game(_vm->getVersion()); } int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) { @@ -75,13 +62,13 @@ int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) { fp.read(mem, flen); - /* set all directory resources to gone */ + // set all directory resources to gone for (i = 0; i < MAX_DIRS; i++) { agid[i].volume = 0xff; agid[i].offset = _EMPTY; } - /* build directory entries */ + // build directory entries for (i = 0; i < flen; i += 3) { agid[i / 3].volume = *(mem + i) >> 4; agid[i / 3].offset = READ_BE_UINT24(mem + i) & (uint32) _EMPTY; @@ -97,7 +84,7 @@ int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) { int AgiLoader_v2::init() { int ec = errOK; - /* load directory files */ + // load directory files ec = loadDir(_vm->_game.dirLogic, LOGDIR); if (ec == errOK) ec = loadDir(_vm->_game.dirPic, PICDIR); @@ -113,10 +100,10 @@ int AgiLoader_v2::deinit() { int ec = errOK; #if 0 - /* unload words */ + // unload words agiV2UnloadWords(); - /* unload objects */ + // unload objects agiV2UnloadObjects(); #endif @@ -144,14 +131,14 @@ int AgiLoader_v2::unloadResource(int t, int n) { return errOK; } -/* +/** * This function does noting but load a raw resource into memory, * if further decoding is required, it must be done by another * routine. NULL is returned if unsucsessfull. */ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { uint8 *data = NULL; - char x[MAX_PATH], *path; + char x[MAXPATHLEN], *path; Common::File fp; unsigned int sig; @@ -178,15 +165,15 @@ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { } fp.close(); } else { - /* we have a bad volume resource */ - /* set that resource to NA */ + // we have a bad volume resource + // set that resource to NA agid->offset = _EMPTY; } return data; } -/* +/** * Loads a resource into memory, a raw resource is loaded in * with above routine, then further decoded here. */ @@ -204,7 +191,7 @@ int AgiLoader_v2::loadResource(int t, int n) { debugC(3, kDebugLevelResources, "loading logic resource %d", n); unloadResource(rLOGIC, n); - /* load raw resource into data */ + // load raw resource into data data = loadVolRes(&_vm->_game.dirLogic[n]); _vm->_game.logics[n].data = data; @@ -213,22 +200,21 @@ int AgiLoader_v2::loadResource(int t, int n) { _vm->_game.logics[n].sIP = 2; } - /* if logic was cached, we get here */ - /* reset code pointers incase it was cached */ + // if logic was cached, we get here + // reset code pointers incase it was cached _vm->_game.logics[n].cIP = _vm->_game.logics[n].sIP; break; case rPICTURE: - /* if picture is currently NOT loaded *OR* cacheing is off, - * unload the resource (caching == off) and reload it - */ + // if picture is currently NOT loaded *OR* cacheing is off, + // unload the resource (caching == off) and reload it debugC(3, kDebugLevelResources, "loading picture resource %d", n); if (_vm->_game.dirPic[n].flags & RES_LOADED) break; - /* if loaded but not cached, unload it */ - /* if cached but not loaded, etc */ + // if loaded but not cached, unload it + // if cached but not loaded, etc unloadResource(rPICTURE, n); data = loadVolRes(&_vm->_game.dirPic[n]); @@ -255,11 +241,10 @@ int AgiLoader_v2::loadResource(int t, int n) { } break; case rVIEW: - /* Load a VIEW resource into memory... - * Since VIEWS alter the view table ALL the time - * can we cache the view? or must we reload it all - * the time? - */ + // Load a VIEW resource into memory... + // Since VIEWS alter the view table ALL the time + // can we cache the view? or must we reload it all + // the time? if (_vm->_game.dirView[n].flags & RES_LOADED) break; diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index e784dad323..9f38a05775 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -31,18 +31,6 @@ namespace Agi { -int AgiLoader_v3::version() { - return 3; -} - -void AgiLoader_v3::setIntVersion(int ver) { - _intVersion = ver; -} - -int AgiLoader_v3::getIntVersion() { - return _intVersion; -} - int AgiLoader_v3::detectGame() { int ec = errUnk; bool found = false; @@ -64,8 +52,8 @@ int AgiLoader_v3::detectGame() { memset(_vm->_game.name, 0, 8); strncpy(_vm->_game.name, f.c_str(), MIN((uint)8, f.size() > 5 ? f.size() - 5 : f.size())); debugC(3, kDebugLevelMain, "game.name = %s", _vm->_game.name); - _intVersion = 0x3149; // setup for 3.002.149 - ec = _vm->v3IdGame(); + + ec = _vm->setupV3Game(_vm->getVersion()); found = true; } @@ -89,13 +77,13 @@ int AgiLoader_v3::loadDir(struct AgiDir *agid, Common::File *fp, if ((mem = (uint8 *)malloc(len + 32)) != NULL) { fp->read(mem, len); - /* set all directory resources to gone */ + // set all directory resources to gone for (i = 0; i < MAX_DIRS; i++) { agid[i].volume = 0xff; agid[i].offset = _EMPTY; } - /* build directory entries */ + // build directory entries for (i = 0; i < len; i += 3) { agid[i / 3].volume = *(mem + i) >> 4; agid[i / 3].offset = READ_BE_UINT24(mem + i) & (uint32) _EMPTY; @@ -136,7 +124,7 @@ int AgiLoader_v3::init() { printf("Failed to open \"%s\"\n", path.c_str()); return errBadFileOpen; } - /* build offset table for v3 directory format */ + // build offset table for v3 directory format fp.read(&xd, 8); fp.seek(0, SEEK_END); @@ -153,7 +141,7 @@ int AgiLoader_v3::init() { fp.seek(0, SEEK_SET); - /* read in directory files */ + // read in directory files ec = loadDir(_vm->_game.dirLogic, &fp, agiVol3[0].sddr, agiVol3[0].len); if (ec == errOK) { @@ -175,10 +163,10 @@ int AgiLoader_v3::deinit() { int ec = errOK; #if 0 - /* unload words */ + // unload words agiV3UnloadWords(); - /* unload objects */ + // unload objects agiV3UnloadObjects(); #endif @@ -204,7 +192,7 @@ int AgiLoader_v3::unloadResource(int t, int n) { return errOK; } -/* +/** * This function does noting but load a raw resource into memory. * If further decoding is required, it must be done by another * routine. @@ -212,7 +200,7 @@ int AgiLoader_v3::unloadResource(int t, int n) { * NULL is returned if unsucsessful. */ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { - char x[MAX_PATH]; + char x[MAXPATHLEN]; uint8 *data = NULL, *compBuffer; Common::File fp; Common::String path; @@ -234,28 +222,27 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { _vm->quitGame(); } - agid->len = READ_LE_UINT16((uint8 *) x + 3); /* uncompressed size */ - agid->clen = READ_LE_UINT16((uint8 *) x + 5); /* compressed len */ + agid->len = READ_LE_UINT16((uint8 *) x + 3); // uncompressed size + agid->clen = READ_LE_UINT16((uint8 *) x + 5); // compressed len compBuffer = (uint8 *)calloc(1, agid->clen + 32); fp.read(compBuffer, agid->clen); if (x[2] & 0x80 || agid->len == agid->clen) { - /* do not decompress */ + // do not decompress data = compBuffer; #if 0 - /* CM: added to avoid problems in - * convert_v2_v3_pic() when clen > len - * e.g. Sierra demo 4, first picture - * (Tue Mar 16 13:13:43 EST 1999) - */ + // CM: added to avoid problems in + // convert_v2_v3_pic() when clen > len + // e.g. Sierra demo 4, first picture + // (Tue Mar 16 13:13:43 EST 1999) agid->len = agid->clen; - /* Now removed to fix Gold Rush! in demo4 */ + // Now removed to fix Gold Rush! in demo4 #endif } else { - /* it is compressed */ + // it is compressed data = (uint8 *)calloc(1, agid->len + 32); lzwExpand(compBuffer, data, agid->len); free(compBuffer); @@ -264,15 +251,15 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { fp.close(); } else { - /* we have a bad volume resource */ - /* set that resource to NA */ + // we have a bad volume resource + // set that resource to NA agid->offset = _EMPTY; } return data; } -/* +/** * Loads a resource into memory, a raw resource is loaded in * with above routine, then further decoded here. */ @@ -285,42 +272,40 @@ int AgiLoader_v3::loadResource(int t, int n) { switch (t) { case rLOGIC: - /* load resource into memory, decrypt messages at the end - * and build the message list (if logic is in memory) - */ + // load resource into memory, decrypt messages at the end + // and build the message list (if logic is in memory) if (~_vm->_game.dirLogic[n].flags & RES_LOADED) { - /* if logic is already in memory, unload it */ + // if logic is already in memory, unload it unloadResource(rLOGIC, n); - /* load raw resource into data */ + // load raw resource into data data = loadVolRes(&_vm->_game.dirLogic[n]); _vm->_game.logics[n].data = data; - /* uncompressed logic files need to be decrypted */ + // uncompressed logic files need to be decrypted if (data != NULL) { - /* resloaded flag gets set by decode logic */ - /* needed to build string table */ + // resloaded flag gets set by decode logic + // needed to build string table ec = _vm->decodeLogic(n); _vm->_game.logics[n].sIP = 2; } else { ec = errBadResource; } - /*logics[n].sIP=2; *//* saved IP = 2 */ - /*logics[n].cIP=2; *//* current IP = 2 */ + // logics[n].sIP=2; // saved IP = 2 + // logics[n].cIP=2; // current IP = 2 _vm->_game.logics[n].cIP = _vm->_game.logics[n].sIP; } - /* if logic was cached, we get here */ - /* reset code pointers incase it was cached */ + // if logic was cached, we get here + // reset code pointers incase it was cached _vm->_game.logics[n].cIP = _vm->_game.logics[n].sIP; break; case rPICTURE: - /* if picture is currently NOT loaded *OR* cacheing is off, - * unload the resource (caching==off) and reload it - */ + // if picture is currently NOT loaded *OR* cacheing is off, + // unload the resource (caching==off) and reload it if (~_vm->_game.dirPic[n].flags & RES_LOADED) { unloadResource(rPICTURE, n); data = loadVolRes(&_vm->_game.dirPic[n]); @@ -347,11 +332,11 @@ int AgiLoader_v3::loadResource(int t, int n) { } break; case rVIEW: - /* Load a VIEW resource into memory... - * Since VIEWS alter the view table ALL the time can we - * cache the view? or must we reload it all the time? - */ - /* load a raw view from a VOL file into data */ + // Load a VIEW resource into memory... + // Since VIEWS alter the view table ALL the time can we + // cache the view? or must we reload it all the time? + // + // load a raw view from a VOL file into data if (_vm->_game.dirView[n].flags & RES_LOADED) break; diff --git a/engines/agi/logic.cpp b/engines/agi/logic.cpp index 4d7cc330c9..cc61d3455a 100644 --- a/engines/agi/logic.cpp +++ b/engines/agi/logic.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" namespace Agi { @@ -40,52 +38,50 @@ int AgiEngine::decodeLogic(int n) { int mstart, mend, mc; uint8 *m0; - /* decrypt messages at end of logic + build message list */ + // decrypt messages at end of logic + build message list - /* report ("decoding logic #%d\n", n); */ + // report ("decoding logic #%d\n", n); m0 = _game.logics[n].data; mstart = READ_LE_UINT16(m0) + 2; mc = *(m0 + mstart); mend = READ_LE_UINT16(m0 + mstart + 1); - m0 += mstart + 3; /* cover header info */ + m0 += mstart + 3; // cover header info mstart = mc << 1; - /* if the logic was not compressed, decrypt the text messages - * only if there are more than 0 messages - */ + // if the logic was not compressed, decrypt the text messages + // only if there are more than 0 messages if ((~_game.dirLogic[n].flags & RES_COMPRESSED) && mc > 0) - decrypt(m0 + mstart, mend - mstart); /* decrypt messages */ + decrypt(m0 + mstart, mend - mstart); // decrypt messages - /* build message list */ + // build message list m0 = _game.logics[n].data; - mstart = READ_LE_UINT16(m0) + 2; /* +2 covers pointer */ + mstart = READ_LE_UINT16(m0) + 2; // +2 covers pointer _game.logics[n].numTexts = *(m0 + mstart); - /* resetp logic pointers */ + // resetp logic pointers _game.logics[n].sIP = 2; _game.logics[n].cIP = 2; - _game.logics[n].size = READ_LE_UINT16(m0) + 2; /* logic end pointer */ + _game.logics[n].size = READ_LE_UINT16(m0) + 2; // logic end pointer - /* allocate list of pointers to point into our data */ + // allocate list of pointers to point into our data _game.logics[n].texts = (const char **)calloc(1 + _game.logics[n].numTexts, sizeof(char *)); - /* cover header info */ + // cover header info m0 += mstart + 3; if (_game.logics[n].texts != NULL) { - /* move list of strings into list to make real pointers */ + // move list of strings into list to make real pointers for (mc = 0; mc < _game.logics[n].numTexts; mc++) { mend = READ_LE_UINT16(m0 + mc * 2); _game.logics[n].texts[mc] = mend ? (const char *)m0 + mend - 2 : (const char *)""; } - /* set loaded flag now its all completly loaded */ + // set loaded flag now its all completly loaded _game.dirLogic[n].flags |= RES_LOADED; } else { - /* unload data - * Note that not every logic has text - */ + // unload data + // Note that not every logic has text free(_game.logics[n].data); ec = errNotEnoughMemory; } @@ -108,7 +104,7 @@ void AgiEngine::unloadLogic(int n) { _game.dirLogic[n].flags &= ~RES_LOADED; } - /* if cached, we end up here */ + // if cached, we end up here _game.logics[n].sIP = 2; _game.logics[n].cIP = 2; } diff --git a/engines/agi/lzw.cpp b/engines/agi/lzw.cpp index a101ebb9f6..bc2f169322 100644 --- a/engines/agi/lzw.cpp +++ b/engines/agi/lzw.cpp @@ -41,21 +41,21 @@ namespace Agi { #define MAXBITS 12 -#define TABLE_SIZE 18041 /* strange number */ +#define TABLE_SIZE 18041 // strange number #define START_BITS 9 static int32 BITS, MAX_VALUE, MAX_CODE; static uint32 *prefixCode; static uint8 *appendCharacter; static uint8 *decodeStack; -static int32 inputBitCount = 0; /* Number of bits in input bit buffer */ +static int32 inputBitCount = 0; // Number of bits in input bit buffer static uint32 inputBitBuffer = 0L; static void initLZW() { decodeStack = (uint8 *)calloc(1, 8192); prefixCode = (uint32 *)malloc(TABLE_SIZE * sizeof(uint32)); appendCharacter = (uint8 *)malloc(TABLE_SIZE * sizeof(uint8)); - inputBitCount = 0; /* Number of bits in input bit buffer */ + inputBitCount = 0; // Number of bits in input bit buffer inputBitBuffer = 0L; } @@ -141,18 +141,18 @@ void lzwExpand(uint8 *in, uint8 *out, int32 len) { initLZW(); - setBits(START_BITS); /* Starts at 9-bits */ - lzwnext = 257; /* Next available code to define */ + setBits(START_BITS); // Starts at 9-bits + lzwnext = 257; // Next available code to define end = (uint8 *)(out + (uint32)len); - lzwold = inputCode(&in); /* Read in the first code */ + lzwold = inputCode(&in); // Read in the first code c = lzwold; lzwnew = inputCode(&in); while ((out < end) && (lzwnew != 0x101)) { if (lzwnew == 0x100) { - /* Code to "start over" */ + // Code to "start over" lzwnext = 258; setBits(START_BITS); lzwold = inputCode(&in); @@ -161,15 +161,14 @@ void lzwExpand(uint8 *in, uint8 *out, int32 len) { lzwnew = inputCode(&in); } else { if (lzwnew >= lzwnext) { - /* Handles special LZW scenario */ + // Handles special LZW scenario *decodeStack = c; s = decodeString(decodeStack + 1, lzwold); } else s = decodeString(decodeStack, lzwnew); - /* Reverse order of decoded string and - * store in out buffer - */ + // Reverse order of decoded string and + // store in out buffer c = *s; while (s >= decodeStack) *out++ = *s--; diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp index 916c4c184f..27e234ebc9 100644 --- a/engines/agi/menu.cpp +++ b/engines/agi/menu.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" #include "agi/sprite.h" #include "agi/graphics.h" @@ -66,6 +64,7 @@ AgiMenu *Menu::getMenu(int i) { AgiMenuOption *Menu::getMenuOption(int i, int j) { AgiMenu *m = getMenu(i); MenuOptionList::iterator iter; + for (iter = m->down.begin(); iter != m->down.end(); ++iter) { AgiMenuOption* d = *iter; if (d->index == j) @@ -82,6 +81,7 @@ void Menu::drawMenuBar() { MenuList::iterator iter; for (iter = _menubar.begin(); iter != _menubar.end(); ++iter) { AgiMenu *m = *iter; + _vm->printText(m->text, 0, m->col, 0, 40, MENU_FG, MENU_BG); } @@ -89,22 +89,26 @@ void Menu::drawMenuBar() { void Menu::drawMenuHilite(int curMenu) { AgiMenu *m = getMenu(curMenu); + debugC(6, kDebugLevelMenu, "[%s]", m->text); + _vm->printText(m->text, 0, m->col, 0, 40, MENU_BG, MENU_FG); _vm->flushLines(0, 0); } -/* draw box and pulldowns. */ +// draw box and pulldowns. void Menu::drawMenuOption(int hMenu) { - /* find which vertical menu it is */ + // find which vertical menu it is AgiMenu *m = getMenu(hMenu); _gfx->drawBox(m->wincol * CHAR_COLS, 1 * CHAR_LINES, (m->wincol + m->width + 2) * CHAR_COLS, (1 + m->height + 2) * CHAR_LINES, MENU_BG, MENU_LINE, 0); MenuOptionList::iterator iter; + for (iter = m->down.begin(); iter != m->down.end(); ++iter) { AgiMenuOption* d = *iter; + _vm->printText(d->text, 0, m->wincol + 1, d->index + 2, m->width + 2, MENU_FG, MENU_BG, !d->enabled); } @@ -127,11 +131,11 @@ void Menu::newMenuSelected(int i) { drawMenuOption(i); } -bool Menu::mouseOverText(unsigned int line, unsigned int col, char *s) { +bool Menu::mouseOverText(int line, int col, char *s) { if (g_mouse.x < col * CHAR_COLS) return false; - if (g_mouse.x > (col + strlen(s)) * CHAR_COLS) + if (g_mouse.x > (int)(col + strlen(s)) * CHAR_COLS) return false; if (g_mouse.y < line * CHAR_LINES) @@ -180,17 +184,24 @@ Menu::~Menu() { MenuList::iterator iterh; for (iterh = _menubar.reverse_begin(); iterh != _menubar.end(); ) { AgiMenu *m = *iterh; + debugC(3, kDebugLevelMenu, "deiniting hmenu %s", m->text); + MenuOptionList::iterator iterv; + for (iterv = m->down.reverse_begin(); iterv != m->down.end(); ) { AgiMenuOption *d = *iterv; + debugC(3, kDebugLevelMenu, " deiniting vmenu %s", d->text); + free(d->text); delete d; + iterv = m->down.reverse_erase(iterv); } free(m->text); delete m; + iterh = _menubar.reverse_erase(iterh); } } @@ -198,8 +209,10 @@ Menu::~Menu() { void Menu::add(const char *s) { AgiMenu *m = new AgiMenu; m->text = strdup(s); + while (m->text[strlen(m->text) - 1] == ' ') m->text[strlen(m->text) - 1] = 0; + m->width = 0; m->height = 0; m->index = _hIndex++; @@ -218,6 +231,7 @@ void Menu::addItem(const char *s, int code) { int l; AgiMenuOption* d = new AgiMenuOption; + d->text = strdup(s); d->enabled = true; d->event = code; @@ -239,22 +253,26 @@ void Menu::addItem(const char *s, int code) { m->width = l; debugC(3, kDebugLevelMenu, "Adding menu item: %s (size = %d)", s, m->height); + m->down.push_back(d); } void Menu::submit() { debugC(3, kDebugLevelMenu, "Submitting menu"); - /* add_about_option (); */ + // add_about_option (); - /* If a menu has no options, delete it */ + // If a menu has no options, delete it MenuList::iterator iter; for (iter = _menubar.reverse_begin(); iter != _menubar.end(); ) { AgiMenu *m = *iter; + if (m->down.empty()) { free(m->text); delete m; + _hMaxMenu--; + iter = _menubar.reverse_erase(iter); } else { --iter; @@ -275,20 +293,23 @@ bool Menu::keyhandler(int key) { _vm->_game.clockEnabled = false; drawMenuBar(); } - /* - * Mouse handling - */ + // + // Mouse handling + // if (g_mouse.button) { int hmenu, vmenu; - buttonUsed = 1; /* Button has been used at least once */ + buttonUsed = 1; // Button has been used at least once + if (g_mouse.y <= CHAR_LINES) { - /* on the menubar */ + // on the menubar hmenu = 0; MenuList::iterator iterh; + for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) { AgiMenu *m = *iterh; + if (mouseOverText(0, m->col, m->text)) { break; } else { @@ -304,13 +325,16 @@ bool Menu::keyhandler(int key) { _hCurMenu = hmenu; } } else { - /* not in menubar */ + // not in menubar vmenu = 0; AgiMenu *m = getMenu(_hCurMenu); + MenuOptionList::iterator iterv; + for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) { AgiMenuOption *do1 = *iterv; + if (mouseOverText(2 + do1->index, m->wincol + 1, do1->text)) { break; } else { @@ -327,7 +351,7 @@ bool Menu::keyhandler(int key) { } } } else if (buttonUsed) { - /* Button released */ + // Button released buttonUsed = 0; debugC(6, kDebugLevelMenu | kDebugLevelInput, "button released!"); @@ -338,25 +362,22 @@ bool Menu::keyhandler(int key) { drawMenuOptionHilite(_hCurMenu, _vCurMenu); if (g_mouse.y <= CHAR_LINES) { - /* on the menubar */ + // on the menubar } else { - /* see which option we selected */ + // see which option we selected AgiMenu *m = getMenu(_hCurMenu); MenuOptionList::iterator iterv; + for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) { AgiMenuOption *d = *iterv; + if (mouseOverText(2 + d->index, m->wincol + 1, d->text)) { - /* activate that option */ + // activate that option if (d->enabled) { debugC(6, kDebugLevelMenu | kDebugLevelInput, "event %d registered", d->event); - _vm->_game.evKeyp[d->event].occured = true; - _vm->_game.evKeyp[d->event].data = d->event; - // In LSL1, event 0x20 is set when changing the game speed to normal via the menu - // Do not set the event data to 0x20, as this event is then incorrectly triggered - // when the spacebar is pressed, which has a keycode equal to 0x20 as well - // Fixes bug #1751390 - "LSL: after changing game speed, space key turn unfunctional" - if (d->event == 0x20) - _vm->_game.evKeyp[d->event].data = d->event + 1; + _vm->_game.controllerOccured[d->event] = true; + _vm->_menuSelected = true; + goto exit_menu; } } @@ -383,9 +404,10 @@ bool Menu::keyhandler(int key) { { debugC(6, kDebugLevelMenu | kDebugLevelInput, "KEY_ENTER"); AgiMenuOption* d = getMenuOption(_hCurMenu, _vCurMenu); + if (d->enabled) { debugC(6, kDebugLevelMenu | kDebugLevelInput, "event %d registered", d->event); - _vm->_game.evKeyp[d->event].occured = true; + _vm->_game.controllerOccured[d->event] = true; goto exit_menu; } break; @@ -428,6 +450,7 @@ exit_menu: _vm->_game.keypress = 0; _vm->_game.clockEnabled = clockVal; _vm->oldInputMode(); + debugC(3, kDebugLevelMenu, "exit_menu: input mode reset to %d", _vm->_game.inputMode); menuActive = false; @@ -435,15 +458,18 @@ exit_menu: } void Menu::setItem(int event, int state) { - /* scan all menus for event number # */ + // scan all menus for event number # debugC(6, kDebugLevelMenu, "event = %d, state = %d", event, state); MenuList::iterator iterh; + for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) { AgiMenu *m = *iterh; MenuOptionList::iterator iterv; + for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) { AgiMenuOption *d = *iterv; + if (d->event == event) { d->enabled = state; // keep going; we need to set the state of every menu item @@ -458,8 +484,10 @@ void Menu::enableAll() { for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) { AgiMenu *m = *iterh; MenuOptionList::iterator iterv; + for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) { AgiMenuOption *d = *iterv; + d->enabled = true; } } diff --git a/engines/agi/menu.h b/engines/agi/menu.h index d27dfa497d..43f6dd2bbd 100644 --- a/engines/agi/menu.h +++ b/engines/agi/menu.h @@ -30,11 +30,11 @@ namespace Agi { -#define MENU_BG 0x0f /* White */ -#define MENU_DISABLED 0x07 /* Grey */ +#define MENU_BG 0x0f // White +#define MENU_DISABLED 0x07 // Grey -#define MENU_FG 0x00 /* Black */ -#define MENU_LINE 0x00 /* Black */ +#define MENU_FG 0x00 // Black +#define MENU_LINE 0x00 // Black struct AgiMenu; struct AgiMenuOption; @@ -80,7 +80,7 @@ private: void drawMenuOption(int hMenu); void drawMenuOptionHilite(int hMenu, int vMenu); void newMenuSelected(int i); - bool mouseOverText(unsigned int line, unsigned int col, char *s); + bool mouseOverText(int line, int col, char *s); }; diff --git a/engines/agi/motion.cpp b/engines/agi/motion.cpp index 58d4eb4a6d..214ebccddd 100644 --- a/engines/agi/motion.cpp +++ b/engines/agi/motion.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" namespace Agi { @@ -76,7 +74,7 @@ void AgiEngine::motionWander(VtEntry *v) { if (isEgoView(v)) { _game.vars[vEgoDir] = v->direction; while (v->parm1 < 6) { - v->parm1 = _rnd->getRandomNumber(50); /* huh? */ + v->parm1 = _rnd->getRandomNumber(50); // huh? } } } @@ -92,10 +90,10 @@ void AgiEngine::motionFollowEgo(VtEntry *v) { objX = v->xPos + v->xSize / 2; objY = v->yPos; - /* Get direction to reach ego */ + // Get direction to reach ego dir = getDirection(objX, objY, egoX, egoY, v->parm1); - /* Already at ego coordinates */ + // Already at ego coordinates if (dir == 0) { v->direction = 0; v->motion = MOTION_NORMAL; @@ -126,12 +124,12 @@ void AgiEngine::motionFollowEgo(VtEntry *v) { if (v->parm3 != 0) { int k; - /* DF: this is ugly and I dont know why this works, but - * other line does not! (watcom complained about lvalue) - * - * if (((int8)v->parm3 -= v->step_size) < 0) - * v->parm3 = 0; - */ + // DF: this is ugly and I dont know why this works, but + // other line does not! (watcom complained about lvalue) + // + // if (((int8)v->parm3 -= v->step_size) < 0) + // v->parm3 = 0; + k = v->parm3; k -= v->stepSize; v->parm3 = k; @@ -146,7 +144,7 @@ void AgiEngine::motionFollowEgo(VtEntry *v) { void AgiEngine::motionMoveObj(VtEntry *v) { v->direction = getDirection(v->xPos, v->yPos, v->parm1, v->parm2, v->stepSize); - /* Update V6 if ego */ + // Update V6 if ego if (isEgoView(v)) _game.vars[vEgoDir] = v->direction; diff --git a/engines/agi/objects.cpp b/engines/agi/objects.cpp index eb33259b82..6897c4d4d3 100644 --- a/engines/agi/objects.cpp +++ b/engines/agi/objects.cpp @@ -44,9 +44,8 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) { _game.numObjects = 0; _objects = NULL; - /* check if first pointer exceeds file size - * if so, its encrypted, else it is not - */ + // check if first pointer exceeds file size + // if so, its encrypted, else it is not if (READ_LE_UINT16(mem) > flen) { report("Decrypting objects... "); @@ -54,11 +53,10 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) { report("done.\n"); } - /* alloc memory for object list - * byte 3 = number of animated objects. this is ignored.. ?? - */ + // alloc memory for object list + // byte 3 = number of animated objects. this is ignored.. ?? if (READ_LE_UINT16(mem) / padsize >= 256) { - /* die with no error! AGDS game needs not to die to work!! :( */ + // die with no error! AGDS game needs not to die to work!! :( return errOK; } @@ -68,7 +66,7 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) { if (allocObjects(_game.numObjects) != errOK) return errNotEnoughMemory; - /* build the object list */ + // build the object list for (i = 0, so = padsize; i < _game.numObjects; i++, so += padsize) { int offset; diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index 1ac8ec5ce3..97255097bc 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -57,7 +57,7 @@ namespace Agi { static struct AgiLogic *curLogic; static AgiEngine *g_agi; -int timerHack; /* Workaround for timer loop in MH1 */ +int timerHack; // Workaround for timer loop in MH1 #define _v game.vars #define cmd(x) static void cmd_##x (uint8 *p) @@ -291,7 +291,7 @@ cmd(release_priority) { vt.flags &= ~FIXED_PRIORITY; } -cmd(set_upper_left) { /* do nothing (AGI 2.917) */ +cmd(set_upper_left) { // do nothing (AGI 2.917) } cmd(start_update) { @@ -497,23 +497,23 @@ cmd(load_game) { game.simpleSave ? g_agi->loadGameSimple() : g_agi->loadGameDialog(); } -cmd(init_disk) { /* do nothing */ +cmd(init_disk) { // do nothing } -cmd(log) { /* do nothing */ +cmd(log) { // do nothing } -cmd(trace_on) { /* do nothing */ +cmd(trace_on) { // do nothing } -cmd(trace_info) { /* do nothing */ +cmd(trace_info) { // do nothing } cmd(show_mem) { g_agi->messageBox("Enough memory"); } -cmd(init_joy) { /* do nothing */ ; +cmd(init_joy) { // do nothing } cmd(script_size) { @@ -521,7 +521,8 @@ cmd(script_size) { } cmd(cancel_line) { - report("cancel.line\n"); + g_agi->_game.inputBuffer[0] = 0; + g_agi->writePrompt(); } // This implementation is based on observations of Amiga's Gold Rush. @@ -535,8 +536,6 @@ cmd(cancel_line) { // 471 (When walking on the first screen's bridge), // 71 (When walking around, using the mouse or the keyboard). cmd(obj_status_f) { - report("obj.status.f\n"); - const char *cycleDesc; // Object's cycle description line const char *motionDesc; // Object's motion description line char msg[256]; // The whole object status message @@ -600,15 +599,14 @@ cmd(obj_status_f) { g_agi->messageBox(msg); } -/* unknown commands: - * unk_170: Force savegame name -- j5 - * unk_171: script save -- j5 - * unk_172: script restore -- j5 - * unk_173: Activate keypressed control (ego only moves while key is pressed) - * unk_174: Change priority table (used in KQ4) -- j5 - * unk_177: Disable menus completely -- j5 - * unk_181: Deactivate keypressed control (default control of ego) - */ +// unknown commands: +// unk_170: Force savegame name -- j5 +// unk_171: script save -- j5 +// unk_172: script restore -- j5 +// unk_173: Activate keypressed control (ego only moves while key is pressed) +// unk_174: Change priority table (used in KQ4) -- j5 +// unk_177: Disable menus completely -- j5 +// unk_181: Deactivate keypressed control (default control of ego) cmd(set_simple) { if (!(g_agi->getFeatures() & (GF_AGI256 | GF_AGI256_2))) { game.simpleSave = true; @@ -627,50 +625,63 @@ cmd(set_simple) { cmd_close_window(NULL); g_picture->showPic(); game.pictureShown = 1; + + // Simulate slowww computer. Many effects rely on this + g_agi->pause(kPausePicture); } } cmd(pop_script) { - report("pop.script\n"); + if (g_agi->getVersion() >= 0x2915) { + report("pop.script\n"); + } } cmd(hold_key) { - report("hold.key\n"); + if (g_agi->getVersion() >= 0x3098) { + g_agi->_egoHoldKey = true; + } } cmd(discard_sound) { - report("discard.sound\n"); + if (g_agi->getVersion() >= 0x2936) { + report("discard.sound\n"); + } } cmd(hide_mouse) { - report("hide.mouse\n"); - - if (g_agi->getPlatform() == Common::kPlatformAmiga && g_agi->getGameID() == GID_GOLDRUSH) { - // WORKAROUND: Turns off current movement that's being caused with the mouse. - // This fixes problems with too many popup boxes appearing in the Amiga - // Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192). - // Previously multiple popup boxes appeared one after another if you tried - // to walk somewhere else than to the right using the mouse. - // FIXME: Write a proper implementation using disassembly and - // apply it to other games as well if applicable. - game.viewTable[0].flags &= ~ADJ_EGO_XY; - } + // WORKAROUND: Turns off current movement that's being caused with the mouse. + // This fixes problems with too many popup boxes appearing in the Amiga + // Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192). + // Previously multiple popup boxes appeared one after another if you tried + // to walk somewhere else than to the right using the mouse. + // FIXME: Write a proper implementation using disassembly and + // apply it to other games as well if applicable. + game.viewTable[0].flags &= ~ADJ_EGO_XY; + + g_system->showMouse(false); } cmd(allow_menu) { - report("allow.menu\n"); + if (g_agi->getVersion() >= 0x3098) { + g_agi->setflag(fMenusWork, ((p0 != 0) ? true : false)); + } } cmd(show_mouse) { - report("show.mouse\n"); + g_system->showMouse(true); } cmd(fence_mouse) { - report("fence.mouse\n"); + g_agi->_game.mouseFence.moveTo(p0, p1); + g_agi->_game.mouseFence.setWidth(p2 - p0); + g_agi->_game.mouseFence.setHeight(p3 - p1); } cmd(release_key) { - report("release.key\n"); + if (g_agi->getVersion() >= 0x3098) { + g_agi->_egoHoldKey = false; + } } cmd(adj_ego_move_to_x_y) { @@ -723,9 +734,8 @@ cmd(call) { int oldCIP; int oldLognum; - /* CM: we don't save sIP because set.scan.start can be - * used in a called script (fixes xmas demo) - */ + // CM: we don't save sIP because set.scan.start can be + // used in a called script (fixes xmas demo) oldCIP = curLogic->cIP; oldLognum = game.lognum; @@ -762,14 +772,19 @@ cmd(draw_pic) { // Fixes bug #1658514: AGI: SQ1 (2.2 DOS ENG) bizzare exploding roger if (g_agi->getGameID() == GID_SQ1 && _v[p0] == 20) g_agi->setflag(103, false); + + // Simulate slowww computer. Many effects rely on this + g_agi->pause(kPausePicture); } cmd(show_pic) { debugC(6, kDebugLevelScripts, "=== show pic ==="); + g_agi->setflag(fOutputMode, false); cmd_close_window(NULL); g_picture->showPic(); game.pictureShown = 1; + debugC(6, kDebugLevelScripts, "--- end of show pic ---"); } @@ -781,16 +796,20 @@ cmd(load_pic) { cmd(discard_pic) { debugC(6, kDebugLevelScripts, "--- discard pic ---"); - /* do nothing */ + // do nothing } cmd(overlay_pic) { debugC(6, kDebugLevelScripts, "--- overlay pic ---"); + g_sprites->eraseBoth(); g_picture->decodePicture(_v[p0], false); g_sprites->blitBoth(); game.pictureShown = 0; g_sprites->commitBoth(); + + // Simulate slowww computer. Many effects rely on this + g_agi->pause(kPausePicture); } cmd(show_pri_screen) { @@ -798,7 +817,9 @@ cmd(show_pri_screen) { g_sprites->eraseBoth(); g_picture->showPic(); g_sprites->blitBoth(); + g_agi->waitKey(); + g_agi->_debug.priority = 0; g_sprites->eraseBoth(); g_picture->showPic(); @@ -818,6 +839,7 @@ cmd(animate_obj) { cmd(unanimate_all) { int i; + for (i = 0; i < MAX_VIEWTABLE; i++) game.viewTable[i].flags &= ~(ANIMATED | DRAWN); } @@ -832,10 +854,11 @@ cmd(draw) { debugC(4, kDebugLevelScripts, "draw entry %d", vt.entry); vt.flags |= UPDATE; - if (g_agi->agiGetRelease() >= 0x3000) { + if (g_agi->getVersion() >= 0x3000) { g_agi->setLoop(&vt, vt.currentLoop); g_agi->setCel(&vt, vt.currentCel); } + g_agi->fixPosition(p0); vt.xPos2 = vt.xPos; vt.yPos2 = vt.yPos; @@ -854,7 +877,7 @@ cmd(draw) { // TODO: Investigate this further and check if any other fanmade AGI // games are affected. If yes, then it'd be best to set this for Space // Trek only - if (g_agi->getFeatures() & GF_FANMADE) /* See Sarien bug #546562 */ + if (g_agi->getFeatures() & GF_FANMADE) // See Sarien bug #546562 vt.flags |= ANIMATED; g_sprites->blitUpdSprites(); @@ -870,6 +893,7 @@ cmd(erase) { return; g_sprites->eraseUpdSprites(); + if (vt.flags & UPDATE) { vt.flags &= ~DRAWN; } else { @@ -1002,7 +1026,7 @@ cmd(normal_motion) { cmd(stop_motion) { vt.direction = 0; vt.motion = MOTION_NORMAL; - if (p0 == 0) { /* ego only */ + if (p0 == 0) { // ego only _v[vEgoDir] = 0; game.playerControl = false; } @@ -1010,7 +1034,7 @@ cmd(stop_motion) { cmd(start_motion) { vt.motion = MOTION_NORMAL; - if (p0 == 0) { /* ego only */ + if (p0 == 0) { // ego only _v[vEgoDir] = 0; game.playerControl = true; } @@ -1035,7 +1059,7 @@ cmd(follow_ego) { } cmd(move_obj) { - /* _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4); */ + // _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4); vt.motion = MOTION_MOVE_OBJ; vt.parm1 = p1; @@ -1052,8 +1076,8 @@ cmd(move_obj) { if (p0 == 0) game.playerControl = false; - /* AGI 2.272 (ddp, xmas) doesn't call move_obj! */ - if (g_agi->agiGetRelease() > 0x2272) + // AGI 2.272 (ddp, xmas) doesn't call move_obj! + if (g_agi->getVersion() > 0x2272) g_agi->moveObj(&vt); } @@ -1073,14 +1097,15 @@ cmd(move_obj_f) { if (p0 == 0) game.playerControl = false; - /* AGI 2.272 (ddp, xmas) doesn't call move_obj! */ - if (g_agi->agiGetRelease() > 0x2272) + // AGI 2.272 (ddp, xmas) doesn't call move_obj! + if (g_agi->getVersion() > 0x2272) g_agi->moveObj(&vt); } cmd(wander) { if (p0 == 0) game.playerControl = false; + vt.motion = MOTION_WANDER; vt.flags |= UPDATE; } @@ -1114,12 +1139,14 @@ cmd(pause) { cmd(set_menu) { debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); + if (curLogic->texts != NULL && p0 <= curLogic->numTexts) g_agi->_menu->add(curLogic->texts[p0 - 1]); } cmd(set_menu_item) { debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); + if (curLogic->texts != NULL && p0 <= curLogic->numTexts) g_agi->_menu->addItem(curLogic->texts[p0 - 1], p1); } @@ -1134,7 +1161,7 @@ cmd(version) { "\n" " \n\n" " Emulating AGI v%x.002.%03x\n"; - /* no Sierra as it wraps textbox */ + // no Sierra as it wraps textbox char *r, *q; int ver, maj, min; char msg[256]; @@ -1143,16 +1170,17 @@ cmd(version) { sprintf(verMsg, TITLE " v%s", gScummVMVersion); - ver = g_agi->agiGetRelease(); + ver = g_agi->getVersion(); maj = (ver >> 12) & 0xf; min = ver & 0xfff; q = maj == 2 ? ver2Msg : ver3Msg; r = strchr(q + 1, '\n'); - /* insert our version into the other version */ + // insert our version into the other version len = strlen(verMsg); gap = r - q; + if (gap < 0) gap = 0; else @@ -1172,17 +1200,18 @@ cmd(configure_screen) { cmd(text_screen) { debugC(4, kDebugLevelScripts, "switching to text mode"); game.gfxMode = false; - /* - * Simulates the "bright background bit" of the PC video - * controller. - */ + + // Simulates the "bright background bit" of the PC video + // controller. if (game.colorBg) game.colorBg |= 0x08; + g_gfx->clearScreen(game.colorBg); } cmd(graphics) { debugC(4, kDebugLevelScripts, "switching to graphics mode"); + if (!game.gfxMode) { game.gfxMode = true; g_gfx->clearScreen(0); @@ -1231,7 +1260,7 @@ cmd(restart_game) { g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons); if (sel == 0) { - g_agi->restartGame = true; + g_agi->_restartGame = true; g_agi->setflag(fRestartGame, true); g_agi->_menu->enableAll(); } @@ -1290,6 +1319,7 @@ cmd(distance) { cmd(accept_input) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal"); + g_agi->newInputMode(INPUT_NORMAL); game.inputEnabled = true; g_agi->writePrompt(); @@ -1297,8 +1327,11 @@ cmd(accept_input) { cmd(prevent_input) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input"); + g_agi->newInputMode(INPUT_NONE); game.inputEnabled = false; + + g_agi->clearPrompt(); } cmd(get_string) { @@ -1310,9 +1343,8 @@ cmd(get_string) { row = p2; col = p3; - /* Workaround for SQLC bug. - * See Sarien bug #792125 for details - */ + // Workaround for SQLC bug. + // See Sarien bug #792125 for details if (row > 24) row = 24; if (col > 39) @@ -1322,37 +1354,42 @@ cmd(get_string) { if (curLogic->texts != NULL && curLogic->numTexts >= tex) { int len = strlen(curLogic->texts[tex]); + g_agi->printText(curLogic->texts[tex], 0, col, row, len, game.colorFg, game.colorBg); g_agi->getString(col + len - 1, row, p4, p0); - /* SGEO: display input char */ + // SGEO: display input char g_gfx->printCharacter((col + len), row, game.cursorChar, game.colorFg, game.colorBg); } do { g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->restartGame)); + } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); } cmd(get_num) { debugC(4, kDebugLevelScripts, "%d %d", p0, p1); + g_agi->newInputMode(INPUT_GETSTRING); if (curLogic->texts != NULL && curLogic->numTexts >= (p0 - 1)) { int len = strlen(curLogic->texts[p0 - 1]); + g_agi->printText(curLogic->texts[p0 - 1], 0, 0, 22, len, game.colorFg, game.colorBg); g_agi->getString(len - 1, 22, 3, MAX_STRINGS); - /* CM: display input char */ + // CM: display input char g_gfx->printCharacter((p3 + len), 22, game.cursorChar, game.colorFg, game.colorBg); } do { g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->restartGame)); + } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); _v[p1] = atoi(game.strings[MAX_STRINGS]); + debugC(4, kDebugLevelScripts, "[%s] -> %d", game.strings[MAX_STRINGS], _v[p1]); + g_agi->clearLines(22, 22, game.colorBg); g_agi->flushLines(22, 22); } @@ -1361,7 +1398,7 @@ cmd(set_cursor_char) { if (curLogic->texts != NULL && (p0 - 1) <= curLogic->numTexts) { game.cursorChar = *curLogic->texts[p0 - 1]; } else { - /* default */ + // default game.cursorChar = '_'; } } @@ -1369,18 +1406,24 @@ cmd(set_cursor_char) { cmd(set_key) { int key; - debugC(4, kDebugLevelScripts, "%d %d %d", p0, p1, p2); - - if (game.evKeyp[p2].data != 0) /* TBC sets c23 (ESC) twice! */ + if (game.lastController >= MAX_CONTROLLERS) { + warning("Number of set.keys exceeded %d", MAX_CONTROLLERS); return; + } + + debugC(4, kDebugLevelScripts, "%d %d %d", p0, p1, p2); key = 256 * p1 + p0; - game.evKeyp[p2].data = key; - game.evKeyp[p2].occured = false; + + game.controllers[game.lastController].keycode = key; + game.controllers[game.lastController].controller = p2; + game.lastController++; + + game.controllerOccured[p2] = false; } cmd(set_string) { - /* CM: to avoid crash in Groza (str = 150) */ + // CM: to avoid crash in Groza (str = 150) if (p0 > MAX_STRINGS) return; strcpy(game.strings[p0], curLogic->texts[p1 - 1]); @@ -1406,12 +1449,13 @@ cmd(clear_text_rect) { if ((c = p4) != 0) c = 15; + x1 = p1 * CHAR_COLS; y1 = p0 * CHAR_LINES; x2 = (p3 + 1) * CHAR_COLS - 1; y2 = (p2 + 1) * CHAR_LINES - 1; - /* Added to prevent crash with x2 = 40 in the iigs demo */ + // Added to prevent crash with x2 = 40 in the iigs demo if (x1 > GFX_WIDTH) x1 = GFX_WIDTH - 1; if (x2 > GFX_WIDTH) @@ -1438,7 +1482,7 @@ cmd(echo_line) { cmd(clear_lines) { uint8 l; - /* Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423 */ + // Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423 l = p1 ? p1 : p0; // Agent06 incorrectly calls clear.lines(1,150,0), see ScummVM bugs @@ -1451,32 +1495,41 @@ cmd(clear_lines) { cmd(print) { int n = p0 < 1 ? 1 : p0; + g_agi->print(curLogic->texts[n - 1], 0, 0, 0); } cmd(print_f) { int n = _v[p0] < 1 ? 1 : _v[p0]; + g_agi->print(curLogic->texts[n - 1], 0, 0, 0); } cmd(print_at) { int n = p0 < 1 ? 1 : p0; + debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3); + g_agi->print(curLogic->texts[n - 1], p1, p2, p3); } cmd(print_at_v) { int n = _v[p0] < 1 ? 1 : _v[p0]; + g_agi->print(curLogic->texts[n - 1], p1, p2, p3); } cmd(push_script) { - if (g_agi->getFeatures() & GF_AGIMOUSE) { + // We run AGIMOUSE always as a side effect + if (g_agi->getFeatures() & GF_AGIMOUSE || 1) { game.vars[27] = g_mouse.button; game.vars[28] = g_mouse.x / 2; game.vars[29] = g_mouse.y; - } else - report("push.script\n"); + } else { + if (g_agi->getVersion() >= 0x2915) { + report("push.script\n"); + } + } } cmd(set_pri_base) { @@ -1484,7 +1537,7 @@ cmd(set_pri_base) { report("Priority base set to %d\n", p0); - /* game.alt_pri = true; */ + // game.alt_pri = true; x = (_HEIGHT - p0) * _HEIGHT / 10; for (i = 0; i < _HEIGHT; i++) { @@ -1521,7 +1574,7 @@ cmd(shake_screen) { g_gfx->shakeStart(); - g_sprites->commitBoth(); /* Fixes SQ1 demo */ + g_sprites->commitBoth(); // Fixes SQ1 demo for (i = 4 * p0; i; i--) { g_gfx->shakeScreen(i & 1); g_gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); @@ -1529,12 +1582,12 @@ cmd(shake_screen) { } g_gfx->shakeEnd(); - //Sets input back to what it was + // Sets input back to what it was game.inputEnabled = originalValue; } static void (*agiCommand[183])(uint8 *) = { - NULL, /* 0x00 */ + NULL, // 0x00 cmd_increment, cmd_decrement, cmd_assignn, @@ -1542,7 +1595,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_addn, cmd_addv, cmd_subn, - cmd_subv, /* 0x08 */ + cmd_subv, // 0x08 cmd_lindirectv, cmd_rindirect, cmd_lindirectn, @@ -1550,7 +1603,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_reset, cmd_toggle, cmd_set_v, - cmd_reset_v, /* 0x10 */ + cmd_reset_v, // 0x10 cmd_toggle_v, cmd_new_room, cmd_new_room_f, @@ -1558,7 +1611,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_load_logic_f, cmd_call, cmd_call_f, - cmd_load_pic, /* 0x18 */ + cmd_load_pic, // 0x18 cmd_draw_pic, cmd_show_pic, cmd_discard_pic, @@ -1566,7 +1619,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_show_pri_screen, cmd_load_view, cmd_load_view_f, - cmd_discard_view, /* 0x20 */ + cmd_discard_view, // 0x20 cmd_animate_obj, cmd_unanimate_all, cmd_draw, @@ -1574,7 +1627,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_position, cmd_position_f, cmd_get_posn, - cmd_reposition, /* 0x28 */ + cmd_reposition, // 0x28 cmd_set_view, cmd_set_view_f, cmd_set_loop, @@ -1582,7 +1635,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_fix_loop, cmd_release_loop, cmd_set_cel, - cmd_set_cel_f, /* 0x30 */ + cmd_set_cel_f, // 0x30 cmd_last_cel, cmd_current_cel, cmd_current_loop, @@ -1590,7 +1643,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_number_of_loops, cmd_set_priority, cmd_set_priority_f, - cmd_release_priority, /* 0x38 */ + cmd_release_priority, // 0x38 cmd_get_priority, cmd_stop_update, cmd_start_update, @@ -1598,7 +1651,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_ignore_horizon, cmd_observe_horizon, cmd_set_horizon, - cmd_object_on_water, /* 0x40 */ + cmd_object_on_water, // 0x40 cmd_object_on_land, cmd_object_on_anything, cmd_ignore_objs, @@ -1606,7 +1659,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_distance, cmd_stop_cycling, cmd_start_cycling, - cmd_normal_cycle, /* 0x48 */ + cmd_normal_cycle, // 0x48 cmd_end_of_loop, cmd_reverse_cycle, cmd_reverse_loop, @@ -1614,7 +1667,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_stop_motion, cmd_start_motion, cmd_step_size, - cmd_step_time, /* 0x50 */ + cmd_step_time, // 0x50 cmd_move_obj, cmd_move_obj_f, cmd_follow_ego, @@ -1622,7 +1675,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_normal_motion, cmd_set_dir, cmd_get_dir, - cmd_ignore_blocks, /* 0x58 */ + cmd_ignore_blocks, // 0x58 cmd_observe_blocks, cmd_block, cmd_unblock, @@ -1630,7 +1683,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_get_f, cmd_drop, cmd_put, - cmd_put_f, /* 0x60 */ + cmd_put_f, // 0x60 cmd_get_room_f, cmd_load_sound, cmd_sound, @@ -1638,7 +1691,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_print, cmd_print_f, cmd_display, - cmd_display_f, /* 0x68 */ + cmd_display_f, // 0x68 cmd_clear_lines, cmd_text_screen, cmd_graphics, @@ -1646,7 +1699,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_set_text_attribute, cmd_shake_screen, cmd_configure_screen, - cmd_status_line_on, /* 0x70 */ + cmd_status_line_on, // 0x70 cmd_status_line_off, cmd_set_string, cmd_get_string, @@ -1654,7 +1707,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_parse, cmd_get_num, cmd_prevent_input, - cmd_accept_input, /* 0x78 */ + cmd_accept_input, // 0x78 cmd_set_key, cmd_add_to_pic, cmd_add_to_pic_f, @@ -1662,7 +1715,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_save_game, cmd_load_game, cmd_init_disk, - cmd_restart_game, /* 0x80 */ + cmd_restart_game, // 0x80 cmd_show_obj, cmd_random, cmd_program_control, @@ -1670,7 +1723,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_obj_status_f, cmd_quit, cmd_show_mem, - cmd_pause, /* 0x88 */ + cmd_pause, // 0x88 cmd_echo_line, cmd_cancel_line, cmd_init_joy, @@ -1678,7 +1731,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_version, cmd_script_size, cmd_set_game_id, - cmd_log, /* 0x90 */ + cmd_log, // 0x90 cmd_set_scan_start, cmd_reset_scan_start, cmd_reposition_to, @@ -1686,7 +1739,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_trace_on, cmd_trace_info, cmd_print_at, - cmd_print_at_v, /* 0x98 */ + cmd_print_at_v, // 0x98 cmd_discard_view, cmd_clear_text_rect, cmd_set_upper_left, @@ -1694,7 +1747,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_set_menu_item, cmd_submit_menu, cmd_enable_item, - cmd_disable_item, /* 0xa0 */ + cmd_disable_item, // 0xa0 cmd_menu_input, cmd_show_obj_v, cmd_open_dialogue, @@ -1702,7 +1755,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_mul_n, cmd_mul_v, cmd_div_n, - cmd_div_v, /* 0xa8 */ + cmd_div_v, // 0xa8 cmd_close_window, cmd_set_simple, cmd_push_script, @@ -1710,7 +1763,7 @@ static void (*agiCommand[183])(uint8 *) = { cmd_hold_key, cmd_set_pri_base, cmd_discard_sound, - cmd_hide_mouse, /* 0xb0 */ + cmd_hide_mouse, // 0xb0 cmd_allow_menu, cmd_show_mouse, cmd_fence_mouse, @@ -1719,8 +1772,6 @@ static void (*agiCommand[183])(uint8 *) = { cmd_adj_ego_move_to_x_y }; -#define CMD_BSIZE 12 - /** * Execute a logic script * @param n Number of the logic resource to execute @@ -1731,8 +1782,13 @@ int AgiEngine::runLogic(int n) { uint8 *code = NULL; g_agi = this; int num = 0; + ScriptPos sp; + + sp.script = n; + sp.curIP = 0; + _game.execStack.push_back(sp); - /* If logic not loaded, load it */ + // If logic not loaded, load it if (~_game.dirLogic[n].flags & RES_LOADED) { debugC(4, kDebugLevelScripts, "logic %d not loaded!", n); agiLoadResource(rLOGIC, n); @@ -1745,7 +1801,7 @@ int AgiEngine::runLogic(int n) { curLogic->cIP = curLogic->sIP; timerHack = 0; - while (ip < _game.logics[n].size && !(shouldQuit() || restartGame)) { + while (ip < _game.logics[n].size && !(shouldQuit() || _restartGame)) { if (_debug.enabled) { if (_debug.steps > 0) { if (_debug.logic0 || n) { @@ -1761,23 +1817,27 @@ int AgiEngine::runLogic(int n) { } } + _game.execStack.back().curIP = ip; + processEvents(); + switch (op = *(code + ip++)) { - case 0xff: /* if (open/close) */ + case 0xff: // if (open/close) testIfCode(n); break; - case 0xfe: /* goto */ - /* +2 covers goto size */ + case 0xfe: // goto + // +2 covers goto size ip += 2 + ((int16)READ_LE_UINT16(code + ip)); - /* timer must keep running even in goto loops, - * but AGI engine can't do that :( - */ + + // timer must keep running even in goto loops, + // but AGI engine can't do that :( if (timerHack > 20) { - g_gfx->pollTimer(); + pollTimer(); updateTimer(); timerHack = 0; } break; - case 0x00: /* return */ + case 0x00: // return + _game.execStack.pop_back(); return 1; default: num = logicNamesCmd[op].numArgs; @@ -1785,7 +1845,7 @@ int AgiEngine::runLogic(int n) { memset(p + num, 0, CMD_BSIZE - num); debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]); - agiCommand[op] (p); + agiCommand[op](p); ip += num; } @@ -1793,7 +1853,9 @@ int AgiEngine::runLogic(int n) { break; } - return 0; /* after executing new.room() */ + _game.execStack.pop_back(); + + return 0; // after executing new.room() } void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) { diff --git a/engines/agi/op_dbg.cpp b/engines/agi/op_dbg.cpp index cd7442c81c..7ed8e2bd17 100644 --- a/engines/agi/op_dbg.cpp +++ b/engines/agi/op_dbg.cpp @@ -23,8 +23,6 @@ * */ - - #include "agi/agi.h" #include "agi/opcodes.h" @@ -58,7 +56,7 @@ struct AgiLogicnames logicNamesTest[] = { _L("controller", 1, 0x00), _L("have.key", 0, 0x00), - /* Not 0 args. Has variable number. */ + // Not 0 args. Has variable number. _L("said", 0, 0x00), _L("compare.strings", 2, 0x00), @@ -66,7 +64,7 @@ struct AgiLogicnames logicNamesTest[] = { _L("center.posn", 5, 0x00), _L("right.posn", 5, 0x00), - /* Haven't seen an official name for this command so tried to name it descriptively. */ + // Haven't seen an official name for this command so tried to name it descriptively. _L("in.motion.using.mouse", 0, 0x00) }; @@ -78,200 +76,200 @@ struct AgiLogicnames logicNamesIf[] = { }; struct AgiLogicnames logicNamesCmd[] = { - _L("return", 0, 0x00), /* 00 */ - _L("increment", 1, 0x80), /* 01 */ - _L("decrement", 1, 0x80), /* 02 */ - _L("assignn", 2, 0x80), /* 03 */ - _L("assignv", 2, 0xC0), /* 04 */ - _L("addn", 2, 0x80), /* 05 */ - _L("addv", 2, 0xC0), /* 06 */ - _L("subn", 2, 0x80), /* 07 */ - _L("subv", 2, 0xC0), /* 08 */ - _L("lindirectv", 2, 0xC0), /* 09 */ - _L("rindirect", 2, 0xC0), /* 0A */ - _L("lindirectn", 2, 0x80), /* 0B */ - _L("set", 1, 0x00), /* 0C */ - _L("reset", 1, 0x00), /* 0D */ - _L("toggle", 1, 0x00), /* 0E */ - _L("set.v", 1, 0x80), /* 0F */ - _L("reset.v", 1, 0x80), /* 10 */ - _L("toggle.v", 1, 0x80), /* 11 */ - _L("new.room", 1, 0x00), /* 12 */ - _L("new.room.v", 1, 0x80), /* 13 */ - _L("load.logics", 1, 0x00), /* 14 */ - _L("load.logics.v", 1, 0x80), /* 15 */ - _L("call", 1, 0x00), /* 16 */ - _L("call.v", 1, 0x80), /* 17 */ - _L("load.pic", 1, 0x80), /* 18 */ - _L("draw.pic", 1, 0x80), /* 19 */ - _L("show.pic", 0, 0x00), /* 1A */ - _L("discard.pic", 1, 0x80), /* 1B */ - _L("overlay.pic", 1, 0x80), /* 1C */ - _L("show.pri.screen", 0, 0x00), /* 1D */ - _L("load.view", 1, 0x00), /* 1E */ - _L("load.view.v", 1, 0x80), /* 1F */ - _L("discard.view", 1, 0x00), /* 20 */ - _L("animate.obj", 1, 0x00), /* 21 */ - _L("unanimate.all", 0, 0x00), /* 22 */ - _L("draw", 1, 0x00), /* 23 */ - _L("erase", 1, 0x00), /* 24 */ - _L("position", 3, 0x00), /* 25 */ - _L("position.v", 3, 0x60), /* 26 */ - _L("get.posn", 3, 0x60), /* 27 */ - _L("reposition", 3, 0x60), /* 28 */ - _L("set.view", 2, 0x00), /* 29 */ - _L("set.view.v", 2, 0x40), /* 2A */ - _L("set.loop", 2, 0x00), /* 2B */ - _L("set.loop.v", 2, 0x40), /* 2C */ - _L("fix.loop", 1, 0x00), /* 2D */ - _L("release.loop", 1, 0x00), /* 2E */ - _L("set.cel", 2, 0x00), /* 2F */ - _L("set.cel.v", 2, 0x40), /* 30 */ - _L("last.cel", 2, 0x40), /* 31 */ - _L("current.cel", 2, 0x40), /* 32 */ - _L("current.loop", 2, 0x40), /* 33 */ - _L("current.view", 2, 0x40), /* 34 */ - _L("number.of.loops", 2, 0x40), /* 35 */ - _L("set.priority", 2, 0x00), /* 36 */ - _L("set.priority.v", 2, 0x40), /* 37 */ - _L("release.priority", 1, 0x00), /* 38 */ - _L("get.priority", 2, 0x40), /* 39 */ - _L("stop.update", 1, 0x00), /* 3A */ - _L("start.update", 1, 0x00), /* 3B */ - _L("force.update", 1, 0x00), /* 3C */ - _L("ignore.horizon", 1, 0x00), /* 3D */ - _L("observe.horizon", 1, 0x00), /* 3E */ - _L("set.horizon", 1, 0x00), /* 3F */ - _L("object.on.water", 1, 0x00), /* 40 */ - _L("object.on.land", 1, 0x00), /* 41 */ - _L("object.on.anything", 1, 0x00), /* 42 */ - _L("ignore.objs", 1, 0x00), /* 43 */ - _L("observe.objs", 1, 0x00), /* 44 */ - _L("distance", 3, 0x20), /* 45 */ - _L("stop.cycling", 1, 0x00), /* 46 */ - _L("start.cycling", 1, 0x00), /* 47 */ - _L("normal.cycle", 1, 0x00), /* 48 */ - _L("end.of.loop", 2, 0x00), /* 49 */ - _L("reverse.cycle", 1, 0x00), /* 4A */ - _L("reverse.loop", 2, 0x00), /* 4B */ - _L("cycle.time", 2, 0x40), /* 4C */ - _L("stop.motion", 1, 0x00), /* 4D */ - _L("start.motion", 1, 0x00), /* 4E */ - _L("step.size", 2, 0x40), /* 4F */ - _L("step.time", 2, 0x40), /* 50 */ - _L("move.obj", 5, 0x00), /* 51 */ - _L("move.obj.v", 5, 0x70), /* 52 */ - _L("follow.ego", 3, 0x00), /* 53 */ - _L("wander", 1, 0x00), /* 54 */ - _L("normal.motion", 1, 0x00), /* 55 */ - _L("set.dir", 2, 0x40), /* 56 */ - _L("get.dir", 2, 0x40), /* 57 */ - _L("ignore.blocks", 1, 0x00), /* 58 */ - _L("observe.blocks", 1, 0x00), /* 59 */ - _L("block", 4, 0x00), /* 5A */ - _L("unblock", 0, 0x00), /* 5B */ - _L("get", 1, 0x00), /* 5C */ - _L("get.v", 1, 0x80), /* 5D */ - _L("drop", 1, 0x00), /* 5E */ - _L("put", 2, 0x00), /* 5F */ - _L("put.v", 2, 0x40), /* 60 */ - _L("get.room.v", 2, 0xC0), /* 61 */ - _L("load.sound", 1, 0x00), /* 62 */ - _L("sound", 2, 0x00), /* 63 */ - _L("stop.sound", 0, 0x00), /* 64 */ - _L("print", 1, 0x00), /* 65 */ - _L("print.v", 1, 0x80), /* 66 */ - _L("display", 3, 0x00), /* 67 */ - _L("display.v", 3, 0xE0), /* 68 */ - _L("clear.lines", 3, 0x00), /* 69 */ - _L("text.screen", 0, 0x00), /* 6A */ - _L("graphics", 0, 0x00), /* 6B */ - _L("set.cursor.char", 1, 0x00), /* 6C */ - _L("set.text.attribute", 2, 0x00), /* 6D */ - _L("shake.screen", 1, 0x00), /* 6E */ - _L("configure.screen", 3, 0x00), /* 6F */ - _L("status.line.on", 0, 0x00), /* 70 */ - _L("status.line.off", 0, 0x00), /* 71 */ - _L("set.string", 2, 0x00), /* 72 */ - _L("get.string", 5, 0x00), /* 73 */ - _L("word.to.string", 2, 0x00), /* 74 */ - _L("parse", 1, 0x00), /* 75 */ - _L("get.num", 2, 0x40), /* 76 */ - _L("prevent.input", 0, 0x00), /* 77 */ - _L("accept.input", 0, 0x00), /* 78 */ - _L("set.key", 3, 0x00), /* 79 */ - _L("add.to.pic", 7, 0x00), /* 7A */ - _L("add.to.pic.v", 7, 0xFE), /* 7B */ - _L("status", 0, 0x00), /* 7C */ - _L("save.game", 0, 0x00), /* 7D */ - _L("restore.game", 0, 0x00), /* 7E */ - _L("init.disk", 0, 0x00), /* 7F */ - _L("restart.game", 0, 0x00), /* 80 */ - _L("show.obj", 1, 0x00), /* 81 */ - _L("random", 3, 0x20), /* 82 */ - _L("program.control", 0, 0x00), /* 83 */ - _L("player.control", 0, 0x00), /* 84 */ - _L("obj.status.v", 1, 0x80), /* 85 */ - /* 0 args for AGI version 2.089 */ - _L("quit", 1, 0x00), /* 86 */ - - _L("show.mem", 0, 0x00), /* 87 */ - _L("pause", 0, 0x00), /* 88 */ - _L("echo.line", 0, 0x00), /* 89 */ - _L("cancel.line", 0, 0x00), /* 8A */ - _L("init.joy", 0, 0x00), /* 8B */ - _L("toggle.monitor", 0, 0x00), /* 8C */ - _L("version", 0, 0x00), /* 8D */ - _L("script.size", 1, 0x00), /* 8E */ - _L("set.game.id", 1, 0x00), /* 8F */ - _L("log", 1, 0x00), /* 90 */ - _L("set.scan.start", 0, 0x00), /* 91 */ - _L("reset.scan.start", 0, 0x00), /* 92 */ - _L("reposition.to", 3, 0x00), /* 93 */ - _L("reposition.to.v", 3, 0x60), /* 94 */ - _L("trace.on", 0, 0x00), /* 95 */ - _L("trace.info", 3, 0x00), /* 96 */ - - /* 3 args for AGI versions before 2.440 */ - _L("print.at", 4, 0x00), /* 97 */ - _L("print.at.v", 4, 0x80), /* 98 */ - - _L("discard.view.v", 1, 0x80), /* 99 */ - _L("clear.text.rect", 5, 0x00), /* 9A */ - _L("set.upper.left", 2, 0x00), /* 9B */ - _L("set.menu", 1, 0x00), /* 9C */ - _L("set.menu.item", 2, 0x00), /* 9D */ - _L("submit.menu", 0, 0x00), /* 9E */ - _L("enable.item", 1, 0x00), /* 9F */ - _L("disable.item", 1, 0x00), /* A0 */ - _L("menu.input", 0, 0x00), /* A1 */ - _L("show.obj.v", 1, 0x01), /* A2 */ - _L("open.dialogue", 0, 0x00), /* A3 */ - _L("close.dialogue", 0, 0x00), /* A4 */ - _L("mul.n", 2, 0x80), /* A5 */ - _L("mul.v", 2, 0xC0), /* A6 */ - _L("div.n", 2, 0x80), /* A7 */ - _L("div.v", 2, 0xC0), /* A8 */ - _L("close.window", 0, 0x00), /* A9 */ - - _L("set.simple", 1, 0x00), /* AA */ - _L("push.script", 0, 0x00), /* AB */ - _L("pop.script", 0, 0x00), /* AC */ - _L("hold.key", 0, 0x00), /* AD */ - _L("set.pri.base", 1, 0x00), /* AE */ - _L("discard.sound", 1, 0x00), /* AF */ - - /* 1 arg for AGI version 3.002.086 */ - _L("hide.mouse", 0, 0x00), /* B0 */ - - _L("allow.menu", 1, 0x00), /* B1 */ - _L("show.mouse", 0, 0x00), /* B2 */ - _L("fence.mouse", 4, 0x00), /* B3 */ - _L("mouse.posn", 2, 0x00), /* B4 */ - _L("release.key", 0, 0x00), /* B5 */ - - /* 2 args for at least the Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. */ - _L("adj.ego.move.to.xy", 0, 0x00), /* B6 */ + _L("return", 0, 0x00), // 00 + _L("increment", 1, 0x80), // 01 + _L("decrement", 1, 0x80), // 02 + _L("assignn", 2, 0x80), // 03 + _L("assignv", 2, 0xC0), // 04 + _L("addn", 2, 0x80), // 05 + _L("addv", 2, 0xC0), // 06 + _L("subn", 2, 0x80), // 07 + _L("subv", 2, 0xC0), // 08 + _L("lindirectv", 2, 0xC0), // 09 + _L("rindirect", 2, 0xC0), // 0A + _L("lindirectn", 2, 0x80), // 0B + _L("set", 1, 0x00), // 0C + _L("reset", 1, 0x00), // 0D + _L("toggle", 1, 0x00), // 0E + _L("set.v", 1, 0x80), // 0F + _L("reset.v", 1, 0x80), // 10 + _L("toggle.v", 1, 0x80), // 11 + _L("new.room", 1, 0x00), // 12 + _L("new.room.v", 1, 0x80), // 13 + _L("load.logics", 1, 0x00), // 14 + _L("load.logics.v", 1, 0x80), // 15 + _L("call", 1, 0x00), // 16 + _L("call.v", 1, 0x80), // 17 + _L("load.pic", 1, 0x80), // 18 + _L("draw.pic", 1, 0x80), // 19 + _L("show.pic", 0, 0x00), // 1A + _L("discard.pic", 1, 0x80), // 1B + _L("overlay.pic", 1, 0x80), // 1C + _L("show.pri.screen", 0, 0x00), // 1D + _L("load.view", 1, 0x00), // 1E + _L("load.view.v", 1, 0x80), // 1F + _L("discard.view", 1, 0x00), // 20 + _L("animate.obj", 1, 0x00), // 21 + _L("unanimate.all", 0, 0x00), // 22 + _L("draw", 1, 0x00), // 23 + _L("erase", 1, 0x00), // 24 + _L("position", 3, 0x00), // 25 + _L("position.v", 3, 0x60), // 26 + _L("get.posn", 3, 0x60), // 27 + _L("reposition", 3, 0x60), // 28 + _L("set.view", 2, 0x00), // 29 + _L("set.view.v", 2, 0x40), // 2A + _L("set.loop", 2, 0x00), // 2B + _L("set.loop.v", 2, 0x40), // 2C + _L("fix.loop", 1, 0x00), // 2D + _L("release.loop", 1, 0x00), // 2E + _L("set.cel", 2, 0x00), // 2F + _L("set.cel.v", 2, 0x40), // 30 + _L("last.cel", 2, 0x40), // 31 + _L("current.cel", 2, 0x40), // 32 + _L("current.loop", 2, 0x40), // 33 + _L("current.view", 2, 0x40), // 34 + _L("number.of.loops", 2, 0x40), // 35 + _L("set.priority", 2, 0x00), // 36 + _L("set.priority.v", 2, 0x40), // 37 + _L("release.priority", 1, 0x00), // 38 + _L("get.priority", 2, 0x40), // 39 + _L("stop.update", 1, 0x00), // 3A + _L("start.update", 1, 0x00), // 3B + _L("force.update", 1, 0x00), // 3C + _L("ignore.horizon", 1, 0x00), // 3D + _L("observe.horizon", 1, 0x00), // 3E + _L("set.horizon", 1, 0x00), // 3F + _L("object.on.water", 1, 0x00), // 40 + _L("object.on.land", 1, 0x00), // 41 + _L("object.on.anything", 1, 0x00), // 42 + _L("ignore.objs", 1, 0x00), // 43 + _L("observe.objs", 1, 0x00), // 44 + _L("distance", 3, 0x20), // 45 + _L("stop.cycling", 1, 0x00), // 46 + _L("start.cycling", 1, 0x00), // 47 + _L("normal.cycle", 1, 0x00), // 48 + _L("end.of.loop", 2, 0x00), // 49 + _L("reverse.cycle", 1, 0x00), // 4A + _L("reverse.loop", 2, 0x00), // 4B + _L("cycle.time", 2, 0x40), // 4C + _L("stop.motion", 1, 0x00), // 4D + _L("start.motion", 1, 0x00), // 4E + _L("step.size", 2, 0x40), // 4F + _L("step.time", 2, 0x40), // 50 + _L("move.obj", 5, 0x00), // 51 + _L("move.obj.v", 5, 0x70), // 52 + _L("follow.ego", 3, 0x00), // 53 + _L("wander", 1, 0x00), // 54 + _L("normal.motion", 1, 0x00), // 55 + _L("set.dir", 2, 0x40), // 56 + _L("get.dir", 2, 0x40), // 57 + _L("ignore.blocks", 1, 0x00), // 58 + _L("observe.blocks", 1, 0x00), // 59 + _L("block", 4, 0x00), // 5A + _L("unblock", 0, 0x00), // 5B + _L("get", 1, 0x00), // 5C + _L("get.v", 1, 0x80), // 5D + _L("drop", 1, 0x00), // 5E + _L("put", 2, 0x00), // 5F + _L("put.v", 2, 0x40), // 60 + _L("get.room.v", 2, 0xC0), // 61 + _L("load.sound", 1, 0x00), // 62 + _L("sound", 2, 0x00), // 63 + _L("stop.sound", 0, 0x00), // 64 + _L("print", 1, 0x00), // 65 + _L("print.v", 1, 0x80), // 66 + _L("display", 3, 0x00), // 67 + _L("display.v", 3, 0xE0), // 68 + _L("clear.lines", 3, 0x00), // 69 + _L("text.screen", 0, 0x00), // 6A + _L("graphics", 0, 0x00), // 6B + _L("set.cursor.char", 1, 0x00), // 6C + _L("set.text.attribute", 2, 0x00), // 6D + _L("shake.screen", 1, 0x00), // 6E + _L("configure.screen", 3, 0x00), // 6F + _L("status.line.on", 0, 0x00), // 70 + _L("status.line.off", 0, 0x00), // 71 + _L("set.string", 2, 0x00), // 72 + _L("get.string", 5, 0x00), // 73 + _L("word.to.string", 2, 0x00), // 74 + _L("parse", 1, 0x00), // 75 + _L("get.num", 2, 0x40), // 76 + _L("prevent.input", 0, 0x00), // 77 + _L("accept.input", 0, 0x00), // 78 + _L("set.key", 3, 0x00), // 79 + _L("add.to.pic", 7, 0x00), // 7A + _L("add.to.pic.v", 7, 0xFE), // 7B + _L("status", 0, 0x00), // 7C + _L("save.game", 0, 0x00), // 7D + _L("restore.game", 0, 0x00), // 7E + _L("init.disk", 0, 0x00), // 7F + _L("restart.game", 0, 0x00), // 80 + _L("show.obj", 1, 0x00), // 81 + _L("random", 3, 0x20), // 82 + _L("program.control", 0, 0x00), // 83 + _L("player.control", 0, 0x00), // 84 + _L("obj.status.v", 1, 0x80), // 85 + // 0 args for AGI version 2.089 + _L("quit", 1, 0x00), // 86 + + _L("show.mem", 0, 0x00), // 87 + _L("pause", 0, 0x00), // 88 + _L("echo.line", 0, 0x00), // 89 + _L("cancel.line", 0, 0x00), // 8A + _L("init.joy", 0, 0x00), // 8B + _L("toggle.monitor", 0, 0x00), // 8C + _L("version", 0, 0x00), // 8D + _L("script.size", 1, 0x00), // 8E + _L("set.game.id", 1, 0x00), // 8F + _L("log", 1, 0x00), // 90 + _L("set.scan.start", 0, 0x00), // 91 + _L("reset.scan.start", 0, 0x00), // 92 + _L("reposition.to", 3, 0x00), // 93 + _L("reposition.to.v", 3, 0x60), // 94 + _L("trace.on", 0, 0x00), // 95 + _L("trace.info", 3, 0x00), // 96 + + // 3 args for AGI versions before 2.440 + _L("print.at", 4, 0x00), // 97 + _L("print.at.v", 4, 0x80), // 98 + + _L("discard.view.v", 1, 0x80), // 99 + _L("clear.text.rect", 5, 0x00), // 9A + _L("set.upper.left", 2, 0x00), // 9B + _L("set.menu", 1, 0x00), // 9C + _L("set.menu.item", 2, 0x00), // 9D + _L("submit.menu", 0, 0x00), // 9E + _L("enable.item", 1, 0x00), // 9F + _L("disable.item", 1, 0x00), // A0 + _L("menu.input", 0, 0x00), // A1 + _L("show.obj.v", 1, 0x01), // A2 + _L("open.dialogue", 0, 0x00), // A3 + _L("close.dialogue", 0, 0x00), // A4 + _L("mul.n", 2, 0x80), // A5 + _L("mul.v", 2, 0xC0), // A6 + _L("div.n", 2, 0x80), // A7 + _L("div.v", 2, 0xC0), // A8 + _L("close.window", 0, 0x00), // A9 + + _L("set.simple", 1, 0x00), // AA + _L("push.script", 0, 0x00), // AB + _L("pop.script", 0, 0x00), // AC + _L("hold.key", 0, 0x00), // AD + _L("set.pri.base", 1, 0x00), // AE + _L("discard.sound", 1, 0x00), // AF + + // 1 arg for AGI version 3.002.086 + _L("hide.mouse", 0, 0x00), // B0 + + _L("allow.menu", 1, 0x00), // B1 + _L("show.mouse", 0, 0x00), // B2 + _L("fence.mouse", 4, 0x00), // B3 + _L("mouse.posn", 2, 0x00), // B4 + _L("release.key", 0, 0x00), // B5 + + // 2 args for at least the Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. + _L("adj.ego.move.to.xy", 0, 0x00), // B6 _L(NULL, 0, 0x00) }; @@ -297,15 +295,15 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { if (_debug.opcodes) { report("%02X %02X %02X %02X %02X %02X %02X %02X %02X\n" " ", - (uint8) * (code + (0 + ip)) & 0xFF, - (uint8) * (code + (1 + ip)) & 0xFF, - (uint8) * (code + (2 + ip)) & 0xFF, - (uint8) * (code + (3 + ip)) & 0xFF, - (uint8) * (code + (4 + ip)) & 0xFF, - (uint8) * (code + (5 + ip)) & 0xFF, - (uint8) * (code + (6 + ip)) & 0xFF, - (uint8) * (code + (7 + ip)) & 0xFF, - (uint8) * (code + (8 + ip)) & 0xFF); + (uint8)*(code + (0 + ip)) & 0xFF, + (uint8)*(code + (1 + ip)) & 0xFF, + (uint8)*(code + (2 + ip)) & 0xFF, + (uint8)*(code + (3 + ip)) & 0xFF, + (uint8)*(code + (4 + ip)) & 0xFF, + (uint8)*(code + (5 + ip)) & 0xFF, + (uint8)*(code + (6 + ip)) & 0xFF, + (uint8)*(code + (7 + ip)) & 0xFF, + (uint8)*(code + (8 + ip)) & 0xFF); } report("%s ", (x + *(code + ip) - 0xFC)->name); break; diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 2e9e4ee337..ca80798a52 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -52,7 +52,7 @@ static AgiEngine *g_agi; #define testHas(obj) (g_agi->objectGetLocation(obj) == EGO_OWNED) #define testObjInRoom(obj, v) (g_agi->objectGetLocation(obj) == g_agi->getvar(v)) -extern int timerHack; /* For the timer loop in MH1 logic 153 */ +extern int timerHack; // For the timer loop in MH1 logic 153 static uint8 testCompareStrings(uint8 s1, uint8 s2) { char ms1[MAX_STRINGLEN]; @@ -113,6 +113,7 @@ static uint8 testKeypressed() { game.keypress = 0; if (!x) { int mode = game.inputMode; + game.inputMode = INPUT_NONE; g_agi->mainCycle(); game.inputMode = mode; @@ -125,7 +126,7 @@ static uint8 testKeypressed() { } static uint8 testController(uint8 cont) { - return game.evKeyp[cont].occured; + return (game.controllerOccured[cont] ? 1 : 0); } static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { @@ -146,7 +147,7 @@ static uint8 testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { v->yPos >= y1 && v->xPos + v->xSize - 1 <= x2 && v->yPos <= y2; } -/* if n is in centre of box */ +// if n is in centre of box static uint8 testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { VtEntry *v = &game.viewTable[n]; @@ -154,7 +155,7 @@ static uint8 testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { v->xPos + v->xSize / 2 <= x2 && v->yPos >= y1 && v->yPos <= y2; } -/* if nect N is in right corner */ +// if nect N is in right corner static uint8 testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { VtEntry *v = &game.viewTable[n]; @@ -162,7 +163,7 @@ static uint8 testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { v->xPos + v->xSize - 1 <= x2 && v->yPos >= y1 && v->yPos <= y2; } -/* When player has entered something, it is parsed elsewhere */ +// When player has entered something, it is parsed elsewhere static uint8 testSaid(uint8 nwords, uint8 *cc) { int c, n = game.numEgoWords; int z = 0; @@ -170,33 +171,32 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { if (g_agi->getflag(fSaidAcceptedInput) || !g_agi->getflag(fEnteredCli)) return false; - /* FR: - * I think the reason for the code below is to add some speed.... - * - * if (nwords != num_ego_words) - * return false; - * - * In the disco scene in Larry 1 when you type "examine blonde", - * inside the logic is expected ( said("examine", "blonde", "rol") ) - * where word("rol") = 9999 - * - * According to the interpreter code 9999 means that whatever the - * user typed should be correct, but it looks like code 9999 means that - * if the string is empty at this point, the entry is also correct... - * - * With the removal of this code, the behaviour of the scene was - * corrected - */ + // FR: + // I think the reason for the code below is to add some speed.... + // + // if (nwords != num_ego_words) + // return false; + // + // In the disco scene in Larry 1 when you type "examine blonde", + // inside the logic is expected ( said("examine", "blonde", "rol") ) + // where word("rol") = 9999 + // + // According to the interpreter code 9999 means that whatever the + // user typed should be correct, but it looks like code 9999 means that + // if the string is empty at this point, the entry is also correct... + // + // With the removal of this code, the behaviour of the scene was + // corrected for (c = 0; nwords && n; c++, nwords--, n--) { z = READ_LE_UINT16(cc); cc += 2; switch (z) { - case 9999: /* rest of line (empty string counts to...) */ + case 9999: // rest of line (empty string counts to...) nwords = 1; break; - case 1: /* any word */ + case 1: // any word break; default: if (game.egoWords[c].id != z) @@ -205,13 +205,12 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { } } - /* The entry string should be entirely parsed, or last word = 9999 */ + // The entry string should be entirely parsed, or last word = 9999 if (n && z != 9999) return false; - /* The interpreter string shouldn't be entirely parsed, but next - * word must be 9999. - */ + // The interpreter string shouldn't be entirely parsed, but next + // word must be 9999. if (nwords != 0 && READ_LE_UINT16(cc) != 9999) return false; @@ -231,7 +230,7 @@ int AgiEngine::testIfCode(int lognum) { uint8 p[16] = { 0 }; bool end_test = false; - while (retval && !(shouldQuit() || restartGame) && !end_test) { + while (retval && !(shouldQuit() || _restartGame) && !end_test) { if (_debug.enabled && (_debug.logic0 || lognum)) debugConsole(lognum, lTEST_MODE, NULL); @@ -240,16 +239,15 @@ int AgiEngine::testIfCode(int lognum) { memmove(p, (code + ip), 16); switch (op) { - case 0xFF: /* END IF, TEST true */ + case 0xFF: // END IF, TEST true end_test = true; break; case 0xFD: notTest = !notTest; continue; - case 0xFC: /* OR */ - /* if or_test is ON and we hit 0xFC, end of OR, then - * or is STILL false so break. - */ + case 0xFC: // OR + // if or_test is ON and we hit 0xFC, end of OR, then + // or is STILL false so break. if (orTest) { ec = false; retval = false; @@ -260,7 +258,7 @@ int AgiEngine::testIfCode(int lognum) { continue; case 0x00: - /* return true? */ + // return true? end_test = true; break; case 0x01: @@ -317,9 +315,9 @@ int AgiEngine::testIfCode(int lognum) { case 0x0E: ec = testSaid(p[0], (uint8 *) code + (ip + 1)); ip = lastIp; - ip++; /* skip opcode */ - ip += p[0] * 2; /* skip num_words * 2 */ - ip++; /* skip num_words opcode */ + ip++; // skip opcode + ip += p[0] * 2; // skip num_words * 2 + ip++; // skip num_words opcode break; case 0x0F: debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", game.strings[p[0]], game.strings[p[1]]); @@ -353,39 +351,38 @@ int AgiEngine::testIfCode(int lognum) { if (op <= 0x12) ip += logicNamesTest[op].numArgs; - /* exchange ec value */ + // exchange ec value if (notTest) ec = !ec; - /* not is only enabled for 1 test command */ + // not is only enabled for 1 test command notTest = false; if (orTest && ec) { - /* a true inside an OR statement passes - * ENTIRE statement scan for end of OR - */ - - /* CM: test for opcode < 0xfc changed from 'op' to - * '*(code+ip)', to avoid problem with the 0xfd (NOT) - * opcode byte. Changed a bad ip += ... ip++ construct. - * This should fix the crash with Larry's logic.0 code: - * - * if ((isset(4) || - * !isset(2) || - * v30 == 2 || - * v30 == 1)) { - * goto Label1; - * } - * - * The bytecode is: - * ff fc 07 04 fd 07 02 01 1e 02 01 1e 01 fc ff - */ - - /* find end of OR */ + // a true inside an OR statement passes + // ENTIRE statement scan for end of OR + + // CM: test for opcode < 0xfc changed from 'op' to + // '*(code+ip)', to avoid problem with the 0xfd (NOT) + // opcode byte. Changed a bad ip += ... ip++ construct. + // This should fix the crash with Larry's logic.0 code: + // + // if ((isset(4) || + // !isset(2) || + // v30 == 2 || + // v30 == 1)) { + // goto Label1; + // } + // + // The bytecode is: + // ff fc 07 04 fd 07 02 01 1e 02 01 1e 01 fc ff + + // find end of OR while (*(code + ip) != 0xFC) { - if (*(code + ip) == 0x0E) { /* said */ + if (*(code + ip) == 0x0E) { // said ip++; - /* cover count + ^words */ + + // cover count + ^words ip += 1 + ((*(code + ip)) * 2); continue; } @@ -404,7 +401,7 @@ int AgiEngine::testIfCode(int lognum) { } } - /* if false, scan for end of IP? */ + // if false, scan for end of IP? if (retval) ip += 2; else { @@ -420,7 +417,7 @@ int AgiEngine::testIfCode(int lognum) { ip++; } } - ip++; /* skip over 0xFF */ + ip++; // skip over 0xFF ip += READ_LE_UINT16(code + ip) + 2; } @@ -430,4 +427,4 @@ int AgiEngine::testIfCode(int lognum) { return retval; } -} // End of namespace Agi +} // End of namespace Agi diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index 01d66296b9..d6801d7cea 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -90,7 +90,7 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) { #else int i, x, y, deltaX, deltaY, stepX, stepY, errorX, errorY, detdelta; - /* Vertical line */ + // Vertical line if (x1 == x2) { if (y1 > y2) { @@ -103,7 +103,7 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) { return; } - /* Horizontal line */ + // Horizontal line if (y1 == y2) { if (x1 > x2) { @@ -231,7 +231,7 @@ void PictureMgr::absoluteDrawLine() { /************************************************************************** ** okToFill **************************************************************************/ -INLINE int PictureMgr::isOkFillHere(int x, int y) { +int PictureMgr::isOkFillHere(int x, int y) { uint8 p; x += _xOffset; @@ -274,7 +274,7 @@ void PictureMgr::agiFill(unsigned int x, unsigned int y) { if (!isOkFillHere(p.x, p.y)) continue; - /* Scan for left border */ + // Scan for left border for (c = p.x - 1; isOkFillHere(c, p.y); c--) ; @@ -592,7 +592,7 @@ void PictureMgr::drawPicture() { break; case 0xe4: // fill (C64) _scrColor = nextByte(); - _scrColor &= 0xF; /* for v3 drawing diff */ + _scrColor &= 0xF; // for v3 drawing diff fill(); break; case 0xe5: // enable screen drawing (C64) @@ -883,7 +883,7 @@ int PictureMgr::decodePicture(byte* data, uint32 length, int clr, int pic_width, * @param n AGI picture resource number */ int PictureMgr::unloadPicture(int n) { - /* remove visual buffer & priority buffer if they exist */ + // remove visual buffer & priority buffer if they exist if (_vm->_game.dirPic[n].flags & RES_LOADED) { free(_vm->_game.pictures[n].rdata); _vm->_game.dirPic[n].flags &= ~RES_LOADED; diff --git a/engines/agi/picture.h b/engines/agi/picture.h index 17cdf50b58..fa77e87bb6 100644 --- a/engines/agi/picture.h +++ b/engines/agi/picture.h @@ -70,7 +70,7 @@ private: void drawLine(int x1, int y1, int x2, int y2); void dynamicDrawLine(); void absoluteDrawLine(); - INLINE int isOkFillHere(int x, int y); + int isOkFillHere(int x, int y); void agiFill(unsigned int x, unsigned int y); void xCorner(bool skipOtherCoords = false); void yCorner(bool skipOtherCoords = false); diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp index 99c2e55f4b..f012426727 100644 --- a/engines/agi/preagi.cpp +++ b/engines/agi/preagi.cpp @@ -54,15 +54,6 @@ PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - /* - const GameSettings *g; - - const char *gameid = ConfMan.get("gameid").c_str(); - for (g = agiSettings; g->gameid; ++g) - if (!scumm_stricmp(g->gameid, gameid)) - _gameId = g->id; - */ - _rnd = new Common::RandomSource(); Common::addDebugChannel(kDebugLevelMain, "Main", "Generic debug level"); @@ -79,29 +70,6 @@ PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : memset(&_game, 0, sizeof(struct AgiGame)); memset(&_debug, 0, sizeof(struct AgiDebug)); memset(&g_mouse, 0, sizeof(struct Mouse)); - -/* - _game.clockEnabled = false; - _game.state = STATE_INIT; - - _keyQueueStart = 0; - _keyQueueEnd = 0; - - _allowSynthetic = false; - - g_tickTimer = 0; - - _intobj = NULL; - - _lastSentence[0] = 0; - memset(&_stringdata, 0, sizeof(struct StringData)); - - _objects = NULL; - - _oldMode = -1; - - _firstSlot = 0; -*/ } void PreAgiEngine::initialize() { @@ -166,11 +134,9 @@ void PreAgiEngine::initialize() { //_timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL); - _game.ver = -1; // Don't display the conf file warning - debugC(2, kDebugLevelMain, "Detect game"); - /* clear all resources and events */ + // clear all resources and events for (int i = 0; i < MAX_DIRS; i++) { memset(&_game.pictures[i], 0, sizeof(struct AgiPicture)); memset(&_game.sounds[i], 0, sizeof(class AgiSound *)); // _game.sounds contains pointers now @@ -190,10 +156,10 @@ PreAgiEngine::~PreAgiEngine() { Common::Error PreAgiEngine::go() { setflag(fSoundOn, true); // enable sound -/* -FIXME (Fingolfin asks): Why are Mickey, Winnie and Troll standalone classes - instead of being subclasses of PreAgiEngine ? -*/ +// +// FIXME (Fingolfin asks): Why are Mickey, Winnie and Troll standalone classes +// instead of being subclasses of PreAgiEngine ? +// // run preagi engine main loop switch (getGameID()) { diff --git a/engines/agi/preagi.h b/engines/agi/preagi.h index d7a1101c68..a134955d86 100644 --- a/engines/agi/preagi.h +++ b/engines/agi/preagi.h @@ -41,9 +41,10 @@ protected: void initialize(); public: - void agiTimerLow() {} - int agiGetKeypressLow() { return 0; } - int agiIsKeypressLow() { return 0; } + void pollTimer(void) {} + int getKeypress(void) { return 0; } + bool isKeypress(void) { return false; } + void clearKeyQueue(void) {} PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc); virtual ~PreAgiEngine(); diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 155fe1ad06..e728f2f695 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -92,8 +92,10 @@ void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) { readExe(offset, buffer, buflen); memcpy(ofs, buffer, sizeof(ofs)); + for (int i = 0; i < 256; i++) ofs[i] = buffer[i*2] + 256 * buffer[i*2+1]; + readExe(ofs[iItem] + IDI_MSA_OFS_EXE, buffer, buflen); } @@ -375,16 +377,16 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) { // Change cursor if (northIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) && - (event.mouse.y >= 0 && event.mouse.y <= 10)) { + (event.mouse.y >= 0 && event.mouse.y <= 10)) { _vm->_gfx->setCursorPalette(true); } else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) && - (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) { + (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) { _vm->_gfx->setCursorPalette(true); } else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) && - (event.mouse.x >= 20 && event.mouse.x <= 30)) { + (event.mouse.x >= 20 && event.mouse.x <= 30)) { _vm->_gfx->setCursorPalette(true); } else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) && - (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) { + (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) { _vm->_gfx->setCursorPalette(true); } else { _vm->_gfx->setCursorPalette(false); @@ -394,27 +396,39 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) { case Common::EVENT_LBUTTONUP: // Click to move if (northIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) && - (event.mouse.y >= 0 && event.mouse.y <= 10)) { - *sel0 = goIndex; *sel1 = northIndex; + (event.mouse.y >= 0 && event.mouse.y <= 10)) { + *sel0 = goIndex; + *sel1 = northIndex; + drawMenu(menu, *sel0, *sel1); + _vm->_gfx->setCursorPalette(false); _clickToMove = true; } else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) && - (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) { - *sel0 = goIndex; *sel1 = southIndex; + (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) { + *sel0 = goIndex; + *sel1 = southIndex; + drawMenu(menu, *sel0, *sel1); + _vm->_gfx->setCursorPalette(false); _clickToMove = true; } else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) && - (event.mouse.x >= 20 && event.mouse.x <= 30)) { - *sel0 = goIndex; *sel1 = westIndex; + (event.mouse.x >= 20 && event.mouse.x <= 30)) { + *sel0 = goIndex; + *sel1 = westIndex; + drawMenu(menu, *sel0, *sel1); + _vm->_gfx->setCursorPalette(false); _clickToMove = true; } else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) && - (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) { - *sel0 = goIndex; *sel1 = eastIndex; + (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) { + *sel0 = goIndex; + *sel1 = eastIndex; + drawMenu(menu, *sel0, *sel1); + _vm->_gfx->setCursorPalette(false); _clickToMove = true; } else { @@ -422,19 +436,26 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) { } return true; case Common::EVENT_RBUTTONUP: - *sel0 = 0; *sel1 = -1; + *sel0 = 0; + *sel1 = -1; return false; case Common::EVENT_WHEELUP: if (iRow < 2) { *sel -= 1; - if (*sel < 0) *sel = nWords - 1; + + if (*sel < 0) + *sel = nWords - 1; + drawMenu(menu, *sel0, *sel1); } break; case Common::EVENT_WHEELDOWN: if (iRow < 2) { *sel += 1; - if (*sel == nWords) *sel = 0; + + if (*sel == nWords) + *sel = 0; + drawMenu(menu, *sel0, *sel1); } break; @@ -458,28 +479,45 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) { break; case Common::KEYCODE_8: if (event.kbd.flags & Common::KBD_CTRL) { - *sel0 = 0; *sel1 = -1; return false; + *sel0 = 0; + *sel1 = -1; + + return false; } break; case Common::KEYCODE_ESCAPE: - *sel0 = 0; *sel1 = -1; return false; + *sel0 = 0; + *sel1 = -1; + + return false; case Common::KEYCODE_s: _vm->flipflag(fSoundOn); break; case Common::KEYCODE_c: inventory(); drawRoom(); - *sel0 = 0; *sel1 = -1; return false; + + *sel0 = 0; + *sel1 = -1; + + return false; case Common::KEYCODE_b: printRoomDesc(); drawMenu(menu, *sel0, *sel1); - *sel0 = 0; *sel1 = -1; return false; + + *sel0 = 0; + *sel1 = -1; + + return false; case Common::KEYCODE_LEFT: case Common::KEYCODE_KP4: case Common::KEYCODE_4: if (iRow < 2) { *sel -= 1; - if (*sel < 0) *sel = nWords - 1; + + if (*sel < 0) + *sel = nWords - 1; + drawMenu(menu, *sel0, *sel1); } break; @@ -489,7 +527,10 @@ bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) { case Common::KEYCODE_6: if (iRow < 2) { *sel += 1; - if (*sel == nWords) *sel = 0; + + if (*sel == nWords) + *sel = 0; + drawMenu(menu, *sel0, *sel1); } break; @@ -529,7 +570,9 @@ void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) { if (getMenuSelRow(menu, sel0, sel1, 0)) { if (_clickToMove) break; + *sel1 = 0; + if (getMenuSelRow(menu, sel0, sel1, 1)) { break; } @@ -557,6 +600,7 @@ void Mickey::centerMenu(MSA_MENU *menu) { } w += menu->row[iRow].count - 1; x = (40 - w) / 2; // FIX + for (iWord = 0; iWord < menu->row[iRow].count; iWord++) { menu->row[iRow].entry[iWord].x0 = x; x += strlen((char *)menu->row[iRow].entry[iWord].szText) + 1; @@ -688,6 +732,7 @@ void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) { Common::File file; if (!file.open(szFile)) return; + uint32 size = file.size(); file.read(buffer, size); file.close(); @@ -709,6 +754,7 @@ void Mickey::drawPic(int iPic) { Common::File file; if (!file.open(szFile)) return; + uint32 size = file.size(); file.read(buffer, size); file.close(); @@ -742,30 +788,32 @@ void Mickey::drawRoomAnimation() { case IDI_MSA_PIC_SHIP_MARS: case IDI_MSA_PIC_SHIP_URANUS: { - // draw blinking ship lights + // draw blinking ship lights - uint8 iColor = 0; + uint8 iColor = 0; - _vm->_picture->setPattern(2, 0); + _vm->_picture->setPattern(2, 0); - for (int i = 0; i < 12; i++) { - iColor = _game.nFrame + i; - if (iColor > 15) iColor -= 15; + for (int i = 0; i < 12; i++) { + iColor = _game.nFrame + i; + if (iColor > 15) + iColor -= 15; - objLight[1] = iColor; - objLight[4] += 7; + objLight[1] = iColor; + objLight[4] += 7; - _vm->_picture->setPictureData(objLight); - _vm->_picture->setPictureFlags(kPicFCircle); - _vm->_picture->drawPicture(); - } - _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT); + _vm->_picture->setPictureData(objLight); + _vm->_picture->setPictureFlags(kPicFCircle); + _vm->_picture->drawPicture(); + } + _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT); - _game.nFrame--; - if (_game.nFrame < 0) _game.nFrame = 15; + _game.nFrame--; + if (_game.nFrame < 0) + _game.nFrame = 15; - playSound(IDI_MSA_SND_PRESS_BLUE); + playSound(IDI_MSA_SND_PRESS_BLUE); } break; @@ -773,7 +821,9 @@ void Mickey::drawRoomAnimation() { // draw XL30 screen if (_game.fAnimXL30) { - if (_game.nFrame > 5) _game.nFrame = 0; + if (_game.nFrame > 5) + _game.nFrame = 0; + drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + _game.nFrame), 0, 4); _game.nFrame++; }; @@ -787,7 +837,8 @@ void Mickey::drawRoomAnimation() { if (!_game.fHasXtal) { switch(_game.iPlanet) { case IDI_MSA_PLANET_VENUS: - if (_game.iRmMenu[_game.iRoom] != 2) break; + if (_game.iRmMenu[_game.iRoom] != 2) + break; default: drawObj( IDI_MSA_OBJECT_CRYSTAL, @@ -882,6 +933,7 @@ void Mickey::drawLogo() { Common::File infile; if (!infile.open(szFile)) return; + infile.read(buffer, infile.size()); infile.close(); @@ -947,6 +999,7 @@ bool Mickey::loadGame() { sprintf(szFile, "%s.s%02d", _vm->getTargetName().c_str(), sel); if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) { printLine("PLEASE CHECK THE DISK DRIVE"); + if (_vm->getSelection(kSelAnyKey) == 0) return false; } else { @@ -1063,6 +1116,7 @@ void Mickey::saveGame() { sprintf(szFile, "%s.s%02d", _vm->getTargetName().c_str(), sel); if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) { printLine("PLEASE CHECK THE DISK DRIVE"); + if (_vm->getSelection(kSelAnyKey) == 0) return; } else { @@ -1658,15 +1712,18 @@ bool Mickey::parse(int cmd, int arg) { if (_game.fItem[IDI_MSA_ITEM_WRENCH]) { _game.iRmMenu[_game.iRoom] = 1; } + printDatMessage(arg); } break; case IDI_MSA_ACTION_USE_WRENCH: _game.fItemUsed[IDI_MSA_ITEM_WRENCH] = true; printDatString(arg); + if (_game.iRmPic[_game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) { _vm->clearRow(22); } + waitAnyKey(); break; case IDI_MSA_ACTION_GET_XTAL_VENUS: @@ -1685,11 +1742,13 @@ bool Mickey::parse(int cmd, int arg) { case IDI_MSA_ACTION_ENTER_OPENING: if (_game.fItemUsed[IDI_MSA_ITEM_CROWBAR]) { _game.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4; + return true; } else { if (_game.fItem[IDI_MSA_ITEM_CROWBAR]) { _game.iRmMenu[_game.iRoom] = 2; } + printDatMessage(arg); } break; @@ -1707,11 +1766,13 @@ bool Mickey::parse(int cmd, int arg) { if (_game.fItem[IDI_MSA_ITEM_SCARF]) { _game.iRmMenu[_game.iRoom] = 1; } + printDatMessage(arg); } break; case IDI_MSA_ACTION_TALK_LEADER: _game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY; + printDatMessage(arg); return true; case IDI_MSA_ACTION_GIVE_SCARF: @@ -1721,6 +1782,7 @@ bool Mickey::parse(int cmd, int arg) { _game.iRmMenu[_game.iRoom] = 0; _game.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2; _game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY; + return true; // MERCURY @@ -1740,7 +1802,9 @@ bool Mickey::parse(int cmd, int arg) { _game.iRmObj[_game.iRoom] = 17; _game.iRmMenu[_game.iRoom] = 2; _game.fItem[IDI_MSA_ITEM_SUNGLASSES] = false; + getXtal(arg); + break; // TITAN (SATURN) @@ -1751,11 +1815,15 @@ bool Mickey::parse(int cmd, int arg) { _game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1; _game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1; } + printDatMessage(arg); + break; case IDI_MSA_ACTION_USE_MATTRESS: _game.iRoom = IDI_MSA_PIC_SATURN_ISLAND; + printDatMessage(arg); + return true; case IDI_MSA_ACTION_GET_XTAL_SATURN: if (_game.fHasXtal) { @@ -1766,7 +1834,9 @@ bool Mickey::parse(int cmd, int arg) { break; case IDI_MSA_ACTION_LEAVE_ISLAND: _game.iRoom = IDI_MSA_PIC_SATURN_LAKE_1; + printDatMessage(arg); + return true; // PLUTO @@ -1785,7 +1855,9 @@ bool Mickey::parse(int cmd, int arg) { _game.fItem[IDI_MSA_ITEM_BONE] = false; _game.iRmMenu[_game.iRoom] = 0; _game.iRmObj[_game.iRoom] = 16; + getXtal(arg); + break; // IO (JUPITER) @@ -1829,12 +1901,15 @@ bool Mickey::parse(int cmd, int arg) { _game.nItems--; _game.iRmObj[_game.iRoom]++; _game.iRmMenu[_game.iRoom] = 0; + drawRoom(); + if (_game.nRocks) { printDatMessage(37); } else { printDatMessage(arg); } + _game.nRocks++; break; @@ -1844,11 +1919,15 @@ bool Mickey::parse(int cmd, int arg) { if (_game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) { _game.iRmMenu[_game.iRoom] = 1; } + printDatMessage(arg); + break; case IDI_MSA_ACTION_USE_FLASHLIGHT: _game.iRoom = IDI_MSA_PIC_MARS_TUBE_1; + printDatMessage(15); + return true; case IDI_MSA_ACTION_PLUTO_DIG: if (_game.fHasXtal) { @@ -1869,6 +1948,7 @@ bool Mickey::parse(int cmd, int arg) { case IDI_MSA_ACTION_ENTER_TEMPLE: _game.iRoom = IDI_MSA_PIC_URANUS_TEMPLE; + return true; case IDI_MSA_ACTION_USE_CRYSTAL: if (_game.iRmMenu[_game.iRoom]) { @@ -1876,8 +1956,11 @@ bool Mickey::parse(int cmd, int arg) { } else { _game.iRmMenu[_game.iRoom] = 1; _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1; + drawRoom(); + _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE; + printDatMessage(arg); } break; @@ -1887,13 +1970,16 @@ bool Mickey::parse(int cmd, int arg) { } else { _game.fTempleDoorOpen = 1; _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2; + drawRoom(); + printDatMessage(arg); } break; case IDI_MSA_ACTION_ENTER_DOOR: if (_game.fTempleDoorOpen) { _game.iRoom = IDI_MSA_PIC_URANUS_STEPS; + return true; } else { printDatMessage(arg); @@ -1911,7 +1997,9 @@ bool Mickey::parse(int cmd, int arg) { break; case IDI_MSA_ACTION_USE_CROWBAR_1: _game.iRmMenu[_game.iRoom] = 0; + getXtal(arg); + break; // SPACESHIP @@ -1935,11 +2023,14 @@ bool Mickey::parse(int cmd, int arg) { if ((_game.iPlanet == _game.iPlanetXtal[_game.nXtals]) || (_game.iPlanet == IDI_MSA_PLANET_EARTH)) { _game.fHasXtal = false; _game.iRoom = IDI_MSA_HOME_PLANET[_game.iPlanet]; + if (_game.iPlanet != IDI_MSA_PLANET_EARTH) insertDisk(1); + return true; } else { _game.iRoom = IDI_MSA_SHIP_PLANET[_game.iPlanet]; + return true; } } else { @@ -1953,13 +2044,17 @@ bool Mickey::parse(int cmd, int arg) { } else { _game.fShipDoorOpen = false; _game.iRmPic[_game.iRoom]--; + drawRoom(); + printDatMessage(2); } } else { _game.fShipDoorOpen = true; _game.iRmPic[_game.iRoom]++; + drawRoom(); + printDatMessage(14); } break; @@ -1969,7 +2064,9 @@ bool Mickey::parse(int cmd, int arg) { _game.fSuit = false; _game.iRmMenu[_game.iRoom] = 0; _game.iRmPic[_game.iRoom] -= 2; + drawRoom(); + printDatMessage(13); } else { printDatMessage(3); @@ -1979,7 +2076,9 @@ bool Mickey::parse(int cmd, int arg) { _game.fSuit = true; _game.iRmMenu[_game.iRoom] = 1; _game.iRmPic[_game.iRoom] += 2; + drawRoom(); + printDatMessage(arg); } else { printDatMessage(12); @@ -1988,11 +2087,11 @@ bool Mickey::parse(int cmd, int arg) { break; case IDI_MSA_ACTION_READ_GAUGE: printDatString(arg); - _vm->drawStr(21, 15, IDA_DEFAULT, - (const char *)IDS_MSA_TEMP_C[_game.iPlanet]); - _vm->drawStr(21, 23, IDA_DEFAULT, - (const char *)IDS_MSA_TEMP_F[_game.iPlanet]); + _vm->drawStr(21, 15, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_C[_game.iPlanet]); + _vm->drawStr(21, 23, IDA_DEFAULT, (const char *)IDS_MSA_TEMP_F[_game.iPlanet]); + waitAnyKey(); + break; case IDI_MSA_ACTION_PRESS_ORANGE: if (_game.fFlying) { @@ -2019,12 +2118,18 @@ bool Mickey::parse(int cmd, int arg) { if (_game.fFlying) { _game.fFlying = false; _game.nButtons = 0; + memset(_game.szAddr, 0, sizeof(_game.szAddr)); + drawRoom(); + printDatString(22); + _vm->drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET, IDA_DEFAULT, (const char *)IDS_MSA_PLANETS[_game.iPlanet]); + waitAnyKey(true); + showPlanetInfo(); } else { printDatMessage(arg); @@ -2037,11 +2142,15 @@ bool Mickey::parse(int cmd, int arg) { if (getPlanet() != -1) { _game.fFlying = true; _game.iPlanet = getPlanet(); + drawRoom(); + printDatMessage(16); } else { _game.nButtons = 0; + memset(_game.szAddr, 0, sizeof(_game.szAddr)); + printDatMessage(17); } } @@ -2060,23 +2169,32 @@ bool Mickey::parse(int cmd, int arg) { } else { _game.iRmMenu[_game.iRoom] = 1; _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1; + drawRoom(); + printDatMessage(arg); } break; case IDI_MSA_ACTION_READ_MAP: _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_STAR_MAP; + drawRoom(); + printDatMessage(46); printDatMessage(47); printDatMessage(48); + _game.iRmPic[_game.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM; + drawRoom(); break; case IDI_MSA_ACTION_GO_WEST: _game.nButtons = 0; + memset(_game.szAddr, 0, sizeof(_game.szAddr)); + _game.iRoom = arg; + return true; } diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp index b72a617948..e34949c8fe 100644 --- a/engines/agi/preagi_troll.cpp +++ b/engines/agi/preagi_troll.cpp @@ -80,7 +80,9 @@ bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { case Common::KEYCODE_t: case Common::KEYCODE_f: inventory(); + return false; + break; case Common::KEYCODE_DOWN: case Common::KEYCODE_SPACE: @@ -282,6 +284,7 @@ void Troll::tutorial() { done = false; while (!done && !_vm->shouldQuit()) { getMenuSel(IDS_TRO_TUTORIAL_1, &iSel, IDI_TRO_MAX_OPTION); + switch(iSel) { case IDI_TRO_SEL_OPTION_1: _vm->clearScreen(0x22, false); @@ -410,6 +413,7 @@ void Troll::gameOver() { _vm->drawStr(21, 1, kColorDefault, szMoves); _vm->drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1); _vm->_gfx->doUpdate(); + pressAnyKey(); } @@ -474,12 +478,6 @@ void Troll::playTune(int tune, int len) { if (!_soundOn) return; - warning("STUB: playTune(%d, %d)", tune, len); - - // TODO: - // - // apparently sound format consist of 16bit LE pairs of frequency and duration - int freq, duration; int ptr = _tunes[tune - 1]; diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index 1341adcef8..ac0d3625b2 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -150,9 +150,11 @@ void Winnie::randomize() { for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) { done = false; + while (!done) { iObj = _vm->rnd(IDI_WTP_MAX_OBJ - 1); done = true; + for (int j = 0; j < IDI_WTP_MAX_OBJ_MISSING; j++) { if (_game.iUsedObj[j] == iObj) { done = false; @@ -167,6 +169,7 @@ void Winnie::randomize() { while (!done) { iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL); done = true; + for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) { if (_game.iObjRoom[j] == iRoom) { done = false; @@ -185,17 +188,23 @@ void Winnie::intro() { _vm->_gfx->doUpdate(); _vm->_system->updateScreen(); _vm->_system->delayMillis(0x640); + if (_vm->getPlatform() == Common::kPlatformAmiga) _vm->_gfx->clearScreen(0); + drawPic(IDS_WTP_FILE_TITLE); + _vm->printStr(IDS_WTP_INTRO_1); _vm->_gfx->doUpdate(); _vm->_system->updateScreen(); _vm->_system->delayMillis(0x640); + if (!playSound(IDI_WTP_SND_POOH_0)) return; + if (!playSound(IDI_WTP_SND_POOH_1)) return; + if (!playSound(IDI_WTP_SND_POOH_2)) return; } @@ -346,6 +355,7 @@ int Winnie::parser(int pc, int index, uint8 *buffer) { case IDI_WTP_SEL_EAST: case IDI_WTP_SEL_WEST: iDir = iSel - IDI_WTP_SEL_NORTH; + if (hdr.roomNew[iDir] == IDI_WTP_ROOM_NONE) { _vm->printStr(IDS_WTP_CANT_GO); _vm->getSelection(kSelAnyKey); @@ -517,6 +527,7 @@ void Winnie::takeObj(int iRoom) { } else { // take object int iObj = getObjInRoom(iRoom); + _game.iObjHave = iObj; _game.iObjRoom[iObj] = 0; @@ -590,8 +601,10 @@ void Winnie::dropObj(int iRoom) { // object has been dropped in the wrong place _vm->printStr(IDS_WTP_WRONG_PLACE); _vm->getSelection(kSelAnyKey); + playSound(IDI_WTP_SND_DROP); drawRoomPic(); + _vm->printStr(IDS_WTP_WRONG_PLACE); _vm->getSelection(kSelAnyKey); @@ -639,6 +652,7 @@ void Winnie::wind() { _vm->printStr(IDS_WTP_WIND_0); playSound(IDI_WTP_SND_WIND_0); _vm->getSelection(kSelAnyKey); + _vm->printStr(IDS_WTP_WIND_1); playSound(IDI_WTP_SND_WIND_0); _vm->getSelection(kSelAnyKey); @@ -652,6 +666,7 @@ void Winnie::wind() { while (!done) { iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL); done = true; + for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) { if (_game.iObjRoom[j] == iRoom) { done = false; @@ -1006,11 +1021,13 @@ phase0: drawRoomPic(); _vm->_gfx->doUpdate(); _vm->_system->updateScreen(); + phase1: if (getObjInRoom(_room)) { printObjStr(getObjInRoom(_room), IDI_WTP_OBJ_DESC); _vm->getSelection(kSelAnyKey); } + phase2: for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) { if (parser(hdr.ofsDesc[iBlock] - _roomOffset, iBlock, roomdata) == IDI_WTP_PAR_BACK) @@ -1047,6 +1064,7 @@ void Winnie::drawPic(const char *szName) { warning ("Could not open file \'%s\'", szFile); return; } + uint32 size = file.size(); file.read(buffer, size); file.close(); diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 59030494bd..c2f031ea75 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -176,9 +176,7 @@ bool AgiEngine::predictiveDialog(void) { } } - /* clear key queue */ - while (_gfx->keypress()) - _gfx->getKey(); + clearKeyQueue(); prefix.clear(); _currentCode.clear(); @@ -234,7 +232,7 @@ bool AgiEngine::predictiveDialog(void) { _gfx->doUpdate(); } - _gfx->pollTimer(); /* msdos driver -> does nothing */ + pollTimer(); key = doPollKeyboard(); processkey = false; switch (key) { @@ -274,7 +272,7 @@ bool AgiEngine::predictiveDialog(void) { active = 14; processkey = true; break; - case 0x09: /* Tab */ + case 0x09: // Tab navigationwithkeys = true; debugC(3, kDebugLevelText, "Focus change"); lastactive = active = lastactive + 1; diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 2130473810..7c84f1dd72 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -23,10 +23,10 @@ * */ -/* - * Savegame support by Vasyl Tsvirkunov <vasyl@pacbell.net> - * Multi-slots by Claudio Matsuoka <claudio@helllabs.org> - */ +// +// Savegame support by Vasyl Tsvirkunov <vasyl@pacbell.net> +// Multi-slots by Claudio Matsuoka <claudio@helllabs.org> +// #include <time.h> // for extended infos @@ -39,22 +39,23 @@ #include "agi/keyboard.h" #include "agi/menu.h" -#define SAVEGAME_VERSION 4 +#define SAVEGAME_VERSION 5 -/* - * Version 0 (Sarien): view table has 64 entries - * Version 1 (Sarien): view table has 256 entries (needed in KQ3) - * Version 2 (ScummVM): first ScummVM version - * Version 3 (ScummVM): added AGIPAL save/load support - * Version 4 (ScummVM): added thumbnails and save creation date/time - */ +// +// Version 0 (Sarien): view table has 64 entries +// Version 1 (Sarien): view table has 256 entries (needed in KQ3) +// Version 2 (ScummVM): first ScummVM version +// Version 3 (ScummVM): added AGIPAL save/load support +// Version 4 (ScummVM): added thumbnails and save creation date/time +// Version 5 (ScummVM): Added game md5 +// namespace Agi { -static const uint32 AGIflag=MKID_BE('AGI:'); +static const uint32 AGIflag = MKID_BE('AGI:'); int AgiEngine::saveGame(const char *fileName, const char *description) { - char gameIDstring[8]="gameIDX"; + char gameIDstring[8] = "gameIDX"; int i; Common::OutSaveFile *out; int result = errOK; @@ -96,6 +97,10 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->write(gameIDstring, 8); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game id (%s, %s)", gameIDstring, _game.id); + const char *tmp = getGameMD5(); + for (i = 0; i < 32; i++) + out->writeByte(tmp[i]); + for (i = 0; i < MAX_FLAGS; i++) out->writeByte(_game.flags[i]); for (i = 0; i < MAX_VARS; i++) @@ -128,20 +133,20 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->writeSint16BE((int16)_game.colorFg); out->writeSint16BE((int16)_game.colorBg); - /* game.hires */ - /* game.sbuf */ - /* game.ego_words */ - /* game.num_ego_words */ + // game.hires + // game.sbuf + // game.ego_words + // game.num_ego_words out->writeSint16BE((int16)_game.numObjects); for (i = 0; i < (int16)_game.numObjects; i++) out->writeSint16BE((int16)objectGetLocation(i)); - /* game.ev_keyp */ + // game.ev_keyp for (i = 0; i < MAX_STRINGS; i++) out->write(_game.strings[i], MAX_STRINGLEN); - /* record info about loaded resources */ + // record info about loaded resources for (i = 0; i < MAX_DIRS; i++) { out->writeByte(_game.dirLogic[i].flags); out->writeSint16BE((int16)_game.logics[i].sIP); @@ -154,10 +159,10 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { for (i = 0; i < MAX_DIRS; i++) out->writeByte(_game.dirSound[i].flags); - /* game.pictures */ - /* game.logics */ - /* game.views */ - /* game.sounds */ + // game.pictures + // game.logics + // game.views + // game.sounds for (i = 0; i < MAX_VIEWTABLE; i++) { VtEntry *v = &_game.viewTable[i]; @@ -169,23 +174,23 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->writeSint16BE(v->yPos); out->writeByte(v->currentView); - /* v->view_data */ + // v->view_data out->writeByte(v->currentLoop); out->writeByte(v->numLoops); - /* v->loop_data */ + // v->loop_data out->writeByte(v->currentCel); out->writeByte(v->numCels); - /* v->cel_data */ - /* v->cel_data_2 */ + // v->cel_data + // v->cel_data_2 out->writeSint16BE(v->xPos2); out->writeSint16BE(v->yPos2); - /* v->s */ + // v->s out->writeSint16BE(v->xSize); out->writeSint16BE(v->ySize); @@ -206,7 +211,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->writeByte(v->parm4); } - /* Save image stack */ + // Save image stack for (i = 0; i < _imageStack.size(); i++) { ImageStackElement ise = _imageStack[i]; @@ -299,19 +304,37 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { strncpy(_game.id, loadId, 8); + if (saveVersion >= 5) { + char md5[32 + 1]; + + for (i = 0; i < 32; i++) { + md5[i] = in->readByte(); + + } + md5[i] = 0; // terminate + + debug(0, "Saved game MD5: %s", md5); + + if (strcmp(md5, getGameMD5())) { + warning("Game was saved with different gamedata - you may encounter problems"); + + debug(0, "You have %s and save is %s.", getGameMD5(), md5); + } + } + for (i = 0; i < MAX_FLAGS; i++) _game.flags[i] = in->readByte(); for (i = 0; i < MAX_VARS; i++) _game.vars[i] = in->readByte(); - setvar(vFreePages, 255); // Set amount of free memory to the maximum value (Overwriting the just loaded value) + setvar(vFreePages, 180); // Set amount of free memory to realistic value (Overwriting the just loaded value) _game.horizon = in->readSint16BE(); _game.lineStatus = in->readSint16BE(); _game.lineUserInput = in->readSint16BE(); _game.lineMinPrint = in->readSint16BE(); - /* These are never saved */ + // These are never saved _game.cursorPos = 0; _game.inputBuffer[0] = 0; _game.echoBuffer[0] = 0; @@ -339,27 +362,27 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { _game.msgBoxTicks = 0; _game.block.active = false; - /* game.window - fixed by close_window() */ - /* game.has_window - fixed by close_window() */ + // game.window - fixed by close_window() + // game.has_window - fixed by close_window() _game.gfxMode = in->readSint16BE(); _game.cursorChar = in->readByte(); _game.colorFg = in->readSint16BE(); _game.colorBg = in->readSint16BE(); - /* game.hires - rebuilt from image stack */ - /* game.sbuf - rebuilt from image stack */ + // game.hires - rebuilt from image stack + // game.sbuf - rebuilt from image stack - /* game.ego_words - fixed by clean_input */ - /* game.num_ego_words - fixed by clean_input */ + // game.ego_words - fixed by clean_input + // game.num_ego_words - fixed by clean_input _game.numObjects = in->readSint16BE(); for (i = 0; i < (int16)_game.numObjects; i++) objectSetLocation(i, in->readSint16BE()); - /* Those are not serialized */ + // Those are not serialized for (i = 0; i < MAX_DIRS; i++) { - _game.evKeyp[i].occured = false; + _game.controllerOccured[i] = false; } for (i = 0; i < MAX_STRINGS; i++) @@ -395,10 +418,10 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { agiUnloadResource(rSOUND, i); } - /* game.pictures - loaded above */ - /* game.logics - loaded above */ - /* game.views - loaded above */ - /* game.sounds - loaded above */ + // game.pictures - loaded above + // game.logics - loaded above + // game.views - loaded above + // game.sounds - loaded above for (i = 0; i < vtEntries; i++) { VtEntry *v = &_game.viewTable[i]; @@ -410,23 +433,23 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { v->yPos = in->readSint16BE(); v->currentView = in->readByte(); - /* v->view_data - fixed below */ + // v->view_data - fixed below v->currentLoop = in->readByte(); v->numLoops = in->readByte(); - /* v->loop_data - fixed below */ + // v->loop_data - fixed below v->currentCel = in->readByte(); v->numCels = in->readByte(); - /* v->cel_data - fixed below */ - /* v->cel_data_2 - fixed below */ + // v->cel_data - fixed below + // v->cel_data_2 - fixed below v->xPos2 = in->readSint16BE(); v->yPos2 = in->readSint16BE(); - /* v->s - fixed below */ + // v->s - fixed below v->xSize = in->readSint16BE(); v->ySize = in->readSint16BE(); @@ -450,7 +473,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { memset(&_game.viewTable[i], 0, sizeof(VtEntry)); } - /* Fix some pointers in viewtable */ + // Fix some pointers in viewtable for (i = 0; i < MAX_VIEWTABLE; i++) { VtEntry *v = &_game.viewTable[i]; @@ -461,20 +484,20 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { if (!(_game.dirView[v->currentView].flags & RES_LOADED)) agiLoadResource(rVIEW, v->currentView); - setView(v, v->currentView); /* Fix v->view_data */ - setLoop(v, v->currentLoop); /* Fix v->loop_data */ - setCel(v, v->currentCel); /* Fix v->cel_data */ + setView(v, v->currentView); // Fix v->view_data + setLoop(v, v->currentLoop); // Fix v->loop_data + setCel(v, v->currentCel); // Fix v->cel_data v->celData2 = v->celData; - v->s = NULL; /* not sure if it is used... */ + v->s = NULL; // not sure if it is used... } _sprites->eraseBoth(); - /* Clear input line */ + // Clear input line _gfx->clearScreen(0); writeStatus(); - /* Recreate background from saved image stack */ + // Recreate background from saved image stack clearImageStack(); while ((t = in->readByte()) != 0) { for (i = 0; i < 7; i++) @@ -483,7 +506,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { parm[3], parm[4], parm[5], parm[6]); } - //Load AGIPAL Data + // Load AGIPAL Data if (saveVersion >= 3) _gfx->setAGIPal(in->readSint16BE()); @@ -492,7 +515,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { setflag(fRestoreJustRan, true); - _game.hasPrompt = 0; /* force input line repaint if necessary */ + _game.hasPrompt = 0; // force input line repaint if necessary cleanInput(); _sprites->eraseBoth(); @@ -517,20 +540,23 @@ const char *AgiEngine::getSavegameFilename(int num) { } void AgiEngine::getSavegameDescription(int num, char *buf, bool showEmpty) { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; Common::InSaveFile *in; debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Current game id is %s", _targetName.c_str()); sprintf(fileName, "%s", getSavegameFilename(num)); if (!(in = _saveFileMan->openForLoading(fileName))) { debugC(4, kDebugLevelMain | kDebugLevelSavegame, "File %s does not exist", fileName); + if (showEmpty) strcpy(buf, " (empty slot)"); else *buf = 0; } else { debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName); + uint32 type = in->readUint32BE(); + if (type == AGIflag) { debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start"); in->read(buf, 31); @@ -546,13 +572,13 @@ void AgiEngine::getSavegameDescription(int num, char *buf, bool showEmpty) { int AgiEngine::selectSlot() { int i, key, active = 0; int rc = -1; - int hm = 1, vm = 3; /* box margins */ + int hm = 1, vm = 3; // box margins int xmin, xmax, slotClicked; char desc[NUM_VISIBLE_SLOTS][40]; int textCentre, buttonLength, buttonX[2], buttonY; const char *buttonText[] = { " OK ", "Cancel", NULL }; - setflag(fNoSaveLoadAllowed, true); + _noSaveLoadAllowed = true; for (i = 0; i < NUM_VISIBLE_SLOTS; i++) { getSavegameDescription(_firstSlot + i, desc[i]); @@ -571,7 +597,7 @@ int AgiEngine::selectSlot() { int oldFirstSlot = _firstSlot + 1; int oldActive = active + 1; - while (!(shouldQuit() || restartGame)) { + while (!(shouldQuit() || _restartGame)) { int sbPos = 0; // Use the extreme scrollbar positions only if the extreme @@ -613,7 +639,7 @@ int AgiEngine::selectSlot() { oldFirstSlot = _firstSlot; } - _gfx->pollTimer(); /* msdos driver -> does nothing */ + pollTimer(); key = doPollKeyboard(); // It may happen that somebody will open GMM while @@ -643,7 +669,7 @@ int AgiEngine::selectSlot() { rc = -1; goto getout; } - slotClicked = ((int)g_mouse.y-1)/CHAR_COLS-(vm+4); + slotClicked = ((int)g_mouse.y - 1) / CHAR_COLS - (vm + 4); xmin = (hm + 1) * CHAR_COLS; xmax = xmin + CHAR_COLS * 34; if ((int)g_mouse.x >= xmin && (int)g_mouse.x <= xmax) { @@ -737,13 +763,13 @@ press: getout: closeWindow(); - setflag(fNoSaveLoadAllowed, false); + _noSaveLoadAllowed = false; return rc; } int AgiEngine::saveGameDialog() { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; char *desc; const char *buttons[] = { "Do as I say!", "I regret", NULL }; char dstr[200]; @@ -828,7 +854,7 @@ int AgiEngine::saveGameDialog() { } int AgiEngine::saveGameSimple() { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; sprintf(fileName, "%s", getSavegameFilename(0)); int result = saveGame(fileName, "Default savegame"); @@ -838,9 +864,9 @@ int AgiEngine::saveGameSimple() { } int AgiEngine::loadGameDialog() { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; int rc, slot = 0; - int hm, vm, hp, vp; /* box margins */ + int hm, vm, hp, vp; // box margins int w; hm = 1; @@ -879,7 +905,7 @@ int AgiEngine::loadGameDialog() { } int AgiEngine::loadGameSimple() { - char fileName[MAX_PATH]; + char fileName[MAXPATHLEN]; int rc = 0; sprintf(fileName, "%s", getSavegameFilename(0)); diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index e93ebd7b43..fb73c6b71f 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -37,8 +37,9 @@ namespace Agi { #define USE_INTERPOLATION static bool g_useChorus = true; -/* TODO: add support for variable sampling rate in the output device - */ +// +// TODO: add support for variable sampling rate in the output device +// AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) { if (data == NULL || len < 2) // Check for too small resource or no resource at all @@ -83,6 +84,7 @@ PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A const uint8 *PCjrSound::getVoicePointer(uint voiceNum) { assert(voiceNum < 4); uint16 voiceStartOffset = READ_LE_UINT16(_data + voiceNum * 2); + return _data + voiceStartOffset; } @@ -99,11 +101,13 @@ IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : // of sample data although header says it should have 16384 bytes. warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", resnum, tailLen, _header.sampleSize); + _header.sampleSize = (uint16) tailLen; // Use the part that's left } if (_header.pitch > 0x7F) { // Check if the pitch is invalid warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); + _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too } @@ -113,6 +117,7 @@ IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : // Convert sample data from 8-bit unsigned to 8-bit signed format stream.seek(sampleStartPos); _sample = new int8[_header.sampleSize]; + if (_sample != NULL) _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize); } @@ -127,6 +132,7 @@ bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { seg[segNum].bp = stream.readByte(); seg[segNum].inc = stream.readUint16LE(); } + return !stream.ioFailed(); } @@ -170,6 +176,7 @@ bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { size = trueSize; // Set the true sample size uint8Wave.seek(startPos); // Seek back to the stream's starting position + return true; } @@ -177,6 +184,7 @@ bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) if (!waves[i].finalize(uint8Wave)) return false; + return true; } @@ -188,6 +196,7 @@ bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillato return false; count = oscillatorCount; // Set the oscillator count + return true; } @@ -195,6 +204,7 @@ bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { for (uint i = 0; i < count; i++) if (!osc[i].finalize(uint8Wave)) return false; + return true; } @@ -225,6 +235,7 @@ bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { instrumentSize = stream.readUint16LE(); sampleSize = stream.readUint16LE(); // Read the instrument header *ignoring* its wave address info + return instrument.read(stream, true); } @@ -287,7 +298,7 @@ static const int16 waveformRamp[WAVEFORM_SIZE] = { 0, -248, -240, -232, -224, -216, -208, -200, -192, -184, -176, -168, -160, -152, -144, -136, -128, -120, -112, -104, -96, -88, -80, -72, - -64, -56, -48, -40, -32, -24, -16, -8 /* Ramp up */ + -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up }; static const int16 waveformSquare[WAVEFORM_SIZE] = { @@ -298,7 +309,7 @@ static const int16 waveformSquare[WAVEFORM_SIZE] = { -255, -230, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -110, 0, 0, 0, 0 /* Square */ + -220, -220, -220, -110, 0, 0, 0, 0 // Square }; static const int16 waveformMac[WAVEFORM_SIZE] = { @@ -356,7 +367,7 @@ void SoundMgr::startSound(int resnum, int flag) { _vm->_game.sounds[resnum]->play(); _playingSound = resnum; - debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d)", resnum, flag); + debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d) type = %d", resnum, flag, type); switch (type) { case AGI_SOUND_SAMPLE: { @@ -369,14 +380,17 @@ void SoundMgr::startSound(int resnum, int flag) { break; case AGI_SOUND_4CHN: PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; - /* Initialize channel info */ + + // Initialize channel info for (i = 0; i < NUM_CHANNELS; i++) { _chn[i].type = type; _chn[i].flags = AGI_SOUND_LOOP; + if (_env) { _chn[i].flags |= AGI_SOUND_ENVELOPE; _chn[i].adsr = AGI_SOUND_ENV_ATTACK; } + _chn[i].ins = _waveform; _chn[i].size = WAVEFORM_SIZE; _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); @@ -390,14 +404,15 @@ void SoundMgr::startSound(int resnum, int flag) { memset(_sndBuffer, 0, BUFFER_SIZE << 1); _endflag = flag; - /* Nat Budin reports that the flag should be reset when sound starts - */ + // Nat Budin reports that the flag should be reset when sound starts _vm->setflag(_endflag, false); } void SoundMgr::stopSound() { int i; + debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); + _endflag = -1; if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { for (i = 0; i < NUM_CHANNELS; i++) @@ -405,7 +420,8 @@ void SoundMgr::stopSound() { } if (_playingSound != -1) { - _vm->_game.sounds[_playingSound]->stop(); + if (_vm->_game.sounds[_playingSound]) // sanity checking + _vm->_game.sounds[_playingSound]->stop(); if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { _gsSound.stopSounds(); @@ -424,9 +440,11 @@ void IIgsSoundMgr::stopSounds() { bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { stopSounds(); IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; + channel.setInstrument(&sampleHeader.instrument, sample); channel.setVolume(sampleHeader.volume); channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64) + return true; } @@ -434,6 +452,7 @@ void IIgsMidiChannel::stopSounds() { // Stops all sounds on this single MIDI channel for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); iter++) iter->stop(); + _gsChannels.clear(); } @@ -458,6 +477,8 @@ int SoundMgr::initSound() { case SOUND_EMU_APPLE2GS: _disabledMidi = !loadInstruments(); break; + case SOUND_EMU_COCO3: + break; } report("Initializing sound:\n"); @@ -476,6 +497,7 @@ int SoundMgr::initSound() { void SoundMgr::deinitSound() { debugC(3, kDebugLevelSound, "()"); + _mixer->stopHandle(_soundHandle); } @@ -483,7 +505,7 @@ void SoundMgr::stopNote(int i) { _chn[i].adsr = AGI_SOUND_ENV_RELEASE; if (g_useChorus) { - /* Stop chorus ;) */ + // Stop chorus ;) if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { stopNote(i + 4); @@ -504,12 +526,15 @@ void SoundMgr::playNote(int i, int freq, int vol) { _chn[i].adsr = AGI_SOUND_ENV_ATTACK; if (g_useChorus) { - /* Add chorus ;) */ + // Add chorus ;) if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + int newfreq = freq * 1007 / 1000; + if (freq == newfreq) newfreq++; + playNote(i + 4, newfreq, vol * 2 / 3); } } @@ -526,6 +551,7 @@ void SoundMgr::playMidiSound() { if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { warning("Error playing Apple IIGS MIDI sound resource"); _playing = false; + return; } @@ -543,11 +569,14 @@ void SoundMgr::playMidiSound() { if (readByte == MIDI_BYTE_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); _playing = false; + midiObj->rewind(); + return; } else if (readByte == MIDI_BYTE_TIMER_SYNC) { debugC(3, kDebugLevelSound, "Timer sync"); p++; // Jump over the timer sync byte as it's not needed + continue; } @@ -562,7 +591,9 @@ void SoundMgr::playMidiSound() { if (*p == MIDI_BYTE_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); _playing = false; + midiObj->rewind(); + return; } @@ -597,6 +628,7 @@ void SoundMgr::playMidiSound() { case MIDI_CMD_PITCH_WHEEL: parm1 = *p++; parm2 = *p++; + uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value _gsSound.midiPitchWheel(wheelPos); break; @@ -675,22 +707,27 @@ void IIgsMidiChannel::removeStoppedSounds() { uint IIgsSoundMgr::activeSounds() const { uint result = 0; + for (Common::Array<IIgsMidiChannel>::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); iter++) result += iter->activeSounds(); + return result; } uint IIgsMidiChannel::activeSounds() const { uint result = 0; + for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); iter++) if (!iter->end) result++; + return result; } void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { _instrument = instrument; _sample = sample; + // Set program on each Apple IIGS channel playing on this MIDI channel for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); iter++) iter->setInstrument(instrument, sample); @@ -698,6 +735,7 @@ void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, cons void IIgsMidiChannel::setVolume(uint8 volume) { _volume = volume; + // Set volume on each Apple IIGS channel playing on this MIDI channel for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); iter++) iter->setChannelVolume(volume); @@ -713,9 +751,11 @@ void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) { void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) { IIgsChannelInfo channel; + // Use the default channel volume and instrument channel.setChannelVolume(_volume); channel.setInstrument(_instrument, _sample); + // Set the note on and save the channel channel.noteOn(note, velocity); _gsChannels.push_back(channel); @@ -742,11 +782,15 @@ void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) { this->origNote = noteParam; this->startEnvVol = intToFrac(0); rewind(); + const IIgsWaveInfo *waveInfo = NULL; + for (uint i = 0; i < ins->oscList.count; i++) if (ins->oscList(i).waves[0].top >= noteParam) waveInfo = &ins->oscList(i).waves[0]; + assert(waveInfo != NULL); + this->relocatedSample = this->unrelocatedSample + waveInfo->addr; this->posAdd = intToFrac(0); this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0); @@ -780,6 +824,35 @@ void SoundMgr::playSampleSound() { _playing = _gsSound.activeSounds() > 0; } +static int cocoFrequencies[] = { + 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, + 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, + 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987, + 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975, + 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951 +}; + +void SoundMgr::playCoCoSound() { + int i = 0; + CoCoNote note; + + do { + note.read(_chn[i].ptr); + + if (note.freq != 0xff) { + playNote(0, cocoFrequencies[note.freq], note.volume); + + uint32 start_time = _vm->_system->getMillis(); + + while (_vm->_system->getMillis() < start_time + note.duration) { + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + } + } while (note.freq != 0xff); +} + void SoundMgr::playAgiSound() { int i; AgiNote note; @@ -808,7 +881,7 @@ void SoundMgr::playAgiSound() { _chn[i].env = 0; if (g_useChorus) { - /* chorus */ + // chorus if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { _chn[i + 4].vol = 0; _chn[i + 4].env = 0; @@ -836,6 +909,8 @@ void SoundMgr::playSound() { playSampleSound(); } } + } else if (_vm->_soundemu == SOUND_EMU_COCO3) { + playCoCoSound(); } else { //debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound"); playAgiSound(); @@ -929,7 +1004,7 @@ uint32 SoundMgr::mixSound(void) { } _gsSound.removeStoppedSounds(); return IIGS_BUFFER_SIZE; - } /* else ... */ + } // else ... // Handle PCjr 4-channel sound mixing here for (c = 0; c < NUM_CHANNELS; c++) { @@ -954,7 +1029,7 @@ uint32 SoundMgr::mixSound(void) { // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what // needs fixing, or remove it! - /* FIXME */ + // FIXME if (_chn[c].flags & AGI_SOUND_LOOP) { p %= _chn[c].size << 8; } else { @@ -968,7 +1043,7 @@ uint32 SoundMgr::mixSound(void) { } _chn[c].phase = p; } else { - /* Add white noise */ + // Add white noise for (i = 0; i < BUFFER_SIZE; i++) { b = _vm->_rnd->getRandomNumber(255) - 128; _sndBuffer[i] += (b * m) >> 4; @@ -977,7 +1052,7 @@ uint32 SoundMgr::mixSound(void) { switch (_chn[c].adsr) { case AGI_SOUND_ENV_ATTACK: - /* not implemented */ + // not implemented _chn[c].adsr = AGI_SOUND_ENV_DECAY; break; case AGI_SOUND_ENV_DECAY: @@ -1040,6 +1115,7 @@ bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const II // Check instrument set's md5sum data->seek(exeInfo.instSetStart); + char md5str[32+1]; Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount); if (scumm_stricmp(md5str, exeInfo.instSet.md5)) { @@ -1053,6 +1129,7 @@ bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const II // Load the instruments _instruments.clear(); _instruments.reserve(exeInfo.instSet.instCount); + IIgsInstrumentHeader instrument; for (uint i = 0; i < exeInfo.instSet.instCount; i++) { if (!instrument.read(*data)) { @@ -1102,6 +1179,7 @@ bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInf "Please report the information on the previous line to the ScummVM team.\n" \ "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix); } + uint8Wave->seek(0); // Seek wave to its start // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result _wave.resize(uint8Wave->size()); diff --git a/engines/agi/sound.h b/engines/agi/sound.h index fd178e3a1d..a24a665b2a 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -51,6 +51,7 @@ namespace Agi { #define SOUND_EMU_MAC 3 #define SOUND_EMU_AMIGA 4 #define SOUND_EMU_APPLE2GS 5 +#define SOUND_EMU_COCO3 6 #define WAVEFORM_SIZE 64 #define ENV_ATTACK 10000 /**< envelope attack rate */ @@ -228,27 +229,42 @@ struct IIgsChannelInfo { bool playing(); ///< Is there a note playing on this channel? }; - /** - * AGI sound resource types. - * It's probably coincidence that all the values here are powers of two - * as they're simply the different used values in AGI sound resources' - * starts (The first 16-bit little endian word, to be precise). - */ - enum AgiSoundType { - AGI_SOUND_SAMPLE = 0x0001, - AGI_SOUND_MIDI = 0x0002, - AGI_SOUND_4CHN = 0x0008 - }; - enum AgiSoundFlags { - AGI_SOUND_LOOP = 0x0001, - AGI_SOUND_ENVELOPE = 0x0002 - }; - enum AgiSoundEnv { - AGI_SOUND_ENV_ATTACK = 3, - AGI_SOUND_ENV_DECAY = 2, - AGI_SOUND_ENV_SUSTAIN = 1, - AGI_SOUND_ENV_RELEASE = 0 - }; +struct CoCoNote { + uint8 freq; + uint8 volume; + uint16 duration; ///< Note duration + + /** Reads a CoCoNote through the given pointer. */ + void read(const uint8 *ptr) { + freq = *ptr; + volume = *(ptr + 1); + duration = READ_LE_UINT16(ptr + 2); + } +}; + +/** + * AGI sound resource types. + * It's probably coincidence that all the values here are powers of two + * as they're simply the different used values in AGI sound resources' + * starts (The first 16-bit little endian word, to be precise). + */ +enum AgiSoundType { + AGI_SOUND_SAMPLE = 0x0001, + AGI_SOUND_MIDI = 0x0002, + AGI_SOUND_4CHN = 0x0008 +}; +enum AgiSoundFlags { + AGI_SOUND_LOOP = 0x0001, + AGI_SOUND_ENVELOPE = 0x0002 +}; +enum AgiSoundEnv { + AGI_SOUND_ENV_ATTACK = 3, + AGI_SOUND_ENV_DECAY = 2, + AGI_SOUND_ENV_SUSTAIN = 1, + AGI_SOUND_ENV_RELEASE = 0 +}; + + /** * AGI engine sound channel structure. */ @@ -485,6 +501,7 @@ public: void stopNote(int i); void playNote(int i, int freq, int vol); void playAgiSound(); + void playCoCoSound(); uint32 mixSound(); bool loadInstruments(); void playMidiSound(); diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 5ca0d5ca1e..f3c0b7365c 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -50,15 +50,14 @@ struct Sprite { #undef ALLOC_DEBUG -#define POOL_SIZE 68000 /* Gold Rush mine room needs > 50000 */ - /* Speeder bike challenge needs > 67000 */ +#define POOL_SIZE 68000 // Gold Rush mine room needs > 50000 + // Speeder bike challenge needs > 67000 void *SpritesMgr::poolAlloc(int size) { uint8 *x; - /* Adjust size to 32-bit boundary to prevent data misalignment - * errors. - */ + // Adjust size to 32-bit boundary to prevent data misalignment + // errors. size = (size + 3) & ~3; x = _poolTop; @@ -73,9 +72,8 @@ void *SpritesMgr::poolAlloc(int size) { return x; } -/* Note: it's critical that pool_release() is called in the exact - reverse order of pool_alloc() -*/ +// Note: it's critical that pool_release() is called in the exact +// reverse order of pool_alloc() void SpritesMgr::poolRelease(void *s) { _poolTop = (uint8 *)s; } @@ -84,27 +82,25 @@ void SpritesMgr::poolRelease(void *s) { * Blitter functions */ -/* Blit one pixel considering the priorities */ - +// Blit one pixel considering the priorities void SpritesMgr::blitPixel(uint8 *p, uint8 *end, uint8 col, int spr, int width, int *hidden) { - int epr = 0, pr = 0; /* effective and real priorities */ + int epr = 0, pr = 0; // effective and real priorities - /* CM: priority 15 overrides control lines and is ignored when - * tracking effective priority. This tweak is needed to fix - * Sarien bug #451768, and should not affect Sierra games because - * sprites shouldn't have priority 15 (like the AGI Mouse - * demo "mouse pointer") - * - * Update: this solution breaks other games, and can't be used. - */ + // CM: priority 15 overrides control lines and is ignored when + // tracking effective priority. This tweak is needed to fix + // Sarien bug #451768, and should not affect Sierra games because + // sprites shouldn't have priority 15 (like the AGI Mouse + // demo "mouse pointer") + // + // Update: this solution breaks other games, and can't be used. if (p >= end) return; - /* Check if we're on a control line */ + // Check if we're on a control line if ((pr = *p & 0xf0) < 0x30) { uint8 *p1; - /* Yes, get effective priority going down */ + // Yes, get effective priority going down for (p1 = p; p1 < end && (epr = *p1 & 0xf0) < 0x30; p1 += width) ; if (p1 >= end) @@ -114,9 +110,8 @@ void SpritesMgr::blitPixel(uint8 *p, uint8 *end, uint8 col, int spr, int width, } if (spr >= epr) { - /* Keep control line information visible, but put our - * priority over water (0x30) surface - */ + // Keep control line information visible, but put our + // priority over water (0x30) surface if (_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2)) *(p + FROM_SBUF16_TO_SBUF256_OFFSET) = col; // Write to 256 color buffer else @@ -124,14 +119,13 @@ void SpritesMgr::blitPixel(uint8 *p, uint8 *end, uint8 col, int spr, int width, *hidden = false; - /* Except if our priority is 15, which should never happen - * (fixes Sarien bug #451768) - * - * Update: breaks other games, can't be used - * - * if (spr == 0xf0) - * *p = spr | col; - */ + // Except if our priority is 15, which should never happen + // (fixes Sarien bug #451768) + // + // Update: breaks other games, can't be used + // + // if (spr == 0xf0) + // *p = spr | col; } } @@ -141,7 +135,7 @@ int SpritesMgr::blitCel(int x, int y, int spr, ViewCel *c, bool agi256_2) { int i, j, t, m, col; int hidden = true; - /* Fixes Sarien bug #477841 (crash in PQ1 map C4 when y == -2) */ + // Fixes Sarien bug #477841 (crash in PQ1 map C4 when y == -2) if (y < 0) y = 0; if (x < 0) @@ -253,7 +247,7 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { * Condition to determine whether a sprite will be in the 'updating' list. */ bool SpritesMgr::testUpdating(VtEntry *v, AgiEngine *agi) { - /* Sanity check (see Sarien bug #779302) */ + // Sanity check (see Sarien bug #779302) if (~agi->_game.dirView[v->currentView].flags & RES_LOADED) return false; @@ -264,7 +258,7 @@ bool SpritesMgr::testUpdating(VtEntry *v, AgiEngine *agi) { * Condition to determine whether a sprite will be in the 'non-updating' list. */ bool SpritesMgr::testNotUpdating(VtEntry *v, AgiEngine *vm) { - /* Sanity check (see Sarien bug #779302) */ + // Sanity check (see Sarien bug #779302) if (~vm->_game.dirView[v->currentView].flags & RES_LOADED) return false; @@ -274,7 +268,7 @@ bool SpritesMgr::testNotUpdating(VtEntry *v, AgiEngine *vm) { /** * Convert sprite priority to y value. */ -INLINE int SpritesMgr::prioToY(int p) { +int SpritesMgr::prioToY(int p) { int i; if (p == 0) @@ -285,7 +279,7 @@ INLINE int SpritesMgr::prioToY(int p) { return i; } - return -1; /* (p - 5) * 12 + 48; */ + return -1; // (p - 5) * 12 + 48; } /** @@ -297,13 +291,13 @@ Sprite *SpritesMgr::newSprite(VtEntry *v) { if (s == NULL) return NULL; - s->v = v; /* link sprite to associated view table entry */ + s->v = v; // link sprite to associated view table entry s->xPos = v->xPos; s->yPos = v->yPos - v->ySize + 1; s->xSize = v->xSize; s->ySize = v->ySize; s->buffer = (uint8 *)poolAlloc(s->xSize * s->ySize); - v->s = s; /* link view table entry to this sprite */ + v->s = s; // link view table entry to this sprite return s; } @@ -326,9 +320,8 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *)) int yVal[0x100]; int minY = 0xff, minIndex = 0; - /* fill the arrays with all sprites that satisfy the 'test' - * condition and their y values - */ + // fill the arrays with all sprites that satisfy the 'test' + // condition and their y values i = 0; for (v = _vm->_game.viewTable; v < &_vm->_game.viewTable[MAX_VIEWTABLE]; v++) { if ((*test)(v, _vm)) { @@ -338,11 +331,11 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *)) } } - /* now look for the smallest y value in the array and put that - * sprite in the list - */ + // now look for the smallest y value in the array and put that + // sprite in the list for (j = 0; j < i; j++) { minY = 0xff; + for (k = 0; k < i; k++) { if (yVal[k] < minY) { minIndex = k; @@ -376,6 +369,7 @@ void SpritesMgr::freeList(SpriteList &l) { SpriteList::iterator iter; for (iter = l.reverse_begin(); iter != l.end(); ) { Sprite* s = *iter; + poolRelease(s->buffer); poolRelease(s); iter = l.reverse_erase(iter); @@ -452,12 +446,15 @@ void SpritesMgr::eraseSprites(SpriteList &l) { void SpritesMgr::blitSprites(SpriteList& l) { int hidden; SpriteList::iterator iter; + for (iter = l.begin(); iter != l.end(); ++iter) { Sprite *s = *iter; + objsSaveArea(s); debugC(8, kDebugLevelSprites, "s->v->entry = %d (prio %d)", s->v->entry, s->v->priority); hidden = blitCel(s->xPos, s->yPos, s->v->priority, s->v->celData, s->v->viewData->agi256_2); - if (s->v->entry == 0) { /* if ego, update f1 */ + + if (s->v->entry == 0) { // if ego, update f1 _vm->setflag(fEgoInvisible, hidden); } } @@ -475,7 +472,7 @@ void SpritesMgr::commitNonupdSprites() { commitSprites(_sprNonupd); } -/* check moves in both lists */ +// check moves in both lists void SpritesMgr::commitBoth() { commitUpdSprites(); commitNonupdSprites(); @@ -584,10 +581,8 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in _vm->recordImageStackCall(ADD_VIEW, view, loop, cel, x, y, pri, mar); - /* - * Was hardcoded to 8, changed to pri_table[y] to fix Gold - * Rush (see Sarien bug #587558) - */ + // Was hardcoded to 8, changed to pri_table[y] to fix Gold + // Rush (see Sarien bug #587558) if (pri == 0) pri = _vm->_game.priTable[y]; @@ -616,15 +611,13 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in debugC(4, kDebugLevelSprites, "blit_cel (%d, %d, %d, c)", x, y, pri); blitCel(x1, y1, pri, c, _vm->_game.views[view].agi256_2); - /* If margin is 0, 1, 2, or 3, the base of the cel is - * surrounded with a rectangle of the corresponding priority. - * If margin >= 4, this extra margin is not shown. - */ + // If margin is 0, 1, 2, or 3, the base of the cel is + // surrounded with a rectangle of the corresponding priority. + // If margin >= 4, this extra margin is not shown. if (mar < 4) { - /* add rectangle around object, don't clobber control - * info in priority data. The box extends to the end of - * its priority band! - */ + // add rectangle around object, don't clobber control + // info in priority data. The box extends to the end of + // its priority band! y3 = (y2 / 12) * 12; // SQ1 needs +1 (see Sarien bug #810331) @@ -640,8 +633,10 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in for (y = y3; y <= y2; y++) { if ((*p1 >> 4) >= 4) *p1 = (mar << 4) | (*p1 & 0x0f); + if ((*p2 >> 4) >= 4) *p2 = (mar << 4) | (*p2 & 0x0f); + p1 += _WIDTH; p2 += _WIDTH; } @@ -652,8 +647,10 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in for (x = x1; x <= x2; x++) { if ((*p1 >> 4) >= 4) *p1 = (mar << 4) | (*p1 & 0x0f); + if ((*p2 >> 4) >= 4) *p2 = (mar << 4) | (*p2 & 0x0f); + p1++; p2++; } @@ -718,6 +715,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { w = x2 - x1 + 1; q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1]; offset = _vm->_game.lineMinPrint * CHAR_LINES; + for (i = y1; i <= y2; i++) { _gfx->putPixelsA(x1, i + offset, w, q); q += _WIDTH; diff --git a/engines/agi/sprite.h b/engines/agi/sprite.h index 3f9b329076..407871ebbd 100644 --- a/engines/agi/sprite.h +++ b/engines/agi/sprite.h @@ -46,9 +46,9 @@ private: uint8 *_spritePool; uint8 *_poolTop; - /* - * Sprite management functions - */ + // + // Sprite management functions + // SpriteList _sprUpd; SpriteList _sprNonupd; @@ -60,7 +60,7 @@ private: void objsSaveArea(Sprite *s); void objsRestoreArea(Sprite *s); - FORCEINLINE int prioToY(int p); + int prioToY(int p); Sprite *newSprite(VtEntry *v); void sprAddlist(SpriteList &l, VtEntry *v); void buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *)); diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 63b109ee83..04af531809 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -24,7 +24,7 @@ */ #include "agi/agi.h" -#include "agi/sprite.h" /* for commit_both() */ +#include "agi/sprite.h" // for commit_both() #include "agi/graphics.h" #include "agi/keyboard.h" @@ -35,7 +35,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff, int x1, y1; int maxx, minx, ofoff; int update; - /* Note: Must be unsigned to use AGDS cyrillic characters! */ + // Note: Must be unsigned to use AGDS cyrillic characters! #ifdef __DS__ // On the DS, a compiler bug causes the text to render incorrectly, because // GCC tries to optimisie out writes to this pointer (tested on DevkitARM v19b and v20) @@ -45,20 +45,19 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff, const unsigned char *m; #endif - /* kludge! */ + // kludge! update = 1; if (l == 2) { update = l = 0; } - /* FR: strings with len == 1 were not printed - */ + // FR: strings with len == 1 were not printed if (len == 1) { _gfx->putTextCharacter(l, xoff + foff, yoff, *msg, fg, bg, checkerboard); maxx = 1; minx = 0; ofoff = foff; - y1 = 0; /* Check this */ + y1 = 0; // Check this } else { maxx = 0; minx = GFX_WIDTH; @@ -69,7 +68,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff, if (*m >= 0x20 || *m == 1 || *m == 2 || *m == 3) { // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what // needs fixing, or remove it! - /* FIXME */ + // FIXME int ypos; ypos = (y1 * CHAR_LINES) + yoff; @@ -92,7 +91,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff, x1++; - /* DF: changed the len-1 to len... */ + // DF: changed the len-1 to len... if (x1 == len && m[len] != '\n') y1++, x1 = foff = 0; } else { @@ -114,17 +113,18 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff, if (update) { _gfx->scheduleUpdate(foff + xoff + minx, yoff, ofoff + xoff + maxx + CHAR_COLS - 1, yoff + y1 * CHAR_LINES + CHAR_LINES + 1); - /* Making synchronous text updates reduces CPU load - * when updating status line and input area - */ + + // Making synchronous text updates reduces CPU load + // when updating status line and input area _gfx->doUpdate(); } } -/* len is in characters, not pixels!! - */ +// +// len is in characters, not pixels!! +// void AgiEngine::blitTextbox(const char *p, int y, int x, int len) { - /* if x | y = -1, then centre the box */ + // if x | y = -1, then center the box int xoff, yoff, lin, h, w; char *msg, *m; @@ -144,7 +144,7 @@ void AgiEngine::blitTextbox(const char *p, int y, int x, int len) { m = msg = wordWrapString(agiSprintf(p), &len); for (lin = 1; *m; m++) { - /* Test \r for MacOS 8 */ + // Test \r for MacOS 8 if (*m == '\n' || *m == '\r') lin++; } @@ -301,9 +301,9 @@ void AgiEngine::closeWindow() { debugC(4, kDebugLevelText, "closeWindow()"); _sprites->eraseBoth(); - eraseTextbox(); /* remove window, if any */ + eraseTextbox(); // remove window, if any _sprites->blitBoth(); - _sprites->commitBoth(); /* redraw sprites */ + _sprites->commitBoth(); // redraw sprites _game.hasWindow = false; } @@ -340,7 +340,7 @@ int AgiEngine::selectionBox(const char *m, const char **b) { int rc = -1; int bx[5], by[5]; - setflag(fNoSaveLoadAllowed, true); + _noSaveLoadAllowed = true; _sprites->eraseBoth(); blitTextbox(m, -1, -1, -1); @@ -350,7 +350,7 @@ int AgiEngine::selectionBox(const char *m, const char **b) { s = _game.window.x2 - _game.window.x1 + 1 - 5 * CHAR_COLS; debugC(3, kDebugLevelText, "selectionBox(): s = %d", s); - /* Automatically position buttons */ + // Automatically position buttons for (i = 0; b[i]; i++) { numButtons++; s -= CHAR_COLS * strlen(b[i]); @@ -371,19 +371,16 @@ int AgiEngine::selectionBox(const char *m, const char **b) { _sprites->blitBoth(); - /* clear key queue */ - while (_gfx->keypress()) { - _gfx->getKey(); - } + clearKeyQueue(); AllowSyntheticEvents on(this); debugC(4, kDebugLevelText, "selectionBox(): waiting..."); - while (!(shouldQuit() || restartGame)) { + while (!(shouldQuit() || _restartGame)) { for (i = 0; b[i]; i++) _gfx->drawCurrentStyleButton(bx[i], by[i], b[i], i == active, false, i == 0); - _gfx->pollTimer(); /* msdos driver -> does nothing */ + pollTimer(); key = doPollKeyboard(); switch (key) { case KEY_ENTER: @@ -410,7 +407,7 @@ int AgiEngine::selectionBox(const char *m, const char **b) { } } break; - case 0x09: /* Tab */ + case 0x09: // Tab debugC(3, kDebugLevelText, "selectionBox(): Focus change"); active++; active %= i; @@ -426,7 +423,7 @@ getout: closeWindow(); debugC(2, kDebugLevelText, "selectionBox(): Result = %d", rc); - setflag(fNoSaveLoadAllowed, false); + _noSaveLoadAllowed = false; return rc; } @@ -449,14 +446,14 @@ int AgiEngine::print(const char *p, int lin, int col, int len) { blitTextbox(p, lin, col, len); if (getflag(fOutputMode)) { - /* non-blocking window */ + // non-blocking window setflag(fOutputMode, false); return 1; } - /* blocking */ + // blocking - setflag(fNoSaveLoadAllowed, true); + _noSaveLoadAllowed = true; if (_game.vars[vWindowReset] == 0) { int k; @@ -464,21 +461,26 @@ int AgiEngine::print(const char *p, int lin, int col, int len) { k = waitKey(); closeWindow(); - setflag(fNoSaveLoadAllowed, false); + _noSaveLoadAllowed = false; return k; } - /* timed window */ + // timed window debugC(3, kDebugLevelText, "f15==0, v21==%d => timed", getvar(21)); _game.msgBoxTicks = getvar(vWindowReset) * 10; setvar(vKey, 0); + _menuSelected = false; + do { if (getflag(fRestoreJustRan)) break; + if (_menuSelected) + break; + mainCycle(); if (_game.keypress == KEY_ENTER) { debugC(4, kDebugLevelText, "KEY_ENTER"); @@ -492,7 +494,7 @@ int AgiEngine::print(const char *p, int lin, int col, int len) { closeWindow(); - setflag(fNoSaveLoadAllowed, false); + _noSaveLoadAllowed = false; return 0; } @@ -561,8 +563,8 @@ char *AgiEngine::agiSprintf(const char *s) { } if (i == 99) { - /* remove all leading 0 */ - /* don't remove the 3rd zero if 000 */ + // remove all leading 0 + // don't remove the 3rd zero if 000 for (i = 0; z[i] == '0' && i < 14; i++) ; } else { @@ -630,10 +632,14 @@ void AgiEngine::writeStatus() { clearLines(_game.lineStatus, _game.lineStatus, 0); flushLines(_game.lineStatus, _game.lineStatus); +#if 0 + // FIXME: Breaks wrist watch prompt in SQ2 + // Clear the user input line as well when clearing the status line // Fixes bug #1893564 - AGI: Texts messed out in Naturette 1 clearLines(_game.lineUserInput, _game.lineUserInput, 0); flushLines(_game.lineUserInput, _game.lineUserInput); +#endif return; } @@ -656,8 +662,11 @@ void AgiEngine::writePrompt() { int l, fg, bg, pos; int promptLength = strlen(agiSprintf(_game.strings[0])); - if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) + if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) { + clearPrompt(); + return; + } l = _game.lineUserInput; fg = _game.colorFg; @@ -676,6 +685,16 @@ void AgiEngine::writePrompt() { _gfx->doUpdate(); } +void AgiEngine::clearPrompt() { + int l; + + l = _game.lineUserInput; + clearLines(l, l, _game.colorBg); + flushLines(l, l); + + _gfx->doUpdate(); +} + /** * Clear text lines in the screen. * @param l1 start line @@ -683,10 +702,9 @@ void AgiEngine::writePrompt() { * @param c color */ void AgiEngine::clearLines(int l1, int l2, int c) { - /* do we need to adjust for +8 on topline? - * inc for endline so it matches the correct num - * ie, from 22 to 24 is 3 lines, not 2 lines. - */ + // do we need to adjust for +8 on topline? + // inc for endline so it matches the correct num + // ie, from 22 to 24 is 3 lines, not 2 lines. l1 *= CHAR_LINES; l2 *= CHAR_LINES; diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index 07387161e8..fb417e86a9 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -36,9 +36,8 @@ void AgiEngine::lSetCel(VtEntry *v, int n) { currentVl = &_game.views[v->currentView].loop[v->currentLoop]; - /* Added by Amit Vainsencher <amitv@subdimension.com> to prevent - * crash in KQ1 -- not in the Sierra interpreter - */ + // Added by Amit Vainsencher <amitv@subdimension.com> to prevent + // crash in KQ1 -- not in the Sierra interpreter if (currentVl->numCels == 0) return; @@ -64,9 +63,8 @@ void AgiEngine::lSetLoop(VtEntry *v, int n) { ViewLoop *currentVl; debugC(7, kDebugLevelResources, "vt entry #%d, loop = %d", v->entry, n); - /* Added to avoid crash when leaving the arcade machine in MH1 - * -- not in AGI 2.917 - */ + // Added to avoid crash when leaving the arcade machine in MH1 + // -- not in AGI 2.917 if (n >= v->numLoops) n = 0; @@ -154,34 +152,35 @@ int AgiEngine::decodeView(int n) { _game.views[n].agi256_2 = (READ_LE_UINT16(v) == 0xf00f); // Detect AGI256-2 views by their header bytes _game.views[n].descr = READ_LE_UINT16(v + 3) ? (char *)(v + READ_LE_UINT16(v + 3)) : (char *)(v + 3); - /* if no loops exist, return! */ + // if no loops exist, return! if ((_game.views[n].numLoops = *(v + 2)) == 0) return errNoLoopsInView; - /* allocate memory for all views */ + // allocate memory for all views _game.views[n].loop = (ViewLoop *) calloc(_game.views[n].numLoops, sizeof(ViewLoop)); if (_game.views[n].loop == NULL) return errNotEnoughMemory; - /* decode all of the loops in this view */ - lptr = v + 5; /* first loop address */ + // decode all of the loops in this view + lptr = v + 5; // first loop address for (loop = 0; loop < _game.views[n].numLoops; loop++, lptr += 2) { - lofs = READ_LE_UINT16(lptr); /* loop header offset */ - vl = &_game.views[n].loop[loop]; /* the loop struct */ + lofs = READ_LE_UINT16(lptr); // loop header offset + vl = &_game.views[n].loop[loop]; // the loop struct vl->numCels = *(v + lofs); debugC(6, kDebugLevelResources, "view %d, num_cels = %d", n, vl->numCels); vl->cel = (ViewCel *)calloc(vl->numCels, sizeof(ViewCel)); + if (vl->cel == NULL) { free(_game.views[n].loop); _game.views[n].numLoops = 0; return errNotEnoughMemory; } - /* decode the cells */ + // decode the cells for (cel = 0; cel < vl->numCels; cel++) { cofs = lofs + READ_LE_UINT16(v + lofs + 1 + (cel * 2)); vc = &vl->cel[cel]; @@ -201,17 +200,17 @@ int AgiEngine::decodeView(int n) { vc->mirror = 0; } - /* skip over width/height/trans|mirror data */ + // skip over width/height/trans|mirror data cofs += 3; vc->data = v + cofs; - /* If mirror_loop is pointing to the current loop, - * then this is the original. - */ + + // If mirror_loop is pointing to the current loop, + // then this is the original. if (vc->mirrorLoop == loop) vc->mirror = 0; - } /* cel */ - } /* loop */ + } // cel + } // loop return errOK; } @@ -227,12 +226,12 @@ void AgiEngine::unloadView(int n) { if (~_game.dirView[n].flags & RES_LOADED) return; - /* Rebuild sprite list, see Sarien bug #779302 */ + // Rebuild sprite list, see Sarien bug #779302 _sprites->eraseBoth(); _sprites->blitBoth(); _sprites->commitBoth(); - /* free all the loops */ + // free all the loops for (x = 0; x < _game.views[n].numLoops; x++) free(_game.views[n].loop[x].cel); @@ -253,7 +252,7 @@ void AgiEngine::setCel(VtEntry *v, int n) { lSetCel(v, n); - /* If position isn't appropriate, update it accordingly */ + // If position isn't appropriate, update it accordingly clipViewCoordinates(v); } @@ -308,6 +307,7 @@ void AgiEngine::setView(VtEntry *v, int n) { if (v->currentView == 118 && v->flags & DRAWN && getGameID() == GID_SQ1) { viewFlags = v->flags; // Store the flags for the view _sprites->eraseUpdSprites(); + if (v->flags & UPDATE) { v->flags &= ~DRAWN; } else { @@ -335,6 +335,7 @@ void AgiEngine::setView(VtEntry *v, int n) { void AgiEngine::startUpdate(VtEntry *v) { if (~v->flags & UPDATE) { _sprites->eraseBoth(); + v->flags |= UPDATE; _sprites->blitBoth(); } @@ -347,14 +348,14 @@ void AgiEngine::startUpdate(VtEntry *v) { void AgiEngine::stopUpdate(VtEntry *v) { if (v->flags & UPDATE) { _sprites->eraseBoth(); + v->flags &= ~UPDATE; _sprites->blitBoth(); } } -/* loops to use according to direction and number of loops in - * the view resource - */ +// loops to use according to direction and number of loops in +// the view resource static int loopTable2[] = { 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x01, 0x01, 0x01 }; @@ -391,16 +392,16 @@ void AgiEngine::updateViewtable() { loop = loopTable4[v->direction]; break; default: - /* for KQ4 */ - if (agiGetRelease() == 0x3086) + // for KQ4 + if (getVersion() == 0x3086) loop = loopTable4[v->direction]; break; } } - /* AGI 2.272 (ddp, xmas) doesn't test step_time_count! */ + // AGI 2.272 (ddp, xmas) doesn't test step_time_count! if (loop != 4 && loop != v->currentLoop) { - if (agiGetRelease() <= 0x2272 || + if (getVersion() <= 0x2272 || v->stepTimeCount == 1) { setLoop(v, loop); } diff --git a/engines/agi/view.h b/engines/agi/view.h index a94de53c87..e71db6c97d 100644 --- a/engines/agi/view.h +++ b/engines/agi/view.h @@ -120,7 +120,7 @@ struct VtEntry { uint8 parm2; uint8 parm3; uint8 parm4; -}; /* struct vt_entry */ +}; // struct vt_entry } // End of namespace Agi diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp index d3726731ca..4396797e6b 100644 --- a/engines/agi/words.cpp +++ b/engines/agi/words.cpp @@ -23,22 +23,22 @@ * */ -/* - * New find_word algorithm by Thomas Akesson <tapilot@home.se> - */ +// +// New find_word algorithm by Thomas Akesson <tapilot@home.se> +// #include "agi/agi.h" -#include "agi/keyboard.h" /* for clean_input() */ +#include "agi/keyboard.h" // for clean_input() namespace Agi { -static uint8 *words; /* words in the game */ -static uint32 wordsFlen; /* length of word memory */ +static uint8 *words; // words in the game +static uint32 wordsFlen; // length of word memory -/* - * Local implementation to avoid problems with strndup() used by - * gcc 3.2 Cygwin (see #635984) - */ +// +// Local implementation to avoid problems with strndup() used by +// gcc 3.2 Cygwin (see #635984) +// static char *myStrndup(char *src, int n) { char *tmp = strncpy((char *)malloc(n + 1), src, n); tmp[n] = 0; @@ -54,7 +54,7 @@ int AgiEngine::loadWords(const char *fname) { if (!fp.open(fname)) { report("Warning: can't open %s\n", fname); - return errOK /*err_BadFileOpen */ ; + return errOK; // err_BadFileOpen } report("Loading dictionary: %s\n", fname); @@ -91,13 +91,14 @@ void AgiEngine::unloadWords() { * Thomas Akesson, November 2001 */ int AgiEngine::findWord(char *word, int *flen) { - int mchr = 0; /* matched chars */ + int mchr = 0; // matched chars int len, fchr, id = -1; uint8 *p = words; uint8 *q = words + wordsFlen; *flen = 0; debugC(2, kDebugLevelScripts, "find_word(%s)", word); + if (word[0] >= 'a' && word[0] <= 'z') fchr = word[0] - 'a'; else @@ -105,22 +106,20 @@ int AgiEngine::findWord(char *word, int *flen) { len = strlen(word); - /* Get the offset to the first word beginning with the - * right character - */ + // Get the offset to the first word beginning with the + // right character p += READ_BE_UINT16(p + 2 * fchr); while (p[0] >= mchr) { if (p[0] == mchr) { p++; - /* Loop through all matching characters */ + // Loop through all matching characters while ((p[0] ^ word[mchr]) == 0x7F && mchr < len) { mchr++; p++; } - /* Check if this is the last character of the word - * and if it matches - */ + // Check if this is the last character of the word + // and if it matches if ((p[0] ^ word[mchr]) == 0xFF && mchr < len) { mchr++; if (word[mchr] == 0 || word[mchr] == 0x20) { @@ -132,9 +131,10 @@ int AgiEngine::findWord(char *word, int *flen) { if (p >= q) return -1; - /* Step to the next word */ + // Step to the next word while (p[0] < 0x80) p++; + p += 3; } @@ -164,20 +164,24 @@ void AgiEngine::dictionaryWords(char *msg) { case -1: debugC(2, kDebugLevelScripts, "unknown word"); _game.egoWords[_game.numEgoWords].word = strdup(p); + q = _game.egoWords[_game.numEgoWords].word; + _game.egoWords[_game.numEgoWords].id = 19999; setvar(vWordNotFound, 1 + _game.numEgoWords); + _game.numEgoWords++; + p += strlen(p); break; case 0: - /* ignore this word */ + // ignore this word debugC(2, kDebugLevelScripts, "ignore word"); p += wlen; q = NULL; break; default: - /* an OK word */ + // an OK word debugC(3, kDebugLevelScripts, "ok word (%d)", wid); _game.egoWords[_game.numEgoWords].id = wid; _game.egoWords[_game.numEgoWords].word = myStrndup(p, wlen); @@ -209,4 +213,4 @@ void AgiEngine::dictionaryWords(char *msg) { } } -}// End of namespace Agi +} // End of namespace Agi diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 3c03ea7be4..f6a85d498d 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -615,8 +615,8 @@ protected: void paletteFadeOut(byte *palPtr, uint num, uint size); - byte *allocateItem(uint size); - byte *allocateTable(uint size); + void *allocateItem(uint size); + void *allocateTable(uint size); void alignTableMem(); Child *findChildOfType(Item *i, uint child); @@ -673,7 +673,7 @@ protected: void uncompressText(byte *ptr); byte *uncompressToken(byte a, byte *ptr); - void showMessageFormat(const char *s, ...); + void showMessageFormat(const char *s, ...) GCC_PRINTF(2, 3); const byte *getStringPtrByID(uint16 stringId, bool upperCase = false); const byte *getLocalStringByID(uint16 stringId); uint getNextStringID(); @@ -848,6 +848,7 @@ protected: void skipSpeech(); + const char *getPixelLength(const char *string, uint16 maxWidth, uint16 &pixels); bool printNameOf(Item *item, uint x, uint y); bool printTextOf(uint a, uint x, uint y); void printVerbOf(uint hitarea_id); @@ -1976,7 +1977,7 @@ protected: virtual void printScreenText(uint vgaSpriteId, uint color, const char *stringPtr, int16 x, int16 y, int16 width); void printInteractText(uint16 num, const char *string); - void sendInteractText(uint16 num, const char *fmt, ...); + void sendInteractText(uint16 num, const char *fmt, ...) GCC_PRINTF(3, 4); void checkLinkBox(); void hyperLinkOn(uint16 x); diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 3be552a083..36399a7b2f 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -367,12 +367,7 @@ bool MoviePlayerDXA::processFrame() { copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); _vm->_system->unlockScreen(); - if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < getCurFrame() + 1) || - _frameSkipped > getFrameRate()) { - if (_frameSkipped > getFrameRate()) { - warning("force frame %i redraw", getCurFrame()); - _frameSkipped = 0; - } + if ((_bgSoundStream == NULL) || ((int)(_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < getCurFrame() + 1)) { if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) { while (_mixer->isSoundHandleActive(_bgSound) && (_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < (uint32)getCurFrame()) { @@ -392,7 +387,6 @@ bool MoviePlayerDXA::processFrame() { } warning("dropped frame %i", getCurFrame()); - _frameSkipped++; return false; } diff --git a/engines/agos/animation.h b/engines/agos/animation.h index 9cd6913f08..4ebcb3d4b3 100644 --- a/engines/agos/animation.h +++ b/engines/agos/animation.h @@ -52,7 +52,6 @@ class MoviePlayer { bool _rightButtonDown; bool _skipMovie; uint32 _ticks; - uint16 _frameSkipped; char baseName[40]; public: diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp index 9ae32a34f4..d23e772306 100644 --- a/engines/agos/charset-fontdata.cpp +++ b/engines/agos/charset-fontdata.cpp @@ -34,6 +34,22 @@ namespace AGOS { +static const byte polish_feebleFontSize[208] = { + 4, 2, 8, 8, 8, 8, 8, 2, 4, 4, 8, 8, 3, 8, 2, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 8, 8, 8, 8, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8, + 8, 8, 8, 8, 8, 8, 7, 8, 8, 4, 5, 7, 3, 8, 8, 8, + 8, 8, 8, 7, 7, 8, 8, 8, 8, 8, 8, 5, 2, 5, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + static const byte feebleFontSize[208] = { 8, 2, 5, 7, 8, 8, 8, 2, 4, 4, 8, 8, 3, 8, 2, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 3, 5, 8, 5, 8, @@ -53,9 +69,210 @@ static const byte feebleFontSize[208] = { uint AGOSEngine::getFeebleFontSize(byte chr) { if (getGameType() == GType_FF && (getFeatures() & GF_DEMO) && chr == 32) return 4; - return feebleFontSize[chr - 32]; + else if (_language == Common::PL_POL) + return polish_feebleFontSize[chr - 32]; + else + return feebleFontSize[chr - 32]; } +static const byte polish_feeble_windowFont[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x0c, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x04, 0x06, 0x00, + 0x04, 0x08, 0x10, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x3e, 0x62, 0x92, 0x64, 0x08, 0x10, 0x20, 0x4c, 0x92, 0x8c, 0x00, 0x00, 0x00, + 0x7c, 0x8a, 0x92, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, + 0x80, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0xfe, 0x18, 0x0c, 0x00, + 0x80, 0x80, 0x90, 0xb0, 0xe0, 0xc0, 0x80, 0x80, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00, + 0x78, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, + 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, + 0x78, 0x84, 0x84, 0x04, 0x04, 0x08, 0x10, 0x20, 0x40, 0xfc, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x02, 0x02, 0x1c, 0x02, 0x02, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x04, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x80, 0xfc, 0x02, 0x02, 0x02, 0x02, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x3e, 0x40, 0x80, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0xfe, 0x02, 0x02, 0x02, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x78, 0x84, 0x84, 0x84, 0x78, 0x84, 0x84, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x8a, 0x92, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x04, 0x08, 0x10, 0x9c, 0xa2, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x7c, 0x92, 0xa2, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x04, 0x08, 0x10, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x3c, 0x42, 0x82, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x04, 0x08, 0x10, 0x7c, 0x80, 0x80, 0x78, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0xfc, 0x82, 0x82, 0x82, 0xfc, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0xfe, 0x80, 0x80, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x80, 0x80, 0x86, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0xe0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x1e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x84, 0x88, 0x90, 0xe0, 0x90, 0x88, 0x84, 0x82, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0x82, 0xc6, 0xaa, 0x92, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x82, 0x82, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0xfc, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x00, + 0xfc, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x7c, 0x82, 0x80, 0x80, 0x7c, 0x02, 0x02, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x92, 0xaa, 0xc6, 0x00, 0x00, 0x00, + 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0xfe, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x04, 0x08, 0x7c, 0x20, 0x40, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x18, 0x0c, 0x00, + 0x04, 0x08, 0x10, 0xfe, 0x04, 0x08, 0x10, 0x20, 0x40, 0xfe, 0x00, 0x00, 0x00, + 0xc0, 0x40, 0x40, 0x60, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, + 0x7c, 0x8a, 0x90, 0x80, 0x7c, 0x02, 0x02, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x18, 0xfe, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x02, 0x7e, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x00, 0x00, 0x00, + 0x1c, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x7c, + 0x80, 0x80, 0x80, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xe0, + 0x80, 0x80, 0x80, 0x84, 0x88, 0x90, 0xe0, 0x90, 0x88, 0x84, 0x00, 0x00, 0x00, + 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x9c, 0xa2, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x7e, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x9c, 0xa2, 0xc2, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x80, 0x80, 0x78, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x7c, + 0x00, 0x00, 0x00, 0xfe, 0x04, 0x08, 0x10, 0x20, 0x40, 0xfe, 0x00, 0x00, 0x00, + 0x30, 0x40, 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x40, 0x30, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, + 0xc0, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0xc0, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0x7c, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x7c, 0x10, 0x10, 0x30, + 0x00, 0x28, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x10, 0x20, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x00, 0x00, 0x00, + 0x10, 0x28, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x08, 0x14, 0x08, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c, 0x10, 0x10, 0x30, + 0x10, 0x28, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x00, 0x7c, 0x82, 0x82, 0xfe, 0x80, 0x80, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x00, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x40, 0xa0, 0x00, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x80, 0x40, 0x00, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x7c, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x10, 0x28, 0x7c, 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x10, 0x20, 0xfe, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x28, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x20, 0x10, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x10, 0x28, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x10, 0x08, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x02, 0x02, 0x7c, + 0x28, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x3e, 0x42, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00, 0x00, 0x00, + 0x40, 0x80, 0x00, 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, 0x00, + 0x10, 0x20, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7e, 0x00, 0x00, 0x00, + 0x14, 0x28, 0x00, 0x9c, 0xa2, 0xc2, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x14, 0x28, 0x82, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0x82, 0x82, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x80, 0x82, 0x84, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x42, 0x82, 0x82, 0x82, 0x84, 0x84, 0x82, 0x82, 0x82, 0x9c, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + static const byte feeble_windowFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, @@ -1885,9 +2102,12 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { if (getGameType() == GType_FF || getGameType() == GType_PP) { dst = getBackGround() + y * _dxSurfacePitch + x + window->textColumnOffset; h = 13; - w = feebleFontSize[chr - 32]; + w = getFeebleFontSize(chr); - src = feeble_windowFont + (chr - 32) * 13; + if (_language == Common::PL_POL) + src = polish_feeble_windowFont + (chr - 32) * 13; + else + src = feeble_windowFont + (chr - 32) * 13; } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; h = 8; diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index c0af375eb5..7877e19646 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -98,7 +98,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOLAUNCHLOAD }; using namespace AGOS; diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h index 8215d8242b..ec21acc0a1 100644 --- a/engines/agos/detection_tables.h +++ b/engines/agos/detection_tables.h @@ -25,6 +25,10 @@ namespace AGOS { +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; + static const AGOSGameDescription gameDescriptions[] = { // Personal Nightmare 1.1 - English Amiga { @@ -40,7 +44,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_PN, @@ -62,7 +67,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_PN, @@ -84,7 +90,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_PN, @@ -106,7 +113,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_PN, @@ -128,7 +136,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -148,7 +157,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -168,7 +178,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -188,7 +199,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -210,7 +222,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -232,7 +245,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -254,7 +268,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -276,7 +291,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -298,7 +314,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -320,7 +337,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -342,7 +360,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -364,7 +383,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA1, @@ -389,7 +409,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -414,7 +435,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -439,7 +461,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -464,7 +487,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -489,7 +513,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -514,7 +539,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -539,7 +565,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -565,7 +592,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -590,7 +618,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -615,7 +644,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -640,7 +670,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -665,7 +696,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -690,7 +722,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -715,7 +748,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -740,7 +774,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_ELVIRA2, @@ -766,7 +801,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -792,7 +828,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -814,7 +851,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_WW, @@ -842,7 +880,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -870,7 +909,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -898,7 +938,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -926,7 +967,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_WW, @@ -949,7 +991,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAcorn, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -973,7 +1016,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAcorn, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_SIMON1, @@ -997,7 +1041,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAcorn, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1020,7 +1065,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1043,7 +1089,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1066,7 +1113,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1089,7 +1137,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1112,7 +1161,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1135,7 +1185,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1158,7 +1209,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1181,7 +1233,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1204,7 +1257,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1227,7 +1281,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1250,7 +1305,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::CZ_CZE, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1273,7 +1329,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1296,7 +1353,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1319,7 +1377,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::CZ_CZE, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1342,7 +1401,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1365,7 +1425,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1388,7 +1449,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1411,7 +1473,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1434,7 +1497,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON1, @@ -1458,7 +1522,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_SIMON1, @@ -1482,7 +1547,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1506,7 +1572,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1530,7 +1597,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1554,7 +1622,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1578,7 +1647,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1602,7 +1672,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::HB_ISR, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1626,7 +1697,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1651,7 +1723,8 @@ static const AGOSGameDescription gameDescriptions[] = { // FIXME: DOS version which uses WAV format Common::IT_ITA, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1675,7 +1748,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1699,7 +1773,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1723,7 +1798,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON1, @@ -1747,7 +1823,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON2, @@ -1771,7 +1848,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON2, @@ -1795,7 +1873,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON2, @@ -1819,7 +1898,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON2, @@ -1843,7 +1923,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_SIMON2, @@ -1867,7 +1948,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -1891,7 +1973,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -1915,7 +1998,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -1939,7 +2023,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -1963,7 +2048,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -1987,7 +2073,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2011,7 +2098,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2035,7 +2123,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2059,7 +2148,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::HB_ISR, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_SIMON2, @@ -2084,7 +2174,8 @@ static const AGOSGameDescription gameDescriptions[] = { // FIXME: DOS version which uses WAV format Common::IT_ITA, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2108,7 +2199,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2132,7 +2224,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::CZ_CZE, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2156,7 +2249,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2180,7 +2274,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2204,7 +2299,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2228,7 +2324,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::PL_POL, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_SIMON2, @@ -2248,7 +2345,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES }, GType_FF, @@ -2268,7 +2366,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES }, GType_FF, @@ -2291,7 +2390,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2314,7 +2414,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2337,7 +2438,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2360,7 +2462,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2383,7 +2486,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2406,7 +2510,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2428,7 +2533,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2443,14 +2549,15 @@ static const AGOSGameDescription gameDescriptions[] = { "2CD", { - { "game22", GAME_BASEFILE, "629762ea9ca9ee9ff85f4774d219f5c7", 259576}, + { "game33", GAME_BASEFILE, "cda37c422c04dde8b8ab3405178b3ef9", 266565}, { "save.999", GAME_RESTFILE, "71512fc98501a8071a26b683a31dde78", 3360}, { "tbllist", GAME_TBLFILE, "0bbfee8e69739111eb36b0d138da8ddf", 668}, { NULL, 0, NULL, 0} }, Common::PL_POL, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2472,7 +2579,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2494,7 +2602,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2516,7 +2625,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2538,7 +2648,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2560,7 +2671,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, GType_FF, @@ -2580,7 +2692,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, @@ -2600,7 +2713,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, @@ -2620,7 +2734,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, @@ -2640,7 +2755,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, @@ -2660,7 +2776,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, @@ -2680,7 +2797,8 @@ static const AGOSGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_PP, diff --git a/engines/agos/feeble.cpp b/engines/agos/feeble.cpp index 492d855614..89b6f6da27 100644 --- a/engines/agos/feeble.cpp +++ b/engines/agos/feeble.cpp @@ -161,21 +161,16 @@ void AGOSEngine_FeebleDemo::exitMenu() { playVideo("fbye1.smk", true); HitArea *ha; - while (!shouldQuit()) { + do { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (!shouldQuit() && _lastHitArea3 == 0) { delay(1); } ha = _lastHitArea; - - if (ha != NULL && ha->id == 21) - break; - } + } while (!shouldQuit() && !(ha != NULL && ha->id == 21)); playVideo("fbye2.smk"); quitGame(); @@ -202,9 +197,7 @@ void AGOSEngine_FeebleDemo::filmMenu() { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (!shouldQuit() && _lastHitArea3 == 0) { handleWobble(); delay(1); } @@ -287,25 +280,23 @@ void AGOSEngine_FeebleDemo::mainMenu() { startInteractiveVideo("mainmenu.smk"); - HitArea *ha; - while (!shouldQuit()) { + HitArea *ha = 0; + do { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (_lastHitArea3 == 0) { + if (shouldQuit()) + return; handleText(); delay(1); } ha = _lastHitArea; + } while (ha == NULL || !(ha->id >= 1 && ha->id <= 6)); - if (ha == NULL) { - } else if (ha->id >= 1 && ha->id <= 6) { - break; - } - } + if (shouldQuit()) + return; stopInteractiveVideo(); @@ -384,11 +375,9 @@ void AGOSEngine_FeebleDemo::waitForSpace() { windowPutChar(_textWindow, *message); mouseOff(); - while (!shouldQuit()) { + do { delay(1); - if (_keyPressed.keycode == Common::KEYCODE_SPACE) - break; - } + } while (!shouldQuit() && (_keyPressed.keycode != Common::KEYCODE_SPACE)); _keyPressed.reset(); mouseOn(); } diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp index c439be3555..49792b99c5 100644 --- a/engines/agos/items.cpp +++ b/engines/agos/items.cpp @@ -41,7 +41,7 @@ Child *AGOSEngine::allocateChildBlock(Item *i, uint type, uint size) { return child; } -byte *AGOSEngine::allocateItem(uint size) { +void *AGOSEngine::allocateItem(uint size) { byte *item = new byte[size]; memset(item, 0, size); diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp index 0080748699..df37a38a7c 100644 --- a/engines/agos/script_e1.cpp +++ b/engines/agos/script_e1.cpp @@ -532,7 +532,7 @@ void AGOSEngine_Elvira1::oe1_moveDirn() { void AGOSEngine_Elvira1::oe1_score() { // 90: score SubPlayer *p = (SubPlayer *)findChildOfType(me(), kPlayerType); - showMessageFormat("Your score is %ld.\n", p->score); + showMessageFormat("Your score is %d.\n", p->score); } void AGOSEngine_Elvira1::oe1_look() { diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp index aa34d7a163..a466be796f 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -333,6 +333,32 @@ void AGOSEngine::loadTextIntoMem(uint16 stringId) { error("loadTextIntoMem: didn't find %d", stringId); } +static const byte polish_charWidth[226] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 2, 8, 7, 6,10, 8, 2, + 4, 4, 7, 6, 3, 4, 2, 3, 6, 4, + 6, 6, 7, 6, 6, 6, 6, 6, 2, 8, + 6, 9, 7, 6, 6, 8, 7, 8, 8, 7, + 6, 9, 8, 2, 6, 7, 6,10, 8, 9, + 7, 9, 7, 7, 8, 8, 8,12, 8, 8, + 7, 6, 7, 6, 4, 7, 7, 7, 7, 6, + 7, 7, 4, 7, 6, 2, 3, 6, 2,10, + 6, 7, 7, 7, 5, 6, 4, 6, 6,10, + 6, 6, 6, 0, 0, 0, 0, 0, 8, 6, + 7, 7, 7, 7, 7, 6, 7, 7, 7, 4, + 4, 3, 8, 8, 7, 0, 0, 7, 7, 7, + 6, 6, 6, 9, 8, 0, 0, 0, 0, 0, + 7, 3, 7, 6, 6, 8, 0, 0, 6, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7 +}; + static const byte charWidth[226] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -359,14 +385,15 @@ static const byte charWidth[226] = { 0, 0, 0, 0, 0, 7 }; -const char *getPixelLength(const char *string, uint16 maxWidth, uint16 &pixels) { +const char *AGOSEngine::getPixelLength(const char *string, uint16 maxWidth, uint16 &pixels) { pixels = 0; while (*string != 0) { byte chr = *string; - if ((pixels + charWidth[chr]) > maxWidth) + uint8 len = (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr]; + if ((pixels + len) > maxWidth) break; - pixels += charWidth[chr]; + pixels += len; string++; } @@ -559,7 +586,7 @@ void AGOSEngine_Feeble::printScreenText(uint vgaSpriteId, uint color, const char } while (*string2 != ' ') { byte chr = *string2; - pixels -= charWidth[chr]; + pixels -= (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr]; string2--; } spaces = (width - pixels) / 12; @@ -609,7 +636,7 @@ void AGOSEngine_Feeble::printInteractText(uint16 num, const char *string) { } while (*string2 != ' ') { byte chr = *string2; - pixels -= charWidth[chr]; + pixels -= (_language == Common::PL_POL) ? polish_charWidth[chr] : charWidth[chr]; string2--; } if (w == 0xFFFF) diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index 742ac48ac8..70ad3404f5 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -226,7 +226,7 @@ void AGOSEngine::alignTableMem() { } } -byte *AGOSEngine::allocateTable(uint size) { +void *AGOSEngine::allocateTable(uint size) { byte *org = _tablesHeapPtr; size = (size + 1) & ~1; diff --git a/engines/agos/vga_ff.cpp b/engines/agos/vga_ff.cpp index 58eb2f4cc0..14451a3dbe 100644 --- a/engines/agos/vga_ff.cpp +++ b/engines/agos/vga_ff.cpp @@ -70,7 +70,7 @@ int AGOSEngine::getScale(int16 y, int16 x) { void AGOSEngine::vc75_setScale() { _baseY = vcReadNextWord(); - _scale = (float)vcReadNextWord() / 1000000.; + _scale = vcReadNextWord() / 1000000.0f; } void AGOSEngine::vc76_setScaleXOffs() { diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp index cc7e843c2b..08722c42e5 100644 --- a/engines/cine/bg.cpp +++ b/engines/cine/bg.cpp @@ -82,7 +82,6 @@ byte loadCtOS(const char *ctName) { ptr += 2; if (bpp == 8) { - memcpy(collisionPage, ptr + 256 * 3, 320 * 200); renderer->loadCt256(ptr, ctName); } else { gfxConvertSpriteToRaw(collisionPage, ptr + 32, 160, 200); diff --git a/engines/cine/cine.h b/engines/cine/cine.h index bf56e9189b..1031d6d449 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -127,11 +127,15 @@ extern CineEngine *g_cine; #define COPY_PROT_FAIL_PRC_NAME "L201.ANI" enum { - VAR_MOUSE_X_MODE = 253, + // Both FW and OS VAR_MOUSE_X_POS = 249, - VAR_MOUSE_Y_MODE = 251, VAR_MOUSE_Y_POS = 250, + // FW only + VAR_MOUSE_X_MODE = 253, + VAR_MOUSE_Y_MODE = 251, // OS only + VAR_MOUSE_X_POS_2ND = 251, // Many times used in conjunction with VAR_MOUSE_X_POS + VAR_MOUSE_Y_POS_2ND = 252, // Many times used in conjunction with VAR_MOUSE_Y_POS VAR_BYPASS_PROTECTION = 255, VAR_LOW_MEMORY = 0 }; diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index f9de74b730..4786005647 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -64,6 +64,8 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { namespace Cine { +using Common::GUIO_NONE; + static const CINEGameDescription gameDescriptions[] = { { { @@ -72,7 +74,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -91,7 +94,8 @@ static const CINEGameDescription gameDescriptions[] = { }, Common::EN_USA, Common::kPlatformPC, - ADGF_CD + ADGF_CD, + GUIO_NONE }, GType_FW, GF_CD | GF_CRYPTED_BOOT_PRC, @@ -105,7 +109,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -118,7 +123,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, GF_ALT_FONT, @@ -131,7 +137,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, GF_ALT_FONT, @@ -144,7 +151,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -157,7 +165,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"), Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -170,7 +179,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"), Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, GF_ALT_FONT, @@ -183,7 +193,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"), Common::ES_ESP, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -196,7 +207,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"), Common::FR_FRA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -209,7 +221,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"), Common::IT_ITA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -226,7 +239,8 @@ static const CINEGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_FW, 0, @@ -239,7 +253,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"), Common::EN_ANY, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -252,7 +267,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"), Common::FR_FRA, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_FW, 0, @@ -265,7 +281,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"), Common::EN_GRB, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -280,7 +297,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"), Common::EN_GRB, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -293,7 +311,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"), Common::EN_USA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -306,7 +325,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"), Common::EN_USA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, GF_CD, @@ -319,7 +339,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -332,7 +353,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -349,7 +371,8 @@ static const CINEGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, GF_CD, @@ -362,7 +385,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -375,7 +399,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -388,7 +413,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"), Common::EN_GRB, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -401,7 +427,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"), Common::EN_GRB, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -414,7 +441,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"), Common::EN_USA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -427,7 +455,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"), Common::DE_DEU, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -440,7 +469,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"), Common::ES_ESP, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -453,7 +483,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"), Common::FR_FRA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -466,7 +497,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"), Common::EN_GRB, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_OS, GF_DEMO, @@ -479,7 +511,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"), Common::EN_GRB, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -492,7 +525,8 @@ static const CINEGameDescription gameDescriptions[] = { AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"), Common::FR_FRA, Common::kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_OS, 0, @@ -519,7 +553,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI }; class CineMetaEngine : public AdvancedMetaEngine { diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index d388a9e206..ddc2d48152 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -90,9 +90,9 @@ static const byte cursorPalette[] = { /*! \brief Initialize renderer */ -FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""), +FWRenderer::FWRenderer() : _background(NULL), _backupPal(), _cmd(""), _cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]), - _activeLowPal(NULL), _changePal(0), _showCollisionPage(false) { + _activePal(), _changePal(0), _showCollisionPage(false) { assert(_backBuffer); @@ -104,21 +104,17 @@ FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""), */ FWRenderer::~FWRenderer() { delete[] _background; - delete[] _palette; delete[] _backBuffer; - delete[] _activeLowPal; } /* \brief Reset renderer state */ void FWRenderer::clear() { delete[] _background; - delete[] _palette; - delete[] _activeLowPal; _background = NULL; - _palette = NULL; - _activeLowPal = NULL; + _backupPal.clear(); + _activePal.clear(); memset(_backBuffer, 0, _screenSize); @@ -550,59 +546,39 @@ void FWRenderer::setCommand(Common::String cmd) { /*! \brief Refresh current palette */ void FWRenderer::refreshPalette() { - int i; - byte pal[16*4]; - - assert(_activeLowPal); - - for (i = 0; i < 16; i++) { - pal[i * 4 + 2] = ((_activeLowPal[i] & 0x007) >> 0) * 32; - pal[i * 4 + 1] = ((_activeLowPal[i] & 0x070) >> 4) * 32; - pal[i * 4 + 0] = ((_activeLowPal[i] & 0x700) >> 8) * 32; - pal[i * 4 + 3] = 0; - } - - g_system->setPalette(pal, 0, 16); + assert(_activePal.isValid() && !_activePal.empty()); + _activePal.setGlobalOSystemPalette(); _changePal = 0; } /*! \brief Load palette of current background */ void FWRenderer::reloadPalette() { - assert(_palette); - - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } - - assert(_activeLowPal); - - memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16)); + assert(_backupPal.isValid() && !_backupPal.empty()); + _activePal = _backupPal; _changePal = 1; } /*! \brief Load background into renderer * \param bg Raw background data + * \todo Combine with OSRenderer's version of loadBg16 */ void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { assert(idx == 0); - int i; if (!_background) { _background = new byte[_screenSize]; } - if (!_palette) { - _palette = new uint16[_lowPalSize]; - } - - assert(_background && _palette); + assert(_background); strcpy(_bgName, name); - for (i = 0; i < _lowPalSize; i++, bg += 2) { - _palette[i] = READ_BE_UINT16(bg); - } + // Load the 16 color palette + _backupPal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); + + // Jump over the palette data to the background data + bg += kLowPalNumBytes; gfxConvertSpriteToRaw(_background, bg, 160, 200); } @@ -668,25 +644,15 @@ const char *FWRenderer::getBgName(uint idx) const { * \param fHandle Savefile open for reading */ void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { - int i; - - if (!_palette) { - _palette = new uint16[_lowPalSize]; - } - - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } - - assert(_palette && _activeLowPal); + byte buf[kLowPalNumBytes]; - for (i = 0; i < _lowPalSize; i++) { - _activeLowPal[i] = fHandle.readUint16BE(); - } + // Load the active 16 color palette from file + fHandle.read(buf, kLowPalNumBytes); + _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); - for (i = 0; i < _lowPalSize; i++) { - _palette[i] = fHandle.readUint16BE(); - } + // Load the backup 16 color palette from file + fHandle.read(buf, kLowPalNumBytes); + _backupPal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); _changePal = 1; } @@ -695,58 +661,59 @@ void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { * \param fHandle Savefile open for writing */ void FWRenderer::savePalette(Common::OutSaveFile &fHandle) { - int i; + byte buf[kLowPalNumBytes]; - assert(_palette && _activeLowPal); + // Make sure the active palette has the correct format and color count + assert(_activePal.colorFormat() == kLowPalFormat); + assert(_activePal.colorCount() == kLowPalNumColors); - for (i = 0; i < _lowPalSize; i++) { - fHandle.writeUint16BE(_activeLowPal[i]); - } + // Make sure the backup palette has the correct format and color count + assert(_backupPal.colorFormat() == kLowPalFormat); + assert(_backupPal.colorCount() == kLowPalNumColors); - for (i = 0; i < _lowPalSize; i++) { - fHandle.writeUint16BE(_palette[i]); - } + // Write the active palette to the file + _activePal.save(buf, sizeof(buf), CINE_BIG_ENDIAN); + fHandle.write(buf, kLowPalNumBytes); + + // Write the backup palette to the file + _backupPal.save(buf, sizeof(buf), CINE_BIG_ENDIAN); + fHandle.write(buf, kLowPalNumBytes); } /*! \brief Write active and backup palette to save * \param fHandle Savefile open for writing + * \todo Add support for saving the palette in the 16 color version of Operation Stealth. + * Possibly combine with FWRenderer's savePalette-method? */ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { - int i; + byte buf[kHighPalNumBytes]; - assert(_activeHiPal); + // Make sure the active palette has the correct format and color count + assert(_activePal.colorFormat() == kHighPalFormat); + assert(_activePal.colorCount() == kHighPalNumColors); // Write the active 256 color palette. - for (i = 0; i < _hiPalSize; i++) { - fHandle.writeByte(_activeHiPal[i]); - } + _activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN); + fHandle.write(buf, kHighPalNumBytes); // Write the active 256 color palette a second time. // FIXME: The backup 256 color palette should be saved here instead of the active one. - for (i = 0; i < _hiPalSize; i++) { - fHandle.writeByte(_activeHiPal[i]); - } + fHandle.write(buf, kHighPalNumBytes); } /*! \brief Restore active and backup palette from save * \param fHandle Savefile open for reading */ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { - int i; - - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - } + byte buf[kHighPalNumBytes]; - assert(_activeHiPal); - - for (i = 0; i < _hiPalSize; i++) { - _activeHiPal[i] = fHandle.readByte(); - } + // Load the active 256 color palette from file + fHandle.read(buf, kHighPalNumBytes); + _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); // Jump over the backup 256 color palette. // FIXME: Load the backup 256 color palette and use it properly. - fHandle.seek(_hiPalSize, SEEK_CUR); + fHandle.seek(kHighPalNumBytes, SEEK_CUR); _changePal = 1; } @@ -754,10 +721,10 @@ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { /*! \brief Rotate active palette * \param a First color to rotate * \param b Last color to rotate - * \param c Possibly rotation step, must be equal to 1 at the moment + * \param c Possibly rotation step, must be 0 or 1 at the moment */ void FWRenderer::rotatePalette(int a, int b, int c) { - palRotate(_activeLowPal, a, b, c); + _activePal.rotateRight(a, b, c); refreshPalette(); } @@ -769,12 +736,11 @@ void FWRenderer::rotatePalette(int a, int b, int c) { * \param b Blue channel transformation */ void FWRenderer::transformPalette(int first, int last, int r, int g, int b) { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); + if (!_activePal.isValid() || _activePal.empty()) { + _activePal = Cine::Palette(kLowPalFormat, kLowPalNumColors); } - transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b); + _backupPal.saturatedAddColor(_activePal, first, last, r, g, b); refreshPalette(); } @@ -889,22 +855,16 @@ void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, i } /*! \brief Fade to black + * \bug Operation Stealth sometimes seems to fade to black using + * transformPalette resulting in double fadeout */ void FWRenderer::fadeToBlack() { - // FIXME: _activeLowPal is invalid when starting Operation Stealth - // Adding this sanity check fixes a crash when the game - // starts, but I'm not sure if this is the best place to check it - if (!_activeLowPal) { - warning("_activeLowPal is invalid"); - return; - } - - assert(_activeLowPal); + assert(_activePal.isValid() && !_activePal.empty()); for (int i = 0; i < 8; i++) { - for (int j = 0; j < 16; j++) { - _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1); - } + // Fade out the whole palette by 1/7th + // (Operation Stealth used 36 / 252, which is 1 / 7. Future Wars used 1 / 7 directly). + _activePal.saturatedAddNormalizedGray(_activePal, 0, _activePal.colorCount() - 1, -1, 7); refreshPalette(); g_system->updateScreen(); @@ -914,45 +874,25 @@ void FWRenderer::fadeToBlack() { /*! \brief Initialize Operation Stealth renderer */ -OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0), +OSRenderer::OSRenderer() : FWRenderer(), _bgTable(), _currentBg(0), _scrollBg(0), _bgShift(0) { - int i; - for (i = 0; i < 9; i++) { - _bgTable[i].bg = NULL; - _bgTable[i].lowPal = NULL; - _bgTable[i].hiPal = NULL; - memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); - } + _bgTable.resize(9); // Resize the background table to its required size } /*! \brief Destroy Operation Stealth renderer */ OSRenderer::~OSRenderer() { - delete[] _activeHiPal; - - for (int i = 0; i < 9; i++) { - delete[] _bgTable[i].bg; - delete[] _bgTable[i].lowPal; - delete[] _bgTable[i].hiPal; + for (uint i = 0; i < _bgTable.size(); i++) { + _bgTable[i].clear(); } } /*! \brief Reset Operation Stealth renderer state */ void OSRenderer::clear() { - delete[] _activeHiPal; - _activeHiPal = NULL; - - for (int i = 0; i < 9; i++) { - delete[] _bgTable[i].bg; - delete[] _bgTable[i].lowPal; - delete[] _bgTable[i].hiPal; - - _bgTable[i].bg = NULL; - _bgTable[i].lowPal = NULL; - _bgTable[i].hiPal = NULL; - memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); + for (uint i = 0; i < _bgTable.size(); i++) { + _bgTable[i].clear(); } _currentBg = 0; @@ -1159,28 +1099,6 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) { } } -/*! \brief Refresh current palette - */ -void OSRenderer::refreshPalette() { - if (!_activeHiPal) { - FWRenderer::refreshPalette(); - return; - } - - int i; - byte pal[256*4]; - - for (i = 0; i < 256; i++) { - pal[i * 4 + 0] = _activeHiPal[i * 3 + 0]; - pal[i * 4 + 1] = _activeHiPal[i * 3 + 1]; - pal[i * 4 + 2] = _activeHiPal[i * 3 + 2]; - pal[i * 4 + 3] = 0; - } - - g_system->setPalette(pal, 0, 256); - _changePal = 0; -} - /*! \brief Load palette of current background */ void OSRenderer::reloadPalette() { @@ -1188,49 +1106,12 @@ void OSRenderer::reloadPalette() { // and 14, shift background has it right palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; - assert(bg->lowPal || bg->hiPal); - - if (bg->lowPal) { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } + assert(bg->pal.isValid() && !(bg->pal.empty())); - assert(_activeLowPal); - - delete[] _activeHiPal; - _activeHiPal = NULL; - - memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16)); - } else { - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - } - - assert(_activeHiPal); - - delete[] _activeLowPal; - _activeLowPal = NULL; - - memcpy(_activeHiPal, bg->hiPal, _hiPalSize); - } + _activePal = bg->pal; _changePal = 1; } -/*! \brief Rotate active palette - * \param a First color to rotate - * \param b Last color to rotate - * \param c Possibly rotation step, must be equal to 1 at the moment - */ -void OSRenderer::rotatePalette(int a, int b, int c) { - if (_activeLowPal) { - FWRenderer::rotatePalette(a, b, c); - return; - } - - palRotate(_activeHiPal, a, b, c); - refreshPalette(); -} - /*! \brief Copy part of backup palette to active palette and transform * \param first First color to transform * \param last Last color to transform @@ -1241,28 +1122,12 @@ void OSRenderer::rotatePalette(int a, int b, int c) { void OSRenderer::transformPalette(int first, int last, int r, int g, int b) { palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; - if (!bg->lowPal) { - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - memset(_activeHiPal, 0, _hiPalSize); - } - - delete[] _activeLowPal; - _activeLowPal = NULL; - - transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b); - } else { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); - } - - delete[] _activeHiPal; - _activeHiPal = NULL; - - transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b); + // Initialize active palette to current background's palette format and size if they differ + if (_activePal.colorFormat() != bg->pal.colorFormat() || _activePal.colorCount() != bg->pal.colorCount()) { + _activePal = Cine::Palette(bg->pal.colorFormat(), bg->pal.colorCount()); } + bg->pal.saturatedAddColor(_activePal, first, last, r, g, b, kLowPalFormat); refreshPalette(); } @@ -1270,29 +1135,24 @@ void OSRenderer::transformPalette(int first, int last, int r, int g, int b) { * \param bg Raw background data * \param name Background filename * \param pos Background index + * \todo Combine with FWRenderer's version of loadBg16 */ void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { - int i; assert(idx < 9); if (!_bgTable[idx].bg) { _bgTable[idx].bg = new byte[_screenSize]; } - if (!_bgTable[idx].lowPal) { - _bgTable[idx].lowPal = new uint16[_lowPalSize]; - } - - assert(_bgTable[idx].bg && _bgTable[idx].lowPal); - - delete[] _bgTable[idx].hiPal; - _bgTable[idx].hiPal = NULL; + assert(_bgTable[idx].bg); strcpy(_bgTable[idx].name, name); - for (i = 0; i < _lowPalSize; i++, bg += 2) { - _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg); - } + // Load the 16 color palette + _bgTable[idx].pal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); + + // Jump over the palette data to the background data + bg += kLowPalNumBytes; gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200); } @@ -1302,7 +1162,10 @@ void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { * \param name Background filename */ void OSRenderer::loadCt16(const byte *ct, const char *name) { - loadBg16(ct, name, 8); + // Make the 9th background point directly to the collision page + // and load the picture into it. + _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage; + loadBg16(ct, name, kCollisionPageBgIdxAlias); } /*! \brief Load 256 color background into renderer @@ -1317,18 +1180,11 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { _bgTable[idx].bg = new byte[_screenSize]; } - if (!_bgTable[idx].hiPal) { - _bgTable[idx].hiPal = new byte[_hiPalSize]; - } - - assert(_bgTable[idx].bg && _bgTable[idx].hiPal); - - delete[] _bgTable[idx].lowPal; - _bgTable[idx].lowPal = NULL; + assert(_bgTable[idx].bg); strcpy(_bgTable[idx].name, name); - memcpy(_bgTable[idx].hiPal, bg, _hiPalSize); - memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize); + _bgTable[idx].pal.load(bg, kHighPalNumBytes, kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + memcpy(_bgTable[idx].bg, bg + kHighPalNumBytes, _screenSize); } /*! \brief Load 256 color CT data as background into renderer @@ -1336,7 +1192,10 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { * \param name Background filename */ void OSRenderer::loadCt256(const byte *ct, const char *name) { - loadBg256(ct, name, 8); + // Make the 9th background point directly to the collision page + // and load the picture into it. + _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage; + loadBg256(ct, name, kCollisionPageBgIdxAlias); } /*! \brief Select active background and load its palette @@ -1344,7 +1203,7 @@ void OSRenderer::loadCt256(const byte *ct, const char *name) { */ void OSRenderer::selectBg(unsigned int idx) { assert(idx < 9 && _bgTable[idx].bg); - assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal); + assert(_bgTable[idx].pal.isValid() && !(_bgTable[idx].pal.empty())); _currentBg = idx; reloadPalette(); @@ -1392,13 +1251,7 @@ void OSRenderer::removeBg(unsigned int idx) { _scrollBg = 0; } - delete[] _bgTable[idx].bg; - delete[] _bgTable[idx].lowPal; - delete[] _bgTable[idx].hiPal; - _bgTable[idx].bg = NULL; - _bgTable[idx].lowPal = NULL; - _bgTable[idx].hiPal = NULL; - memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name)); + _bgTable[idx].clear(); } void OSRenderer::saveBgNames(Common::OutSaveFile &fHandle) { @@ -1412,27 +1265,6 @@ const char *OSRenderer::getBgName(uint idx) const { return _bgTable[idx].name; } -/*! \brief Fade to black - * \bug Operation Stealth sometimes seems to fade to black using - * transformPalette resulting in double fadeout - */ -void OSRenderer::fadeToBlack() { - if (!_activeHiPal) { - FWRenderer::fadeToBlack(); - return; - } - - for (int i = 0; i < 8; i++) { - for (int j = 0; j < _hiPalSize; j++) { - _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255); - } - - refreshPalette(); - g_system->updateScreen(); - g_system->delayMillis(50); - } -} - void setMouseCursor(int cursor) { static int currentMouseCursor = -1; assert(cursor >= 0 && cursor < 3); diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 0ed1626ab0..f1503a4c46 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -31,13 +31,34 @@ namespace Cine { +extern byte *collisionPage; +static const int kCollisionPageBgIdxAlias = 8; + /*! \brief Background with palette */ struct palBg { byte *bg; ///< Background data - byte *hiPal; ///< 256 color palette - uint16 *lowPal; ///< 16 color palette + Cine::Palette pal; ///< Background color palette char name[15]; ///< Background filename + + /** @brief Default constructor. */ + palBg() : bg(NULL), pal(), name() { + // Make sure the name is empty (Maybe this is not needed?) + memset(this->name, 0, sizeof(this->name)); + } + + /** @brief Clears the struct (Releases allocated memory etc). */ + void clear() { + // In Operation Stealth the 9th background is sometimes aliased to + // the collision page so we should take care not to double delete it + // (The collision page is deleted elsewhere). + if (this->bg != collisionPage) { + delete[] this->bg; + } + this->bg = NULL; + this->pal.clear(); + memset(this->name, 0, sizeof(this->name)); + } }; /*! \brief Future Wars renderer @@ -46,10 +67,10 @@ struct palBg { * without calling drawFrame() all the time */ class FWRenderer : public Common::NonCopyable { +protected: private: byte *_background; ///< Current background char _bgName[13]; ///< Background filename - uint16 *_palette; ///< 16 color backup palette Common::String _cmd; ///< Player command string @@ -57,10 +78,10 @@ protected: static const int _screenSize = 320 * 200; ///< Screen size static const int _screenWidth = 320; ///< Screen width static const int _screenHeight = 200; ///< Screen height - static const int _lowPalSize = 16; ///< 16 color palette size byte *_backBuffer; ///< Screen backbuffer - uint16 *_activeLowPal; ///< Active 16 color palette + Cine::Palette _backupPal; ///< The backup color palette + Cine::Palette _activePal; ///< The active color palette int _changePal; ///< Load active palette to video backend on next frame bool _showCollisionPage; ///< Should we show the collision page instead of the back buffer? Used for debugging. @@ -130,15 +151,12 @@ public: */ class OSRenderer : public FWRenderer { private: - // FIXME: Background table's size is probably 8 instead of 9. Check to make sure and correct if necessary. - palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer - byte *_activeHiPal; ///< Active 256 color palette + Common::Array<palBg> _bgTable; ///< Table of backgrounds loaded into renderer (Maximum is 9) unsigned int _currentBg; ///< Current background unsigned int _scrollBg; ///< Current scroll background unsigned int _bgShift; ///< Background shift protected: - static const int _hiPalSize = 256 * 3; ///< 256 color palette size void drawSprite(const objectStruct &obj); int drawChar(char character, int x, int y); @@ -169,19 +187,15 @@ public: void saveBgNames(Common::OutSaveFile &fHandle); const char *getBgName(uint idx = 0) const; - void refreshPalette(); void reloadPalette(); void restorePalette(Common::SeekableReadStream &fHandle); void savePalette(Common::OutSaveFile &fHandle); - void rotatePalette(int a, int b, int c); void transformPalette(int first, int last, int r, int g, int b); - void fadeToBlack(); }; void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy); -extern byte *collisionPage; extern FWRenderer *renderer; void setMouseCursor(int cursor); diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index c6bca84e46..44e4e43a6c 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -288,6 +288,8 @@ void CineEngine::mainLoop(int bootScriptIdx) { globalVars[VAR_MOUSE_X_POS] = 0; globalVars[VAR_MOUSE_Y_POS] = 0; if (g_cine->getGameType() == Cine::GType_OS) { + globalVars[VAR_MOUSE_X_POS_2ND] = 0; + globalVars[VAR_MOUSE_Y_POS_2ND] = 0; globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc. } diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index 49edaef5e4..b3e3629239 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -103,65 +103,6 @@ void loadRelatedPalette(const char *fileName) { } } -void palRotate(uint16 *pal, byte a, byte b, byte c) { - assert(pal); - - if (c == 1) { - uint16 currentColor = pal[b]; - - for (int i = b; i > a; i--) { - pal[i] = pal[i - 1]; - } - - pal[a] = currentColor; - } -} - -void palRotate(byte *pal, byte a, byte b, byte c) { - assert(pal); - - if (c == 1) { - byte currentR = pal[3 * b + 0]; - byte currentG = pal[3 * b + 1]; - byte currentB = pal[3 * b + 2]; - - for (int i = b; i > a; i--) { - pal[3 * i + 0] = pal[3 * (i - 1) + 0]; - pal[3 * i + 1] = pal[3 * (i - 1) + 1]; - pal[3 * i + 2] = pal[3 * (i - 1) + 2]; - } - - pal[3 * a + 0] = currentR; - pal[3 * a + 1] = currentG; - pal[3 * a + 2] = currentB; - } -} - -uint16 transformColor(uint16 baseColor, int r, int g, int b) { - int8 oriR = CLIP( (baseColor & 0x007) + b, 0, 7); - int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7); - int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7); - - return oriR | (oriG << 4) | (oriB << 8); -} - -void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) { - assert(srcPal && dstPal); - - for (int i = startColor; i <= stopColor; i++) - dstPal[i] = transformColor(srcPal[i], r, g, b); -} - -void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) { - assert(srcPal && dstPal); - - for (int i = startColor; i <= stopColor; i++) { - dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 36, 0, 252); - dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 36, 0, 252); - dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 36, 0, 252); - } -} - /*! \brief Shift byte to the left by given amount (Handles negative shifting amounts too, otherwise this would be trivial). */ byte shiftByteLeft(const byte value, const signed shiftLeft) { if (shiftLeft >= 0) @@ -198,13 +139,17 @@ int bytePos(const int bitPos, const int numBytes, const bool bigEndian) { } // a.k.a. palRotate -Palette &Palette::rotateRight(byte firstIndex, byte lastIndex) { - const Color lastColor = _colors[lastIndex]; +Palette &Palette::rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount) { + assert(rotationAmount == 0 || rotationAmount == 1); + + if (rotationAmount == 1) { + const Color lastColor = _colors[lastIndex]; - for (int i = lastIndex; i > firstIndex; i--) - _colors[i] = _colors[i - 1]; + for (int i = lastIndex; i > firstIndex; i--) + _colors[i] = _colors[i - 1]; - _colors[firstIndex] = lastColor; + _colors[firstIndex] = lastColor; + } return *this; } @@ -277,18 +222,18 @@ Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastI Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed rSource, signed gSource, signed bSource, const Graphics::PixelFormat &sourceFormat) { // Convert the source color to the internal color format ensuring that no divide by zero will happen - const signed r = _format.rMax() * rSource / MAX<int>(sourceFormat.rMax(), 1); - const signed g = _format.gMax() * gSource / MAX<int>(sourceFormat.gMax(), 1); - const signed b = _format.bMax() * bSource / MAX<int>(sourceFormat.bMax(), 1); + const signed r = ((signed) _format.rMax()) * rSource / MAX<int>(sourceFormat.rMax(), 1); + const signed g = ((signed) _format.gMax()) * gSource / MAX<int>(sourceFormat.gMax(), 1); + const signed b = ((signed) _format.bMax()) * bSource / MAX<int>(sourceFormat.bMax(), 1); return saturatedAddColor(output, firstIndex, lastIndex, r, g, b); } Palette &Palette::saturatedAddNormalizedGray(Palette& output, byte firstIndex, byte lastIndex, int grayDividend, int grayDenominator) { assert(grayDenominator != 0); - const signed r = _format.rMax() * grayDividend / grayDenominator; - const signed g = _format.gMax() * grayDividend / grayDenominator; - const signed b = _format.bMax() * grayDividend / grayDenominator; + const signed r = ((signed) _format.rMax()) * grayDividend / grayDenominator; + const signed g = ((signed) _format.gMax()) * grayDividend / grayDenominator; + const signed b = ((signed) _format.bMax()) * grayDividend / grayDenominator; return saturatedAddColor(output, firstIndex, lastIndex, r, g, b); } diff --git a/engines/cine/pal.h b/engines/cine/pal.h index fd0ea8587b..26513eb5a1 100644 --- a/engines/cine/pal.h +++ b/engines/cine/pal.h @@ -74,16 +74,8 @@ void loadPal(const char *fileName); void loadRelatedPalette(const char *fileName); -void palRotate(uint16 *pal, byte a, byte b, byte c); -void palRotate(byte *pal, byte a, byte b, byte c); -uint16 transformColor(uint16 baseColor, int r, int g, int b); -void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b); -void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b); - -// This class might be used for handling Cine-engine's palettes in the future. WIP! -// TODO: Document -// TODO: Make use of -// TODO: Test +// A class for handling Cine-engine's palettes. +// TODO: Test a bit more class Palette { public: struct Color { @@ -136,7 +128,10 @@ public: */ byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endian, const byte firstIndex = 0) const; - Palette &rotateRight(byte firstIndex, byte lastIndex); + /*! \brief Rotate the palette in color range [firstIndex, lastIndex] to the right by the specified rotation amount. + * \param rotationAmount Amount to rotate the sub-palette to the right. Only values 0 and 1 are currently supported! + */ + Palette &rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount = 1); Palette &saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed r, signed g, signed b); /*! \brief Saturated add an RGB color in given color format to current palette's subset and save the modified colors in the given output palette. diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp index 164c5a9ca5..65b384ac7d 100644 --- a/engines/cine/sound.cpp +++ b/engines/cine/sound.cpp @@ -507,8 +507,6 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) { } int freq, note, oct; findNote(frequency, ¬e, &oct); - - note += oct * 12; if (ins->amDepth) { note = ins->amDepth; } diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp index ffc36b4b1a..3dceae2fa4 100644 --- a/engines/cine/texte.cpp +++ b/engines/cine/texte.cpp @@ -37,8 +37,6 @@ const char **otherMessages; const char *defaultCommandPreposition; const char **commandPrepositionTable; -void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency); - /*! \brief Loads font data from the given file. * The number of characters used in the font varies between game versions: * 78 (Most PC, Amiga and Atari ST versions of Future Wars, but also Operation Stealth's Amiga demo), diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 1ec558c217..7192afcd92 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1095,8 +1095,8 @@ uint16 executePlayerInput(void) { // This fixes swimming at the bottom of the ocean after // having been thrown into it with the girl. if (g_cine->getGameType() == Cine::GType_OS) { - globalVars[251] = globalVars[VAR_MOUSE_X_POS]; - globalVars[252] = globalVars[VAR_MOUSE_Y_POS]; + globalVars[VAR_MOUSE_X_POS_2ND] = globalVars[VAR_MOUSE_X_POS]; + globalVars[VAR_MOUSE_Y_POS_2ND] = globalVars[VAR_MOUSE_Y_POS]; } return var_5E; @@ -1501,10 +1501,7 @@ void processSeqListElement(SeqListElement &element) { if (xMoveKeyb != kKeybMoveRight) { adder = -adder; } - // FIXME: In Operation Stealth's disassembly global variable 251 is used here - // but it's named as VAR_MOUSE_Y_MODE in ScummVM. Is it correct or a - // left over from Future Wars's reverse engineering? - globalVars[VAR_MOUSE_X_POS] = globalVars[251] = ptr1[4] + x + adder; + globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = ptr1[4] + x + adder; } if (yMoveKeyb && allowPlayerInput) { @@ -1512,8 +1509,7 @@ void processSeqListElement(SeqListElement &element) { if (yMoveKeyb != kKeybMoveDown) { adder = -adder; } - // TODO: Name currently unnamed global variable 252 - globalVars[VAR_MOUSE_Y_POS] = globalVars[252] = ptr1[5] + y + adder; + globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = ptr1[5] + y + adder; } if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) { diff --git a/engines/cine/various.h b/engines/cine/various.h index bdbbc6fb86..1f9aa7dc78 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -80,8 +80,6 @@ extern int16 commandVar3[4]; extern char currentDatName[30]; extern uint16 musicIsPlaying; -void setTextWindow(uint16 param1, uint16 param2, uint16 param3, uint16 param4); - extern uint16 errorVar; extern byte menuVar; diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp index 734f4b95c5..4656704cb8 100644 --- a/engines/cruise/cruise.cpp +++ b/engines/cruise/cruise.cpp @@ -52,26 +52,24 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc _currentVolumeFile = new Common::File(); #endif - Common::addDebugChannel(kCruiseDebugScript, "Script", - "Script debug level"); + Common::addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level"); + Common::addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level"); // Setup mixer _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, - ConfMan.getInt("sfx_volume")); + ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, - ConfMan.getInt("music_volume")); + ConfMan.getInt("music_volume")); _vm = this; _debugger = new Debugger(); - _music = new MusicPlayer(); - _sound = new SoundPlayer(); + _sound = new PCSound(_mixer, this); syst->getEventManager()->registerRandomSource(_rnd, "cruise"); } CruiseEngine::~CruiseEngine() { delete _debugger; - delete _music; delete _sound; freeSystem(); @@ -126,9 +124,8 @@ void CruiseEngine::initialize() { readVolCnf(); // Setup mixer - _musicVolume = ConfMan.getInt("music_volume"); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); +// _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); +// _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); _mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); @@ -230,4 +227,8 @@ const char *CruiseEngine::getSavegameFile(int saveGameIdx) { return buffer; } +void CruiseEngine::syncSoundSettings() { + _sound->syncSounds(); +} + } // End of namespace Cruise diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index 2fc69acea0..af098b4997 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -57,10 +57,8 @@ private: bool _preLoad; Debugger *_debugger; MidiDriver *_driver; - MusicPlayer *_music; - SoundPlayer *_sound; + PCSound *_sound; bool _mt32, _adlib; - int _musicVolume; Common::StringList _langStrings; CursorType _savedCursor; uint32 lastTick, lastTickDebug; @@ -90,8 +88,7 @@ public: uint32 getFeatures() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; - MusicPlayer &music() { return *_music; } - SoundPlayer &sound() { return *_sound; } + PCSound &sound() { return *_sound; } bool mt32() const { return _mt32; } bool adlib() const { return _adlib; } virtual GUI::Debugger *getDebugger() { return _debugger; } @@ -103,6 +100,7 @@ public: virtual bool canLoadGameStateCurrently(); virtual Common::Error saveGameState(int slot, const char *desc); virtual bool canSaveGameStateCurrently(); + virtual void syncSoundSettings(); const CRUISEGameDescription *_gameDescription; void initAllData(void); @@ -128,7 +126,8 @@ enum { }; enum { - kCruiseDebugScript = 1 << 0 + kCruiseDebugScript = 1 << 0, + kCruiseDebugSound = 1 << 1 }; enum { diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 136aa92b81..26f66d4433 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -81,12 +81,11 @@ int getNumObjectsByClass(int scriptIdx, int param) { return (counter); } -void resetFileEntryRange(int param1, int param2) { +void resetFileEntryRange(int start, int count) { int i; - for (i = param1; i < param2; i++) { - resetFileEntry(i); - } + for (i = 0; i < count; ++i) + resetFileEntry(start + i); } int getProcParam(int overlayIdx, int param2, const char *name) { @@ -294,15 +293,15 @@ int loadFileSub1(uint8 **ptr, const char *name, uint8 *ptr2) { if (!strcmp(buffer, ".SPL")) { removeExtention(name, buffer); - // if (useH32) - { - strcat(buffer, ".H32"); - } - /* else + /* if (useH32) + *{ + * strcat(buffer, ".H32"); + *} + * else * if (useAdlib) - * { - * strcatuint8(buffer,".ADL"); - * } + * { */ + strcat(buffer,".ADL"); + /* } * else * { * strcatuint8(buffer,".HP"); @@ -1739,6 +1738,9 @@ void CruiseEngine::mainLoop(void) { int quitValue2 = 1; int quitValue = 0; + if (ConfMan.hasKey("save_slot")) + loadGameState(ConfMan.getInt("save_slot")); + do { // Handle frame delay uint32 currentTick = g_system->getMillis(); @@ -1915,8 +1917,12 @@ void CruiseEngine::mainLoop(void) { char* pText = getText(autoMsg, autoOvl); - if (strlen(pText)) + if (strlen(pText)) { userWait = 1; + + mainDraw(0); + flipScreen(); + } } changeScriptParamInList(-1, -1, &relHead, 9998, 0); diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index 86e8dc1591..d2e9350d70 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -96,7 +96,6 @@ void *mallocAndZero(int32 size); uint8 *mainProc14(uint16 overlay, uint16 idx); void printInfoBlackBox(const char *string); void waitForPlayerInput(void); -int initCt(const char * ctpName); void loadPackedFileToMem(int fileIdx, uint8 * buffer); int getNumObjectsByClass(int scriptIdx, int param); void resetFileEntryRange(int param1, int param2); @@ -108,7 +107,6 @@ void resetPtr2(scriptInstanceStruct * ptr); void getFileExtention(const char *name, char *buffer); void *allocAndZero(int size); void freeStuff2(void); -const char *getObjectName(int index, const char * string); void mainLoop(void); void getMouseStatus(int16 *pMouseVar, int16 *pMouseX, int16 *pMouseButton, int16 *pMouseY); bool testMask(int x, int y, unsigned char* pData, int stride); diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp index d725e1bb89..3cf3957703 100644 --- a/engines/cruise/dataLoader.cpp +++ b/engines/cruise/dataLoader.cpp @@ -257,13 +257,15 @@ int loadFile(const char* name, int idx, int destIdx) { return loadFNTSub(ptr, idx); break; } - case type_UNK: { - break; - } case type_SPL: { + // Sound file + loadSPLSub(ptr, idx); break; } + default: + error("Unknown fileType in loadFile"); } + return -1; } @@ -293,13 +295,15 @@ int loadFileRange(const char *name, int startIdx, int currentEntryIdx, int numId loadFNTSub(ptr, startIdx); break; } - case type_UNK: { - break; - } case type_SPL: { + // Sound file + loadSPLSub(ptr, startIdx); break; } + default: + error("Unknown fileType in loadFileRange"); } + return 0; } @@ -316,6 +320,7 @@ int loadFullBundle(const char *name, int startIdx) { switch (fileType) { case type_SET: { + // Sprite set int i; int numMaxEntriesInSet; @@ -328,15 +333,17 @@ int loadFullBundle(const char *name, int startIdx) { break; } case type_FNT: { + // Font file loadFNTSub(ptr, startIdx); break; } - case type_UNK: { - break; - } case type_SPL: { + // Sound file + loadSPLSub(ptr, startIdx); break; } + default: + error("Unknown fileType in loadFullBundle"); } return 0; @@ -387,6 +394,23 @@ int loadFNTSub(uint8 *ptr, int destIdx) { return 1; } +int loadSPLSub(uint8 *ptr, int destIdx) { + uint8 *destPtr; + int fileIndex; + + if (destIdx == -1) { + fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1); + } else { + fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1); + } + + destPtr = filesDatabase[fileIndex].subData.ptr; + memcpy(destPtr, ptr, loadFileVar1); + + return 1; +} + + int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentDestEntry) { uint8 *ptr3; int offset; diff --git a/engines/cruise/dataLoader.h b/engines/cruise/dataLoader.h index 2e433acfcb..f6bea29cde 100644 --- a/engines/cruise/dataLoader.h +++ b/engines/cruise/dataLoader.h @@ -29,6 +29,7 @@ namespace Cruise { int loadFNTSub(uint8 *ptr, int destIdx); +int loadSPLSub(uint8 *ptr, int destIdx); int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentDestEntry); int loadFile(const char* name, int idx, int destIdx); int loadData(const char * name, int startIdx); diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index 610812780a..879fad0210 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -64,6 +64,8 @@ static const PlainGameDescriptor cruiseGames[] = { namespace Cruise { +using Common::GUIO_NONE; + static const CRUISEGameDescription gameDescriptions[] = { { { @@ -72,7 +74,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "41a7a4d426dbd048eb369cfee4bb2717"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -84,7 +87,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "a90d2b9ead6b4d812cd14268672cf178"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -96,7 +100,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "e258865807ea31b2d523340e6f0a606b"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -108,7 +113,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "287d2ec1799e2f881dee23c70be96e81"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -120,7 +126,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "f2a26522d49983c4ae32bcccbb801b02"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -132,7 +139,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "e19a4ab2e24a69087e4ea994a5506231"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -144,7 +152,8 @@ static const CRUISEGameDescription gameDescriptions[] = { AD_ENTRY1("D1", "9a302ada55600d96061fda1d63a6ccda"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_CRUISE, 0, @@ -170,7 +179,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI }; class CruiseMetaEngine : public AdvancedMetaEngine { @@ -198,7 +209,8 @@ bool CruiseMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSupportsListSaves) || (f == kSupportsDeleteSave) || (f == kSavesSupportMetaInfo) || - (f == kSavesSupportThumbnail); + (f == kSavesSupportThumbnail) || + (f == kSupportsLoadingDuringStartup); } SaveStateList CruiseMetaEngine::listSaves(const char *target) const { diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index 7789cb6fb1..eab69c6846 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -32,6 +32,10 @@ namespace Cruise { +uint32 Period(uint32 hz) { + return ((uint32)(100000000L / ((uint32)hz * 28L))); +} + //#define FUNCTION_DEBUG int16 Op_LoadOverlay(void) { @@ -198,15 +202,15 @@ int16 Op_Random(void) { int16 Op_PlayFX(void) { int volume = popVar(); int speed = popVar(); - int channelNum = popVar(); + /*int channelNum = */popVar(); int sampleNum = popVar(); if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) { if (speed == -1) speed = filesDatabase[sampleNum].subData.transparency; - _vm->sound().startSound(channelNum, filesDatabase[sampleNum].subData.ptr, - filesDatabase[sampleNum].width, speed, volume, false); + _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr, + filesDatabase[sampleNum].width, volume); } return (0); @@ -215,15 +219,15 @@ int16 Op_PlayFX(void) { int16 Op_LoopFX(void) { int volume = popVar(); int speed = popVar(); - int channelNum = popVar(); + /*int channelNum = */popVar(); int sampleNum = popVar(); if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) { if (speed == -1) speed = filesDatabase[sampleNum].subData.transparency; - _vm->sound().startSound(channelNum, filesDatabase[sampleNum].subData.ptr, - filesDatabase[sampleNum].width, speed, volume, true); + _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr, + filesDatabase[sampleNum].width, volume); } return (0); @@ -246,15 +250,14 @@ int16 Op_StopFX(void) { int16 Op_FreqFX(void) { int volume = popVar(); - int speed = popVar(); + int freq2 = popVar(); int channelNum = popVar(); int sampleNum = popVar(); if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) { - if (speed == -1) - speed = filesDatabase[sampleNum].subData.transparency; - - _vm->sound().startNote(channelNum, volume, speed); + int freq = Period(freq2 * 1000); + + _vm->sound().startNote(channelNum, volume, freq); } return (0); @@ -357,10 +360,10 @@ int16 Op_FindSet(void) { } int16 Op_RemoveFrame(void) { - int var1 = popVar(); - int var2 = popVar(); + int count = popVar(); + int start = popVar(); - resetFileEntryRange(var2, var1); + resetFileEntryRange(start, count); return (0); } @@ -563,26 +566,22 @@ int16 Op_LoadFrame(void) { } int16 Op_LoadAbs(void) { - int param1; -// int param2; -// int param3; + int slot; char name[36] = ""; char *ptr; int result = 0; ptr = (char *) popPtr(); + slot = popVar(); - strcpy(name, ptr); - - param1 = popVar(); - - if (param1 >= 0 || param1 < NUM_FILE_ENTRIES) { + if ((slot >= 0) && (slot < NUM_FILE_ENTRIES)) { + strcpy(name, ptr); strToUpper(name); gfxModuleData_gfxWaitVSync(); gfxModuleData_gfxWaitVSync(); - result = loadFullBundle(name, param1); + result = loadFullBundle(name, slot); } changeCursor(CURSOR_NORMAL); @@ -774,8 +773,6 @@ int16 Op_UnfreezeParent(void) { return 0; } -int16 protectionCode = 0; - int16 Op_ProtectionFlag(void) { int16 temp = protectionCode; int16 newVar; @@ -1356,22 +1353,22 @@ int16 Op_LoadSong(void) { strcpy(buffer, ptr); strToUpper(buffer); - _vm->music().loadSong(buffer); + _vm->sound().loadMusic(buffer); changeCursor(CURSOR_NORMAL); return 0; } int16 Op_PlaySong(void) { - if (_vm->music().songLoaded() && !_vm->music().songPlayed()) - _vm->music().startSong(); + if (_vm->sound().songLoaded() && !_vm->sound().songPlayed()) + _vm->sound().playMusic(); return 0; } int16 Op_StopSong(void) { - if (_vm->music().isPlaying()) - _vm->music().stop(); + if (_vm->sound().isPlaying()) + _vm->sound().stopMusic(); return 0; } @@ -1385,12 +1382,12 @@ int16 Op_RestoreSong(void) { int16 Op_SongSize(void) { int size, oldSize; - if (_vm->music().songLoaded()) { - byte *pSize = _vm->music().songData() + 470; - oldSize = *pSize; + if (_vm->sound().songLoaded()) { + oldSize = _vm->sound().numOrders(); + size = popVar(); if ((size >= 1) && (size < 128)) - *pSize = size; + _vm->sound().setNumOrders(size); } else oldSize = 0; @@ -1401,35 +1398,34 @@ int16 Op_SetPattern(void) { int value = popVar(); int offset = popVar(); - if (_vm->music().songLoaded()) { - byte *pData = _vm->music().songData(); - *(pData + 472 + offset) = (byte)value; + if (_vm->sound().songLoaded()) { + _vm->sound().setPattern(offset, value); } return 0; } int16 Op_FadeSong(void) { - _vm->music().fadeSong(); + _vm->sound().fadeSong(); return 0; } int16 Op_FreeSong(void) { - _vm->music().stop(); - _vm->music().removeSong(); + _vm->sound().stopMusic(); + _vm->sound().removeMusic(); return 0; } int16 Op_SongLoop(void) { - bool oldLooping = _vm->music().looping(); - _vm->music().setLoop(popVar() != 0); + bool oldLooping = _vm->sound().musicLooping(); + _vm->sound().musicLoop(popVar() != 0); return oldLooping; } int16 Op_SongPlayed(void) { - return _vm->music().songPlayed(); + return _vm->sound().songPlayed(); } void setVar49Value(int value) { @@ -1634,25 +1630,29 @@ int16 Op_GetNodeY(void) { } int16 Op_SetVolume(void) { - int oldVolume = _vm->music().getVolume() >> 2; + int oldVolume = _vm->sound().getVolume(); int newVolume = popVar(); - // TODO: The game seems to expect the volume will only range from 0 - 63, so for now - // I'm doing a translation of the full range 0 - 255 to the 0 - 63 for this script. - // Need to verify at some point that there's no problem with this if (newVolume > 63) newVolume = 63; if (newVolume >= 0) { int volume = 63 - newVolume; - _vm->music().setVolume(volume << 2); + _vm->sound().setVolume(volume); } return oldVolume >> 2; } int16 Op_SongExist(void) { - char* songName = (char*)popPtr(); + const char *songName = (char*)popPtr(); + + if (songName) { + char name[33]; + strcpy(name, songName); + strToUpper(name); - warning("Unimplemented \"Op_SongExist\": %s", songName); + if (!strcmp(_vm->sound().musicName(), name)) + return 1; + } return 0; } diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 136bd281dc..0e9ab55c82 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -207,7 +207,7 @@ int playerMenu(int menuX, int menuY) { if (playerMenuEnabled && displayOn) { if (remdo) { - _vm->music().removeSong(); + _vm->sound().stopMusic(); freeStuff2(); } /* @@ -261,6 +261,7 @@ int playerMenu(int menuX, int menuY) { loadSavegameData(0); break; case 6: // restart + _vm->sound().fadeOutMusic(); Op_FadeOut(); memset(globalScreen, 0, 320 * 200); initVars(); diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index 0084b10cb9..7fcc5ecb1b 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -25,6 +25,7 @@ #include "cruise/cruise_main.h" #include "cruise/cruise.h" +#include "cruise/vars.h" #include "common/serializer.h" #include "common/savefile.h" @@ -143,6 +144,7 @@ static void syncBasicInfo(Common::Serializer &s) { s.syncAsSint16LE(flagCt); s.syncAsSint16LE(var41); s.syncAsSint16LE(playerMenuEnabled); + s.syncAsSint16LE(protectionCode); } static void syncBackgroundTable(Common::Serializer &s) { @@ -608,7 +610,7 @@ static void syncCT(Common::Serializer &s) { static void DoSync(Common::Serializer &s) { syncBasicInfo(s); - _vm->music().doSync(s); + _vm->sound().doSync(s); syncPalette(s, newPal); syncPalette(s, workpal); @@ -818,6 +820,7 @@ Common::Error loadSavegameData(int saveGameIdx) { printInfoBlackBox("Loading in progress..."); initVars(); + _vm->sound().stopMusic(); // Skip over the savegame header CruiseSavegameHeader header; @@ -895,11 +898,15 @@ Common::Error loadSavegameData(int saveGameIdx) { printf("Unsupported mono file load!\n"); ASSERT(0); //loadFileMode1(filesDatabase[j].subData.name,filesDatabase[j].subData.var4); - } else */{ + } else */ + if (strlen(filesDatabase[i].subData.name) > 0) { loadFileRange(filesDatabase[i].subData.name, filesDatabase[i].subData.index, i, j - i); - i = j - 1; + } else { + filesDatabase[i].subData.ptr = NULL; + filesDatabase[i].subData.ptrMask = NULL; } + i = j - 1; lowMemory = lowMemorySave; } } @@ -926,8 +933,6 @@ Common::Error loadSavegameData(int saveGameIdx) { currentcellHead = currentcellHead->next; } - //TODO: here, restart music - if (strlen(currentCtpName)) { loadCtFromSave = 1; initCt(currentCtpName); diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp index fd638e6be5..92c2ac6256 100644 --- a/engines/cruise/sound.cpp +++ b/engines/cruise/sound.cpp @@ -30,199 +30,856 @@ #include "cruise/sound.h" #include "cruise/volume.h" +#include "sound/audiostream.h" +#include "sound/fmopl.h" +#include "sound/mods/soundfx.h" + namespace Cruise { -MusicPlayer::MusicPlayer(): _looping(false), _isPlaying(false), _songPlayed(false) { - _songPointer = NULL; - _masterVolume = 0; +class PCSoundDriver { +public: + typedef void (*UpdateCallback)(void *); + + virtual ~PCSoundDriver() {} + + virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0; + virtual void setChannelFrequency(int channel, int frequency) = 0; + virtual void stopChannel(int channel) = 0; + virtual void playSample(const byte *data, int size, int channel, int volume) = 0; + virtual void stopAll() = 0; + virtual const char *getInstrumentExtension() const { return ""; } + virtual void syncSounds(); + + void setUpdateCallback(UpdateCallback upCb, void *ref); + void resetChannel(int channel); + void findNote(int freq, int *note, int *oct) const; + + +protected: + UpdateCallback _upCb; + void *_upRef; + uint8 _musicVolume; + uint8 _sfxVolume; + + static const int _noteTable[]; + static const int _noteTableCount; +}; + +const int PCSoundDriver::_noteTable[] = { + 0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7, + 0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647, + 0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4, + 0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D, + 0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191, + 0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD, + 0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F, + 0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064, + 0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F, + 0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027, + 0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019, + 0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F +}; + +const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable); + +struct AdlibRegisterSoundInstrument { + uint8 vibrato; + uint8 attackDecay; + uint8 sustainRelease; + uint8 feedbackStrength; + uint8 keyScaling; + uint8 outputLevel; + uint8 freqMod; +}; + +struct AdlibSoundInstrument { + byte mode; + byte channel; + AdlibRegisterSoundInstrument regMod; + AdlibRegisterSoundInstrument regCar; + byte waveSelectMod; + byte waveSelectCar; + byte amDepth; +}; + +struct VolumeEntry { + int original; + int adjusted; +}; + +class AdlibSoundDriver : public PCSoundDriver, Audio::AudioStream { +public: + AdlibSoundDriver(Audio::Mixer *mixer); + virtual ~AdlibSoundDriver(); + + // PCSoundDriver interface + virtual void setupChannel(int channel, const byte *data, int instrument, int volume); + virtual void stopChannel(int channel); + virtual void stopAll(); + + // AudioStream interface + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const { return false; } + virtual int getRate() const { return _sampleRate; } + + void initCard(); + void update(int16 *buf, int len); + void setupInstrument(const byte *data, int channel); + void setupInstrument(const AdlibSoundInstrument *ins, int channel); + void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg); + virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0; + virtual void syncSounds(); + + void adjustVolume(int channel, int volume); + +protected: + FM_OPL *_opl; + int _sampleRate; + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + byte _vibrato; + VolumeEntry _channelsVolumeTable[5]; + AdlibSoundInstrument _instrumentsTable[5]; + + static const int _freqTable[]; + static const int _freqTableCount; + static const int _operatorsTable[]; + static const int _operatorsTableCount; + static const int _voiceOperatorsTable[]; + static const int _voiceOperatorsTableCount; +}; + +const int AdlibSoundDriver::_freqTable[] = { + 0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB, + 0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A +}; + +const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable); + +const int AdlibSoundDriver::_operatorsTable[] = { + 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 +}; + +const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable); + +const int AdlibSoundDriver::_voiceOperatorsTable[] = { + 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13 +}; + +const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable); + +class AdlibSoundDriverADL : public AdlibSoundDriver { +public: + AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {} + virtual const char *getInstrumentExtension() const { return ".ADL"; } + virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi); + virtual void setChannelFrequency(int channel, int frequency); + virtual void playSample(const byte *data, int size, int channel, int volume); +}; + +class PCSoundFxPlayer { +private: + enum { + NUM_INSTRUMENTS = 15, + NUM_CHANNELS = 4 + }; + + void update(); + void handleEvents(); + void handlePattern(int channel, const byte *patternData); + + char _musicName[33]; + bool _playing; + bool _songPlayed; + int _currentPos; + int _currentOrder; + int _numOrders; + int _eventsDelay; + bool _looping; + int _fadeOutCounter; + int _updateTicksCounter; + int _instrumentsChannelTable[NUM_CHANNELS]; + byte *_sfxData; + byte *_instrumentsData[NUM_INSTRUMENTS]; + PCSoundDriver *_driver; + +public: + PCSoundFxPlayer(PCSoundDriver *driver); + ~PCSoundFxPlayer(); + + bool load(const char *song); + void play(); + void stop(); + void unload(); + void fadeOut(); + void doSync(Common::Serializer &s); + + static void updateCallback(void *ref); + + bool songLoaded() const { return _sfxData != NULL; } + bool songPlayed() const { return _songPlayed; } + bool playing() const { return _playing; } + uint8 numOrders() const { assert(_sfxData); return _sfxData[470]; } + void setNumOrders(uint8 v) { assert(_sfxData); _sfxData[470] = v; } + void setPattern(int offset, uint8 value) { assert(_sfxData); _sfxData[472 + offset] = value; } + const char *musicName() { return _musicName; } + + // Note: Original game never actually uses looping variable. Songs are hardcoded to loop + bool looping() const { return _looping; } + void setLooping(bool v) { _looping = v; } +}; + +byte *readBundleSoundFile(const char *name) { + // Load the correct file + int fileIdx = findFileInDisks(name); + if (fileIdx < 0) return NULL; + + int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2; + byte *data = (byte *)malloc(unpackedSize); + assert(data); + + if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) { + uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2); + + loadPackedFileToMem(fileIdx, packedBuffer); + + //uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4); + + delphineUnpack(data, packedBuffer, volumePtrToFileDescriptor[fileIdx].size); + + free(packedBuffer); + } else { + loadPackedFileToMem(fileIdx, data); + } + + return data; } -MusicPlayer::~MusicPlayer() { - stop(); - if (_songPointer != NULL) - free(_songPointer); + +void PCSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) { + _upCb = upCb; + _upRef = ref; } -void MusicPlayer::setVolume(int volume) { - _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); +void PCSoundDriver::findNote(int freq, int *note, int *oct) const { + *note = _noteTableCount - 1; + for (int i = 0; i < _noteTableCount; ++i) { + if (_noteTable[i] <= freq) { + *note = i; + break; + } + } - if (_masterVolume == volume) - return; + *oct = *note / 12; + *note %= 12; +} - _masterVolume = volume; +void PCSoundDriver::resetChannel(int channel) { + stopChannel(channel); + stopAll(); } -void MusicPlayer::stop() { - _isPlaying = false; - _songPlayed = songLoaded(); +void PCSoundDriver::syncSounds() { + // Get the new music and sfx volumes + _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume")); + _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume")); } -void MusicPlayer::pause() { - setVolume(-1); - _isPlaying = false; +AdlibSoundDriver::AdlibSoundDriver(Audio::Mixer *mixer) + : _mixer(mixer) { + _sampleRate = _mixer->getOutputRate(); + _opl = makeAdlibOPL(_sampleRate); + + for (int i = 0; i < 5; ++i) { + _channelsVolumeTable[i].original = 0; + _channelsVolumeTable[i].adjusted = 0; + } + memset(_instrumentsTable, 0, sizeof(_instrumentsTable)); + initCard(); + _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); + + _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume")); + _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume")); } -void MusicPlayer::resume() { - setVolume(_masterVolume); - _isPlaying = true; - _songPlayed = false; +AdlibSoundDriver::~AdlibSoundDriver() { + _mixer->stopHandle(_soundHandle); + OPLDestroy(_opl); } -void MusicPlayer::doSync(Common::Serializer &s) { - // synchronise current music name, if any, state, and position - s.syncBytes((byte *)_musicName, 33); - uint16 v = (uint16)songLoaded(); - s.syncAsSint16LE(v); - s.syncAsSint16LE(_songPlayed); - s.syncAsSint16LE(_looping); +void AdlibSoundDriver::syncSounds() { + PCSoundDriver::syncSounds(); + + // Force all instruments to reload on the next playing point + for (int i = 0; i < 5; ++i) { + adjustVolume(i, _channelsVolumeTable[i].original); + AdlibSoundInstrument *ins = &_instrumentsTable[i]; + setupInstrument(ins, i); + } } -void MusicPlayer::loadSong(const char *name) { - char tempName[20], baseName[20]; - uint8 *sampleData; +void AdlibSoundDriver::adjustVolume(int channel, int volume) { + _channelsVolumeTable[channel].original = volume; - if (songLoaded()) - removeSong(); + if (volume > 80) { + volume = 80; + } else if (volume < 0) { + volume = 0; + } + volume += volume / 4; + if (volume > 127) { + volume = 127; + } - // Load the correct file - int fileIdx = findFileInDisks(name); - if (fileIdx < 0) return; + int volAdjust = (channel == 4) ? _sfxVolume : _musicVolume; + volume = (volume * volAdjust) / 128; - int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2; - _songPointer = (byte *)malloc(unpackedSize); - assert(_songPointer); + if (volume > 127) + volume = 127; - if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) { - uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2); + _channelsVolumeTable[channel].adjusted = volume; +} - loadPackedFileToMem(fileIdx, packedBuffer); +void AdlibSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) { + assert(channel < 5); + if (data) { + adjustVolume(channel, volume); + setupInstrument(data, channel); + } +} - uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4); +void AdlibSoundDriver::stopChannel(int channel) { + assert(channel < 5); + AdlibSoundInstrument *ins = &_instrumentsTable[channel]; + if (ins->mode != 0 && ins->channel == 6) { + channel = 6; + } + if (ins->mode == 0 || channel == 6) { + OPLWriteReg(_opl, 0xB0 | channel, 0); + } + if (ins->mode != 0) { + _vibrato &= ~(1 << (10 - ins->channel)); + OPLWriteReg(_opl, 0xBD, _vibrato); + } +} - delphineUnpack(_songPointer, packedBuffer, volumePtrToFileDescriptor[fileIdx].size); - _songSize = realUnpackedSize; +void AdlibSoundDriver::stopAll() { + int i; + for (i = 0; i < 18; ++i) { + OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63); + } + for (i = 0; i < 9; ++i) { + OPLWriteReg(_opl, 0xB0 | i, 0); + } + OPLWriteReg(_opl, 0xBD, 0); +} - free(packedBuffer); - } else { - loadPackedFileToMem(fileIdx, _songPointer); - _songSize = unpackedSize; +int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) { + update(buffer, numSamples); + return numSamples; +} + +void AdlibSoundDriver::initCard() { + _vibrato = 0x20; + OPLWriteReg(_opl, 0xBD, _vibrato); + OPLWriteReg(_opl, 0x08, 0x40); + + static const int oplRegs[] = { 0x40, 0x60, 0x80, 0x20, 0xE0 }; + + for (int i = 0; i < 9; ++i) { + OPLWriteReg(_opl, 0xB0 | i, 0); + } + for (int i = 0; i < 9; ++i) { + OPLWriteReg(_opl, 0xC0 | i, 0); } - strcpy(_musicName, name); + for (int j = 0; j < 5; j++) { + for (int i = 0; i < 18; ++i) { + OPLWriteReg(_opl, oplRegs[j] | _operatorsTable[i], 0); + } + } - // Get the details of the song - // TODO: Figure this out for sure for use in actually playing song - //int size = *(_songPointer + 470); - //int speed = 244 - *(_songPointer + 471); - //int musicSpeed = (speed * 100) / 1060; + OPLWriteReg(_opl, 1, 0x20); + OPLWriteReg(_opl, 1, 0); +} +void AdlibSoundDriver::update(int16 *buf, int len) { + static int samplesLeft = 0; + while (len != 0) { + int count = samplesLeft; + if (count > len) { + count = len; + } + samplesLeft -= count; + len -= count; + YM3812UpdateOne(_opl, buf, count); + if (samplesLeft == 0) { + if (_upCb) { + (*_upCb)(_upRef); + } + samplesLeft = _sampleRate / 50; + } + buf += count; + } +} - // Get the file without the extension - strcpy(baseName, name); - char *p = strchr(baseName, '.'); - if (p) - *p = '\0'; +void AdlibSoundDriver::setupInstrument(const byte *data, int channel) { + assert(channel < 5); + AdlibSoundInstrument *ins = &_instrumentsTable[channel]; + loadInstrument(data, ins); - // Get the instruments states file - strcpy(tempName, baseName); - strcat(tempName, ".IST"); + setupInstrument(ins, channel); +} + +void AdlibSoundDriver::setupInstrument(const AdlibSoundInstrument *ins, int channel) { + int mod, car, tmp; + const AdlibRegisterSoundInstrument *reg; - fileIdx = findFileInDisks(tempName); - if (fileIdx >= 0) { - // TODO: Figure out instrument state usage - uint8 instrumentState[15]; - loadPackedFileToMem(fileIdx, instrumentState); + if (ins->mode != 0) { + mod = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 0]]; + car = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 1]]; + } else { + mod = _operatorsTable[_voiceOperatorsTable[2 * channel + 0]]; + car = _operatorsTable[_voiceOperatorsTable[2 * channel + 1]]; } - for (int instrumentCtr = 0; instrumentCtr < 15; ++instrumentCtr) { - if (_vm->mt32()) { - // Handle loading Roland instrument data - strcpy(tempName, baseName); - strcat(tempName, ".H32"); + if (ins->mode == 0 || ins->channel == 6) { + reg = &ins->regMod; + OPLWriteReg(_opl, 0x20 | mod, reg->vibrato); + if (reg->freqMod) { + tmp = reg->outputLevel & 0x3F; + } else { + tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted; + tmp = 63 - (2 * tmp + 127) / (2 * 127); + } + OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6)); + OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay); + OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease); + if (ins->mode != 0) { + OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength); + } else { + OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength); + } + OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod); + } - sampleData = loadInstrument(tempName, instrumentCtr); - if (sampleData) { - int v = *sampleData; - if ((v >= 128) && (v < 192)) - patchMidi(0x80000L + (instrumentCtr * 512), sampleData + 1, 254); + reg = &ins->regCar; + OPLWriteReg(_opl, 0x20 | car, reg->vibrato); + tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted; + tmp = 63 - (2 * tmp + 127) / (2 * 127); + OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6)); + OPLWriteReg(_opl, 0x60 | car, reg->attackDecay); + OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease); + OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar); +} - // TODO: Currently I'm freeing the instrument data immediately. The original - // holds onto the sample data, so it may actually still be needed - free(sampleData); - } - } else if (_vm->adlib()) { - // Handle loading Adlib instrument data - strcpy(tempName, baseName); - strcat(tempName, ".ADL"); +void AdlibSoundDriver::loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg) { + reg->vibrato = 0; + if (READ_LE_UINT16(data + 18)) { // amplitude vibrato + reg->vibrato |= 0x80; + } + if (READ_LE_UINT16(data + 20)) { // frequency vibrato + reg->vibrato |= 0x40; + } + if (READ_LE_UINT16(data + 10)) { // sustaining sound + reg->vibrato |= 0x20; + } + if (READ_LE_UINT16(data + 22)) { // envelope scaling + reg->vibrato |= 0x10; + } + reg->vibrato |= READ_LE_UINT16(data + 2) & 0xF; // frequency multiplier - fileIdx = findFileInDisks(tempName); - if (fileIdx >= 0) { - sampleData = (byte *)malloc(volumePtrToFileDescriptor[fileIdx].extSize + 2); - assert(sampleData); - loadPackedFileToMem(fileIdx, sampleData); + reg->attackDecay = READ_LE_UINT16(data + 6) << 4; // attack rate + reg->attackDecay |= READ_LE_UINT16(data + 12) & 0xF; // decay rate - // TODO: Make use of sample data + reg->sustainRelease = READ_LE_UINT16(data + 8) << 4; // sustain level + reg->sustainRelease |= READ_LE_UINT16(data + 14) & 0xF; // release rate - free(sampleData); - } + reg->feedbackStrength = READ_LE_UINT16(data + 4) << 1; // feedback + if (READ_LE_UINT16(data + 24) == 0) { // frequency modulation + reg->feedbackStrength |= 1; + } + + reg->keyScaling = READ_LE_UINT16(data); + reg->outputLevel = READ_LE_UINT16(data + 16); + reg->freqMod = READ_LE_UINT16(data + 24); +} + +void AdlibSoundDriverADL::loadInstrument(const byte *data, AdlibSoundInstrument *asi) { + asi->mode = *data++; + asi->channel = *data++; + asi->waveSelectMod = *data++ & 3; + asi->waveSelectCar = *data++ & 3; + asi->amDepth = *data++; + ++data; + loadRegisterInstrument(data, &asi->regMod); data += 26; + loadRegisterInstrument(data, &asi->regCar); data += 26; +} + +void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) { + assert(channel < 5); + AdlibSoundInstrument *ins = &_instrumentsTable[channel]; + if (ins->mode != 0) { + channel = ins->channel; + if (channel == 9) { + channel = 8; + } else if (channel == 10) { + channel = 7; } } + int freq, note, oct; + findNote(frequency, ¬e, &oct); - _songPlayed = false; - _isPlaying = false; + note += oct * 12; + if (ins->amDepth) { + note = ins->amDepth; + } + if (note < 0) { + note = 0; + } + + freq = _freqTable[note % 12]; + OPLWriteReg(_opl, 0xA0 | channel, freq); + freq = ((note / 12) << 2) | ((freq & 0x300) >> 8); + if (ins->mode == 0) { + freq |= 0x20; + } + OPLWriteReg(_opl, 0xB0 | channel, freq); + if (ins->mode != 0) { + _vibrato |= 1 << (10 - channel); + OPLWriteReg(_opl, 0xBD, _vibrato); + } } -void MusicPlayer::startSong() { - if (songLoaded()) { - // Start playing song here +void AdlibSoundDriverADL::playSample(const byte *data, int size, int channel, int volume) { + assert(channel < 5); + adjustVolume(channel, 127); + + setupInstrument(data, channel); + AdlibSoundInstrument *ins = &_instrumentsTable[channel]; + if (ins->mode != 0 && ins->channel == 6) { + OPLWriteReg(_opl, 0xB0 | channel, 0); + } + if (ins->mode != 0) { + _vibrato &= ~(1 << (10 - ins->channel)); + OPLWriteReg(_opl, 0xBD, _vibrato); } + if (ins->mode != 0) { + channel = ins->channel; + if (channel == 9) { + channel = 8; + } else if (channel == 10) { + channel = 7; + } + } + uint16 note = 48; + if (ins->amDepth) { + note = ins->amDepth; + } + int freq = _freqTable[note % 12]; + OPLWriteReg(_opl, 0xA0 | channel, freq); + freq = ((note / 12) << 2) | ((freq & 0x300) >> 8); + if (ins->mode == 0) { + freq |= 0x20; + } + OPLWriteReg(_opl, 0xB0 | channel, freq); + if (ins->mode != 0) { + _vibrato |= 1 << (10 - channel); + OPLWriteReg(_opl, 0xBD, _vibrato); + } +} + +PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver) + : _playing(false), _songPlayed(false), _driver(driver) { + memset(_instrumentsData, 0, sizeof(_instrumentsData)); + _sfxData = NULL; + _fadeOutCounter = 0; + _driver->setUpdateCallback(updateCallback, this); } -void MusicPlayer::removeSong() { - if (isPlaying()) +PCSoundFxPlayer::~PCSoundFxPlayer() { + _driver->setUpdateCallback(NULL, NULL); + if (_playing) { stop(); + } +} + +bool PCSoundFxPlayer::load(const char *song) { + debug(9, "PCSoundFxPlayer::load('%s')", song); - if (_songPointer) { - free(_songPointer); - _songPointer = NULL; + /* stop (w/ fade out) the previous song */ + while (_fadeOutCounter != 0 && _fadeOutCounter < 100) { + g_system->delayMillis(50); + } + _fadeOutCounter = 0; + + if (_playing) { + stop(); } + strcpy(_musicName, song); _songPlayed = false; + _looping = false; + _sfxData = readBundleSoundFile(song); + if (!_sfxData) { + warning("Unable to load soundfx module '%s'", song); + return 0; + } + + for (int i = 0; i < NUM_INSTRUMENTS; ++i) { + _instrumentsData[i] = NULL; + + char instrument[64]; + memset(instrument, 0, 64); // Clear the data first + memcpy(instrument, _sfxData + 20 + i * 30, 12); + instrument[63] = '\0'; - strcpy(_musicName, ""); + if (strlen(instrument) != 0) { + char *dot = strrchr(instrument, '.'); + if (dot) { + *dot = '\0'; + } + strcat(instrument, _driver->getInstrumentExtension()); + _instrumentsData[i] = readBundleSoundFile(instrument); + if (!_instrumentsData[i]) { + warning("Unable to load soundfx instrument '%s'", instrument); + } + } + } + return 1; } -void MusicPlayer::fadeSong() { - // TODO: Implement fading properly - stop(); +void PCSoundFxPlayer::play() { + debug(9, "PCSoundFxPlayer::play()"); + if (_sfxData) { + for (int i = 0; i < NUM_CHANNELS; ++i) { + _instrumentsChannelTable[i] = -1; + } + _currentPos = 0; + _currentOrder = 0; + _numOrders = _sfxData[470]; + _eventsDelay = (244 - _sfxData[471]) * 100 / 1060; + _updateTicksCounter = 0; + _playing = true; + } } -void MusicPlayer::patchMidi(uint32 adr, const byte *data, int size) { - // TODO: Handle patching midi +void PCSoundFxPlayer::stop() { + if (_playing || _fadeOutCounter != 0) { + _fadeOutCounter = 0; + _playing = false; + for (int i = 0; i < NUM_CHANNELS; ++i) { + _driver->stopChannel(i); + } + _driver->stopAll(); + unload(); + } } -byte *MusicPlayer::loadInstrument(const char *name, int i) { - // Find the resource - int fileIdx = findFileInDisks(name); - if (fileIdx < 0) { - warning("Instrument '%s' not found", name); - return NULL; +void PCSoundFxPlayer::fadeOut() { + if (_playing) { + _fadeOutCounter = 1; + _playing = false; + } +} + +void PCSoundFxPlayer::updateCallback(void *ref) { + ((PCSoundFxPlayer *)ref)->update(); +} + +void PCSoundFxPlayer::update() { + if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) { + ++_updateTicksCounter; + if (_updateTicksCounter > _eventsDelay) { + handleEvents(); + _updateTicksCounter = 0; + } } +} + +void PCSoundFxPlayer::handleEvents() { + const byte *patternData = _sfxData + 600 + 1800; + const byte *orderTable = _sfxData + 472; + uint16 patternNum = orderTable[_currentOrder] * 1024; - int size = volumePtrToFileDescriptor[fileIdx].extSize; + for (int i = 0; i < 4; ++i) { + handlePattern(i, patternData + patternNum + _currentPos); + patternData += 4; + } - // Get the data - byte *tmp = (byte *)malloc(size); - assert(tmp); - loadPackedFileToMem(fileIdx, tmp); + if (_fadeOutCounter != 0 && _fadeOutCounter < 100) { + _fadeOutCounter += 2; + } + if (_fadeOutCounter >= 100) { + stop(); + return; + } - // Create a copy of the resource that's 22 bytes smaller - byte *result = (byte *)malloc(size - 22); - assert(result); - Common::copy(tmp, tmp + size - 22, result); + _currentPos += 16; + if (_currentPos >= 1024) { + _currentPos = 0; + ++_currentOrder; + if (_currentOrder == _numOrders) { + _currentOrder = 0; + } + } + debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos); +} + +void PCSoundFxPlayer::handlePattern(int channel, const byte *patternData) { + int instrument = patternData[2] >> 4; + if (instrument != 0) { + --instrument; + if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) { + _instrumentsChannelTable[channel] = instrument; + const int volume = _sfxData[instrument] - _fadeOutCounter; + _driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume); + } + } + int16 freq = (int16)READ_BE_UINT16(patternData); + if (freq > 0) { + _driver->stopChannel(channel); + _driver->setChannelFrequency(channel, freq); + } +} + +void PCSoundFxPlayer::unload() { + for (int i = 0; i < NUM_INSTRUMENTS; ++i) { + free(_instrumentsData[i]); + _instrumentsData[i] = NULL; + } + free(_sfxData); + _sfxData = NULL; + _songPlayed = true; +} + +void PCSoundFxPlayer::doSync(Common::Serializer &s) { + s.syncBytes((byte *)_musicName, 33); + uint16 v = (uint16)songLoaded(); + s.syncAsSint16LE(v); + + if (s.isLoading() && v) { + load(_musicName); + + for (int i = 0; i < NUM_CHANNELS; ++i) { + _instrumentsChannelTable[i] = -1; + } + } + + s.syncAsSint16LE(_songPlayed); + s.syncAsSint16LE(_looping); + s.syncAsSint16LE(_currentPos); + s.syncAsSint16LE(_currentOrder); + s.syncAsSint16LE(_playing); +} + +PCSound::PCSound(Audio::Mixer *mixer, CruiseEngine *vm) { + _vm = vm; + _mixer = mixer; + _soundDriver = new AdlibSoundDriverADL(_mixer); + _player = new PCSoundFxPlayer(_soundDriver); +} + +PCSound::~PCSound() { + delete _player; + delete _soundDriver; +} + +void PCSound::loadMusic(const char *name) { + debugC(5, kCruiseDebugSound, "PCSound::loadMusic('%s')", name); + _player->load(name); +} + +void PCSound::playMusic() { + debugC(5, kCruiseDebugSound, "PCSound::playMusic()"); + _player->play(); +} + +void PCSound::stopMusic() { + debugC(5, kCruiseDebugSound, "PCSound::stopMusic()"); + _player->stop(); +} + +void PCSound::removeMusic() { + debugC(5, kCruiseDebugSound, "PCSound::removeMusic()"); + _player->unload(); +} + +void PCSound::fadeOutMusic() { + debugC(5, kCruiseDebugSound, "PCSound::fadeOutMusic()"); + _player->fadeOut(); +} + +void PCSound::playSound(const uint8 *data, int size, int volume) { + debugC(5, kCruiseDebugSound, "PCSound::playSound() channel %d size %d", 4, size); + _soundDriver->playSample(data, size, 4, volume); +} + +void PCSound::stopSound(int channel) { + debugC(5, kCruiseDebugSound, "PCSound::stopSound() channel %d", channel); + _soundDriver->resetChannel(channel); +} + +void PCSound::stopChannel(int channel) { + debugC(5, kCruiseDebugSound, "PCSound::stopChannel() channel %d", channel); + _soundDriver->stopChannel(channel); +} + +bool PCSound::isPlaying() const { + return _player->playing(); +} + +bool PCSound::songLoaded() const { + return _player->songLoaded(); +} + +bool PCSound::songPlayed() const { + return _player->songPlayed(); +} + +void PCSound::fadeSong() { + _player->fadeOut(); +} + +uint8 PCSound::numOrders() const { + return _player->numOrders(); +} + +void PCSound::setNumOrders(uint8 v) { + _player->setNumOrders(v); +} + +void PCSound::setPattern(int offset, uint8 value) { + _player->setPattern(offset, value); +} + +bool PCSound::musicLooping() const { + return _player->looping(); +} + +void PCSound::musicLoop(bool v) { + _player->setLooping(v); +} + +void PCSound::startNote(int channel, int volume, int freq) { + warning("TODO: startNote"); +// _soundDriver->setVolume(channel, volume); + _soundDriver->setChannelFrequency(channel, freq); +} + +void PCSound::doSync(Common::Serializer &s) { + _player->doSync(s); + s.syncAsSint16LE(_genVolume); +} + +const char *PCSound::musicName() { + return _player->musicName(); +} - free(tmp); - return result; +void PCSound::syncSounds() { + _soundDriver->syncSounds(); } } // End of namespace Cruise diff --git a/engines/cruise/sound.h b/engines/cruise/sound.h index faf3df995d..13a6b2ac5a 100644 --- a/engines/cruise/sound.h +++ b/engines/cruise/sound.h @@ -29,62 +29,55 @@ #include "sound/mididrv.h" #include "sound/midiparser.h" #include "sound/mixer.h" + +#include "common/config-manager.h" #include "common/serializer.h" namespace Cruise { -class MusicPlayer { -private: - byte _channelVolume[16]; - int _fadeVolume; - char _musicName[33]; - - bool _isPlaying; - bool _songPlayed; - bool _looping; - byte _masterVolume; - - byte *_songPointer; - // TODO: lib_SongSize - int _songSize; +class CruiseEngine; +class PCSoundDriver; +class PCSoundFxPlayer; - void patchMidi(uint32 adr, const byte *data, int size); - byte *loadInstrument(const char *name, int i); +class PCSound { +private: + Audio::Mixer *_mixer; + CruiseEngine *_vm; + int _genVolume; +protected: + PCSoundDriver *_soundDriver; + PCSoundFxPlayer *_player; public: - MusicPlayer(); - ~MusicPlayer(); - - void setVolume(int volume); - int getVolume() const { return _masterVolume; } - - void stop(); - void pause(); - void resume(); - - // Common public access methods + PCSound(Audio::Mixer *mixer, CruiseEngine *vm); + virtual ~PCSound(); + + virtual void loadMusic(const char *name); + virtual void playMusic(); + virtual void stopMusic(); + virtual void removeMusic(); + virtual void fadeOutMusic(); + + virtual void playSound(const uint8 *data, int size, int volume); + virtual void stopSound(int channel); + void doSync(Common::Serializer &s); - void loadSong(const char *name); - void startSong(); - void stopSong(); - void removeSong(); + const char *musicName(); + void stopChannel(int channel); + bool isPlaying() const; + bool songLoaded() const; + bool songPlayed() const; void fadeSong(); - - bool songLoaded() const { return _songPointer != NULL; } - bool songPlayed() const { return _songPlayed; } - bool isPlaying() const { return _isPlaying; } - bool looping() const { return _looping; } - byte *songData() { return _songPointer; } - void setPlaying(bool playing) { _isPlaying = playing; } - void setLoop(bool loop) { _looping = loop; } -}; - -class SoundPlayer { -public: - SoundPlayer() {} - - void startSound(int channelNum, const byte *ptr, int size, int speed, int volume, bool loop) {} - void startNote(int channelNum, int speed, int volume) {} - void stopChannel(int channelNum) {} + uint8 numOrders() const; + void setNumOrders(uint8 v); + void setPattern(int offset, uint8 value); + bool musicLooping() const; + void musicLoop(bool v); + void startNote(int channel, int volume, int freq); + void syncSounds(); + + // Note: Volume variable accessed by these methods is never actually used in original game + void setVolume(int volume) { _genVolume = volume; } + uint8 getVolume() const { return _genVolume; } }; } // End of namespace Cruise diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index 3ea591ed43..94fd00cbfd 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -79,6 +79,8 @@ int16 volumeNumberOfEntry; int16 displayOn = 1; +int16 protectionCode = 0; + int16 globalVars[2000]; dataFileEntry filesDatabase[NUM_FILE_ENTRIES]; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index 7208a8bea0..4bb94ff691 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -183,6 +183,8 @@ extern int16 volumeNumberOfEntry; extern int16 displayOn; +extern int16 protectionCode; + #define NUM_FILE_ENTRIES 257 extern int16 globalVars[2000]; diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp index fda3b6bc1f..2b8cce0f05 100644 --- a/engines/cruise/volume.cpp +++ b/engines/cruise/volume.cpp @@ -107,11 +107,8 @@ int getVolumeDataEntry(volumeDataStruct *entry) { changeCursor(CURSOR_DISK); - currentVolumeFile.read(&volumeNumberOfEntry, 2); - currentVolumeFile.read(&volumeSizeOfEntry, 2); - - bigEndianShortToNative(&volumeNumberOfEntry); - bigEndianShortToNative(&volumeSizeOfEntry); + volumeNumberOfEntry = currentVolumeFile.readSint16BE(); + volumeSizeOfEntry = currentVolumeFile.readSint16BE(); volumeNumEntry = volumeNumberOfEntry; @@ -129,16 +126,10 @@ int getVolumeDataEntry(volumeDataStruct *entry) { for (i = 0; i < volumeNumEntry; i++) { currentVolumeFile.read(&volumePtrToFileDescriptor[i].name, 14); - currentVolumeFile.read(&volumePtrToFileDescriptor[i].offset, 4); - currentVolumeFile.read(&volumePtrToFileDescriptor[i].size, 4); - currentVolumeFile.read(&volumePtrToFileDescriptor[i].extSize, 4); - currentVolumeFile.read(&volumePtrToFileDescriptor[i].unk3, 4); - } - - for (i = 0; i < volumeNumEntry; i++) { - bigEndianLongToNative(&volumePtrToFileDescriptor[i].offset); - bigEndianLongToNative(&volumePtrToFileDescriptor[i].size); - bigEndianLongToNative(&volumePtrToFileDescriptor[i].extSize); + volumePtrToFileDescriptor[i].offset = currentVolumeFile.readSint32BE(); + volumePtrToFileDescriptor[i].size = currentVolumeFile.readSint32BE(); + volumePtrToFileDescriptor[i].extSize = currentVolumeFile.readSint32BE(); + volumePtrToFileDescriptor[i].unk3 = currentVolumeFile.readSint32BE(); } strcpy(currentBaseName, entry->ident); @@ -355,29 +346,23 @@ int16 readVolCnf(void) { return (0); } - fileHandle.read(&numOfDisks, 2); - bigEndianShortToNative(&numOfDisks); - - fileHandle.read(&sizeHEntry, 2); - bigEndianShortToNative(&sizeHEntry); // size of one header entry - 20 bytes + numOfDisks = fileHandle.readSint16BE(); + sizeHEntry = fileHandle.readSint16BE(); // size of one header entry - 20 bytes for (i = 0; i < numOfDisks; i++) { // fread(&volumeData[i],20,1,fileHandle); fileHandle.read(&volumeData[i].ident, 10); fileHandle.read(&volumeData[i].ptr, 4); - fileHandle.read(&volumeData[i].diskNumber, 2); - fileHandle.read(&volumeData[i].size, 4); + volumeData[i].diskNumber = fileHandle.readSint16BE(); + volumeData[i].size = fileHandle.readSint32BE(); - bigEndianShortToNative(&volumeData[i].diskNumber); debug(1, "Disk number: %d", volumeData[i].diskNumber); - bigEndianLongToNative(&volumeData[i].size); } for (i = 0; i < numOfDisks; i++) { dataFileName *ptr; - fileHandle.read(&volumeData[i].size, 4); - bigEndianLongToNative(&volumeData[i].size); + volumeData[i].size = fileHandle.readSint32BE(); ptr = (dataFileName *) mallocAndZero(volumeData[i].size); diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 97c947aef0..a923379c81 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -277,6 +277,7 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // addVolumeControls(this, "ScummConfig."); + setVolumeSettingsState(true); // could disable controls by GUI options // // Subtitle speed and toggle controllers @@ -285,6 +286,7 @@ ConfigDialog::ConfigDialog(bool subtitleControls) if (subtitleControls) { // Global talkspeed range of 0-255 addSubtitleControls(this, "ScummConfig.", 255); + setSubtitleSettingsState(true); // could disable controls by GUI options } // diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 50da7d3552..8df2df2200 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -66,6 +66,8 @@ static const PlainGameDescriptor drasculaGames[] = { namespace Drascula { +using Common::GUIO_NONE; + static const DrasculaGameDescription gameDescriptions[] = { { @@ -76,7 +78,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("14.ald", "09b2735953edcd43af115c65ae00b10e", 1595), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, }, @@ -88,7 +91,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("packet.001", "c6a8697396e213a18472542d5f547cb4", 32847563), Common::EN_ANY, Common::kPlatformPC, - ADGF_KEEPMATCH | GF_PACKED + ADGF_KEEPMATCH | GF_PACKED, + GUIO_NONE }, }, @@ -104,7 +108,8 @@ static const DrasculaGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, @@ -120,7 +125,8 @@ static const DrasculaGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, @@ -132,7 +138,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("packet.001", "3c971aba65a037d29d0b479cad6f5943", 31702652), Common::ES_ESP, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, @@ -144,7 +151,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("14.ald", "0746ed1a5cc8d9728f790c29813f4b43", 23059), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, }, @@ -156,7 +164,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("14.ald", "72e46089033d56bad1c179ac36e2a9d2", 610), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, }, @@ -168,7 +177,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("14.ald", "eeeee96b82169003630e08992248296c", 608), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, }, @@ -180,7 +190,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("packet.001", "0253e924af223f5fe52537023385159b", 32564209), Common::IT_ITA, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, { @@ -191,7 +202,8 @@ static const DrasculaGameDescription gameDescriptions[] = { AD_ENTRY1s("14.ald", "02b49a18328d0bf2efe6ba658c9c7a1d", 2098), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, }, @@ -207,7 +219,8 @@ static const DrasculaGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, @@ -223,7 +236,8 @@ static const DrasculaGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - GF_PACKED + GF_PACKED, + GUIO_NONE }, }, @@ -248,7 +262,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOMIDI }; class DrasculaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/engine.cpp b/engines/engine.cpp index 33eb424b76..1fd77eb310 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -318,9 +318,25 @@ void Engine::syncSoundSettings() { int soundVolumeSFX = ConfMan.getInt("sfx_volume"); int soundVolumeSpeech = ConfMan.getInt("speech_volume"); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech); + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : soundVolumeMusic)); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX)); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech)); +} + +void Engine::flipMute() { + bool mute = false; + + if (ConfMan.hasKey("mute")) { + mute = !ConfMan.getBool("mute"); + } + + ConfMan.setBool("mute", mute); + + syncSoundSettings(); } Common::Error Engine::loadGameState(int slot) { diff --git a/engines/engine.h b/engines/engine.h index d59e8ed9bd..c643d5895f 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -177,6 +177,11 @@ public: virtual void syncSoundSettings(); /** + * Flip mute all sound option. + */ + virtual void flipMute(); + + /** * Load a game state. * @param slot the slot from which a savestate should be loaded * @return returns kNoError on success, else an error code. diff --git a/engines/game.cpp b/engines/game.cpp index c8cfcc663b..0bd1c59791 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -48,13 +48,30 @@ GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) { setVal("description", pgd.description); } -GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p) { +GameDescriptor::GameDescriptor(const PlainGameDescriptorGUIOpts &pgd) { + setVal("gameid", pgd.gameid); + setVal("description", pgd.description); + + if (pgd.guioptions != 0) + setVal("guioptions", Common::getGameGUIOptionsDescription(pgd.guioptions)); +} + +GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p, uint32 guioptions) { setVal("gameid", g); setVal("description", d); if (l != Common::UNK_LANG) setVal("language", Common::getLanguageCode(l)); if (p != Common::kPlatformUnknown) setVal("platform", Common::getPlatformCode(p)); + if (guioptions != 0) + setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); +} + +void GameDescriptor::setGUIOptions(uint32 guioptions) { + if (guioptions != 0) + setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions)); + else + erase("guioptions"); } void GameDescriptor::updateDesc(const char *extra) { diff --git a/engines/game.h b/engines/game.h index 6c73941577..63c988a345 100644 --- a/engines/game.h +++ b/engines/game.h @@ -47,6 +47,17 @@ struct PlainGameDescriptor { }; /** + * Same as PlainGameDsscriptor except it adds Game GUI options parameter + * This is a plain struct to make it possible to declare NULL-terminated C arrays + * consisting of PlainGameDescriptors. + */ +struct PlainGameDescriptorGUIOpts { + const char *gameid; + const char *description; + uint32 guioptions; +}; + +/** * Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor * matching the given gameid. If not match is found return 0. * The end of the list must marked by a PlainGameDescriptor with gameid equal to 0. @@ -64,16 +75,20 @@ class GameDescriptor : public Common::StringMap { public: GameDescriptor(); GameDescriptor(const PlainGameDescriptor &pgd); + GameDescriptor(const PlainGameDescriptorGUIOpts &pgd); GameDescriptor(const Common::String &gameid, const Common::String &description, Common::Language language = Common::UNK_LANG, - Common::Platform platform = Common::kPlatformUnknown); + Common::Platform platform = Common::kPlatformUnknown, + uint32 guioptions = 0); /** * Update the description string by appending (LANG/PLATFORM/EXTRA) to it. */ void updateDesc(const char *extra = 0); + void setGUIOptions(uint32 options); + Common::String &gameid() { return getVal("gameid"); } Common::String &description() { return getVal("description"); } const Common::String &gameid() const { return getVal("gameid"); } diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index a37586aee6..f59fa80e8d 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -239,7 +239,7 @@ int16 DataIO::getChunk(const char *chunkName) { } dataDesc = _dataFiles[file]; - for (int16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { + for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0) continue; @@ -334,7 +334,6 @@ uint32 DataIO::getChunkPos(int16 handle) const { int32 DataIO::getChunkSize(const char *chunkName) { int16 file; - int16 chunk; struct ChunkDesc *dataDesc; int16 slot; int32 realSize; @@ -344,7 +343,7 @@ int32 DataIO::getChunkSize(const char *chunkName) { return -1; dataDesc = _dataFiles[file]; - for (chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { + for (uint16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) { if (scumm_stricmp(chunkName, dataDesc->chunkName) != 0) continue; @@ -488,6 +487,16 @@ int16 DataIO::openData(const char *path) { return file_open(path); } +bool DataIO::existData(const char *path) { + int16 handle = openData(path); + + if (handle < 0) + return false; + + closeData(handle); + return true; +} + DataStream *DataIO::openAsStream(int16 handle, bool dispose) { uint32 curPos = getPos(handle); seekData(handle, 0, SEEK_END); @@ -575,6 +584,9 @@ byte *DataIO::getData(const char *path) { } DataStream *DataIO::getDataStream(const char *path) { + if (!path || (path[0] == '\0') || !existData(path)) + return 0; + uint32 size = getDataSize(path); byte *data = getData(path); diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h index c67dc89df8..1f55cac90d 100644 --- a/engines/gob/dataio.h +++ b/engines/gob/dataio.h @@ -80,6 +80,7 @@ public: byte *getUnpackedData(const char *name); void closeData(int16 handle); int16 openData(const char *path); + bool existData(const char *path); DataStream *openAsStream(int16 handle, bool dispose = false); int32 getDataSize(const char *name); @@ -92,7 +93,7 @@ public: protected: Common::File _filesHandles[MAX_FILES]; struct ChunkDesc *_dataFiles[MAX_DATA_FILES]; - int16 _numDataChunks[MAX_DATA_FILES]; + uint16 _numDataChunks[MAX_DATA_FILES]; int16 _dataFileHandles[MAX_DATA_FILES]; bool _dataFileItk[MAX_DATA_FILES]; int32 _chunkPos[MAX_SLOT_COUNT * MAX_DATA_FILES]; diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp index eb7ca1ccb1..0229bb7515 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -50,11 +50,13 @@ DemoPlayer::Script DemoPlayer::_scripts[] = { "slide tumid.imd 1\nslide post.imd 1\nslide posta.imd 1\n" \ "slide postb.imd 1\nslide postc.imd 1\nslide xdome.imd 20\n" \ "slide xant.imd 20\nslide tum.imd 20\nslide voile.imd 20\n" \ - "slide int.imd 20\nslide voila.imd 1\nslide voilb.imd 1\n"} + "slide int.imd 20\nslide voila.imd 1\nslide voilb.imd 1\n"}, + {kScriptSourceFile, "coktelplayer.scn"}, }; DemoPlayer::DemoPlayer(GobEngine *vm) : _vm(vm) { _doubleMode = false; + _rebase0 = false; } DemoPlayer::~DemoPlayer() { @@ -121,7 +123,9 @@ void DemoPlayer::init() { void DemoPlayer::clearScreen() { debugC(1, kDebugDemo, "Clearing the screen"); - _vm->_video->clearScreen(); + _vm->_video->clearSurf(*_vm->_draw->_backSurface); + _vm->_draw->forceBlit(); + _vm->_video->retrace(); } void DemoPlayer::playVideo(const char *fileName) { @@ -148,10 +152,21 @@ void DemoPlayer::playVideo(const char *fileName) { debugC(1, kDebugDemo, "Playing video \"%s\"", file); - if (_vm->_vidPlayer->primaryOpen(file)) { + int16 x = _rebase0 ? 0 : -1; + int16 y = _rebase0 ? 0 : -1; + if (_vm->_vidPlayer->primaryOpen(file, x, y)) { bool videoSupportsDouble = ((_vm->_vidPlayer->getFeatures() & Graphics::CoktelVideo::kFeaturesSupportsDouble) != 0); + if (_autoDouble) { + int16 defX = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultX(); + int16 defY = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultY(); + int16 right = defX + _vm->_vidPlayer->getWidth() - 1; + int16 bottom = defY + _vm->_vidPlayer->getHeight() - 1; + + _doubleMode = ((right < 320) && (bottom < 200)); + } + if (_doubleMode) { if (videoSupportsDouble) { _vm->_vidPlayer->slotSetDoubleMode(-1, true); @@ -176,13 +191,16 @@ void DemoPlayer::playVideoNormal() { } void DemoPlayer::playVideoDoubled() { - const char *fileNameOpened = _vm->_vidPlayer->getFileName(); + Common::String fileNameOpened = _vm->_vidPlayer->getFileName(); _vm->_vidPlayer->primaryClose(); - if (_vm->_vidPlayer->primaryOpen(fileNameOpened, 0, -1, VideoPlayer::kFlagOtherSurface)) { + int16 x = _rebase0 ? 0 : -1; + int16 y = _rebase0 ? 0 : -1; + if (_vm->_vidPlayer->primaryOpen(fileNameOpened.c_str(), x, y, + VideoPlayer::kFlagScreenSurface)) { + for (int i = 0; i < _vm->_vidPlayer->getFramesCount(); i++) { - if (_vm->_vidPlayer->primaryPlay(i, i)) - break; + _vm->_vidPlayer->playFrame(i); Graphics::CoktelVideo::State state = _vm->_vidPlayer->getState(); @@ -191,11 +209,26 @@ void DemoPlayer::playVideoDoubled() { int16 wD = (state.left * 2) + (w * 2); int16 hD = (state.top * 2) + (h * 2); - _vm->_video->drawSpriteDouble(_vm->_draw->_spritesArray[0], _vm->_draw->_frontSurface, + _vm->_video->drawSpriteDouble(*_vm->_draw->_spritesArray[0], *_vm->_draw->_frontSurface, state.left, state.top, state.right, state.bottom, state.left, state.top, 0); _vm->_draw->dirtiedRect(_vm->_draw->_frontSurface, state.left * 2, state.top * 2, wD, hD); _vm->_video->retrace(); + + _vm->_util->processInput(); + if (_vm->shouldQuit()) + break; + + int16 key; + bool end = false; + while (_vm->_util->checkKey(key)) + if (key == 0x011B) + end = true; + if (end) + break; + + _vm->_vidPlayer->slotWaitEndFrame(); + } } } @@ -203,10 +236,16 @@ void DemoPlayer::playVideoDoubled() { void DemoPlayer::evaluateVideoMode(const char *mode) { debugC(2, kDebugDemo, "Video mode \"%s\"", mode); - if (!scumm_strnicmp(mode, "VESA", 4)) - _doubleMode = false; - else if (!scumm_strnicmp(mode, "VGA", 3) && _vm->is640()) - _doubleMode = true; + _autoDouble = false; + _doubleMode = false; + + // Only applicable when we actually can double + if (_vm->is640()) { + if (!scumm_strnicmp(mode, "AUTO", 4)) + _autoDouble = true; + else if (!scumm_strnicmp(mode, "VGA", 3) && _vm->is640()) + _doubleMode = true; + } } } // End of namespace Gob diff --git a/engines/gob/demos/demoplayer.h b/engines/gob/demos/demoplayer.h index 52c089c8f1..64c98b58c5 100644 --- a/engines/gob/demos/demoplayer.h +++ b/engines/gob/demos/demoplayer.h @@ -45,6 +45,8 @@ public: protected: GobEngine *_vm; bool _doubleMode; + bool _autoDouble; + bool _rebase0; virtual bool playStream(Common::SeekableReadStream &stream) = 0; diff --git a/engines/gob/demos/scnplayer.cpp b/engines/gob/demos/scnplayer.cpp index dc86652bd2..616da3272a 100644 --- a/engines/gob/demos/scnplayer.cpp +++ b/engines/gob/demos/scnplayer.cpp @@ -62,6 +62,10 @@ bool SCNPlayer::playStream(Common::SeekableReadStream &scn) { playVideo(line.c_str() + 4); } else if (lineStartsWith(line, "GOTO ")) { gotoLabel(scn, labels, line.c_str() + 5); + } else if (lineStartsWith(line, "REBASE0:ON")) { + _rebase0 = true; + } else if (lineStartsWith(line, "REBASE0:OFF")) { + _rebase0 = false; } // Mind user input diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 15e0f6ef6b..9426c01ef2 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -61,13 +61,14 @@ static const PlainGameDescriptor gobGames[] = { {"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"}, {"dynasty", "The Last Dynasty"}, {"urban", "Urban Runner"}, - {"archi", "Playtoon 1 - Uncle Archibald"}, - {"spirou", "Playtoon 2 - The Case of the Counterfeit Collaborator"}, - {"chato", "Playtoon 3 - The Secret of the Castle"}, - {"manda", "Playtoon 4 - The Mandarine Prince"}, - {"wakan", "Playtoon 5 - The Stone of Wakan"}, - {"playtnck2", "Playtoon Construction Kit 2 - Les chevaliers"}, - {"bambou", "Playtoon Limited Edition - Bambou le sauveur de la jungle"}, + {"playtoons1", "Playtoons 1 - Uncle Archibald"}, + {"playtoons2", "Playtoons 2 - The Case of the Counterfeit Collaborator"}, + {"playtoons3", "Playtoons 3 - The Secret of the Castle"}, + {"playtoons4", "Playtoons 4 - The Mandarine Prince"}, + {"playtoons5", "Playtoons 5 - The Stone of Wakan"}, + {"playtnck1", "Playtoons Construction Kit 1 - Monsters"}, + {"playtnck2", "Playtoons Construction Kit 2 - Knights"}, + {"bambou", "Playtoons Limited Edition - Bambou le sauveur de la jungle"}, {"fascination", "Fascination"}, {"geisha", "Geisha"}, {"adibou4", "Adibou v4"}, @@ -83,6 +84,10 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { namespace Gob { +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; +using Common::GUIO_NONE; + static const GOBGameDescription gameDescriptions[] = { { // Supplied by Florian Zeitz on scummvm-devel { @@ -91,7 +96,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -104,7 +110,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"), RU_RUS, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -117,7 +124,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -130,7 +138,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -143,7 +152,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -156,7 +166,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -169,7 +180,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -182,7 +194,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -195,7 +208,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -208,7 +222,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -221,7 +236,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -234,7 +250,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -247,7 +264,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -260,7 +278,64 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -273,7 +348,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"), UNK_LANG, kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -286,7 +362,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -299,7 +376,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -312,7 +390,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582), FR_FRA, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -325,7 +404,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), EN_ANY, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -338,7 +418,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), EN_ANY, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -351,7 +432,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), DE_DEU, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -364,7 +446,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), FR_FRA, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -377,7 +460,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), IT_ITA, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -390,13 +474,14 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), ES_ESP, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, 0, 0, 0 }, - { + { // Supplied by Hkz on #scummvm { "gob1", "", @@ -407,7 +492,152 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -424,7 +654,8 @@ static const GOBGameDescription gameDescriptions[] = { }, DE_DEU, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -437,7 +668,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014), EN_ANY, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -450,7 +682,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"), DE_DEU, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -463,7 +696,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"), IT_ITA, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -476,7 +710,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680), FR_FRA, kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -493,7 +728,8 @@ static const GOBGameDescription gameDescriptions[] = { }, UNK_LANG, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -510,7 +746,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -523,7 +760,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -536,7 +774,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -549,7 +788,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -562,7 +802,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -575,7 +816,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -588,7 +830,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -601,7 +844,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -614,7 +858,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"), RU_RUS, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -627,7 +872,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -640,7 +886,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -653,7 +900,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -666,7 +914,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -679,7 +928,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -692,7 +942,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -705,7 +956,78 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -718,7 +1040,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -731,7 +1054,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -744,7 +1068,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"), UNK_LANG, kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -757,7 +1082,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063), UNK_LANG, kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -774,7 +1100,44 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -791,7 +1154,8 @@ static const GOBGameDescription gameDescriptions[] = { }, DE_DEU, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -808,7 +1172,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_GRB, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -821,7 +1186,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719), FR_FRA, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -834,7 +1200,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458), FR_FRA, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -847,7 +1214,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192), DE_DEU, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -864,7 +1232,8 @@ static const GOBGameDescription gameDescriptions[] = { }, IT_ITA, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -881,7 +1250,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_GRB, kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -894,7 +1264,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"), FR_FRA, kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -907,7 +1278,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -920,7 +1292,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -933,7 +1306,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -946,7 +1320,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -959,7 +1334,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -972,7 +1348,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -985,7 +1362,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -998,7 +1376,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"), EN_USA, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1011,7 +1390,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1024,7 +1404,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109), FR_FRA, kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1037,7 +1418,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1050,7 +1432,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1063,7 +1446,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825), EN_ANY, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1076,7 +1460,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1089,7 +1474,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1102,7 +1488,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1115,7 +1502,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1128,7 +1516,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1141,7 +1530,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1154,7 +1544,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1171,7 +1562,8 @@ static const GOBGameDescription gameDescriptions[] = { }, UNK_LANG, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -1184,7 +1576,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628), EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -1197,7 +1590,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1210,7 +1604,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238), HB_ISR, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1223,7 +1618,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "3712e7527ba8ce5637d2aadf62783005", 72318), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1236,7 +1632,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1249,7 +1646,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1266,7 +1664,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1279,7 +1678,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1292,7 +1692,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1305,7 +1706,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1318,7 +1720,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1331,7 +1734,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1344,7 +1748,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1357,7 +1762,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1370,7 +1776,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1383,7 +1790,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1396,7 +1804,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1409,7 +1818,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1422,7 +1832,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1433,9 +1844,38 @@ static const GOBGameDescription gameDescriptions[] = { "lostintime", "", AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - UNK_LANG, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "lostintime", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + FR_FRA, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "lostintime", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1449,6 +1889,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES }, kGameTypeFascination, kFeaturesCD, @@ -1462,6 +1903,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1475,13 +1917,13 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, "intro.stk", 0, 0 }, - //Provided by Sanguine - { + { // Supplied by sanguine { "fascination", "VGA 3 disks edition", @@ -1489,6 +1931,21 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdlib, + "disk0.stk", 0, 0 + }, + { // Supplied by windlepoons in bug report #2809247 + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1502,6 +1959,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1515,6 +1973,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1528,6 +1987,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1541,6 +2001,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1554,6 +2015,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1567,6 +2029,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1580,6 +2043,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1592,7 +2056,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1605,7 +2070,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1618,7 +2084,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1631,7 +2098,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582), HB_ISR, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1644,7 +2112,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1661,7 +2130,44 @@ static const GOBGameDescription gameDescriptions[] = { }, DE_DEU, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1678,7 +2184,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_GRB, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1691,7 +2198,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1704,7 +2212,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1717,7 +2226,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1730,7 +2240,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1743,7 +2254,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"), RU_RUS, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1756,7 +2268,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1769,7 +2282,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1782,7 +2296,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), EN_GRB, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1795,7 +2310,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), DE_DEU, kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1808,7 +2324,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1821,7 +2338,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1834,7 +2352,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1847,7 +2366,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1860,7 +2380,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1873,7 +2394,64 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1886,7 +2464,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"), FR_FRA, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1899,7 +2478,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"), FR_FRA, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1912,7 +2492,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"), UNK_LANG, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1925,7 +2506,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561), EN_ANY, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1942,7 +2524,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1955,7 +2538,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -1968,7 +2552,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -1981,7 +2566,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -1994,7 +2580,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2007,7 +2594,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2020,7 +2608,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2033,7 +2622,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2046,7 +2636,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2059,7 +2650,64 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), EN_USA, kPlatformWindows, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdlib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2085,7 +2733,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib | kFeaturesBATDemo, @@ -2098,7 +2747,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2111,7 +2761,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2124,7 +2775,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2137,7 +2789,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2150,7 +2803,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2163,7 +2817,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2176,7 +2831,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2189,7 +2845,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2202,7 +2859,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2215,7 +2873,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2228,7 +2887,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2241,7 +2901,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2254,7 +2915,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2267,7 +2929,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2280,7 +2943,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2293,7 +2957,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2306,7 +2971,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2319,7 +2985,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2332,7 +2999,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2345,7 +3013,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), EN_GRB, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2358,7 +3027,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2371,7 +3041,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2384,7 +3055,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2397,7 +3069,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2410,7 +3083,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979), PL_POL, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2427,7 +3101,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640 | kFeaturesSCNDemo, @@ -2440,7 +3115,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2453,7 +3129,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2466,7 +3143,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2479,7 +3157,22 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2492,7 +3185,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864), EN_USA, kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, kGameTypeDynasty, kFeatures640, @@ -2505,7 +3199,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774), UNK_LANG, kPlatformWindows, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, kGameTypeDynasty, kFeatures640, @@ -2518,7 +3213,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724), DE_DEU, kPlatformWindows, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, kGameTypeDynasty, kFeatures640, @@ -2531,7 +3227,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436), EN_USA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2544,7 +3241,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2557,7 +3255,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2570,7 +3269,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2588,7 +3288,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeUrban, kFeatures640 | kFeaturesSCNDemo, @@ -2596,7 +3297,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2605,7 +3306,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2613,8 +3315,8 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", - "Pack mes histoires animées", + "playtoons1", + "Pack mes histoires anim\xE9""es", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, @@ -2622,7 +3324,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2630,7 +3333,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2639,7 +3342,8 @@ static const GOBGameDescription gameDescriptions[] = { }, DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2647,7 +3351,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, @@ -2661,7 +3365,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2669,7 +3374,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, @@ -2678,7 +3383,8 @@ static const GOBGameDescription gameDescriptions[] = { }, EN_ANY, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2686,7 +3392,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, @@ -2699,7 +3405,8 @@ static const GOBGameDescription gameDescriptions[] = { }, IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2707,7 +3414,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, @@ -2719,7 +3426,8 @@ static const GOBGameDescription gameDescriptions[] = { }, ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2727,7 +3435,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "spirou", + "playtoons2", "", { {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, @@ -2736,7 +3444,26 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2744,7 +3471,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2753,7 +3480,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2761,8 +3489,26 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", - "Pack mes histoires animées", + "playtoons3", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "Pack mes histoires anim\xE9""es", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, @@ -2770,7 +3516,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2778,7 +3525,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2787,15 +3534,35 @@ static const GOBGameDescription gameDescriptions[] = { }, DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, "intro2.stk", 0, 0 }, + { { - "wakan", + "playtoons4", + "", + { + {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, + {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons5", "", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, @@ -2804,7 +3571,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2821,11 +3589,30 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, kFeatures640, - 0, 0, 0 + "intro.stk", "intro.tot", 0 + }, + { + { + "playtnck1", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytnCk, + kFeatures640, + "intro2.stk", 0, 0 }, { { @@ -2833,11 +3620,13 @@ static const GOBGameDescription gameDescriptions[] = { "", { {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, {0, 0, 0, 0} }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -2850,7 +3639,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibou4, kFeatures640, @@ -2863,7 +3653,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibou4, kFeatures640, @@ -2876,7 +3667,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibou4, kFeatures640, @@ -2889,7 +3681,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibou4, kFeaturesNone, @@ -2901,7 +3694,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "904a93f46687617bb34e672020fc17a4", 248724), FR_FRA, kPlatformAtariST, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2914,7 +3708,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2927,7 +3722,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132), ES_ESP, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2940,7 +3736,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2953,7 +3750,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2966,7 +3764,8 @@ static const GOBGameDescription gameDescriptions[] = { AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), DE_DEU, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2975,11 +3774,12 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBÙ 2 Ambiente", + "ADIB\xD9 2 Ambiente", AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -2988,7 +3788,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBÙ prima elementare : Imparo a leggere e a contare", + "ADIB\xD9 prima elementare : Imparo a leggere e a contare", { {"intro.stk", 0, "092707829555f27706920e4cacf1fada", 8737958}, {"appbou2.itk", 0, "f7bf045f6bdce5a7607c720e36704f33", 200005632}, @@ -2996,7 +3796,8 @@ static const GOBGameDescription gameDescriptions[] = { }, IT_ITA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -3005,7 +3806,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBOU présente La Magie (STK2.1/OBC)", + "ADIBOU pr\xE9sente La Magie (STK2.1/OBC)", { {"adibou.stk", 0, "977d2449d398f3df23238d718fca35b5", 61097}, {"magic.stk", 0, "9776765dead3e338a32c43bf344b5819", 302664}, @@ -3013,7 +3814,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -3030,7 +3832,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -3047,7 +3850,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -3064,7 +3868,8 @@ static const GOBGameDescription gameDescriptions[] = { }, FR_FRA, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, kGameTypeAdibouUnknown, kFeaturesNone, @@ -3081,7 +3886,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -3094,7 +3900,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -3107,7 +3914,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3120,7 +3928,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3133,7 +3942,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -3146,7 +3956,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -3159,7 +3970,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -3172,7 +3984,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -3185,7 +3998,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -3198,7 +4012,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3211,7 +4026,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3224,7 +4040,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -3237,7 +4054,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeaturesCD, @@ -3245,12 +4063,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "archi", + "playtoons1", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3258,12 +4077,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "spirou", + "playtoons2", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3271,12 +4091,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "chato", + "playtoons3", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3284,12 +4105,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "manda", + "playtoons4", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3297,12 +4119,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "wakan", + "playtoons5", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3315,7 +4138,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -3328,7 +4152,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, kFeatures640, @@ -3341,7 +4166,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -3354,7 +4180,8 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -3367,12 +4194,27 @@ static const GOBGameDescription fallbackDescs[] = { AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdibou4, kFeatures640, "adif41.stk", 0, 0 }, + { + { + "coktelplayer", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeUrban, + kFeatures640 | kFeaturesSCNDemo, + "", "", 8 + } }; static const ADFileBasedFallback fileBased[] = { @@ -3400,6 +4242,7 @@ static const ADFileBasedFallback fileBased[] = { { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, { &fallbackDescs[22], { "adif41.stk", "adim41.stk", 0 } }, + { &fallbackDescs[23], { "coktelplayer.scn", 0 } }, { 0, { 0 } } }; @@ -3421,7 +4264,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) Gob::fileBased, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOLAUNCHLOAD }; class GobMetaEngine : public AdvancedMetaEngine { diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 73facb4ac3..b3e5e7418c 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -30,6 +30,7 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/inter.h" #include "gob/video.h" #include "gob/palanim.h" @@ -62,8 +63,7 @@ Draw::Draw(GobEngine *vm) : _vm(vm) { for (int i = 0; i < 8; i++) _fonts[i] = 0; - for (int i = 0; i < SPRITES_COUNT; i++) - _spritesArray[i] = 0; + _spritesArray.resize(SPRITES_COUNT); _invalidatedCount = 0; for (int i = 0; i < 30; i++) { @@ -78,9 +78,6 @@ Draw::Draw(GobEngine *vm) : _vm(vm) { _paletteCleared = false; _applyPal = false; - _backSurface = 0; - _frontSurface = 0; - for (int i = 0; i < 18; i++) _unusedPalette1[i] = 0; for (int i = 0; i < 16; i++) @@ -109,10 +106,6 @@ Draw::Draw(GobEngine *vm) : _vm(vm) { _cursorHotspotXVar = -1; _cursorHotspotYVar = -1; - _cursorSprites = 0; - _cursorSpritesBack = 0; - _scummvmCursor = 0; - _cursorAnim = 0; for (int i = 0; i < 40; i++) { _cursorAnimLow[i] = 0; @@ -265,7 +258,7 @@ void Draw::blitInvalidated() { _vm->_video->_doRangeClamp = false; for (int i = 0; i < _invalidatedCount; i++) { - _vm->_video->drawSprite(_backSurface, _frontSurface, + _vm->_video->drawSprite(*_backSurface, *_frontSurface, _invalidatedLefts[i], _invalidatedTops[i], _invalidatedRights[i], _invalidatedBottoms[i], _invalidatedLefts[i], _invalidatedTops[i], 0); @@ -302,7 +295,7 @@ void Draw::dirtiedRect(int16 surface, dirtiedRect(_spritesArray[surface], left, top, right, bottom); } -void Draw::dirtiedRect(SurfaceDesc::Ptr surface, +void Draw::dirtiedRect(SurfaceDescPtr surface, int16 left, int16 top, int16 right, int16 bottom) { if (surface == _backSurface) @@ -316,7 +309,7 @@ void Draw::initSpriteSurf(int16 index, int16 width, int16 height, _spritesArray[index] = _vm->_video->initSurfDesc(_vm->_global->_videoMode, width, height, flags); - _vm->_video->clearSurf(_spritesArray[index]); + _vm->_video->clearSurf(*_spritesArray[index]); } void Draw::adjustCoords(char adjust, int16 *coord1, int16 *coord2) { @@ -379,7 +372,7 @@ int Draw::stringLength(const char *str, int16 fontIndex) { } void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc *dest, Video::FontDesc *font) { + int16 transp, SurfaceDesc &dest, Video::FontDesc *font) { while (*str != '\0') { _vm->_video->drawLetter(*str, x, y, font, transp, color1, color2, dest); @@ -397,11 +390,10 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, adjustCoords(1, &left, &top); adjustCoords(1, &right, &bottom); - if (READ_LE_UINT16(_vm->_game->_totFileData + 0x7E) != 0) { - byte *storedIP = _vm->_global->_inter_execPtr; + uint16 centerOffset = _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter); + if (centerOffset != 0) { + _vm->_game->_script->call(centerOffset); - _vm->_global->_inter_execPtr = _vm->_game->_totFileData + - READ_LE_UINT16(_vm->_game->_totFileData + 0x7E); WRITE_VAR(17, (uint32) id); WRITE_VAR(18, (uint32) left); WRITE_VAR(19, (uint32) top); @@ -409,7 +401,7 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, WRITE_VAR(21, (uint32) (bottom - top + 1)); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); } if (str[0] == '\0') @@ -447,7 +439,7 @@ int32 Draw::getSpriteRectSize(int16 index) { } void Draw::forceBlit(bool backwards) { - if ((_frontSurface == 0) || (_backSurface == 0)) + if (!_frontSurface || !_backSurface) return; if (_frontSurface == _backSurface) return; @@ -457,12 +449,12 @@ void Draw::forceBlit(bool backwards) { return; if (!backwards) { - _vm->_video->drawSprite(_backSurface, _frontSurface, 0, 0, + _vm->_video->drawSprite(*_backSurface, *_frontSurface, 0, 0, _backSurface->getWidth() - 1, _backSurface->getHeight() - 1, 0, 0, 0); _vm->_video->dirtyRectsAll(); } else - _vm->_video->drawSprite(_frontSurface, _backSurface, 0, 0, + _vm->_video->drawSprite(*_frontSurface, *_backSurface, 0, 0, _frontSurface->getWidth() - 1, _frontSurface->getHeight() - 1, 0, 0, 0); @@ -511,7 +503,7 @@ const int16 Draw::_wobbleTable[360] = { -0x0A03, -0x08E8, -0x07CC, -0x06B0, -0x0593, -0x0476, -0x0359, -0x023B, -0x011D }; -void Draw::wobble(SurfaceDesc *surfDesc) { +void Draw::wobble(SurfaceDesc &surfDesc) { int16 amplitude = 32; uint16 curFrame = 0; uint16 frameWobble = 0; @@ -535,7 +527,7 @@ void Draw::wobble(SurfaceDesc *surfDesc) { amplitude--; for (uint16 y = 0; y < _vm->_height; y++) - _vm->_video->drawSprite(surfDesc, _frontSurface, + _vm->_video->drawSprite(surfDesc, *_frontSurface, 0, y, _vm->_width - 1, y, offsets[y], y, 0); _vm->_palAnim->fadeStep(0); @@ -543,7 +535,7 @@ void Draw::wobble(SurfaceDesc *surfDesc) { _vm->_video->waitRetrace(); } - _vm->_video->drawSprite(surfDesc, _frontSurface, + _vm->_video->drawSprite(surfDesc, *_frontSurface, 0, 0, _vm->_width - 1, _vm->_height - 1, 0, 0, 0); _applyPal = false; diff --git a/engines/gob/draw.h b/engines/gob/draw.h index ccdd91d1e4..26f78ce3b3 100644 --- a/engines/gob/draw.h +++ b/engines/gob/draw.h @@ -78,7 +78,7 @@ public: FontToSprite _fontToSprite[4]; Video::FontDesc *_fonts[8]; - SurfaceDesc::Ptr _spritesArray[SPRITES_COUNT]; + Common::Array<SurfaceDescPtr> _spritesArray; int16 _invalidatedCount; int16 _invalidatedTops[30]; @@ -92,8 +92,8 @@ public: bool _paletteCleared; bool _applyPal; - SurfaceDesc::Ptr _backSurface; - SurfaceDesc::Ptr _frontSurface; + SurfaceDescPtr _backSurface; + SurfaceDescPtr _frontSurface; int16 _unusedPalette1[18]; int16 _unusedPalette2[16]; @@ -117,9 +117,9 @@ public: int16 _cursorHotspotXVar; int16 _cursorHotspotYVar; - SurfaceDesc::Ptr _cursorSprites; - SurfaceDesc::Ptr _cursorSpritesBack; - SurfaceDesc::Ptr _scummvmCursor; + SurfaceDescPtr _cursorSprites; + SurfaceDescPtr _cursorSpritesBack; + SurfaceDescPtr _scummvmCursor; int16 _cursorAnim; int8 _cursorAnimLow[40]; @@ -139,12 +139,12 @@ public: void clearPalette(); void dirtiedRect(int16 surface, int16 left, int16 top, int16 right, int16 bottom); - void dirtiedRect(SurfaceDesc::Ptr surface, int16 left, int16 top, int16 right, int16 bottom); + void dirtiedRect(SurfaceDescPtr surface, int16 left, int16 top, int16 right, int16 bottom); void initSpriteSurf(int16 index, int16 width, int16 height, int16 flags); void freeSprite(int16 index) { assert(index < SPRITES_COUNT); - _spritesArray[index] = 0; + _spritesArray[index].reset(); } void adjustCoords(char adjust, int16 *coord1, int16 *coord2); void adjustCoords(char adjust, uint16 *coord1, uint16 *coord2) { @@ -152,14 +152,14 @@ public: } int stringLength(const char *str, int16 fontIndex); void drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc *dest, Video::FontDesc *font); + int16 transp, SurfaceDesc &dest, Video::FontDesc *font); void printTextCentered(int16 id, int16 left, int16 top, int16 right, int16 bottom, const char *str, int16 fontIndex, int16 color); int32 getSpriteRectSize(int16 index); void forceBlit(bool backwards = false); static const int16 _wobbleTable[360]; - void wobble(SurfaceDesc *surfDesc); + void wobble(SurfaceDesc &surfDesc); virtual void initScreen() = 0; virtual void closeScreen() = 0; diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 1943c327d8..94ee32a031 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -32,6 +32,7 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/resources.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/sound/sound.h" @@ -131,8 +132,8 @@ void Draw_v1::animateCursor(int16 cursor) { newY -= hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar); } - _vm->_video->clearSurf(_scummvmCursor); - _vm->_video->drawSprite(_cursorSprites, _scummvmCursor, + _vm->_video->clearSurf(*_scummvmCursor); + _vm->_video->drawSprite(*_cursorSprites, *_scummvmCursor, cursorIndex * _cursorWidth, 0, (cursorIndex + 1) * _cursorWidth - 1, _cursorHeight - 1, 0, 0, 0); @@ -173,12 +174,12 @@ void Draw_v1::printTotText(int16 id) { _vm->_sound->cdPlayMultMusic(); - if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr) + TextItem *textItem = _vm->_game->_resources->getTextItem(id); + if (!textItem) return; - dataPtr = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[id].offset; - ptr = dataPtr; + dataPtr = textItem->getData(); + ptr = dataPtr; destX = READ_LE_UINT16(ptr) & 0x7FFF; destY = READ_LE_UINT16(ptr + 2); @@ -312,7 +313,9 @@ void Draw_v1::printTotText(int16 id) { } } + delete textItem; _renderFlags = savedFlags; + if (_renderFlags & RENDERFLAG_COLLISIONS) _vm->_game->checkCollisions(0, 0, 0, 0); @@ -323,11 +326,10 @@ void Draw_v1::printTotText(int16 id) { } void Draw_v1::spriteOperation(int16 operation) { - uint16 id; - byte *dataBuf; int16 len; int16 x, y; int16 perLine; + Resource *resource; if (_sourceSurface >= 100) _sourceSurface -= 80; @@ -354,8 +356,8 @@ void Draw_v1::spriteOperation(int16 operation) { switch (operation) { case DRAW_BLITSURF: - _vm->_video->drawSprite(_spritesArray[_sourceSurface], - _spritesArray[_destSurface], + _vm->_video->drawSprite(*_spritesArray[_sourceSurface], + *_spritesArray[_destSurface], _spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, @@ -367,13 +369,13 @@ void Draw_v1::spriteOperation(int16 operation) { case DRAW_PUTPIXEL: _vm->_video->putPixel(_destSpriteX, _destSpriteY, - _frontColor, _spritesArray[_destSurface]); + _frontColor, *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX, _destSpriteY); break; case DRAW_FILLRECT: - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -383,7 +385,7 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_DRAWLINE: - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); @@ -396,30 +398,20 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_LOADSPRITE: - id = _spriteLeft; - if (id >= 30000) { - dataBuf = - _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom); - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, _spritesArray[_destSurface]); - dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); - delete[] dataBuf; - break; - } + resource = _vm->_game->_resources->getResource((uint16) _spriteLeft, + &_spriteRight, &_spriteBottom); - if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom))) + if (!resource) break; - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, _spritesArray[_destSurface]); + _vm->_video->drawPackedSprite(resource->getData(), + _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, + _transparency, *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); + + delete resource; break; case DRAW_PRINTTEXT: @@ -434,26 +426,26 @@ void Draw_v1::spriteOperation(int16 operation) { _fonts[_fontIndex], _transparency, _frontColor, _backColor, - _spritesArray[_destSurface]); + *_spritesArray[_destSurface]); _destSpriteX += _fonts[_fontIndex]->itemWidth; } break; case DRAW_DRAWBAR: - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); @@ -462,7 +454,7 @@ void Draw_v1::spriteOperation(int16 operation) { case DRAW_CLEARRECT: if (_backColor < 16) { - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); @@ -471,7 +463,7 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); @@ -488,7 +480,7 @@ void Draw_v1::spriteOperation(int16 operation) { _fonts[_fontIndex], _transparency, _frontColor, _backColor, - _spritesArray[_destSurface]); + *_spritesArray[_destSurface]); break; } @@ -506,8 +498,8 @@ void Draw_v1::spriteOperation(int16 operation) { _destSpriteX + _fontToSprite[_fontIndex].width, _destSpriteY + _fontToSprite[_fontIndex].height); - _vm->_video->drawSprite(_spritesArray[(int16)_fontToSprite[_fontIndex].sprite], - _spritesArray[_destSurface], x, y, + _vm->_video->drawSprite(*_spritesArray[(int16)_fontToSprite[_fontIndex].sprite], + *_spritesArray[_destSurface], x, y, x + _fontToSprite[_fontIndex].width, y + _fontToSprite[_fontIndex].height, _destSpriteX, _destSpriteY, _transparency); diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 852e0b51fb..2843456f42 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -32,6 +32,8 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/video.h" @@ -48,7 +50,7 @@ void Draw_v2::initScreen() { initSpriteSurf(21, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0); _backSurface = _spritesArray[21]; - _vm->_video->clearSurf(_backSurface); + _vm->_video->clearSurf(*_backSurface); if (!_spritesArray[23]) { initSpriteSurf(23, 32, 16, 2); @@ -162,8 +164,8 @@ void Draw_v2::animateCursor(int16 cursor) { newY -= hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar); } - _vm->_video->clearSurf(_scummvmCursor); - _vm->_video->drawSprite(_cursorSprites, _scummvmCursor, + _vm->_video->clearSurf(*_scummvmCursor); + _vm->_video->drawSprite(*_cursorSprites, *_scummvmCursor, cursorIndex * _cursorWidth, 0, (cursorIndex + 1) * _cursorWidth - 1, _cursorHeight - 1, 0, 0, 0); @@ -205,12 +207,6 @@ void Draw_v2::printTotText(int16 id) { id &= 0xFFF; - if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr || - (id >= _vm->_game->_totTextData->itemsCount) || - (_vm->_game->_totTextData->items[id].offset == -1) || - (_vm->_game->_totTextData->items[id].size == 0)) - return; - _vm->validateLanguage(); // WORKAROUND: In the scripts of some Gobliins 2 versions, the dialog text IDs @@ -234,13 +230,18 @@ void Draw_v2::printTotText(int16 id) { } - size = _vm->_game->_totTextData->items[id].size; - dataPtr = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[id].offset; - ptr = dataPtr; + TextItem *textItem = _vm->_game->_resources->getTextItem(id); + if (!textItem) + return; - if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80)) + size = textItem->getSize(); + dataPtr = textItem->getData(); + ptr = dataPtr; + + if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80)) { + delete textItem; return; + } if (_renderFlags & RENDERFLAG_DOUBLECOORDS) { destX = (READ_LE_UINT16(ptr) & 0x7FFF) * 2; @@ -328,7 +329,7 @@ void Draw_v2::printTotText(int16 id) { ptrEnd = ptr; while (((ptrEnd - dataPtr) < size) && (*ptrEnd != 1)) { // Converting to unknown commands/characters to spaces - if ((_vm->_game->_totFileData[0x29] < 0x32) && (*ptrEnd > 3) && (*ptrEnd < 32)) + if ((_vm->_game->_script->getVersionMinor() < 2) && (*ptrEnd > 3) && (*ptrEnd < 32)) *ptrEnd = 32; switch (*ptrEnd) { @@ -524,7 +525,7 @@ void Draw_v2::printTotText(int16 id) { case 10: str[0] = (char) 255; WRITE_LE_UINT16((uint16 *) (str + 1), - ptr - _vm->_game->_totTextData->dataPtr); + ptr - _vm->_game->_resources->getTexts()); str[3] = 0; ptr++; for (int i = *ptr++; i > 0; i--) { @@ -597,7 +598,9 @@ void Draw_v2::printTotText(int16 id) { } } + delete textItem; _renderFlags = savedFlags; + if (!(_renderFlags & RENDERFLAG_COLLISIONS)) return; @@ -610,14 +613,13 @@ void Draw_v2::printTotText(int16 id) { } void Draw_v2::spriteOperation(int16 operation) { - uint16 id; - byte *dataBuf; int16 len; int16 x, y; - SurfaceDesc *sourceSurf, *destSurf; + SurfaceDescPtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; + Resource *resource; // Always assigned to -1 in Game::loadTotFile() int16 someHandle = -1; @@ -705,14 +707,19 @@ void Draw_v2::spriteOperation(int16 operation) { sourceSurf = _spritesArray[_sourceSurface]; destSurf = _spritesArray[_destSurface]; + if (!destSurf) { + warning("Can't do operation %d on surface %d: nonexistent", operation, _destSurface); + return; + } + switch (operation) { case DRAW_BLITSURF: case DRAW_DRAWLETTER: if (!sourceSurf || !destSurf) break; - _vm->_video->drawSprite(_spritesArray[_sourceSurface], - _spritesArray[_destSurface], + _vm->_video->drawSprite(*_spritesArray[_sourceSurface], + *_spritesArray[_destSurface], _spriteLeft, spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, @@ -724,13 +731,13 @@ void Draw_v2::spriteOperation(int16 operation) { case DRAW_PUTPIXEL: _vm->_video->putPixel(_destSpriteX, _destSpriteY, _frontColor, - _spritesArray[_destSurface]); + *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX, _destSpriteY); break; case DRAW_FILLRECT: - _vm->_video->fillRect(_spritesArray[_destSurface], destSpriteX, + _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -739,7 +746,7 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_DRAWLINE: - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); @@ -747,7 +754,7 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_INVALIDATE: - _vm->_video->drawCircle(_spritesArray[_destSurface], _destSpriteX, + _vm->_video->drawCircle(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _frontColor); dirtiedRect(_destSurface, _destSpriteX - _spriteRight, _destSpriteY - _spriteBottom, @@ -755,41 +762,20 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_LOADSPRITE: - id = _spriteLeft; - - if ((id >= 30000) || (_vm->_game->_lomHandle >= 0)) { - dataBuf = 0; + resource = _vm->_game->_resources->getResource((uint16) _spriteLeft, + &_spriteRight, &_spriteBottom); - if (_vm->_game->_lomHandle >= 0) - warning("Urban Stub: LOADSPRITE %d, LOM", id); - else - dataBuf = _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom); - - if (!dataBuf) - break; - - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, - _transparency, _spritesArray[_destSurface]); - - dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); - - delete[] dataBuf; + if (!resource) break; - } - // Load from .TOT resources - if (!(dataBuf = _vm->_game->loadTotResource(id, 0, &_spriteRight, &_spriteBottom))) - break; - - _vm->_video->drawPackedSprite(dataBuf, - _spriteRight, _spriteBottom, - _destSpriteX, _destSpriteY, - _transparency, _spritesArray[_destSurface]); + _vm->_video->drawPackedSprite(resource->getData(), + _spriteRight, _spriteBottom, _destSpriteX, _destSpriteY, + _transparency, *_spritesArray[_destSurface]); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); + + delete resource; break; case DRAW_PRINTTEXT: @@ -802,16 +788,16 @@ void Draw_v2::spriteOperation(int16 operation) { if (((int8) _textToPrint[0]) == -1) { _vm->validateLanguage(); - dataBuf = _vm->_game->_totTextData->dataPtr + _textToPrint[1] + 1; + byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1; len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, _destSpriteY, _fonts[_fontIndex], _transparency, _frontColor, - _backColor, _spritesArray[_destSurface]); + _backColor, *_spritesArray[_destSurface]); } } else { drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor, - _backColor, _transparency, _spritesArray[_destSurface], + _backColor, _transparency, *_spritesArray[_destSurface], _fonts[_fontIndex]); _destSpriteX += len * _fonts[_fontIndex]->itemWidth; } @@ -820,7 +806,7 @@ void Draw_v2::spriteOperation(int16 operation) { if ((someHandle < 0) || (_textToPrint[i] != ' ')) { _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, _destSpriteY, _fonts[_fontIndex], _transparency, - _frontColor, _backColor, _spritesArray[_destSurface]); + _frontColor, _backColor, *_spritesArray[_destSurface]); _destSpriteX += *(_fonts[_fontIndex]->extraData + (_textToPrint[i] - _fonts[_fontIndex]->startItem)); } @@ -839,8 +825,8 @@ void Draw_v2::spriteOperation(int16 operation) { * _fontToSprite[_fontIndex].height; x = ((_textToPrint[i] - _fontToSprite[_fontIndex].base) % ratio) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(_spritesArray[_fontToSprite[_fontIndex].sprite], - _spritesArray[_destSurface], x, y, + _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], + *_spritesArray[_destSurface], x, y, x + _fontToSprite[_fontIndex].width - 1, y + _fontToSprite[_fontIndex].height - 1, _destSpriteX, _destSpriteY, _transparency); @@ -854,35 +840,35 @@ void Draw_v2::spriteOperation(int16 operation) { case DRAW_DRAWBAR: if (_needAdjust != 2) { - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _spriteBottom - 1, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _destSpriteX + 1, _spriteBottom, _frontColor); - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _spriteRight - 1, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _destSpriteY + 1, _frontColor); } else { - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(_spritesArray[_destSurface], + _vm->_video->drawLine(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); } @@ -892,7 +878,7 @@ void Draw_v2::spriteOperation(int16 operation) { case DRAW_CLEARRECT: if ((_backColor != 16) && (_backColor != 144)) { - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); @@ -902,7 +888,7 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(_spritesArray[_destSurface], + _vm->_video->fillRect(*_spritesArray[_destSurface], _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp index 24c2d8e37b..aff971164f 100644 --- a/engines/gob/driver_vga.cpp +++ b/engines/gob/driver_vga.cpp @@ -38,26 +38,26 @@ static void plotPixel(int x, int y, int color, void *data) { dest->getVidMem()[(y * dest->getWidth()) + x] = color; } -void VGAVideoDriver::putPixel(int16 x, int16 y, byte color, SurfaceDesc *dest) { - if ((x >= 0) && (x < dest->getWidth()) && - (y >= 0) && (y < dest->getHeight())) - dest->getVidMem()[(y * dest->getWidth()) + x] = color; +void VGAVideoDriver::putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest) { + if ((x >= 0) && (x < dest.getWidth()) && + (y >= 0) && (y < dest.getHeight())) + dest.getVidMem()[(y * dest.getWidth()) + x] = color; } -void VGAVideoDriver::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, +void VGAVideoDriver::drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color) { - Graphics::drawLine(x0, y0, x1, y1, color, &plotPixel, dest); + Graphics::drawLine(x0, y0, x1, y1, color, &plotPixel, &dest); } -void VGAVideoDriver::fillRect(SurfaceDesc *dest, int16 left, int16 top, +void VGAVideoDriver::fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color) { - if ((left >= dest->getWidth()) || (right >= dest->getWidth()) || - (top >= dest->getHeight()) || (bottom >= dest->getHeight())) + if ((left >= dest.getWidth()) || (right >= dest.getWidth()) || + (top >= dest.getHeight()) || (bottom >= dest.getHeight())) return; - byte *pos = dest->getVidMem() + (top * dest->getWidth()) + left; + byte *pos = dest.getVidMem() + (top * dest.getWidth()) + left; int16 width = (right - left) + 1; int16 height = (bottom - top) + 1; @@ -65,19 +65,19 @@ void VGAVideoDriver::fillRect(SurfaceDesc *dest, int16 left, int16 top, for (int16 i = 0; i < width; ++i) pos[i] = color; - pos += dest->getWidth(); + pos += dest.getWidth(); } } void VGAVideoDriver::drawLetter(unsigned char item, int16 x, int16 y, Video::FontDesc *fontDesc, byte color1, byte color2, - byte transp, SurfaceDesc *dest) { + byte transp, SurfaceDesc &dest) { byte *src, *dst; uint16 data; src = fontDesc->dataPtr + (item - fontDesc->startItem) * (fontDesc->itemSize & 0xFF); - dst = dest->getVidMem() + x + dest->getWidth() * y; + dst = dest.getVidMem() + x + dest.getWidth() * y; int nWidth = fontDesc->itemWidth; @@ -106,26 +106,26 @@ void VGAVideoDriver::drawLetter(unsigned char item, int16 x, int16 y, } - dst += dest->getWidth() - fontDesc->itemWidth; + dst += dest.getWidth() - fontDesc->itemWidth; } } -void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, +void VGAVideoDriver::drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { - if ((x >= dest->getWidth()) || (x < 0) || - (y >= dest->getHeight()) || (y < 0)) + if ((x >= dest.getWidth()) || (x < 0) || + (y >= dest.getHeight()) || (y < 0)) return; - int16 width = MIN((right - left) + 1, (int) dest->getWidth()); - int16 height = MIN((bottom - top) + 1, (int) dest->getHeight()); + int16 width = MIN((right - left) + 1, (int) dest.getWidth()); + int16 height = MIN((bottom - top) + 1, (int) dest.getHeight()); if ((width < 1) || (height < 1)) return; - const byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left; - byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x; + const byte *srcPos = source.getVidMem() + (top * source.getWidth()) + left; + byte *destPos = dest.getVidMem() + (y * dest.getWidth()) + x; uint32 size = width * height; @@ -137,8 +137,8 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, destPos[i] = srcPos[i]; } - srcPos += source->getWidth(); - destPos += dest->getWidth(); + srcPos += source.getWidth(); + destPos += dest.getWidth(); } } else if (((srcPos >= destPos) && (srcPos <= (destPos + size))) || @@ -147,8 +147,8 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, while (height--) { memmove(destPos, srcPos, width); - srcPos += source->getWidth(); - destPos += dest->getWidth(); + srcPos += source.getWidth(); + destPos += dest.getWidth(); } } else { @@ -156,29 +156,29 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, while (height--) { memcpy(destPos, srcPos, width); - srcPos += source->getWidth(); - destPos += dest->getWidth(); + srcPos += source.getWidth(); + destPos += dest.getWidth(); } } } -void VGAVideoDriver::drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, +void VGAVideoDriver::drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { - if ((x >= dest->getWidth()) || (x < 0) || - (y >= dest->getHeight()) || (y < 0)) + if ((x >= dest.getWidth()) || (x < 0) || + (y >= dest.getHeight()) || (y < 0)) return; - int16 width = MIN<int>((right - left) + 1, dest->getWidth() / 2); - int16 height = MIN<int>((bottom - top) + 1, dest->getHeight() / 2); + int16 width = MIN<int>((right - left) + 1, dest.getWidth() / 2); + int16 height = MIN<int>((bottom - top) + 1, dest.getHeight() / 2); if ((width < 1) || (height < 1)) return; - const byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left; - byte *destPos = dest->getVidMem() + ((y * 2) * dest->getWidth()) + (x * 2); + const byte *srcPos = source.getVidMem() + (top * source.getWidth()) + left; + byte *destPos = dest.getVidMem() + ((y * 2) * dest.getWidth()) + (x * 2); while (height--) { const byte *srcBak = srcPos; @@ -193,19 +193,19 @@ void VGAVideoDriver::drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, } } - destPos += dest->getWidth(); + destPos += dest.getWidth(); } - srcPos = srcBak + source->getWidth(); + srcPos = srcBak + source.getWidth(); } } void VGAVideoDriver::drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, byte transp, SurfaceDesc *dest) { + int16 x, int16 y, byte transp, SurfaceDesc &dest) { int destRight = x + width; int destBottom = y + height; - byte *dst = dest->getVidMem() + x + dest->getWidth() * y; + byte *dst = dest.getVidMem() + x + dest.getWidth() * y; int curx = x; int cury = y; @@ -223,14 +223,14 @@ void VGAVideoDriver::drawPackedSprite(byte *sprBuf, int16 width, int16 height, val >>= 4; for (unsigned int i = 0; i < repeat; ++i) { - if (curx < dest->getWidth() && cury < dest->getHeight()) + if (curx < dest.getWidth() && cury < dest.getHeight()) if (!transp || val) *dst = val; dst++; curx++; if (curx == destRight) { - dst += dest->getWidth() + x - curx; + dst += dest.getWidth() + x - curx; curx = x; cury++; if (cury == destBottom) diff --git a/engines/gob/driver_vga.h b/engines/gob/driver_vga.h index c67fd1cb2f..c50ea5c475 100644 --- a/engines/gob/driver_vga.h +++ b/engines/gob/driver_vga.h @@ -35,20 +35,20 @@ public: VGAVideoDriver() {} virtual ~VGAVideoDriver() {} - void putPixel(int16 x, int16 y, byte color, SurfaceDesc *dest); - void drawLine(SurfaceDesc *dest, int16 x0, int16 y0, + void putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest); + void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color); - void fillRect(SurfaceDesc *dest, int16 left, int16 top, + void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color); void drawLetter(unsigned char item, int16 x, int16 y, Video::FontDesc *fontDesc, byte color1, byte color2, - byte transp, SurfaceDesc *dest); - void drawSprite(SurfaceDesc *source, SurfaceDesc *dest, int16 left, + byte transp, SurfaceDesc &dest); + void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, int16 left, + void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); void drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, byte transp, SurfaceDesc *dest); + int16 x, int16 y, byte transp, SurfaceDesc &dest); }; } diff --git a/engines/gob/expression.cpp b/engines/gob/expression.cpp new file mode 100644 index 0000000000..61376b2212 --- /dev/null +++ b/engines/gob/expression.cpp @@ -0,0 +1,1144 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/expression.h" +#include "gob/global.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/inter.h" + +namespace Gob { + +Expression::Stack::Stack(size_t size) { + opers = new byte[size]; + values = new int32[size]; + memset(opers , 0, size * sizeof(byte )); + memset(values, 0, size * sizeof(int32)); +} + +Expression::Stack::~Stack() { + delete[] opers; + delete[] values; +} + +Expression::StackFrame::StackFrame(const Stack &stack) { + opers = stack.opers - 1; + values = stack.values - 1; + pos = -1; +} + +void Expression::StackFrame::push(int count) { + opers += count; + values += count; + pos += count; +} + +void Expression::StackFrame::pop(int count) { + opers -= count; + values -= count; + pos -= count; +} + +Expression::Expression(GobEngine *vm) : _vm(vm) { + _resultStr[0] = 0; + _resultInt = 0; +} + +int32 Expression::encodePtr(byte *ptr, int type) { + int32 offset = 0; + + switch (type) { + case kExecPtr: + offset = _vm->_game->_script->getOffset(ptr); + break; + case kInterVar: + offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0)); + break; + case kResStr: + offset = ptr - ((byte *) _resultStr); + break; + default: + error("Expression::encodePtr(): Unknown pointer type"); + } + assert((offset & 0xF0000000) == 0); + return (type << 28) | offset; +} + +byte *Expression::decodePtr(int32 n) { + byte *ptr; + + switch (n >> 28) { + case kExecPtr: + return _vm->_game->_script->getData((n & 0x0FFFFFFF)); + case kInterVar: + ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0); + break; + case kResStr: + ptr = (byte *) _resultStr; + break; + default: + error("Expression::decodePtr(): Unknown pointer type"); + } + return ptr + (n & 0x0FFFFFFF); +} + +void Expression::skipExpr(char stopToken) { + int16 dimCount; + byte operation; + int16 num; + int16 dim; + + num = 0; + while (true) { + operation = _vm->_game->_script->readByte(); + + if ((operation >= 14) && (operation <= OP_FUNC)) { + switch (operation) { + case 14: + _vm->_game->_script->skip(4); + if (_vm->_game->_script->peekByte() == 97) + _vm->_game->_script->skip(1); + break; + + case OP_LOAD_VAR_INT16: + case OP_LOAD_VAR_INT8: + case OP_LOAD_IMM_INT16: + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + _vm->_game->_script->skip(2); + break; + + case OP_LOAD_IMM_INT32: + _vm->_game->_script->skip(4); + break; + + case OP_LOAD_IMM_INT8: + _vm->_game->_script->skip(1); + break; + + case OP_LOAD_IMM_STR: + _vm->_game->_script->skip(strlen(_vm->_game->_script->peekString()) + 1); + break; + + case OP_LOAD_VAR_STR: + _vm->_game->_script->skip(2); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + skipExpr(OP_END_MARKER); + } + break; + + case 15: + _vm->_game->_script->skip(2); + + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + dimCount = _vm->_game->_script->peekByte(2); + // skip header and dimensions + _vm->_game->_script->skip(3 + dimCount); + // skip indices + for (dim = 0; dim < dimCount; dim++) + skipExpr(OP_END_MARKER); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + skipExpr(OP_END_MARKER); + } + break; + + case OP_FUNC: + _vm->_game->_script->skip(1); + skipExpr(OP_END_EXPR); + } + continue; + } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) + + if (operation == OP_BEGIN_EXPR) { + num++; + continue; + } + + if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) + continue; + + if ((operation >= OP_OR) && (operation <= OP_NEQ)) + continue; + + if (operation == OP_END_EXPR) + num--; + + if (operation != stopToken) + continue; + + if ((stopToken != OP_END_EXPR) || (num < 0)) + return; + } +} + +void Expression::printExpr(char stopToken) { + // Expression printing disabled by default + return; + + int32 savedPos = _vm->_game->_script->pos(); + printExpr_internal(stopToken); + + // restore IP to start of expression + _vm->_game->_script->seek(savedPos); +} + +void Expression::printExpr_internal(char stopToken) { + int16 dimCount; + byte operation; + int16 num; + int16 dim; + byte *arrDesc; + byte func; + + num = 0; + while (true) { + operation = _vm->_game->_script->readByte(); + + if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) { + // operands + + switch (operation) { + case OP_LOAD_VAR_INT16: // int16 variable load + debugN(5, "var16_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_VAR_INT8: // int8 variable load: + debugN(5, "var8_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_IMM_INT32: // int32/uint32 immediate + debugN(5, "%d", _vm->_game->_script->readInt32()); + break; + + case OP_LOAD_IMM_INT16: // int16 immediate + debugN(5, "%d", _vm->_game->_script->readInt16()); + break; + + case OP_LOAD_IMM_INT8: // int8 immediate + debugN(5, "%d", _vm->_game->_script->readInt8()); + break; + + case OP_LOAD_IMM_STR: // string immediate + debugN(5, "\42%s\42", _vm->_game->_script->readString()); + break; + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + debugN(5, "var_%d", _vm->_game->_script->readUint16()); + break; + + case OP_LOAD_VAR_STR: // string variable load + debugN(5, "(&var_%d)", _vm->_game->_script->readUint16()); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + debugN(5, "{"); + printExpr_internal(OP_END_MARKER); // this also prints the closing } + } + break; + + case OP_ARRAY_INT8: // int8 array access + case OP_ARRAY_INT32: // int32 array access + case OP_ARRAY_INT16: // int16 array access + case OP_ARRAY_STR: // string array access + debugN(5, "\n"); + if (operation == OP_ARRAY_STR) + debugN(5, "(&"); + + debugN(5, "var_%d[", _vm->_game->_script->readInt16()); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + for (dim = 0; dim < dimCount; dim++) { + printExpr_internal(OP_END_MARKER); + debugN(5, " of %d", (int16) arrDesc[dim]); + if (dim != dimCount - 1) + debugN(5, ","); + } + debugN(5, "]"); + if (operation == OP_ARRAY_STR) + debugN(5, ")"); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "{"); + printExpr_internal(OP_END_MARKER); // this also prints the closing } + } + break; + + case OP_FUNC: // function + func = _vm->_game->_script->readByte(); + if (func == FUNC_SQR) + debugN(5, "sqr("); + else if (func == FUNC_RAND) + debugN(5, "rand("); + else if (func == FUNC_ABS) + debugN(5, "abs("); + else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3)) + debugN(5, "sqrt("); + else + debugN(5, "id("); + printExpr_internal(OP_END_EXPR); + break; + } + continue; + } // if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) + + // operators + switch (operation) { + case OP_BEGIN_EXPR: + debugN(5, "("); + break; + + case OP_NOT: + debugN(5, "!"); + break; + + case OP_END_EXPR: + debugN(5, ")"); + break; + + case OP_NEG: + debugN(5, "-"); + break; + + case OP_ADD: + debugN(5, "+"); + break; + + case OP_SUB: + debugN(5, "-"); + break; + + case OP_BITOR: + debugN(5, "|"); + break; + + case OP_MUL: + debugN(5, "*"); + break; + + case OP_DIV: + debugN(5, "/"); + break; + + case OP_MOD: + debugN(5, "%%"); + break; + + case OP_BITAND: + debugN(5, "&"); + break; + + case OP_OR: + debugN(5, "||"); + break; + + case 31: + debugN(5, "&&"); + break; + + case OP_LESS: + debugN(5, "<"); + break; + + case OP_LEQ: + debugN(5, "<="); + break; + + case OP_GREATER: + debugN(5, ">"); + break; + + case OP_GEQ: + debugN(5, ">="); + break; + + case OP_EQ: + debugN(5, "=="); + break; + + case OP_NEQ: + debugN(5, "!="); + break; + + case 99: + debugN(5, "\n"); + break; + + case OP_END_MARKER: + debugN(5, "}"); + if (stopToken != OP_END_MARKER) { + debugN(5, "Closing paren without opening?"); + } + break; + + default: + debugN(5, "<%d>", (int16) operation); + error("Expression::printExpr(): invalid operator in expression"); + break; + } + + if (operation == OP_BEGIN_EXPR) { + num++; + continue; + } + + if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) + continue; + + if ((operation >= OP_OR) && (operation <= OP_NEQ)) + continue; + + if (operation == OP_END_EXPR) + num--; + + if (operation == stopToken) { + if ((stopToken != OP_END_EXPR) || (num < 0)) { + return; + } + } + } +} + + +void Expression::printVarIndex() { + byte *arrDesc; + int16 dim; + int16 dimCount; + int16 operation; + int16 temp; + + int32 pos = _vm->_game->_script->pos(); + + operation = _vm->_game->_script->readByte(); + switch (operation) { + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_STR: + temp = _vm->_game->_script->readUint16() * 4; + debugN(5, "&var_%d", temp); + if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "+"); + printExpr(OP_END_MARKER); + } + break; + + case OP_ARRAY_INT32: + case OP_ARRAY_STR: + debugN(5, "&var_%d[", _vm->_game->_script->readUint16()); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + for (dim = 0; dim < dimCount; dim++) { + printExpr(OP_END_MARKER); + debugN(5, " of %d", (int16) arrDesc[dim]); + if (dim != dimCount - 1) + debugN(5, ","); + } + debugN(5, "]"); + + if ((operation == OP_ARRAY_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + debugN(5, "+"); + printExpr(OP_END_MARKER); + } + break; + + default: + debugN(5, "var_0"); + break; + } + debugN(5, "\n"); + + _vm->_game->_script->seek(pos); + return; +} + +int Expression::cmpHelper(const StackFrame &stackFrame) { + byte type = stackFrame.opers[-3]; + int cmpTemp = 0; + + if (type == OP_LOAD_IMM_INT16) { + cmpTemp = (int)stackFrame.values[-3] - (int)stackFrame.values[-1]; + } else if (type == OP_LOAD_IMM_STR) { + if ((char *)decodePtr(stackFrame.values[-3]) != _resultStr) { + strcpy(_resultStr, (char *)decodePtr(stackFrame.values[-3])); + stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr); + } + cmpTemp = strcmp(_resultStr, (char *)decodePtr(stackFrame.values[-1])); + } + + return cmpTemp; +} + +bool Expression::getVarBase(uint32 &varBase, bool mindStop, + uint16 *size, uint16 *type) { + + varBase = 0; + + byte operation = _vm->_game->_script->peekByte(); + while ((operation == 14) || (operation == 15)) { + _vm->_game->_script->skip(1); + + if (operation == 14) { + // Add a direct offset + + varBase += _vm->_game->_script->readInt16() * 4; + + if (size) + *size = _vm->_game->_script->peekUint16(); + if (type) + *type = 14; + + _vm->_game->_script->skip(2); + + debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation); + + if (_vm->_game->_script->peekByte() != 97) { + if (mindStop) + return true; + } else + _vm->_game->_script->skip(1); + + } else if (operation == 15) { + // Add an offset from an array + + varBase += _vm->_game->_script->readInt16() * 4; + + uint16 offset1 = _vm->_game->_script->readUint16(); + + if (size) + *size = offset1; + if (type) + *type = 15; + + uint8 dimCount = _vm->_game->_script->readByte(); + byte *dimArray = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + + _vm->_game->_script->skip(dimCount); + + uint16 offset2 = 0; + for (int i = 0; i < dimCount; i++) { + int16 dim = CLIP<int>(parseValExpr(OP_END_MARKER), 0, dimArray[i] - 1); + + offset2 = offset2 * dimArray[i] + dim; + } + + varBase += offset2 * offset1 * 4; + + debugC(2, kDebugExpression, "varBase: %d, by %d", varBase, operation); + + if (_vm->_game->_script->peekByte() != 97) { + if (mindStop) + return true; + } else + _vm->_game->_script->skip(1); + } + + operation = _vm->_game->_script->peekByte(); + } + + return false; +} + +int16 Expression::parseVarIndex(uint16 *size, uint16 *type) { + int16 temp2; + byte *arrDesc; + int16 dim; + int16 dimCount; + int16 operation; + int16 temp; + int16 offset; + int16 val; + uint32 varBase; + + if (getVarBase(varBase, true, size, type)) + return varBase; + + operation = _vm->_game->_script->readByte(); + + if (size) + *size = 0; + if (type) + *type = operation; + + debugC(5, kDebugExpression, "var parse = %d", operation); + switch (operation) { + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + temp = _vm->_game->_script->readInt16(); + dimCount = _vm->_game->_script->readByte(); + arrDesc = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + offset = 0; + for (dim = 0; dim < dimCount; dim++) { + temp2 = parseValExpr(OP_END_MARKER); + offset = arrDesc[dim] * offset + temp2; + } + if (operation == OP_ARRAY_INT8) + return varBase + temp + offset; + if (operation == OP_ARRAY_INT32) + return varBase + (temp + offset) * 4; + if (operation == OP_ARRAY_INT16) + return varBase + (temp + offset) * 2; + temp *= 4; + offset *= 4; + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp += parseValExpr(OP_END_MARKER); + } + return varBase + offset * _vm->_global->_inter_animDataSize + temp; + + case OP_LOAD_VAR_INT16: + return varBase + _vm->_game->_script->readInt16() * 2; + + case OP_LOAD_VAR_INT8: + return varBase + _vm->_game->_script->readInt16(); + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + case OP_LOAD_VAR_STR: + temp = _vm->_game->_script->readInt16() * 4; + debugC(5, kDebugExpression, "oper = %d", _vm->_game->_script->peekInt16()); + if ((operation == OP_LOAD_VAR_STR) && (_vm->_game->_script->peekByte() == 13)) { + _vm->_game->_script->skip(1); + val = parseValExpr(OP_END_MARKER); + temp += val; + debugC(5, kDebugExpression, "parse subscript = %d", val); + } + return varBase + temp; + + default: + return 0; + } +} + +int16 Expression::parseValExpr(byte stopToken) { + parseExpr(stopToken, 0); + + return _resultInt; +} + +// Load a value according to the operation +void Expression::loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame) { + int16 dimCount; + int16 temp; + int16 temp2; + int16 offset; + int16 dim; + byte *arrDescPtr; + int32 prevPrevVal; + int32 prevVal; + int32 curVal; + + switch (operation) { + case OP_ARRAY_INT8: + case OP_ARRAY_INT32: + case OP_ARRAY_INT16: + case OP_ARRAY_STR: + *stackFrame.opers = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16; + temp = _vm->_game->_script->readInt16(); + dimCount = _vm->_game->_script->readByte(); + arrDescPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(dimCount); + offset = 0; + for (dim = 0; dim < dimCount; dim++) { + temp2 = parseValExpr(OP_END_MARKER); + offset = offset * arrDescPtr[dim] + temp2; + } + if (operation == OP_ARRAY_INT8) + *stackFrame.values = (int8) READ_VARO_UINT8(varBase + temp + offset); + else if (operation == OP_ARRAY_INT32) + *stackFrame.values = READ_VARO_UINT32(varBase + temp * 4 + offset * 4); + else if (operation == OP_ARRAY_INT16) + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + temp * 2 + offset * 2); + else if (operation == OP_ARRAY_STR) { + *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8( + varBase + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), + kInterVar); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp2 = parseValExpr(OP_END_MARKER); + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT8(varBase + temp * 4 + + offset * 4 * _vm->_global->_inter_animDataSize + temp2); + } + } + break; + + case OP_LOAD_VAR_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 2); + break; + + case OP_LOAD_VAR_INT8: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int8) READ_VARO_UINT8(varBase + _vm->_game->_script->readInt16()); + break; + + case OP_LOAD_IMM_INT32: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt32(); + break; + + case OP_LOAD_IMM_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt16(); + break; + + case OP_LOAD_IMM_INT8: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _vm->_game->_script->readInt8(); + break; + + case OP_LOAD_IMM_STR: + *stackFrame.opers = OP_LOAD_IMM_STR; + *stackFrame.values = encodePtr((byte *) _vm->_game->_script->readString(), kExecPtr); + break; + + case OP_LOAD_VAR_INT32: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT32(varBase + _vm->_game->_script->readInt16() * 4); + break; + + case OP_LOAD_VAR_INT32_AS_INT16: + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = (int16) READ_VARO_UINT16(varBase + _vm->_game->_script->readInt16() * 4); + break; + + case OP_LOAD_VAR_STR: + *stackFrame.opers = OP_LOAD_IMM_STR; + temp = _vm->_game->_script->readInt16() * 4; + *stackFrame.values = encodePtr(_vm->_inter->_variables->getAddressOff8(varBase + temp), kInterVar); + if (_vm->_game->_script->peekByte() == 13) { + _vm->_game->_script->skip(1); + temp += parseValExpr(OP_END_MARKER); + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = READ_VARO_UINT8(varBase + temp); + } + break; + + case OP_FUNC: + operation = _vm->_game->_script->readByte(); + parseExpr(OP_END_EXPR, 0); + + switch (operation) { + case FUNC_SQRT1: + case FUNC_SQRT2: + case FUNC_SQRT3: + curVal = 1; + prevVal = 1; + + do { + prevPrevVal = prevVal; + prevVal = curVal; + curVal = (curVal + _resultInt / curVal) / 2; + } while ((curVal != prevVal) && (curVal != prevPrevVal)); + _resultInt = curVal; + break; + + case FUNC_SQR: + _resultInt = + _resultInt * _resultInt; + break; + + case FUNC_ABS: + if (_resultInt < 0) + _resultInt = -_resultInt; + break; + + case FUNC_RAND: + _resultInt = + _vm->_util->getRandom(_resultInt); + break; + } + + *stackFrame.opers = OP_LOAD_IMM_INT16; + *stackFrame.values = _resultInt; + break; + } +} + +void Expression::simpleArithmetic1(StackFrame &stackFrame) { + switch (stackFrame.opers[-1]) { + case OP_ADD: + if (stackFrame.opers[-2] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stackFrame.values[-2]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-2])); + stackFrame.values[-2] = encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[0])); + stackFrame.pop(2); + } + break; + + case OP_MUL: + stackFrame.values[-2] *= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-2] /= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-2] %= stackFrame.values[0]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-2] &= stackFrame.values[0]; + stackFrame.pop(2); + break; + } +} + +void Expression::simpleArithmetic2(StackFrame &stackFrame) { + if (stackFrame.pos > 1) { + if (stackFrame.opers[-2] == OP_NEG) { + stackFrame.opers[-2] = OP_LOAD_IMM_INT16; + stackFrame.values[-2] = -stackFrame.values[-1]; + stackFrame.pop(); + } else if (stackFrame.opers[-2] == OP_NOT) { + stackFrame.opers[-2] = (stackFrame.opers[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(); + } + } + + if (stackFrame.pos > 2) { + switch (stackFrame.opers[-2]) { + case OP_MUL: + stackFrame.values[-3] *= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-3] /= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-3] %= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-3] &= stackFrame.values[-1]; + stackFrame.pop(2); + break; + } + } + +} + +// Complex arithmetics with brackets +bool Expression::complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart) { + switch (stackFrame.opers[-2]) { + case OP_ADD: + if (stack.opers[brackStart] == OP_LOAD_IMM_INT16) { + stack.values[brackStart] += stackFrame.values[-1]; + } else if (stack.opers[brackStart] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stack.values[brackStart]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stack.values[brackStart])); + stack.values[brackStart] = + encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1])); + } + stackFrame.pop(2); + break; + + case OP_SUB: + stack.values[brackStart] -= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITOR: + stack.values[brackStart] |= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MUL: + stackFrame.values[-3] *= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_DIV: + stackFrame.values[-3] /= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_MOD: + stackFrame.values[-3] %= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_BITAND: + stackFrame.values[-3] &= stackFrame.values[-1]; + stackFrame.pop(2); + break; + + case OP_OR: + // (x OR false) == x + // (x OR true) == true + if (stackFrame.opers[-3] == GOB_FALSE) + stackFrame.opers[-3] = stackFrame.opers[-1]; + stackFrame.pop(2); + break; + + case OP_AND: + // (x AND false) == false + // (x AND true) == x + if (stackFrame.opers[-3] == GOB_TRUE) + stackFrame.opers[-3] = stackFrame.opers[-1]; + stackFrame.pop(2); + break; + + case OP_LESS: + stackFrame.opers[-3] = (cmpHelper(stackFrame) < 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_LEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) <= 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_GREATER: + stackFrame.opers[-3] = (cmpHelper(stackFrame) > 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_GEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) >= 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_EQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) == 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + case OP_NEQ: + stackFrame.opers[-3] = (cmpHelper(stackFrame) != 0) ? GOB_TRUE : GOB_FALSE; + stackFrame.pop(2); + break; + + default: + return true; + } + + return false; +} + +// Assign the result to the appropriate _result variable +void Expression::getResult(byte operation, int32 value, byte *type) { + if (type != 0) + *type = operation; + + switch (operation) { + case OP_NOT: + if (type != 0) + *type ^= 1; + break; + + case OP_LOAD_IMM_INT16: + _resultInt = value; + break; + + case OP_LOAD_IMM_STR: + if ((char *) decodePtr(value) != _resultStr) + strcpy(_resultStr, (char *) decodePtr(value)); + break; + + case OP_LOAD_VAR_INT32: + case OP_LOAD_VAR_INT32_AS_INT16: + break; + + default: + _resultInt = 0; + if (type != 0) + *type = OP_LOAD_IMM_INT16; + break; + } +} + +int16 Expression::parseExpr(byte stopToken, byte *type) { + Stack stack; + StackFrame stackFrame(stack); + byte operation; + bool escape; + int16 brackStart; + uint32 varBase; + + while (true) { + getVarBase(varBase); + + stackFrame.push(); + + operation = _vm->_game->_script->readByte(); + if ((operation >= OP_ARRAY_INT8) && (operation <= OP_FUNC)) { + + loadValue(operation, varBase, stackFrame); + + if ((stackFrame.pos > 0) && ((stackFrame.opers[-1] == OP_NEG) || (stackFrame.opers[-1] == OP_NOT))) { + stackFrame.pop(); + + if (*stackFrame.opers == OP_NEG) { + *stackFrame.opers = OP_LOAD_IMM_INT16; + stackFrame.values[0] = -stackFrame.values[1]; + } else + *stackFrame.opers = (stackFrame.opers[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; + } + + if (stackFrame.pos <= 0) + continue; + + simpleArithmetic1(stackFrame); + + continue; + } // (op >= OP_ARRAY_INT8) && (op <= OP_FUNC) + + if ((operation == stopToken) || (operation == OP_OR) || + (operation == OP_AND) || (operation == OP_END_EXPR)) { + while (stackFrame.pos >= 2) { + escape = false; + if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && + ((operation == OP_END_EXPR) || (operation == stopToken))) { + stackFrame.opers[-2] = stackFrame.opers[-1]; + if ((stackFrame.opers[-2] == OP_LOAD_IMM_INT16) || (stackFrame.opers[-2] == OP_LOAD_IMM_STR)) + stackFrame.values[-2] = stackFrame.values[-1]; + + stackFrame.pop(); + + simpleArithmetic2(stackFrame); + + if (operation != stopToken) + break; + } // if ((stackFrame.opers[-2] == OP_BEGIN_EXPR) && ...) + + for (brackStart = (stackFrame.pos - 2); (brackStart > 0) && + (stack.opers[brackStart] < OP_OR) && (stack.opers[brackStart] != OP_BEGIN_EXPR); + brackStart--) + ; + + if ((stack.opers[brackStart] >= OP_OR) || (stack.opers[brackStart] == OP_BEGIN_EXPR)) + brackStart++; + + if (complexArithmetic(stack, stackFrame, brackStart)) + break; + + } // while (stackFrame.pos >= 2) + + if ((operation == OP_OR) || (operation == OP_AND)) { + if (stackFrame.opers[-1] == OP_LOAD_IMM_INT16) { + if (stackFrame.values[-1] != 0) + stackFrame.opers[-1] = GOB_TRUE; + else + stackFrame.opers[-1] = GOB_FALSE; + } + + if (((operation == OP_OR) && (stackFrame.opers[-1] == GOB_TRUE)) || + ((operation == OP_AND) && (stackFrame.opers[-1] == GOB_FALSE))) { + if ((stackFrame.pos > 1) && (stackFrame.opers[-2] == OP_BEGIN_EXPR)) { + skipExpr(OP_END_EXPR); + stackFrame.opers[-2] = stackFrame.opers[-1]; + stackFrame.pop(2); + } else { + skipExpr(stopToken); + } + operation = _vm->_game->_script->peekByte(-1); + if ((stackFrame.pos > 0) && (stackFrame.opers[-1] == OP_NOT)) { + if (stackFrame.opers[0] == GOB_FALSE) + stackFrame.opers[-1] = GOB_TRUE; + else + stackFrame.opers[-1] = GOB_FALSE; + + stackFrame.pop(); + } + } else + stackFrame.opers[0] = operation; + } else + stackFrame.pop(); + + if (operation != stopToken) + continue; + + getResult(stack.opers[0], stack.values[0], type); + + return 0; + } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) + + if ((operation < OP_NEG) || (operation > OP_NOT)) { + if ((operation < OP_LESS) || (operation > OP_NEQ)) + continue; + + if (stackFrame.pos > 2) { + if (stackFrame.opers[-2] == OP_ADD) { + if (stackFrame.opers[-3] == OP_LOAD_IMM_INT16) { + stackFrame.values[-3] += stackFrame.values[-1]; + } else if (stackFrame.opers[-3] == OP_LOAD_IMM_STR) { + if ((char *) decodePtr(stackFrame.values[-3]) != _resultStr) { + strcpy(_resultStr, (char *) decodePtr(stackFrame.values[-3])); + stackFrame.values[-3] = encodePtr((byte *) _resultStr, kResStr); + } + strcat(_resultStr, (char *) decodePtr(stackFrame.values[-1])); + } + stackFrame.pop(2); + + } else if (stackFrame.opers[-2] == OP_SUB) { + stackFrame.values[-3] -= stackFrame.values[-1]; + stackFrame.pop(2); + } else if (stackFrame.opers[-2] == OP_BITOR) { + stackFrame.values[-3] |= stackFrame.values[-1]; + stackFrame.pop(2); + } + } + } + *stackFrame.opers = operation; + } +} + +int32 Expression::getResultInt() { + return _resultInt; +} + +char *Expression::getResultStr() { + return _resultStr; +} + +} // End of namespace Gob diff --git a/engines/gob/expression.h b/engines/gob/expression.h new file mode 100644 index 0000000000..894704e2a9 --- /dev/null +++ b/engines/gob/expression.h @@ -0,0 +1,178 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_EXPRESSION_H +#define GOB_EXPRESSION_H + +#include "common/scummsys.h" + +namespace Gob { + +class GobEngine; + +enum { + OP_NEG = 1, + OP_ADD = 2, + OP_SUB = 3, + OP_BITOR = 4, + OP_MUL = 5, + OP_DIV = 6, + OP_MOD = 7, + OP_BITAND = 8, + OP_BEGIN_EXPR = 9, + OP_END_EXPR = 10, + OP_NOT = 11, + + OP_END_MARKER = 12, // Marks end of an array or string + + + OP_ARRAY_INT8 = 16, + OP_LOAD_VAR_INT16 = 17, + OP_LOAD_VAR_INT8 = 18, + OP_LOAD_IMM_INT32 = 19, + OP_LOAD_IMM_INT16 = 20, + OP_LOAD_IMM_INT8 = 21, + OP_LOAD_IMM_STR = 22, + OP_LOAD_VAR_INT32 = 23, + OP_LOAD_VAR_INT32_AS_INT16 = 24, + OP_LOAD_VAR_STR = 25, + OP_ARRAY_INT32 = 26, + OP_ARRAY_INT16 = 27, + OP_ARRAY_STR = 28, + + OP_FUNC = 29, + + OP_OR = 30, // Logical OR + OP_AND = 31, // Logical AND + OP_LESS = 32, + OP_LEQ = 33, + OP_GREATER = 34, + OP_GEQ = 35, + OP_EQ = 36, + OP_NEQ = 37 +}; + +enum { + FUNC_SQRT1 = 0, + FUNC_SQRT2 = 1, + FUNC_SQRT3 = 6, + + FUNC_SQR = 5, + FUNC_ABS = 7, + FUNC_RAND = 10 +}; + +enum { + TYPE_IMM_INT8 = OP_LOAD_IMM_INT8, // 21 + TYPE_IMM_INT32 = OP_LOAD_IMM_INT32, // 19 + TYPE_IMM_INT16 = OP_LOAD_IMM_INT16, // 20 + TYPE_IMM_STR = OP_LOAD_IMM_STR, // 22 + TYPE_VAR_INT8 = OP_LOAD_VAR_INT8, // 18 + TYPE_VAR_INT16 = OP_LOAD_VAR_INT16, // 17 + TYPE_VAR_INT32 = OP_LOAD_VAR_INT32, // 23 + TYPE_VAR_STR = OP_LOAD_VAR_STR, // 25 + TYPE_ARRAY_INT8 = OP_ARRAY_INT8, // 16 + TYPE_ARRAY_INT16 = OP_ARRAY_INT16, // 27 + TYPE_ARRAY_INT32 = OP_ARRAY_INT32, // 26 + TYPE_ARRAY_STR = OP_ARRAY_STR, // 28 + TYPE_VAR_INT32_AS_INT16 = OP_LOAD_VAR_INT32_AS_INT16 // 24 +}; + +enum { + // FIXME: The following two 'truth values' are stored inside the list + // of "operators". So they somehow coincide with OP_LOAD_VAR_INT32 + // and OP_LOAD_VAR_INT32_AS_INT16. I haven't yet quite understood + // how, resp. what that means. You have been warned. + GOB_TRUE = 24, + GOB_FALSE = 23 +}; + +class Expression { +public: + Expression(GobEngine *vm); + virtual ~Expression() {} + + void skipExpr(char stopToken); + void printExpr(char stopToken); + void printVarIndex(void); + + int16 parseVarIndex(uint16 *size = 0, uint16 *type = 0); + int16 parseValExpr(byte stopToken = 99); + int16 parseExpr(byte stopToken, byte *type); + + int32 getResultInt(); + char *getResultStr(); + +private: + class Stack { + public: + byte *opers; + int32 *values; + + Stack(size_t size = 20); + ~Stack(); + }; + class StackFrame { + public: + byte *opers; + int32 *values; + int16 pos; + + StackFrame(const Stack &stack); + + void push(int count = 1); + void pop(int count = 1); + }; + + enum PointerType { + kExecPtr = 0, + kInterVar = 1, + kResStr = 2 + }; + + GobEngine *_vm; + + int32 _resultInt; + char _resultStr[200]; + + int32 encodePtr(byte *ptr, int type); + byte *decodePtr(int32 n); + + void printExpr_internal(char stopToken); + + bool getVarBase(uint32 &varBase, bool mindStop = false, + uint16 *size = 0, uint16 *type = 0); + int cmpHelper(const StackFrame &stackFrame); + void loadValue(byte operation, uint32 varBase, const StackFrame &stackFrame); + + void simpleArithmetic1(StackFrame &stackFrame); + void simpleArithmetic2(StackFrame &stackFrame); + bool complexArithmetic(Stack &stack, StackFrame &stackFrame, int16 brackStart); + void getResult(byte operation, int32 value, byte *type); +}; + +} // End of namespace Gob + +#endif // GOB_EXPRESSION_H diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index d5c81098cc..5771ee9f76 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -31,8 +31,10 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/variables.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" -#include "gob/parse.h" #include "gob/draw.h" #include "gob/mult.h" #include "gob/videoplayer.h" @@ -40,21 +42,139 @@ namespace Gob { +Environments::Environments(GobEngine *vm) : _vm(vm) { + _environments = new Environment[kEnvironmentCount]; + + for (uint i = 0; i < kEnvironmentCount; i++) { + Environment &e = _environments[i]; + + e.cursorHotspotX = 0; + e.cursorHotspotY = 0; + e.variables = 0; + e.script = 0; + e.resources = 0; + e.curTotFile[0] = '\0'; + } +} + +Environments::~Environments() { + clear(); + + delete[] _environments; +} + +void Environments::clear() { + // Deleting unique variables, script and resources + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].variables == _vm->_inter->_variables) + continue; + + if (!has(_environments[i].variables, i + 1)) + delete _environments[i].variables; + } + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].script == _vm->_game->_script) + continue; + + if (!has(_environments[i].script, i + 1)) + delete _environments[i].script; + } + + for (uint i = 0; i < kEnvironmentCount; i++) { + if (_environments[i].resources == _vm->_game->_resources) + continue; + + if (!has(_environments[i].resources, i + 1)) + delete _environments[i].resources; + } +} + +void Environments::set(uint8 env) { + if (env >= kEnvironmentCount) + return; + + Environment &e = _environments[env]; + + // If it already has a unique script or resource assigned, delete them + if ((e.script != _vm->_game->_script) && !has(e.script, 0, env)) + delete e.script; + if ((e.resources != _vm->_game->_resources) && !has(e.resources, 0, env)) + delete e.resources; + + e.cursorHotspotX = _vm->_draw->_cursorHotspotXVar; + e.cursorHotspotY = _vm->_draw->_cursorHotspotYVar; + e.script = _vm->_game->_script; + e.resources = _vm->_game->_resources; + e.variables = _vm->_inter->_variables; + strncpy(e.curTotFile, _vm->_game->_curTotFile, 14); +} + +void Environments::get(uint8 env) const { + if (env >= kEnvironmentCount) + return; + + const Environment &e = _environments[env]; + + _vm->_draw->_cursorHotspotXVar = e.cursorHotspotX; + _vm->_draw->_cursorHotspotYVar = e.cursorHotspotY; + _vm->_game->_script = e.script; + _vm->_game->_resources = e.resources; + _vm->_inter->_variables = e.variables; + strncpy(_vm->_game->_curTotFile, e.curTotFile, 14); +} + +const char *Environments::getTotFile(uint8 env) const { + if (env >= kEnvironmentCount) + return ""; + + return _environments[env].curTotFile; +} + +bool Environments::has(Variables *variables, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].variables == variables) + return true; + } + + return false; +} + +bool Environments::has(Script *script, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].script == script) + return true; + } + + return false; +} + +bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const { + for (uint i = startEnv; i < kEnvironmentCount; i++) { + if ((except >= 0) && (((uint16) except) == i)) + continue; + + if (_environments[i].resources == resources) + return true; + } + + return false; +} + + Game::Game(GobEngine *vm) : _vm(vm) { - _extTable = 0; - _totFileData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extHandle = 0; - _lomHandle = -1; _collisionAreas = 0; _shouldPushColls = 0; _captureCount = 0; - _foundTotLoc = false; - _totTextData = 0; - _collStackSize = 0; for (int i = 0; i < 5; i++) { @@ -63,7 +183,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { } _curTotFile[0] = 0; - _curExtFile[0] = 0; _totToLoad[0] = 0; _startTimeKey = 0; @@ -85,138 +204,20 @@ Game::Game(GobEngine *vm) : _vm(vm) { _noCd = false; _tempStr[0] = 0; - _curImaFile[0] = 0; _collStr[0] = 0; - _backupedCount = 0; - _curBackupPos = 0; + _numEnvironments = 0; + _curEnvironment = 0; - for (int i = 0; i < 5; i++) { - _cursorHotspotXArray[i] = 0; - _cursorHotspotYArray[i] = 0; - _totTextDataArray[i] = 0; - _totFileDataArray[i] = 0; - _totResourceTableArray[i] = 0; - _extTableArray[i] = 0; - _extHandleArray[i] = 0; - _imFileDataArray[i] = 0; - _variablesArray[i] = 0; - _curTotFileArray[i][0] = 0; - } + _environments = new Environments(_vm); + _script = new Script(_vm); + _resources = new Resources(_vm); } Game::~Game() { - delete[] _vm->_game->_totFileData; - if (_vm->_game->_totTextData) { - if (_vm->_game->_totTextData->items) - delete[] _vm->_game->_totTextData->items; - delete _vm->_game->_totTextData; - } - if (_vm->_game->_totResourceTable) { - delete[] _vm->_game->_totResourceTable->items; - delete _vm->_game->_totResourceTable; - } -} - -byte *Game::loadExtData(int16 itemId, int16 *pResWidth, - int16 *pResHeight, uint32 *dataSize) { - int16 commonHandle; - int16 itemsCount; - int32 offset; - uint32 size; - uint32 realSize; - ExtItem *item; - bool isPacked; - int16 handle; - int32 tableSize; - char path[20]; - byte *dataBuf; - byte *packedBuf; - byte *dataPtr; - - itemId -= 30000; - if (_extTable == 0) - return 0; - - commonHandle = -1; - itemsCount = _extTable->itemsCount; - item = &_extTable->items[itemId]; - tableSize = szGame_ExtTable + szGame_ExtItem * itemsCount; - - offset = item->offset; - size = item->size; - isPacked = (item->width & 0x8000) != 0; - - if ((pResWidth != 0) && (pResHeight != 0)) { - *pResWidth = item->width & 0x7FFF; - - if (*pResWidth & 0x4000) - size += 1 << 16; - if (*pResWidth & 0x2000) - size += 2 << 16; - if (*pResWidth & 0x1000) - size += 4 << 16; - - *pResWidth &= 0xFFF; - - *pResHeight = item->height; - debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)", - itemId, *pResWidth, *pResHeight); - } - - debugC(7, kDebugFileIO, "loadExtData(%d, 0, 0)", itemId); - - if (item->height == 0) - size += (item->width & 0x7FFF) << 16; - - debugC(7, kDebugFileIO, "size: %d off: %d", size, offset); - if (offset < 0) { - offset = -(offset + 1); - tableSize = 0; - _vm->_dataIO->closeData(_extHandle); - strcpy(path, "commun.ex1"); - path[strlen(path) - 1] = *(_totFileData + 0x3C) + '0'; - commonHandle = _vm->_dataIO->openData(path); - handle = commonHandle; - } else - handle = _extHandle; - - DataStream *stream = _vm->_dataIO->openAsStream(handle); - - debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize); - stream->seek(offset + tableSize); - realSize = size; - if (isPacked) - dataBuf = new byte[size + 2]; - else - dataBuf = new byte[size]; - - dataPtr = dataBuf; - while (size > 32000) { - // BUG: huge->far conversion. Need normalization? - stream->read(dataPtr, 32000); - size -= 32000; - dataPtr += 32000; - } - stream->read(dataPtr, size); - - delete stream; - if (commonHandle != -1) { - _vm->_dataIO->closeData(commonHandle); - _extHandle = _vm->_dataIO->openData(_curExtFile); - } - - if (isPacked) { - packedBuf = dataBuf; - realSize = READ_LE_UINT32(packedBuf); - dataBuf = new byte[realSize]; - _vm->_dataIO->unpackData(packedBuf, dataBuf); - delete[] packedBuf; - } - - if (dataSize) - *dataSize = realSize; - return dataBuf; + delete _environments; + delete _script; + delete _resources; } void Game::freeCollision(int16 id) { @@ -281,39 +282,9 @@ void Game::capturePop(char doDraw) { _vm->_draw->freeSprite(30 + _captureCount); } -byte *Game::loadTotResource(int16 id, - int16 *dataSize, int16 *width, int16 *height) { - - TotResItem *itemPtr; - int32 offset; - - if (id >= _vm->_game->_totResourceTable->itemsCount) { - warning("Trying to load non-existent TOT resource (%s, %d/%d)", - _curTotFile, id, _totResourceTable->itemsCount - 1); - return 0; - } - - itemPtr = &_totResourceTable->items[id]; - offset = itemPtr->offset; - - if (dataSize) - *dataSize = itemPtr->size; - if (width) - *width = itemPtr->width; - if (height) - *height = itemPtr->height; - - if (offset < 0) { - offset = (-offset - 1) * 4; - return _imFileData + (int32) READ_LE_UINT32(_imFileData + offset); - } else - return _totResourceTable->dataPtr + szGame_TotResTable + - szGame_TotResItem * _totResourceTable->itemsCount + offset; -} - void Game::freeSoundSlot(int16 slot) { if (slot == -1) - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot)); } @@ -416,104 +387,6 @@ int16 Game::adjustKey(int16 key) { return key - 0x20; } -int32 Game::loadTotFile(const char *path) { - int16 handle; - int32 size; - - _lomHandle = -1; - - size = -1; - handle = _vm->_dataIO->openData(path); - if (handle >= 0) { - - if (!scumm_stricmp(path + strlen(path) - 3, "LOM")) { - warning("Urban Stub: loadTotFile %s", path); - - _lomHandle = handle; - - DataStream *stream = _vm->_dataIO->openAsStream(handle); - - stream->seek(48); - size = stream->readUint32LE(); - stream->seek(0); - - _totFileData = new byte[size]; - stream->read(_totFileData, size); - - delete stream; - } else { - _vm->_dataIO->closeData(handle); - size = _vm->_dataIO->getDataSize(path); - _totFileData = _vm->_dataIO->getData(path); - } - - } else { - Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path); - - if (videoExtraData) { - warning("Found \"%s\" in video file", path); - - size = videoExtraData->size(); - _totFileData = new byte[size]; - videoExtraData->read(_totFileData, size); - delete videoExtraData; - } else - _totFileData = 0; - } - - return size; -} - -void Game::loadExtTable(void) { - int16 count; - - // Function is correct. [sev] - - _extHandle = _vm->_dataIO->openData(_curExtFile); - if (_extHandle < 0) - return; - - DataStream *stream = _vm->_dataIO->openAsStream(_extHandle); - count = stream->readUint16LE(); - - stream->seek(0); - _extTable = new ExtTable; - _extTable->items = 0; - if (count) - _extTable->items = new ExtItem[count]; - - _extTable->itemsCount = stream->readUint16LE(); - _extTable->unknown = stream->readByte(); - - for (int i = 0; i < count; i++) { - _extTable->items[i].offset = stream->readUint32LE(); - _extTable->items[i].size = stream->readUint16LE(); - _extTable->items[i].width = stream->readUint16LE(); - _extTable->items[i].height = stream->readUint16LE(); - } - - delete stream; -} - -void Game::loadImFile(void) { - char path[20]; - int16 handle; - - if ((_totFileData[0x3D] != 0) && (_totFileData[0x3B] == 0)) - return; - - strcpy(path, "commun.im1"); - if (_totFileData[0x3B] != 0) - path[strlen(path) - 1] = '0' + _totFileData[0x3B]; - - handle = _vm->_dataIO->openData(path); - if (handle < 0) - return; - - _vm->_dataIO->closeData(handle); - _imFileData = _vm->_dataIO->getData(path); -} - void Game::start(void) { _collisionAreas = new Collision[250]; memset(_collisionAreas, 0, 250 * sizeof(Collision)); @@ -526,34 +399,24 @@ void Game::start(void) { for (int i = 0; i < SPRITES_COUNT; i++) _vm->_draw->freeSprite(i); - _vm->_draw->_scummvmCursor = 0; + _vm->_draw->_scummvmCursor.reset(); } // flagbits: 0 = freeInterVariables, 1 = skipPlay void Game::totSub(int8 flags, const char *newTotFile) { int8 curBackupPos; - if (_backupedCount >= 5) + if (_numEnvironments >= Environments::kEnvironmentCount) return; - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - - curBackupPos = _curBackupPos; - _backupedCount++; - _curBackupPos = _backupedCount; - - _totTextData = 0; - _totFileData = 0; - _totResourceTable = 0; + _environments->set(_numEnvironments); + + curBackupPos = _curEnvironment; + _numEnvironments++; + _curEnvironment = _numEnvironments; + + _script = new Script(_vm); + _resources = new Resources(_vm); if (flags & 1) _vm->_inter->_variables = 0; @@ -563,8 +426,10 @@ void Game::totSub(int8 flags, const char *newTotFile) { // else strcat(_curTotFile, ".TOT"); - if (_vm->_inter->_terminate != 0) + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); return; + } pushCollisions(0); @@ -582,197 +447,64 @@ void Game::totSub(int8 flags, const char *newTotFile) { _vm->_inter->delocateVars(); } - _backupedCount--; - _curBackupPos = curBackupPos; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount]; - _totTextData = _totTextDataArray[_backupedCount]; - _totFileData = _totFileDataArray[_backupedCount]; - _totResourceTable = _totResourceTableArray[_backupedCount]; - _extTable = _extTableArray[_backupedCount]; - _extHandle = _extHandleArray[_backupedCount]; - _imFileData = _imFileDataArray[_backupedCount]; - _vm->_inter->_variables = _variablesArray[_backupedCount]; - strcpy(_curTotFile, _curTotFileArray[_backupedCount]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); + clearUnusedEnvironment(); + + _numEnvironments--; + _curEnvironment = curBackupPos; + _environments->get(_numEnvironments); } void Game::switchTotSub(int16 index, int16 skipPlay) { int16 backupedCount; int16 curBackupPos; - if ((_backupedCount - index) < 1) + if ((_numEnvironments - index) < 1) + return; + + int16 newPos = _curEnvironment - index - ((index >= 0) ? 1 : 0); + if (newPos >= Environments::kEnvironmentCount) return; - int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0); // WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable // in the dreamland screen, resulting in a crash when it's clicked. if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) && - !scumm_stricmp(_curTotFileArray[newPos], "gob06.tot")) + !scumm_stricmp(_environments->getTotFile(newPos), "gob06.tot")) return; - curBackupPos = _curBackupPos; - backupedCount = _backupedCount; - if (_curBackupPos == _backupedCount) { - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - _backupedCount++; - } - _curBackupPos -= index; - if (index >= 0) - _curBackupPos--; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos]; - _totTextData = _totTextDataArray[_curBackupPos]; - _totFileData = _totFileDataArray[_curBackupPos]; - _totResourceTable = _totResourceTableArray[_curBackupPos]; - _imFileData = _imFileDataArray[_curBackupPos]; - _extTable = _extTableArray[_curBackupPos]; - _extHandle = _extHandleArray[_curBackupPos]; - _vm->_inter->_variables = _variablesArray[_curBackupPos]; - strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); - - if (_vm->_inter->_terminate != 0) - return; + curBackupPos = _curEnvironment; + backupedCount = _numEnvironments; + if (_curEnvironment == _numEnvironments) + _environments->set(_numEnvironments++); - _vm->_game->pushCollisions(0); - _vm->_game->playTot(skipPlay); + _curEnvironment -= index; + if (index >= 0) + _curEnvironment--; - if (_vm->_inter->_terminate != 2) - _vm->_inter->_terminate = 0; + clearUnusedEnvironment(); - _vm->_game->popCollisions(); - - _curBackupPos = curBackupPos; - _backupedCount = backupedCount; - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_curBackupPos]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_curBackupPos]; - _totTextData = _totTextDataArray[_curBackupPos]; - _totFileData = _totFileDataArray[_curBackupPos]; - _totResourceTable = _totResourceTableArray[_curBackupPos]; - _extTable = _extTableArray[_curBackupPos]; - _extHandle = _extHandleArray[_curBackupPos]; - _imFileData = _imFileDataArray[_curBackupPos]; - _vm->_inter->_variables = _variablesArray[_curBackupPos]; - strcpy(_curTotFile, _curTotFileArray[_curBackupPos]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); -} + _environments->get(_curEnvironment); -int16 Game::openLocTextFile(char *locTextFile, int language) { - int n; - - n = strlen(locTextFile); - if (n < 4) - return -1; - - locTextFile[n - 4] = 0; - switch (language) { - case 0: - strcat(locTextFile, ".dat"); - break; - case 1: - strcat(locTextFile, ".all"); - break; - case 3: - strcat(locTextFile, ".esp"); - break; - case 4: - strcat(locTextFile, ".ita"); - break; - case 5: - strcat(locTextFile, ".usa"); - break; - case 6: - strcat(locTextFile, ".ndl"); - break; - case 7: - strcat(locTextFile, ".kor"); - break; - case 8: - strcat(locTextFile, ".isr"); - break; - default: - strcat(locTextFile, ".ang"); - break; + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); + return; } - return _vm->_dataIO->openData(locTextFile); -} - -byte *Game::loadLocTexts(int32 *dataSize) { - char locTextFile[20]; - int16 handle; - int i; - - strcpy(locTextFile, _curTotFile); - - handle = openLocTextFile(locTextFile, _vm->_global->_languageWanted); - if (handle >= 0) { - - _foundTotLoc = true; - _vm->_global->_language = _vm->_global->_languageWanted; - - } else if (!_foundTotLoc) { - bool found = false; - - if (_vm->_global->_languageWanted == 2) { - handle = openLocTextFile(locTextFile, 5); - if (handle >= 0) { - _vm->_global->_language = 5; - found = true; - } - } else if (_vm->_global->_languageWanted == 5) { - handle = openLocTextFile(locTextFile, 2); - if (handle >= 0) { - _vm->_global->_language = 2; - found = true; - } - } - if (!found) { - for (i = 0; i < 10; i++) { - handle = openLocTextFile(locTextFile, i); - if (handle >= 0) { - _vm->_global->_language = i; - break; - } - } - } - - } + pushCollisions(0); + playTot(skipPlay); - debugC(1, kDebugFileIO, "Using language %d for %s", - _vm->_global->_language, _curTotFile); + if (_vm->_inter->_terminate != 2) + _vm->_inter->_terminate = 0; - if (handle >= 0) { - _vm->_dataIO->closeData(handle); + popCollisions(); - if (dataSize) - *dataSize = _vm->_dataIO->getDataSize(locTextFile); + clearUnusedEnvironment(); - return _vm->_dataIO->getData(locTextFile); - } - return 0; + _curEnvironment = curBackupPos; + _numEnvironments = backupedCount; + _environments->get(_curEnvironment); } void Game::setCollisions(byte arg_0) { - byte *savedIP; uint16 left; uint16 top; uint16 width; @@ -783,12 +515,12 @@ void Game::setCollisions(byte arg_0) { if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) continue; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + collArea->funcSub; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + _script->call(collArea->funcSub); + + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { left += _vm->_draw->_backDeltaX; @@ -807,16 +539,15 @@ void Game::setCollisions(byte arg_0) { collArea->top = top; collArea->right = left + width - 1; collArea->bottom = top + height - 1; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } } void Game::collSub(uint16 offset) { - byte *savedIP; int16 collStackSize; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + offset; + _script->call(offset); _shouldPushColls = 1; collStackSize = _collStackSize; @@ -827,7 +558,9 @@ void Game::collSub(uint16 offset) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); + setCollisions(); } @@ -852,4 +585,16 @@ void Game::collAreaSub(int16 index, int8 enter) { } } +void Game::clearUnusedEnvironment() { + if (!_environments->has(_script)) { + delete _script; + _script = 0; + } + if (!_environments->has(_resources)) { + delete _resources; + _resources = 0; + } + +} + } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index 3264288a32..ead4a56492 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,10 +26,45 @@ #ifndef GOB_GAME_H #define GOB_GAME_H -#include "gob/variables.h" - namespace Gob { +class Script; +class Resources; +class Variables; + +class Environments { +public: + static const uint8 kEnvironmentCount = 5; + + Environments(GobEngine *vm); + ~Environments(); + + void set(uint8 env); + void get(uint8 env) const; + + const char *getTotFile(uint8 env) const; + + bool has(Variables *variables, uint8 startEnv = 0, int16 except = -1) const; + bool has(Script *script , uint8 startEnv = 0, int16 except = -1) const; + bool has(Resources *resources, uint8 startEnv = 0, int16 except = -1) const; + + void clear(); + +private: + struct Environment { + int16 cursorHotspotX; + int16 cursorHotspotY; + char curTotFile[14]; + Variables *variables; + Script *script; + Resources *resources; + }; + + GobEngine *_vm; + + Environment *_environments; +}; + class Game { public: @@ -46,20 +81,7 @@ public: uint16 funcEnter; uint16 funcLeave; uint16 funcSub; - byte *totFileData; - } PACKED_STRUCT; - -#define szGame_TotTextItem (2 + 2) - struct TotTextItem { - int16 offset; - int16 size; - } PACKED_STRUCT; - -#define szGame_TotTextTable (2) - struct TotTextTable { - int16 itemsCount; - TotTextItem *items; - byte *dataPtr; + Script *script; } PACKED_STRUCT; struct InputDesc { @@ -74,18 +96,10 @@ public: Collision *_collisionAreas; Collision *_collStack[5]; - bool _foundTotLoc; - TotTextTable *_totTextData; + Script *_script; + Resources *_resources; char _curTotFile[14]; - char _curExtFile[14]; - - byte *_imFileData; - byte *_totFileData; - - int16 _extHandle; - int16 _lomHandle; - char _totToLoad[20]; int32 _startTimeKey; @@ -100,9 +114,6 @@ public: Game(GobEngine *vm); virtual ~Game(); - byte *loadExtData(int16 dataId, int16 *pResWidth, int16 *pResHeight, uint32 *dataSize = 0); - byte *loadTotResource(int16 id, int16 *dataSize = 0, int16 *width = 0, int16 *height = 0); - void capturePush(int16 left, int16 top, int16 width, int16 height); void capturePop(char doDraw); @@ -142,42 +153,6 @@ public: virtual void popCollisions(void) = 0; protected: -#include "common/pack-start.h" // START STRUCT PACKING - -#define szGame_TotResItem (4 + 2 + 2 + 2) - struct TotResItem { - int32 offset; // if > 0, then offset from end of resource table. - // If < 0, then -offset-1 is index in .IM file table - int16 size; - int16 width; - int16 height; - } PACKED_STRUCT; - -#define szGame_TotResTable (2 + 1) - struct TotResTable { - int16 itemsCount; - byte unknown; - TotResItem *items; - byte *dataPtr; - } PACKED_STRUCT; - -#define szGame_ExtItem (4 + 2 + 2 + 2) - struct ExtItem { - int32 offset; // offset from the table end - uint16 size; - int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag - int16 height; // not zero - } PACKED_STRUCT; - -#define szGame_ExtTable (2 + 1) - struct ExtTable { - int16 itemsCount; - byte unknown; - ExtItem *items; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - int16 _lastCollKey; int16 _lastCollAreaIndex; int16 _lastCollId; @@ -190,10 +165,6 @@ protected: char _tempStr[256]; - TotResTable *_totResourceTable; - ExtTable *_extTable; - char _curImaFile[18]; - int16 _collStackSize; int16 _collStackElemSizes[5]; @@ -206,35 +177,22 @@ protected: char _collStr[256]; // For totSub() - int8 _backupedCount; - int8 _curBackupPos; - int16 _cursorHotspotXArray[5]; - int16 _cursorHotspotYArray[5]; - TotTextTable *_totTextDataArray[5]; - byte *_totFileDataArray[5]; - TotResTable *_totResourceTableArray[5]; - ExtTable *_extTableArray[5]; - int16 _extHandleArray[5]; - byte *_imFileDataArray[5]; - Variables *_variablesArray[5]; - char _curTotFileArray[5][14]; + int8 _curEnvironment; + int8 _numEnvironments; + Environments *_environments; GobEngine *_vm; virtual int16 adjustKey(int16 key); - byte *loadLocTexts(int32 *dataSize = 0); - int32 loadTotFile(const char *path); - void loadExtTable(void); - void loadImFile(void); - void collAreaSub(int16 index, int8 enter); - int16 openLocTextFile(char *locTextFile, int language); virtual void setCollisions(byte arg_0 = 1); virtual void collSub(uint16 offset); virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0; + + void clearUnusedEnvironment(); }; class Game_v1 : public Game { diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp index 8e77141ce6..38ad03f0f8 100644 --- a/engines/gob/game_fascin.cpp +++ b/engines/gob/game_fascin.cpp @@ -35,7 +35,6 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index b46cc00f90..87dc78e3b1 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -32,11 +32,12 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/inter.h" #include "gob/mult.h" #include "gob/video.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -49,12 +50,12 @@ void Game_v1::playTot(int16 skipPlay) { int16 _captureCounter; int16 breakFrom; int16 nestLevel; - int32 variablesCount; int16 *oldNestLevel = _vm->_inter->_nestLevel; int16 *oldBreakFrom = _vm->_inter->_breakFromLevel; int16 *oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - byte *savedIP = _vm->_global->_inter_execPtr; + + _script->push(); _vm->_inter->_nestLevel = &nestLevel; _vm->_inter->_breakFromLevel = &breakFrom; @@ -93,86 +94,23 @@ void Game_v1::playTot(int16 skipPlay) { for (int i = 0; i < 20; i++) freeSoundSlot(i); - _totTextData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extTable = 0; - _extHandle = -1; - _totToLoad[0] = 0; - if ((_curTotFile[0] == 0) && (_totFileData == 0)) + if ((_curTotFile[0] == 0) && !_script->isLoaded()) break; - loadTotFile(_curTotFile); - if (_totFileData == 0) { + if (!_script->load(_curTotFile)) { _vm->_draw->blitCursor(); break; } - strcpy(_curImaFile, _curTotFile); - strcpy(_curExtFile, _curTotFile); - - _curImaFile[strlen(_curImaFile) - 4] = 0; - strcat(_curImaFile, ".ima"); - - _curExtFile[strlen(_curExtFile) - 4] = 0; - strcat(_curExtFile, ".ext"); - - debugC(4, kDebugFileIO, "IMA: %s", _curImaFile); - debugC(4, kDebugFileIO, "EXT: %s", _curExtFile); - - byte *filePtr = _totFileData + 0x30; - - _totTextData = 0; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totTextData = new TotTextTable; - _totTextData->dataPtr = - (_totFileData + READ_LE_UINT32(_totFileData + 0x30)); - Common::MemoryReadStream totTextData(_totTextData->dataPtr, - 4294967295U); - - _totTextData->itemsCount = totTextData.readSint16LE(); - - _totTextData->items = new TotTextItem[_totTextData->itemsCount]; - for (int i = 0; i < _totTextData->itemsCount; ++i) { - _totTextData->items[i].offset = totTextData.readSint16LE(); - _totTextData->items[i].size = totTextData.readSint16LE(); - } - } - - filePtr = _totFileData + 0x34; - _totResourceTable = 0; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totResourceTable = new TotResTable; - _totResourceTable->dataPtr = - _totFileData + READ_LE_UINT32( _totFileData + 0x34); - Common::MemoryReadStream totResTable(_totResourceTable->dataPtr, - 4294967295U); - - _totResourceTable->itemsCount = totResTable.readSint16LE(); - _totResourceTable->unknown = totResTable.readByte(); - - _totResourceTable->items = - new TotResItem[_totResourceTable->itemsCount]; - for (int i = 0; i < _totResourceTable->itemsCount; ++i) { - _totResourceTable->items[i].offset = totResTable.readSint32LE(); - _totResourceTable->items[i].size = totResTable.readSint16LE(); - _totResourceTable->items[i].width = totResTable.readSint16LE(); - _totResourceTable->items[i].height = totResTable.readSint16LE(); - } - } - - loadImFile(); - loadExtTable(); + _resources->load(_curTotFile); - _vm->_global->_inter_animDataSize = - READ_LE_UINT16(_totFileData + 0x38); + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += READ_LE_UINT32(_totFileData + 0x64); + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); _vm->_inter->renewTimeInVars(); @@ -182,39 +120,16 @@ void Game_v1::playTot(int16 skipPlay) { WRITE_VAR(16, _vm->_global->_language); _vm->_inter->callSub(2); + _script->setFinished(false); if (_totToLoad[0] != 0) _vm->_inter->_terminate = 0; - variablesCount = READ_LE_UINT32(_totFileData + 0x2C); _vm->_draw->blitInvalidated(); - delete[] _totFileData; - _totFileData = 0; - - if (_totTextData) { - delete[] _totTextData->items; - delete _totTextData; - } - _totTextData = 0; - - if (_totResourceTable) { - delete[] _totResourceTable->items; - delete _totResourceTable; - } - _totResourceTable = 0; - - delete[] _imFileData; - _imFileData = 0; - if (_extTable) - delete[] _extTable->items; - delete _extTable; - _extTable = 0; + _script->unload(); - if (_extHandle >= 0) - _vm->_dataIO->closeData(_extHandle); - - _extHandle = -1; + _resources->unload(); for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) capturePop(0); @@ -241,7 +156,8 @@ void Game_v1::playTot(int16 skipPlay) { _vm->_inter->_nestLevel = oldNestLevel; _vm->_inter->_breakFromLevel = oldBreakFrom; _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } void Game_v1::clearCollisions() { @@ -279,7 +195,7 @@ int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = 0; + ptr->script = 0; return i; } @@ -331,7 +247,6 @@ void Game_v1::popCollisions(void) { int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, int16 *pResIndex) { - byte *savedIP; int16 resIndex; int16 key; int16 oldIndex; @@ -357,12 +272,9 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; - + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); } } @@ -423,12 +335,10 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); } _lastCollKey = 0; @@ -463,12 +373,11 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = 0; return key; @@ -476,24 +385,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if ((_lastCollKey != 0) && (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcLeave; + _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } } else { @@ -507,23 +414,22 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, if (key != _lastCollKey) { if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[oldIndex].funcLeave; + _script->call(_collisionAreas[oldIndex].funcLeave); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } _lastCollKey = key; if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_lastCollAreaIndex].funcEnter; + _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); _vm->_inter->funcBlock(0); - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + } + } } } @@ -549,9 +455,9 @@ void Game_v1::prepareStart(void) { _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); _vm->_draw->initScreen(); - _vm->_video->fillRect(_vm->_draw->_backSurface, 0, 0, 319, 199, 1); + _vm->_video->fillRect(*_vm->_draw->_backSurface, 0, 0, 319, 199, 1); _vm->_draw->_frontSurface = _vm->_global->_primarySurfDesc; - _vm->_video->fillRect(_vm->_draw->_frontSurface, 0, 0, 319, 199, 1); + _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, 319, 199, 1); _vm->_util->setMousePos(152, 92); _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; @@ -588,7 +494,6 @@ void Game_v1::collisionsBlock(void) { int16 array[250]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -615,27 +520,27 @@ void Game_v1::collisionsBlock(void) { int16 collStackPos; Collision *collPtr; uint32 timeKey; - byte *savedIP; if (_shouldPushColls) pushCollisions(1); collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - descIndex2 = _vm->_global->_inter_execPtr[2]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; + _script->skip(1); + count = _script->readByte(); + _handleMouse = _script->readByte(); + deltaTime = 1000 * _script->readByte(); + descIndex2 = _script->readByte(); + stackPos2 = _script->readByte(); + descIndex = _script->readByte(); if ((stackPos2 != 0) || (descIndex != 0)) deltaTime /= 100; timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(1); + + uint32 startPos = _script->pos(); - startIP = _vm->_global->_inter_execPtr; WRITE_VAR(16, 0); var_22 = 0; index = 0; @@ -643,26 +548,25 @@ void Game_v1::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } cmd &= 0x7F; @@ -680,16 +584,16 @@ void Game_v1::collisionsBlock(void) { _vm->_util->clearKeyBuf(); var_22 = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd < 5) || (cmd > 8)) { descArray[index].ptr = 0; } else { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += _vm->_inter->load16(); + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->readInt16()); } if (left == 0xFFFF) @@ -698,12 +602,9 @@ void Game_v1::collisionsBlock(void) { if ((cmd & 1) == 0) { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + top + height - 1, cmd, key, 0, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } else { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, @@ -713,18 +614,15 @@ void Game_v1::collisionsBlock(void) { break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0); + (flags << 4) + cmdHigh + 2, key, _script->pos(), 0); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -732,61 +630,48 @@ void Game_v1::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + (flags << 4) + cmdHigh + 2, key, 0, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, cmd + cmdHigh, key, - startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData); + startPos, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; - - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; + + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmd + cmdHigh, key, - startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData); + startPos, _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } } @@ -895,9 +780,11 @@ void Game_v1::collisionsBlock(void) { if (collPtr->funcLeave != 0) { timeKey = _vm->_util->getTimeKey(); - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = - _totFileData + collPtr->funcLeave; + + uint32 savedPos = _script->pos(); + + _script->seek(collPtr->funcLeave); + _shouldPushColls = 1; savedCollStackSize = _collStackSize; _vm->_inter->funcBlock(0); @@ -906,7 +793,8 @@ void Game_v1::collisionsBlock(void) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); @@ -986,9 +874,9 @@ void Game_v1::collisionsBlock(void) { WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); if (_collisionAreas[_activeCollIndex].funcEnter != 0) { - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + - _collisionAreas[_activeCollIndex].funcEnter; + uint32 savedPos = _script->pos(); + + _script->seek(_collisionAreas[_activeCollIndex].funcEnter); _shouldPushColls = 1; @@ -997,7 +885,8 @@ void Game_v1::collisionsBlock(void) { if (collStackPos != _collStackSize) popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); } WRITE_VAR(16, 0); @@ -1071,10 +960,8 @@ void Game_v1::collisionsBlock(void) { WRITE_VAR(17, 1); } - savedIP = 0; if (!_vm->_inter->_terminate) { - savedIP = _totFileData + - _collisionAreas[_activeCollIndex].funcLeave; + _script->seek(_collisionAreas[_activeCollIndex].funcLeave); WRITE_VAR(2, _vm->_global->_inter_mouseX); WRITE_VAR(3, _vm->_global->_inter_mouseY); @@ -1082,12 +969,11 @@ void Game_v1::collisionsBlock(void) { if (VAR(16) == 0) WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); - - _vm->_global->_inter_execPtr = savedIP; } int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos, diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 777eae14bc..08184e73d0 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -32,11 +32,12 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -55,15 +56,12 @@ void Game_v2::playTot(int16 skipPlay) { int16 _captureCounter; int16 breakFrom; int16 nestLevel; - int32 totSize; - byte *filePtr; - byte *savedIP; - bool totTextLoc; oldNestLevel = _vm->_inter->_nestLevel; oldBreakFrom = _vm->_inter->_breakFromLevel; oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - savedIP = _vm->_global->_inter_execPtr; + + _script->push(); _vm->_inter->_nestLevel = &nestLevel; _vm->_inter->_breakFromLevel = &breakFrom; @@ -94,125 +92,30 @@ void Game_v2::playTot(int16 skipPlay) { } else _vm->_inter->initControlVars(0); - _totTextData = 0; - _totResourceTable = 0; - _imFileData = 0; - _extTable = 0; - _extHandle = -1; - _vm->_draw->_cursorHotspotXVar = -1; _totToLoad[0] = 0; - if ((_curTotFile[0] == 0) && (_totFileData == 0)) + if ((_curTotFile[0] == 0) && (!_script->isLoaded())) break; - totSize = loadTotFile(_curTotFile); - if (skipPlay == -2) { _vm->_vidPlayer->primaryClose(); skipPlay = 0; } - if (_totFileData == 0) { + if (!_script->load(_curTotFile)) { _vm->_draw->blitCursor(); _vm->_inter->_terminate = 2; break; } - strcpy(_curImaFile, _curTotFile); - strcpy(_curExtFile, _curTotFile); - - _curImaFile[strlen(_curImaFile) - 4] = 0; - strcat(_curImaFile, ".ima"); - - _curExtFile[strlen(_curExtFile) - 4] = 0; - strcat(_curExtFile, ".ext"); - - debugC(4, kDebugFileIO, "IMA: %s", _curImaFile); - debugC(4, kDebugFileIO, "EXT: %s", _curExtFile); - - filePtr = _totFileData + 0x30; - - _totTextData = 0; - totTextLoc = false; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totTextData = new TotTextTable; - - int32 size; - - if (READ_LE_UINT32(filePtr) == 0) { - _totTextData->dataPtr = loadLocTexts(&size); - totTextLoc = true; - } else { - _totTextData->dataPtr = - (_totFileData + READ_LE_UINT32(_totFileData + 0x30)); - size = totSize; - _vm->_global->_language = _vm->_global->_languageWanted; - } - - _totTextData->items = 0; - if (_totTextData->dataPtr != 0) { - Common::MemoryReadStream totTextData(_totTextData->dataPtr, - 4294967295U); - _totTextData->itemsCount = totTextData.readSint16LE() & 0x3FFF; - - _totTextData->items = new TotTextItem[_totTextData->itemsCount]; - for (int i = 0; i < _totTextData->itemsCount; ++i) { - _totTextData->items[i].offset = totTextData.readSint16LE(); - _totTextData->items[i].size = totTextData.readSint16LE(); - } - } - } - - filePtr = _totFileData + 0x34; - _totResourceTable = 0; - int32 resSize; - if (READ_LE_UINT32(filePtr) != (uint32) -1) { - _totResourceTable = new TotResTable; - _totResourceTable->dataPtr = - _totFileData + READ_LE_UINT32(_totFileData + 0x34); - Common::MemoryReadStream totResTable(_totResourceTable->dataPtr, - 4294967295U); - - _totResourceTable->itemsCount = totResTable.readSint16LE(); - resSize = _totResourceTable->itemsCount * szGame_TotResItem + szGame_TotResTable; - if (totSize > (resSize + 0x34)) { - _totResourceTable->unknown = totResTable.readByte(); - - _totResourceTable->items = - new TotResItem[_totResourceTable->itemsCount]; - for (int i = 0; i < _totResourceTable->itemsCount; ++i) { - _totResourceTable->items[i].offset = totResTable.readSint32LE(); - _totResourceTable->items[i].size = totResTable.readSint16LE(); - _totResourceTable->items[i].width = totResTable.readSint16LE(); - _totResourceTable->items[i].height = totResTable.readSint16LE(); - } - } - else { - // WORKAROUND: In the original asm, _totResourceTable is - // only assigned in playTot and evaluated later, right - // before using it. In the Gobliins 2 demo, there is a - // dummy tot that loads another tot, overwriting the dummy - // pointer with the real one. - debugC(1, kDebugFileIO, - "Attempted to load invalid resource table (size = %d, totSize = %d)", - resSize, totSize); - delete _totResourceTable; - _totResourceTable = 0; - } - } - - loadImFile(); - loadExtTable(); + _resources->load(_curTotFile); - _vm->_global->_inter_animDataSize = - READ_LE_UINT16(_totFileData + 0x38); + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C)); + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_totFileData + 0x64); + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); _vm->_inter->renewTimeInVars(); @@ -227,35 +130,10 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_inter->_terminate = 0; _vm->_draw->blitInvalidated(); - delete[] _totFileData; - _totFileData = 0; - - if (_totTextData) { - delete[] _totTextData->items; - if (totTextLoc) - delete[] _totTextData->dataPtr; - delete _totTextData; - } - _totTextData = 0; - if (_totResourceTable) { - delete[] _totResourceTable->items; - delete _totResourceTable; - } - _totResourceTable = 0; - - delete[] _imFileData; - _imFileData = 0; - - if (_extTable) - delete[] _extTable->items; - delete _extTable; - _extTable = 0; - - if (_extHandle >= 0) - _vm->_dataIO->closeData(_extHandle); + _script->unload(); - _extHandle = -1; + _resources->unload(); for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) capturePop(0); @@ -282,9 +160,7 @@ void Game_v2::playTot(int16 skipPlay) { } else { _vm->_inter->initControlVars(0); _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = _totFileData; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_totFileData + (skipPlay << 1) + 0x66); + _script->seek(_script->getFunctionOffset(skipPlay + 1)); _menuLevel++; _vm->_inter->callSub(2); @@ -299,7 +175,8 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_inter->_nestLevel = oldNestLevel; _vm->_inter->_breakFromLevel = oldBreakFrom; _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _vm->_global->_inter_execPtr = savedIP; + + _script->pop(); } void Game_v2::clearCollisions() { @@ -337,7 +214,7 @@ int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = 0; + ptr->script = 0; return i; } @@ -571,7 +448,7 @@ void Game_v2::prepareStart(void) { _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); _vm->_draw->initScreen(); - _vm->_video->fillRect(_vm->_draw->_frontSurface, 0, 0, + _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); _vm->_util->setMousePos(152, 92); @@ -604,7 +481,6 @@ void Game_v2::collisionsBlock(void) { int16 array[250]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -621,7 +497,6 @@ void Game_v2::collisionsBlock(void) { int16 stackPos2; int16 descIndex; int16 timeVal; - int16 offsetIP; char *str; int16 i; int16 counter; @@ -631,8 +506,9 @@ void Game_v2::collisionsBlock(void) { Collision *collPtr; Collision *collArea; int16 timeKey; - byte *savedIP; byte collAreaStart; + uint32 startPos; + uint32 offsetPos; if (_shouldPushColls) pushCollisions(0); @@ -645,21 +521,22 @@ void Game_v2::collisionsBlock(void) { _shouldPushColls = 0; collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; + _script->skip(1); + count = _script->readByte(); - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; + _handleMouse = _script->readByte(); + deltaTime = 1000 * _script->readByte(); + _script->skip(1); + stackPos2 = _script->readByte(); + descIndex = _script->readByte(); if ((stackPos2 != 0) || (descIndex != 0)) deltaTime /= 100; timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(1); - startIP = _vm->_global->_inter_execPtr; + startPos = _script->pos(); WRITE_VAR(16, 0); var_1C = 0; @@ -668,28 +545,27 @@ void Game_v2::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - offsetIP = _vm->_global->_inter_execPtr - _totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + offsetPos = _script->pos(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - offsetIP = 0; - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + offsetPos = 0; + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { @@ -712,46 +588,37 @@ void Game_v2::collisionsBlock(void) { switch (cmd) { case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); - - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + (flags << 4) + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); + _script->skip(_script->peekUint16(2) + 2); break; case 3: @@ -764,23 +631,20 @@ void Game_v2::collisionsBlock(void) { case 10: _vm->_util->clearKeyBuf(); var_1C = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2; + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->peekUint16() + 2); } else descArray[index].ptr = 0; if (left == 0xFFFF) { if ((cmd & 1) == 0) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } break; } @@ -789,11 +653,9 @@ void Game_v2::collisionsBlock(void) { addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, top + height - 1, cmd, key, 0, - _vm->_global->_inter_execPtr - _totFileData); + _script->pos()); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } else addNewCollision(curCmd + 0x8000, left, top, left + width * _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, @@ -803,35 +665,31 @@ void Game_v2::collisionsBlock(void) { break; case 11: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xE000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 12: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xD000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -839,34 +697,30 @@ void Game_v2::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP); + _script->pos(), 0, offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } @@ -1116,10 +970,8 @@ void Game_v2::collisionsBlock(void) { if (_handleMouse == 1) _vm->_draw->blitCursor(); - savedIP = 0; if (!_vm->_inter->_terminate) { - savedIP = _totFileData + - _collisionAreas[_activeCollIndex].funcLeave; + _script->seek(_collisionAreas[_activeCollIndex].funcLeave); _vm->_inter->storeMouse(); if (VAR(16) == 0) { @@ -1128,7 +980,8 @@ void Game_v2::collisionsBlock(void) { else WRITE_VAR(16, _activeCollResId & 0xFFF); } - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); @@ -1138,8 +991,6 @@ void Game_v2::collisionsBlock(void) { ((_collisionAreas[i].id & 0xF000) == 0x9000)) _collisionAreas[i].id |= 0x4000; } - - _vm->_global->_inter_execPtr = savedIP; } int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos, diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp index 9d9bd1faa3..8d40d41acc 100644 --- a/engines/gob/game_v6.cpp +++ b/engines/gob/game_v6.cpp @@ -31,9 +31,10 @@ #include "gob/game.h" #include "gob/helper.h" #include "gob/global.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/draw.h" -#include "gob/parse.h" namespace Gob { @@ -48,27 +49,17 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { if ((flags == 16) || (flags == 17)) warning("Urban Stub: Game_v6::totSub(), flags == %d", flags); - if (_backupedCount >= 5) + if (_numEnvironments >= Environments::kEnvironmentCount) return; - _cursorHotspotXArray[_backupedCount] = _vm->_draw->_cursorHotspotXVar; - _cursorHotspotYArray[_backupedCount] = _vm->_draw->_cursorHotspotYVar; - _totTextDataArray[_backupedCount] = _totTextData; - _totFileDataArray[_backupedCount] = _totFileData; - _totResourceTableArray[_backupedCount] = _totResourceTable; - _extTableArray[_backupedCount] = _extTable; - _extHandleArray[_backupedCount] = _extHandle; - _imFileDataArray[_backupedCount] = _imFileData; - _variablesArray[_backupedCount] = _vm->_inter->_variables; - strcpy(_curTotFileArray[_backupedCount], _curTotFile); - - curBackupPos = _curBackupPos; - _backupedCount++; - _curBackupPos = _backupedCount; - - _totTextData = 0; - _totFileData = 0; - _totResourceTable = 0; + _environments->set(_numEnvironments); + + curBackupPos = _curEnvironment; + _numEnvironments++; + _curEnvironment = _numEnvironments; + + _script = new Script(_vm); + _resources = new Resources(_vm); if (flags & 0x80) warning("Urban Stub: Game_v6::totSub(), flags & 0x80"); @@ -79,8 +70,10 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { strncpy0(_curTotFile, newTotFile, 9); strcat(_curTotFile, ".TOT"); - if (_vm->_inter->_terminate != 0) + if (_vm->_inter->_terminate != 0) { + clearUnusedEnvironment(); return; + } pushCollisions(0); @@ -99,22 +92,11 @@ void Game_v6::totSub(int8 flags, const char *newTotFile) { _vm->_inter->delocateVars(); } - _backupedCount--; - _curBackupPos = curBackupPos; - - _vm->_draw->_cursorHotspotXVar = _cursorHotspotXArray[_backupedCount]; - _vm->_draw->_cursorHotspotYVar = _cursorHotspotYArray[_backupedCount]; - _totTextData = _totTextDataArray[_backupedCount]; - _totFileData = _totFileDataArray[_backupedCount]; - _totResourceTable = _totResourceTableArray[_backupedCount]; - _extTable = _extTableArray[_backupedCount]; - _extHandle = _extHandleArray[_backupedCount]; - _imFileData = _imFileDataArray[_backupedCount]; - _vm->_inter->_variables = _variablesArray[_backupedCount]; - strcpy(_curTotFile, _curTotFileArray[_backupedCount]); - strcpy(_curExtFile, _curTotFile); - _curExtFile[strlen(_curExtFile) - 4] = '\0'; - strcat(_curExtFile, ".EXT"); + clearUnusedEnvironment(); + + _numEnvironments--; + _curEnvironment = curBackupPos; + _environments->get(_numEnvironments); } int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, @@ -148,7 +130,7 @@ int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, ptr->funcEnter = funcEnter; ptr->funcLeave = funcLeave; ptr->funcSub = funcSub; - ptr->totFileData = _totFileData; + ptr->script = _script; return i; } @@ -383,7 +365,6 @@ void Game_v6::collisionsBlock(void) { int16 array[300]; byte count; int16 collResId; - byte *startIP; int16 curCmd; int16 cmd; int16 cmdHigh; @@ -397,7 +378,6 @@ void Game_v6::collisionsBlock(void) { int16 stackPos2; int16 descIndex; int16 timeVal; - int16 offsetIP; char *str; int16 i; int16 counter; @@ -406,10 +386,11 @@ void Game_v6::collisionsBlock(void) { int16 collStackPos; Collision *collPtr; Collision *collArea; - byte *savedIP; byte collAreaStart; int16 activeCollResId = 0; int16 activeCollIndex = 0; + uint32 startPos; + uint32 offsetPos; if (_shouldPushColls) pushCollisions(0); @@ -422,25 +403,25 @@ void Game_v6::collisionsBlock(void) { _shouldPushColls = 0; collResId = -1; - _vm->_global->_inter_execPtr++; - count = *_vm->_global->_inter_execPtr++; + _script->skip(1); + count = _script->readByte(); - _handleMouse = _vm->_global->_inter_execPtr[0]; - deltaTime = 1000 * _vm->_global->_inter_execPtr[1]; - stackPos2 = _vm->_global->_inter_execPtr[3]; - descIndex = _vm->_global->_inter_execPtr[4]; - byte var_42 = _vm->_global->_inter_execPtr[5]; + _handleMouse = _script->peekByte(0); + deltaTime = 1000 * _script->peekByte(1); + stackPos2 = _script->peekByte(3); + descIndex = _script->peekByte(4); + byte var_42 = _script->peekByte(5); if ((stackPos2 != 0) || (descIndex != 0)) { deltaTime /= 100; - if (_vm->_global->_inter_execPtr[1] == 100) + if (_script->peekByte(1) == 100) deltaTime = 2; } timeVal = deltaTime; - _vm->_global->_inter_execPtr += 6; + _script->skip(6); - startIP = _vm->_global->_inter_execPtr; + startPos = _script->pos(); WRITE_VAR(16, 0); byte var_41 = 0; @@ -452,28 +433,27 @@ void Game_v6::collisionsBlock(void) { for (curCmd = 0; curCmd < count; curCmd++) { array[curCmd] = 0; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _script->readByte(); if ((cmd & 0x40) != 0) { cmd -= 0x40; - cmdHigh = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr++; + cmdHigh = _script->readByte(); cmdHigh <<= 8; } else cmdHigh = 0; if ((cmd & 0x80) != 0) { - offsetIP = _vm->_global->_inter_execPtr - _totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + offsetPos = _script->pos(); + left = _script->readValExpr(); + top = _script->readValExpr(); + width = _script->readValExpr(); + height = _script->readValExpr(); } else { - offsetIP = 0; - left = _vm->_inter->load16(); - top = _vm->_inter->load16(); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); + offsetPos = 0; + left = _script->readUint16(); + top = _script->readUint16(); + width = _script->readUint16(); + height = _script->readUint16(); } if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { @@ -496,45 +476,37 @@ void Game_v6::collisionsBlock(void) { switch (cmd) { case 0: - _vm->_global->_inter_execPtr += 6; - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(6); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 1: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); - startIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + startPos = _script->pos(); + _script->skip(_script->peekUint16(2) + 2); if (key == 0) key = curCmd + 0xA000; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startIP - _totFileData, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + (flags << 4) + cmd + cmdHigh, key, startPos, + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; @@ -548,23 +520,20 @@ void Game_v6::collisionsBlock(void) { case 10: _vm->_util->clearKeyBuf(); var_1C = 1; - key = _vm->_parse->parseVarIndex(); - descArray[index].fontIndex = _vm->_inter->load16(); - descArray[index].backColor = *_vm->_global->_inter_execPtr++; - descArray[index].frontColor = *_vm->_global->_inter_execPtr++; + key = _script->readVarIndex(); + descArray[index].fontIndex = _script->readInt16(); + descArray[index].backColor = _script->readByte(); + descArray[index].frontColor = _script->readByte(); if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _vm->_global->_inter_execPtr + 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr) + 2; + descArray[index].ptr = _script->getData() + _script->pos() + 2; + _script->skip(_script->peekUint16() + 2); } else descArray[index].ptr = 0; if (left == 0xFFFF) { if ((cmd & 1) == 0) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } break; } @@ -575,50 +544,44 @@ void Game_v6::collisionsBlock(void) { funcLeave = 0; if (!(cmd & 1)) - funcLeave = _vm->_global->_inter_execPtr - _totFileData; + funcLeave = _script->pos(); addNewCollision(curCmd + 0x8000, left, top, right, top + height - 1, cmd, key, 0, funcLeave, 0); if (!(cmd & 1)) { - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); } index++; break; case 11: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xE000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 12: - _vm->_global->_inter_execPtr += 6; + _script->skip(6); for (i = 0; i < 150; i++) { if ((_collisionAreas[i].id & 0xF000) == 0xD000) { _collisionAreas[i].id &= 0xBFFF; _collisionAreas[i].funcEnter = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); _collisionAreas[i].funcLeave = - _vm->_global->_inter_execPtr - _totFileData; + _script->pos(); } } - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 20: @@ -626,34 +589,30 @@ void Game_v6::collisionsBlock(void) { // Fall through to case 2 case 2: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16(); + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16(); addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, 0, - _vm->_global->_inter_execPtr - _totFileData, offsetIP); + _script->pos(), offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; case 21: - key = _vm->_inter->load16(); - array[curCmd] = _vm->_inter->load16(); - flags = _vm->_inter->load16() & 3; + key = _script->readInt16(); + array[curCmd] = _script->readInt16(); + flags = _script->readInt16() & 3; addNewCollision(curCmd + 0x8000, left, top, left + width - 1, top + height - 1, (flags << 4) + cmdHigh + 2, key, - _vm->_global->_inter_execPtr - _totFileData, 0, offsetIP); + _script->pos(), 0, offsetPos); - _vm->_global->_inter_execPtr += 2; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _script->skip(_script->peekUint16(2) + 2); break; } @@ -915,10 +874,8 @@ void Game_v6::collisionsBlock(void) { if (_handleMouse == 1) _vm->_draw->blitCursor(); - savedIP = 0; if (!_vm->_inter->_terminate && (var_41 == 0)) { - savedIP = _totFileData + - _collisionAreas[activeCollIndex].funcLeave; + _script->seek(_collisionAreas[activeCollIndex].funcLeave); _vm->_inter->storeMouse(); if (VAR(16) == 0) { @@ -927,7 +884,8 @@ void Game_v6::collisionsBlock(void) { else WRITE_VAR(16, activeCollResId & 0xFFF); } - } + } else + _script->setFinished(true); for (curCmd = 0; curCmd < count; curCmd++) freeCollision(curCmd + 0x8000); @@ -937,8 +895,6 @@ void Game_v6::collisionsBlock(void) { ((_collisionAreas[i].id & 0xF000) == 0x9000)) _collisionAreas[i].id |= 0x4000; } - - _vm->_global->_inter_execPtr = savedIP; } void Game_v6::setCollisions(byte arg_0) { @@ -950,23 +906,22 @@ void Game_v6::setCollisions(byte arg_0) { if (collArea->flags & 0x80) continue; - byte *totFileData = collArea->totFileData; - - if (!totFileData) - totFileData = _totFileData; + Script *curScript = _script; - byte *savedIP = _vm->_global->_inter_execPtr; + _script = collArea->script; + if (!_script) + _script = curScript; - _vm->_global->_inter_execPtr = totFileData + collArea->funcSub; + _script->call(collArea->funcSub); - int16 left = _vm->_parse->parseValExpr(); - int16 top = _vm->_parse->parseValExpr(); - int16 width = _vm->_parse->parseValExpr(); - int16 height = _vm->_parse->parseValExpr(); + int16 left = _script->readValExpr(); + int16 top = _script->readValExpr(); + int16 width = _script->readValExpr(); + int16 height = _script->readValExpr(); uint16 flags = 0; if ((collArea->id & 0xF000) == 0xA000) - flags = _vm->_parse->parseValExpr(); + flags = _script->readValExpr(); if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != -1)) { @@ -1001,16 +956,18 @@ void Game_v6::setCollisions(byte arg_0) { if ((collArea->id & 0xF000) == 0xA000) collArea->flags = flags; - _vm->_global->_inter_execPtr = savedIP; + _script->pop(); + + _script = curScript; } } void Game_v6::collSub(uint16 offset) { - byte *savedIP; int16 collStackSize; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _totFileData + offset; + uint32 savedPos = _script->pos(); + + _script->seek(offset); _shouldPushColls = 1; collStackSize = _collStackSize; @@ -1021,7 +978,8 @@ void Game_v6::collSub(uint16 offset) { popCollisions(); _shouldPushColls = 0; - _vm->_global->_inter_execPtr = savedIP; + + _script->seek(savedPos); if ((_vm->_util->getTimeKey() - _someTimeDly) > 500) setCollisions(0); diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index 8283552f2c..4165938966 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -37,35 +37,36 @@ Global::Global(GobEngine *vm) : _vm(vm) { _presentVGA = UNDEF; _presentHER = UNDEF; - _videoMode = 0; + _videoMode = 0; _fakeVideoMode = 0; - _oldMode = 3; + _oldMode = 3; _soundFlags = 0; - _language = 0x8000; + _language = 0x8000; _languageWanted = 0x8000; + _foundLanguage = false; - _useMouse = UNDEF; + _useMouse = UNDEF; _mousePresent = UNDEF; - _mouseXShift = 3; - _mouseYShift = 3; + _mouseXShift = 3; + _mouseYShift = 3; - _mouseMinX = 0; - _mouseMinY = 0; + _mouseMinX = 0; + _mouseMinY = 0; _mouseMaxX = 320; _mouseMaxY = 200; _useJoystick = 1; - _primaryWidth = 0; + _primaryWidth = 0; _primaryHeight = 0; _colorCount = 16; for (int i = 0; i < 256; i++) { - _redPalette[i] = 0; + _redPalette [i] = 0; _greenPalette[i] = 0; - _bluePalette[i] = 0; + _bluePalette [i] = 0; } _unusedPalette1[ 0] = (int16) 0x0000; @@ -109,17 +110,12 @@ Global::Global(GobEngine *vm) : _vm(vm) { _pPaletteDesc = 0; - _setAllPalette = false; + _setAllPalette = false; _dontSetPalette = false; - _primarySurfDesc = 0; - _debugFlag = 0; _inVM = 0; - _inter_resStr[0] = 0; - _inter_resVal = 0; - _inter_execPtr = 0; _inter_animDataSize = 10; diff --git a/engines/gob/global.h b/engines/gob/global.h index 5c63f2b68a..982ce113cb 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -33,37 +33,51 @@ namespace Gob { -#define VIDMODE_CGA 0x05 -#define VIDMODE_EGA 0x0D -#define VIDMODE_VGA 0x13 -#define VIDMODE_HER 7 - -#define PROAUDIO_FLAG 0x10 -#define ADLIB_FLAG 0x08 -#define BLASTER_FLAG 0x04 -#define INTERSOUND_FLAG 0x02 -#define SPEAKER_FLAG 0x01 -#define MIDI_FLAG 0x4000 - -#define NO 0 -#define YES 1 -#define UNDEF 2 - -#define F1_KEY 0x3B00 -#define F2_KEY 0x3C00 -#define F3_KEY 0x3D00 -#define F4_KEY 0x3E00 -#define F5_KEY 0x3F00 -#define F6_KEY 0x4000 -#define ESCAPE 0x001B -#define ENTER 0x000D +#define VIDMODE_CGA 0x05 +#define VIDMODE_EGA 0x0D +#define VIDMODE_VGA 0x13 +#define VIDMODE_HER 0x07 + +#define MIDI_FLAG 0x4000 +#define PROAUDIO_FLAG 0x0010 +#define ADLIB_FLAG 0x0008 +#define BLASTER_FLAG 0x0004 +#define INTERSOUND_FLAG 0x0002 +#define SPEAKER_FLAG 0x0001 + +#define NO 0 +#define YES 1 +#define UNDEF 2 + +#define F1_KEY 0x3B00 +#define F2_KEY 0x3C00 +#define F3_KEY 0x3D00 +#define F4_KEY 0x3E00 +#define F5_KEY 0x3F00 +#define F6_KEY 0x4000 +#define ESCAPE 0x001B +#define ENTER 0x000D /* Video drivers */ -#define UNK_DRIVER 0 -#define VGA_DRIVER 1 -#define EGA_DRIVER 2 -#define CGA_DRIVER 3 -#define HER_DRIVER 4 +#define UNK_DRIVER 0 +#define VGA_DRIVER 1 +#define EGA_DRIVER 2 +#define CGA_DRIVER 3 +#define HER_DRIVER 4 + +enum Language { + kLanguageFrench = 0, + kLanguageGerman = 1, + kLanguageBritish = 2, + kLanguageSpanish = 3, + kLanguageItalian = 4, + kLanguageAmerican = 5, + kLanguageDutch = 6, + kLanguageKorean = 7, + kLanguageHebrew = 8, + kLanguagePortuguese = 9, + kLanguageJapanese = 10 +}; class Global { public: @@ -82,6 +96,7 @@ public: uint16 _language; uint16 _languageWanted; + bool _foundLanguage; char _useMouse; int16 _mousePresent; @@ -112,14 +127,11 @@ public: bool _setAllPalette; bool _dontSetPalette; - SurfaceDesc::Ptr _primarySurfDesc; + SurfaceDescPtr _primarySurfDesc; int16 _debugFlag; int16 _inVM; - char _inter_resStr[200]; - int32 _inter_resVal; - byte *_inter_execPtr; int16 _inter_animDataSize; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 436a1bf1f3..e534464cce 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -31,6 +31,9 @@ #include "common/md5.h" #include "sound/mididrv.h" +#include "gui/GuiManager.h" +#include "gui/widget.h" + #include "gob/gob.h" #include "gob/global.h" #include "gob/util.h" @@ -44,7 +47,6 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/videoplayer.h" #include "gob/save/saveload.h" @@ -67,13 +69,44 @@ const Common::Language GobEngine::_gobToScummVMLang[] = { Common::JA_JPN }; + +PauseDialog::PauseDialog() : GUI::Dialog("PauseDialog") { + _backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial; + + _message = "Game paused. Press Ctrl+p again to continue."; + _text = new GUI::StaticTextWidget(this, 4, 0, 10, 10, + _message, Graphics::kTextAlignCenter); +} + +void PauseDialog::reflowLayout() { + const int screenW = g_system->getOverlayWidth(); + const int screenH = g_system->getOverlayHeight(); + + int width = g_gui.getStringWidth(_message) + 16; + int height = g_gui.getFontHeight() + 8; + + _w = width; + _h = height; + _x = (screenW - width) / 2; + _y = (screenH - height) / 2; + + _text->setSize(_w - 8, _h); +} + +void PauseDialog::handleKeyDown(Common::KeyState state) { + // Close on CTRL+p + if ((state.flags == Common::KBD_CTRL) && (state.keycode == Common::KEYCODE_p)) + close(); +} + + GobEngine::GobEngine(OSystem *syst) : Engine(syst) { - _sound = 0; _mult = 0; _game = 0; - _global = 0; _dataIO = 0; _goblin = 0; - _vidPlayer = 0; _init = 0; _inter = 0; - _map = 0; _palAnim = 0; _parse = 0; - _scenery = 0; _draw = 0; _util = 0; - _video = 0; _saveLoad = 0; + _sound = 0; _mult = 0; _game = 0; + _global = 0; _dataIO = 0; _goblin = 0; + _vidPlayer = 0; _init = 0; _inter = 0; + _map = 0; _palAnim = 0; _scenery = 0; + _draw = 0; _util = 0; _video = 0; + _saveLoad = 0; _pauseStart = 0; @@ -87,7 +120,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { Common::addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); Common::addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); Common::addDebugChannel(kDebugSound, "Sound", "Sound output debug level"); - Common::addDebugChannel(kDebugParser, "Parser", "Parser debug level"); + Common::addDebugChannel(kDebugExpression, "Expression", "Expression parser debug level"); Common::addDebugChannel(kDebugGameFlow, "Gameflow", "Gameflow debug level"); Common::addDebugChannel(kDebugFileIO, "FileIO", "File Input/Output debug level"); Common::addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); @@ -214,42 +247,42 @@ Common::Error GobEngine::run() { switch (_language) { case Common::FR_FRA: case Common::RU_RUS: - _global->_language = 0; + _global->_language = kLanguageFrench; break; case Common::DE_DEU: - _global->_language = 1; + _global->_language = kLanguageGerman; break; case Common::EN_ANY: case Common::EN_GRB: - _global->_language = 2; + case Common::HU_HUN: + _global->_language = kLanguageBritish; break; case Common::ES_ESP: - _global->_language = 3; + _global->_language = kLanguageSpanish; break; case Common::IT_ITA: - _global->_language = 4; + _global->_language = kLanguageItalian; break; case Common::EN_USA: - _global->_language = 5; + _global->_language = kLanguageAmerican; break; case Common::NL_NLD: - _global->_language = 6; + _global->_language = kLanguageDutch; break; case Common::KO_KOR: - _global->_language = 7; + _global->_language = kLanguageKorean; break; case Common::HB_ISR: - _global->_language = 8; + _global->_language = kLanguageHebrew; break; case Common::PT_BRA: - _global->_language = 9; + _global->_language = kLanguagePortuguese; break; case Common::JA_JPN: - _global->_language = 10; + _global->_language = kLanguageJapanese; break; default: - // Default to English - _global->_language = 2; + _global->_language = kLanguageBritish; break; } _global->_languageWanted = _global->_language; @@ -277,6 +310,16 @@ void GobEngine::pauseEngineIntern(bool pause) { _mixer->pauseAll(pause); } +void GobEngine::pauseGame() { + pauseEngineIntern(true); + + PauseDialog pauseDialog; + + pauseDialog.runModal(); + + pauseEngineIntern(false); +} + bool GobEngine::initGameParts() { _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; @@ -296,7 +339,6 @@ bool GobEngine::initGameParts() { _init = new Init_v1(this); _video = new Video_v1(this); _inter = new Inter_v1(this); - _parse = new Parse_v1(this); _mult = new Mult_v1(this); _draw = new Draw_v1(this); _game = new Game_v1(this); @@ -309,7 +351,6 @@ bool GobEngine::initGameParts() { _init = new Init_v2(this); _video = new Video_v2(this); _inter = new Inter_Fascination(this); - _parse = new Parse_v1(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_Fascination(this); @@ -324,7 +365,6 @@ bool GobEngine::initGameParts() { _init = new Init_v2(this); _video = new Video_v2(this); _inter = new Inter_v2(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v2(this); @@ -338,7 +378,6 @@ bool GobEngine::initGameParts() { _init = new Init_v2(this); _video = new Video_v2(this); _inter = new Inter_Bargon(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_Bargon(this); _game = new Game_v2(this); @@ -353,7 +392,6 @@ bool GobEngine::initGameParts() { _init = new Init_v3(this); _video = new Video_v2(this); _inter = new Inter_v3(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v2(this); @@ -367,7 +405,6 @@ bool GobEngine::initGameParts() { _init = new Init_v3(this); _video = new Video_v2(this); _inter = new Inter_v3(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v2(this); @@ -381,7 +418,6 @@ bool GobEngine::initGameParts() { _init = new Init_v3(this); _video = new Video_v2(this); _inter = new Inter_v4(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v2(this); @@ -398,7 +434,6 @@ bool GobEngine::initGameParts() { _init = new Init_v3(this); _video = new Video_v2(this); _inter = new Inter_v5(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v2(this); @@ -413,7 +448,6 @@ bool GobEngine::initGameParts() { _init = new Init_v3(this); _video = new Video_v6(this); _inter = new Inter_v6(this); - _parse = new Parse_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); _game = new Game_v6(this); @@ -429,20 +463,22 @@ bool GobEngine::initGameParts() { break; } + _inter->setupOpcodes(); + if (is640()) { _video->_surfWidth = _width = 640; _video->_surfHeight = _video->_splitHeight1 = _height = 480; _global->_mouseMaxX = 640; _global->_mouseMaxY = 480; _mode = 0x18; - _global->_primarySurfDesc = new SurfaceDesc(0x18, 640, 480); + _global->_primarySurfDesc = SurfaceDescPtr(new SurfaceDesc(0x18, 640, 480)); } else { _video->_surfWidth = _width = 320; _video->_surfHeight = _video->_splitHeight1 = _height = 200; _global->_mouseMaxX = 320; _global->_mouseMaxY = 200; _mode = 0x14; - _global->_primarySurfDesc = new SurfaceDesc(0x14, 320, 200); + _global->_primarySurfDesc = SurfaceDescPtr(new SurfaceDesc(0x14, 320, 200)); } return true; @@ -459,7 +495,6 @@ void GobEngine::deinitGameParts() { delete _inter; _inter = 0; delete _map; _map = 0; delete _palAnim; _palAnim = 0; - delete _parse; _parse = 0; delete _scenery; _scenery = 0; delete _draw; _draw = 0; delete _util; _util = 0; diff --git a/engines/gob/gob.h b/engines/gob/gob.h index 65d6ffeced..5d1cb3ecf2 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -29,8 +29,14 @@ #include "common/system.h" #include "common/savefile.h" +#include "gui/dialog.h" + #include "engines/engine.h" +namespace GUI { + class StaticTextWidget; +} + namespace Gob { class Game; @@ -46,7 +52,6 @@ class Inter; class Map; class Mult; class PalAnim; -class Parse; class Scenery; class Util; class SaveLoad; @@ -122,7 +127,7 @@ enum { kDebugDrawOp = 1 << 1, kDebugGobOp = 1 << 2, kDebugSound = 1 << 3, - kDebugParser = 1 << 4, + kDebugExpression = 1 << 4, kDebugGameFlow = 1 << 5, kDebugFileIO = 1 << 6, kDebugSaveLoad = 1 << 7, @@ -134,6 +139,18 @@ enum { struct GOBGameDescription; +class PauseDialog : public GUI::Dialog { +public: + PauseDialog(); + + virtual void reflowLayout(); + virtual void handleKeyDown(Common::KeyState state); + +private: + Common::String _message; + GUI::StaticTextWidget *_text; +}; + class GobEngine : public Engine { private: GameType _gameType; @@ -179,7 +196,6 @@ public: Map *_map; Mult *_mult; PalAnim *_palAnim; - Parse *_parse; Scenery *_scenery; Inter *_inter; SaveLoad *_saveLoad; @@ -189,6 +205,8 @@ public: void validateLanguage(); void validateVideoMode(int16 videoMode); + void pauseGame(); + Endianness getEndianness() const; Common::Platform getPlatform() const; GameType getGameType() const; diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index 90303e46a7..45fb643166 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -233,7 +233,7 @@ void Goblin::drawObjects(void) { if (objDesc->toRedraw == 0) continue; - _vm->_video->drawSprite(_vm->_mult->_animSurf, _vm->_draw->_backSurface, + _vm->_video->drawSprite(*_vm->_mult->_animSurf, *_vm->_draw->_backSurface, objDesc->left, objDesc->top, objDesc->right, objDesc->bottom, objDesc->left, objDesc->top, 0); diff --git a/engines/gob/helper.h b/engines/gob/helper.h index fbb5ae7ec8..d1f24792a5 100644 --- a/engines/gob/helper.h +++ b/engines/gob/helper.h @@ -35,58 +35,6 @@ inline char *strncpy0(char *dest, const char *src, size_t n) { return dest; } -/** A "smart" reference counting templated class. */ -template<typename T> -class ReferenceCounter { -public: - class Ptr { - public: - bool operator==(const Ptr &p) const { return _p == p._p; } - bool operator==(const ReferenceCounter *p) const { return _p == p; } - - T *operator-> () { return _p; } - T &operator* () { return *_p; } - operator T*() { return _p; } - - Ptr(T *p) : _p(p) { ++_p->_references; } - Ptr() : _p(0) { } - - ~Ptr() { - if (_p && (--_p->_references == 0)) - delete _p; - } - - Ptr(const Ptr &p) : _p(p._p) { ++_p->_references; } - - Ptr &operator= (const Ptr &p) { - ++p._p->_references; - if (_p && (--_p->_references == 0)) - delete _p; - _p = p._p; - return *this; - } - Ptr *operator= (const Ptr *p) { - if (p) - ++p->_p->_references; - if (_p && (--_p->_references == 0)) - delete _p; - - _p = p ? p->_p : 0; - return this; - } - - private: - T *_p; - }; - - ReferenceCounter() : _references(0) { } - virtual ~ReferenceCounter() {} - -private: - unsigned _references; - friend class Ptr; -}; - } // End of namespace Gob #endif // GOB_HELPER_H diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index be14b71661..f9a22f52fb 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -32,6 +32,7 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/inter.h" #include "gob/video.h" @@ -50,7 +51,7 @@ Init::Init(GobEngine *vm) : _vm(vm) { void Init::cleanup() { _vm->_video->freeDriver(); - _vm->_global->_primarySurfDesc = 0; + _vm->_global->_primarySurfDesc.reset(); _vm->_sound->speakerOff(); _vm->_sound->blasterStop(0); @@ -80,9 +81,6 @@ void Init::doDemo() { } void Init::initGame() { - int16 handle2; - int16 handle; - int16 imdHandle; byte *infBuf; char *infPtr; char *infEnd; @@ -91,11 +89,8 @@ void Init::initGame() { initVideo(); if (!_vm->isDemo()) { - handle2 = _vm->_dataIO->openData(_vm->_startStk.c_str()); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + if (_vm->_dataIO->existData(_vm->_startStk.c_str())) _vm->_dataIO->openDataFile(_vm->_startStk.c_str()); - } } _vm->_util->initInput(); @@ -104,8 +99,6 @@ void Init::initGame() { _vm->_global->_mouseXShift = 1; _vm->_global->_mouseYShift = 1; - _vm->_game->_totTextData = 0; - _vm->_game->_totFileData = 0; _palDesc = new Video::PalDesc; _vm->validateVideoMode(_vm->_global->_videoMode); @@ -127,19 +120,13 @@ void Init::initGame() { return; } - handle = _vm->_dataIO->openData("intro.inf"); + if (!_vm->_dataIO->existData("intro.inf")) { - if (handle < 0) { - for (int i = 0; i < 4; i++) { - handle2 = _vm->_dataIO->openData(_fontNames[i]); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + for (int i = 0; i < 4; i++) + if (_vm->_dataIO->existData(_fontNames[i])) _vm->_draw->_fonts[i] = _vm->_util->loadFont(_fontNames[i]); - } - } - } else { - _vm->_dataIO->closeData(handle); + } else { infBuf = _vm->_dataIO->getData("intro.inf"); infPtr = (char *) infBuf; @@ -153,11 +140,8 @@ void Init::initGame() { buffer[j] = 0; strcat(buffer, ".let"); - handle2 = _vm->_dataIO->openData(buffer); - if (handle2 >= 0) { - _vm->_dataIO->closeData(handle2); + if (_vm->_dataIO->existData(buffer)) _vm->_draw->_fonts[i] = _vm->_util->loadFont(buffer); - } if ((infPtr + 1) >= infEnd) break; @@ -167,26 +151,16 @@ void Init::initGame() { delete[] infBuf; } - strcpy(buffer, _vm->_startTot.c_str()); - handle = _vm->_dataIO->openData(buffer); + if (_vm->_dataIO->existData(_vm->_startTot.c_str())) { + _vm->_inter->allocateVars(Script::getVariablesCount(_vm->_startTot.c_str(), _vm)); - if (handle >= 0) { - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); - - stream->seek(0x2C); - _vm->_inter->allocateVars(stream->readUint16LE()); - - delete stream; - - strcpy(_vm->_game->_curTotFile, buffer); + strcpy(_vm->_game->_curTotFile, _vm->_startTot.c_str()); _vm->_sound->cdTest(1, "GOB"); _vm->_sound->cdLoadLIC("gob.lic"); // Search for a Coktel logo animation or image to display - imdHandle = _vm->_dataIO->openData("coktel.imd"); - if (imdHandle >= 0) { - _vm->_dataIO->closeData(imdHandle); + if (_vm->_dataIO->existData("coktel.imd")) { _vm->_draw->initScreen(); _vm->_draw->_cursorIndex = -1; @@ -198,22 +172,20 @@ void Init::initGame() { } _vm->_draw->closeScreen(); - } else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) { + } else if (_vm->_dataIO->existData("coktel.clt")) { _vm->_draw->initScreen(); - - stream = _vm->_dataIO->openAsStream(imdHandle, true); _vm->_util->clearPalette(); + + DataStream *stream = _vm->_dataIO->getDataStream("coktel.clt"); stream->read((byte *) _vm->_draw->_vgaPalette, 768); delete stream; - imdHandle = _vm->_dataIO->openData("coktel.ims"); - if (imdHandle >= 0) { + if (_vm->_dataIO->existData("coktel.ims")) { byte *sprBuf; - _vm->_dataIO->closeData(imdHandle); sprBuf = _vm->_dataIO->getData("coktel.ims"); _vm->_video->drawPackedSprite(sprBuf, 320, 200, 0, 0, 0, - _vm->_draw->_frontSurface); + *_vm->_draw->_frontSurface); _vm->_palAnim->fade(_palDesc, 0, 0); _vm->_util->delay(500); diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp index 9c52bd2eea..4c65b8102c 100644 --- a/engines/gob/init_v2.cpp +++ b/engines/gob/init_v2.cpp @@ -42,7 +42,7 @@ void Init_v2::initVideo() { _vm->_draw->_frontSurface = _vm->_global->_primarySurfDesc; _vm->_video->initSurfDesc(_vm->_global->_videoMode, - _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0x80); + _vm->_video->_surfWidth, _vm->_video->_surfHeight, PRIMARY_SURFACE); _vm->_global->_mousePresent = 1; diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index ce7f2ba319..8be07034c6 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -33,7 +33,8 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/expression.h" +#include "gob/script.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -67,65 +68,93 @@ Inter::~Inter() { delocateVars(); } -void Inter::initControlVars(char full) { - *_nestLevel = 0; - *_breakFromLevel = -1; +void Inter::setupOpcodes() { + setupOpcodesDraw(); + setupOpcodesFunc(); + setupOpcodesGob(); +} - *_vm->_scenery->_pCaptureCounter = 0; +void Inter::executeOpcodeDraw(byte i) { + debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", i, i, getDescOpcodeDraw(i)); - _break = false; - _terminate = 0; + if (_opcodesDraw[i].proc && _opcodesDraw[i].proc->isValid()) + (*_opcodesDraw[i].proc)(); + else + warning("unimplemented opcodeDraw: %d [0x%X]", i, i); +} - if (full == 1) { - for (int i = 0; i < 8; i++) - _animPalDir[i] = 0; - _soundEndTimeKey = 0; +bool Inter::executeOpcodeFunc(byte i, byte j, OpFuncParams ¶ms) { + debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", + i, j, i, j, getDescOpcodeFunc(i, j)); + + if ((i > 4) || (j > 15)) { + warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j); + return false; } + + i = i * 16 + j; + if (_opcodesFunc[i].proc && _opcodesFunc[i].proc->isValid()) + return (*_opcodesFunc[i].proc)(params); + else + warning("unimplemented opcodeFunc: %d.%d [0x%X.0x%X]", i, j, i, j); + + return false; } -int16 Inter::load16() { - int16 tmp = (int16) READ_LE_UINT16(_vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 2; - return tmp; +void Inter::executeOpcodeGob(int i, OpGobParams ¶ms) { + debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", + i, i, getDescOpcodeGob(i)); + + OpcodeEntry<OpcodeGob> *op = 0; + + if (_opcodesGob.contains(i)) + op = &_opcodesGob.getVal(i); + + if (op && op->proc && op->proc->isValid()) { + (*op->proc)(params); + return; + } + + _vm->_game->_script->skip(params.paramCount << 1); + warning("unimplemented opcodeGob: %d [0x%X]", i, i); } -char Inter::evalExpr(int16 *pRes) { - byte token; +const char *Inter::getDescOpcodeDraw(byte i) { + const char *desc = _opcodesDraw[i].desc; - _vm->_parse->printExpr(99); + return ((desc) ? desc : ""); +} - _vm->_parse->parseExpr(99, &token); - if (!pRes) - return token; +const char *Inter::getDescOpcodeFunc(byte i, byte j) { + if ((i > 4) || (j > 15)) + return ""; - switch (token) { - case 20: - *pRes = _vm->_global->_inter_resVal; - break; + const char *desc = _opcodesFunc[i * 16 + j].desc; - case 22: - case 23: - *pRes = 0; - break; + return ((desc) ? desc : ""); +} - case 24: - *pRes = 1; - break; - } +const char *Inter::getDescOpcodeGob(int i) { + if (_opcodesGob.contains(i)) + return _opcodesGob.getVal(i).desc; - return token; + return ""; } -bool Inter::evalBoolResult() { - byte token; +void Inter::initControlVars(char full) { + *_nestLevel = 0; + *_breakFromLevel = -1; + + *_vm->_scenery->_pCaptureCounter = 0; - _vm->_parse->printExpr(99); + _break = false; + _terminate = 0; - _vm->_parse->parseExpr(99, &token); - if ((token == 24) || ((token == 20) && _vm->_global->_inter_resVal)) - return true; - else - return false; + if (full == 1) { + for (int i = 0; i < 8; i++) + _animPalDir[i] = 0; + _soundEndTimeKey = 0; + } } void Inter::renewTimeInVars() { @@ -185,14 +214,14 @@ void Inter::storeKey(int16 key) { void Inter::writeVar(uint32 offset, uint16 type, uint32 value) { switch (type) { - case 16: - case 18: + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: WRITE_VARO_UINT8(offset, value); break; - case 17: - case 24: - case 27: + case TYPE_VAR_INT16: + case TYPE_VAR_INT32_AS_INT16: + case TYPE_ARRAY_INT16: WRITE_VARO_UINT16(offset, value); break; @@ -209,20 +238,20 @@ void Inter::funcBlock(int16 retFlag) { params.retFlag = retFlag; - if (!_vm->_global->_inter_execPtr) + if (_vm->_game->_script->isFinished()) return; _break = false; - _vm->_global->_inter_execPtr++; - params.cmdCount = *_vm->_global->_inter_execPtr++; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(1); + params.cmdCount = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(2); if (params.cmdCount == 0) { - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return; } - int startaddr = _vm->_global->_inter_execPtr - _vm->_game->_totFileData; + int startaddr = _vm->_game->_script->pos(); params.counter = 0; do { @@ -237,7 +266,7 @@ void Inter::funcBlock(int16 retFlag) { (_vm->getPlatform() == Common::kPlatformMacintosh) || (_vm->getPlatform() == Common::kPlatformWindows))) { - int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData; + int addr = _vm->_game->_script->pos(); if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || @@ -263,20 +292,19 @@ void Inter::funcBlock(int16 retFlag) { } // End of workaround - cmd = *_vm->_global->_inter_execPtr; + cmd = _vm->_game->_script->readByte(); if ((cmd >> 4) >= 12) { cmd2 = 16 - (cmd >> 4); cmd &= 0xF; } else cmd2 = 0; - _vm->_global->_inter_execPtr++; params.counter++; if (cmd2 == 0) cmd >>= 4; - if (executeFuncOpcode(cmd2, cmd, params)) + if (executeOpcodeFunc(cmd2, cmd, params)) return; if (_vm->shouldQuit()) @@ -292,17 +320,17 @@ void Inter::funcBlock(int16 retFlag) { } } while (params.counter != params.cmdCount); - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return; } void Inter::callSub(int16 retFlag) { byte block; - while (!_vm->shouldQuit() && _vm->_global->_inter_execPtr && - (_vm->_global->_inter_execPtr != _vm->_game->_totFileData)) { + while (!_vm->shouldQuit() && !_vm->_game->_script->isFinished() && + (_vm->_game->_script->pos() != 0)) { - block = *_vm->_global->_inter_execPtr; + block = _vm->_game->_script->peekByte(); if (block == 1) funcBlock(retFlag); else if (block == 2) @@ -311,7 +339,7 @@ void Inter::callSub(int16 retFlag) { error("Unknown block type %d in Inter::callSub()", block); } - if (_vm->_global->_inter_execPtr == _vm->_game->_totFileData) + if (!_vm->_game->_script->isFinished() && (_vm->_game->_script->pos() == 0)) _terminate = 1; } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index ee49658318..d4ed2d3240 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -26,6 +26,9 @@ #ifndef GOB_INTER_H #define GOB_INTER_H +#include "common/func.h" +#include "common/hashmap.h" + #include "gob/goblin.h" #include "gob/variables.h" @@ -34,11 +37,54 @@ namespace Gob { // This is to help devices with small memory (PDA, smartphones, ...) // to save abit of memory used by opcode names in the Scumm engine. #ifndef REDUCE_MEMORY_USAGE -# define _OPCODE(ver, x) { &ver::x, #x } + #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), #x) + #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), #x) + #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), #x) #else -# define _OPCODE(ver, x) { &ver::x, "" } + #define _OPCODEDRAW(ver, x) setProc(new Common::Functor0Mem<void, ver>(this, &ver::x), "") + #define _OPCODEFUNC(ver, x) setProc(new Common::Functor1Mem<OpFuncParams &, bool, ver>(this, &ver::x), "") + #define _OPCODEGOB(ver, x) setProc(new Common::Functor1Mem<OpGobParams &, void, ver>(this, &ver::x), "") #endif +#define CLEAROPCODEDRAW(i) _opcodesDraw[i].setProc(0, 0) +#define CLEAROPCODEFUNC(i) _opcodesFunc[i].setProc(0, 0) +#define CLEAROPCODEGOB(i) _opcodesGob.erase(i) + +typedef Common::Functor0<void> OpcodeDraw; +typedef Common::Functor1<struct OpFuncParams &, bool> OpcodeFunc; +typedef Common::Functor1<struct OpGobParams &, void> OpcodeGob; + +struct OpFuncParams { + byte cmdCount; + byte counter; + int16 retFlag; +}; +struct OpGobParams { + int16 extraData; + int16 paramCount; + VariableReference retVarPtr; + Goblin::Gob_Object *objDesc; +}; + +template<typename T> +struct OpcodeEntry : Common::NonCopyable { + T *proc; + const char *desc; + + OpcodeEntry() : proc(0), desc(0) {} + ~OpcodeEntry() { + setProc(0, 0); + } + + void setProc(T *p, const char *d) { + if (proc != p) { + delete proc; + proc = p; + } + desc = d; + } +}; + class Inter { public: uint8 _terminate; @@ -51,10 +97,9 @@ public: Variables *_variables; + void setupOpcodes(); + void initControlVars(char full); - int16 load16(); - char evalExpr(int16 *pRes); - bool evalBoolResult(); void renewTimeInVars(); void storeMouse(); void storeKey(int16 key); @@ -74,16 +119,9 @@ public: virtual ~Inter(); protected: - struct OpFuncParams { - byte cmdCount; - byte counter; - int16 retFlag; - }; - struct OpGobParams { - int16 extraData; - VariableReference retVarPtr; - Goblin::Gob_Object *objDesc; - }; + OpcodeEntry<OpcodeDraw> _opcodesDraw[256]; + OpcodeEntry<OpcodeFunc> _opcodesFunc[256]; + Common::HashMap<int, OpcodeEntry<OpcodeGob> > _opcodesGob; bool _break; @@ -99,15 +137,19 @@ protected: GobEngine *_vm; - virtual void setupOpcodes() = 0; - virtual void executeDrawOpcode(byte i) = 0; - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) = 0; - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms) = 0; - virtual const char *getOpcodeDrawDesc(byte i) = 0; - virtual const char *getOpcodeFuncDesc(byte i, byte j) = 0; - virtual const char *getOpcodeGoblinDesc(int i) = 0; + void executeOpcodeDraw(byte i); + bool executeOpcodeFunc(byte i, byte j, OpFuncParams ¶ms); + void executeOpcodeGob(int i, OpGobParams ¶ms); + + const char *getDescOpcodeDraw(byte i); + const char *getDescOpcodeFunc(byte i, byte j); + const char *getDescOpcodeGob(int i); - virtual void checkSwitchTable(byte **ppExec) = 0; + virtual void setupOpcodesDraw() = 0; + virtual void setupOpcodesFunc() = 0; + virtual void setupOpcodesGob() = 0; + + virtual void checkSwitchTable(uint32 &offset) = 0; void o_drawNOP() {} bool o_funcNOP(OpFuncParams ¶ms) { return false; } @@ -123,35 +165,11 @@ public: virtual void animPalette(); protected: - typedef void (Inter_v1::*OpcodeDrawProcV1)(); - typedef bool (Inter_v1::*OpcodeFuncProcV1)(OpFuncParams &); - typedef void (Inter_v1::*OpcodeGoblinProcV1)(OpGobParams &); - struct OpcodeDrawEntryV1 { - OpcodeDrawProcV1 proc; - const char *desc; - }; - struct OpcodeFuncEntryV1 { - OpcodeFuncProcV1 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV1 { - OpcodeGoblinProcV1 proc; - const char *desc; - }; - const OpcodeDrawEntryV1 *_opcodesDrawV1; - const OpcodeFuncEntryV1 *_opcodesFuncV1; - const OpcodeGoblinEntryV1 *_opcodesGoblinV1; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - - virtual void checkSwitchTable(byte **ppExec); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + + virtual void checkSwitchTable(uint32 &offset); void o1_loadMult(); void o1_playMult(); @@ -185,7 +203,7 @@ protected: bool o1_repeatUntil(OpFuncParams ¶ms); bool o1_whileDo(OpFuncParams ¶ms); bool o1_if(OpFuncParams ¶ms); - bool o1_evaluateStore(OpFuncParams ¶ms); + bool o1_assign(OpFuncParams ¶ms); bool o1_loadSpriteToPos(OpFuncParams ¶ms); bool o1_printText(OpFuncParams ¶ms); bool o1_loadTot(OpFuncParams ¶ms); @@ -318,35 +336,11 @@ public: virtual void animPalette(); protected: - typedef void (Inter_v2::*OpcodeDrawProcV2)(); - typedef bool (Inter_v2::*OpcodeFuncProcV2)(OpFuncParams &); - typedef void (Inter_v2::*OpcodeGoblinProcV2)(OpGobParams &); - struct OpcodeDrawEntryV2 { - OpcodeDrawProcV2 proc; - const char *desc; - }; - struct OpcodeFuncEntryV2 { - OpcodeFuncProcV2 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV2 { - OpcodeGoblinProcV2 proc; - const char *desc; - }; - const OpcodeDrawEntryV2 *_opcodesDrawV2; - const OpcodeFuncEntryV2 *_opcodesFuncV2; - const OpcodeGoblinEntryV2 *_opcodesGoblinV2; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - - virtual void checkSwitchTable(byte **ppExec); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + + virtual void checkSwitchTable(uint32 &offset); void o2_playMult(); void o2_freeMultKeys(); @@ -383,7 +377,7 @@ protected: void o2_closeItk(); void o2_setImdFrontSurf(); void o2_resetImdFrontSurf(); - bool o2_evaluateStore(OpFuncParams ¶ms); + bool o2_assign(OpFuncParams ¶ms); bool o2_printText(OpFuncParams ¶ms); bool o2_animPalInit(OpFuncParams ¶ms); bool o2_addCollision(OpFuncParams ¶ms); @@ -410,33 +404,9 @@ public: virtual ~Inter_Bargon() {} protected: - typedef void (Inter_Bargon::*OpcodeDrawProcBargon)(); - typedef bool (Inter_Bargon::*OpcodeFuncProcBargon)(OpFuncParams &); - typedef void (Inter_Bargon::*OpcodeGoblinProcBargon)(OpGobParams &); - struct OpcodeDrawEntryBargon { - OpcodeDrawProcBargon proc; - const char *desc; - }; - struct OpcodeFuncEntryBargon { - OpcodeFuncProcBargon proc; - const char *desc; - }; - struct OpcodeGoblinEntryBargon { - OpcodeGoblinProcBargon proc; - const char *desc; - }; - const OpcodeDrawEntryBargon *_opcodesDrawBargon; - const OpcodeFuncEntryBargon *_opcodesFuncBargon; - const OpcodeGoblinEntryBargon *_opcodesGoblinBargon; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void oBargon_intro0(OpGobParams ¶ms); void oBargon_intro1(OpGobParams ¶ms); @@ -456,33 +426,9 @@ public: virtual ~Inter_Fascination() {} protected: - typedef void (Inter_Fascination::*OpcodeDrawProcFascination)(); - typedef bool (Inter_Fascination::*OpcodeFuncProcFascination)(OpFuncParams &); - typedef void (Inter_Fascination::*OpcodeGoblinProcFascination)(OpGobParams &); - struct OpcodeDrawEntryFascination { - OpcodeDrawProcFascination proc; - const char *desc; - }; - struct OpcodeFuncEntryFascination { - OpcodeFuncProcFascination proc; - const char *desc; - }; - struct OpcodeGoblinEntryFascination { - OpcodeGoblinProcFascination proc; - const char *desc; - }; - const OpcodeDrawEntryFascination *_opcodesDrawFascination; - const OpcodeFuncEntryFascination *_opcodesFuncFascination; - const OpcodeGoblinEntryFascination *_opcodesGoblinFascination; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void oFascin_playProtracker(OpGobParams ¶ms); @@ -517,39 +463,12 @@ public: virtual ~Inter_v3() {} protected: - typedef void (Inter_v3::*OpcodeDrawProcV3)(); - typedef bool (Inter_v3::*OpcodeFuncProcV3)(OpFuncParams &); - typedef void (Inter_v3::*OpcodeGoblinProcV3)(OpGobParams &); - struct OpcodeDrawEntryV3 { - OpcodeDrawProcV3 proc; - const char *desc; - }; - struct OpcodeFuncEntryV3 { - OpcodeFuncProcV3 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV3 { - OpcodeGoblinProcV3 proc; - const char *desc; - }; - const OpcodeDrawEntryV3 *_opcodesDrawV3; - const OpcodeFuncEntryV3 *_opcodesFuncV3; - const OpcodeGoblinEntryV3 *_opcodesGoblinV3; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); bool o3_getTotTextItemPart(OpFuncParams ¶ms); bool o3_copySprite(OpFuncParams ¶ms); - bool o3_checkData(OpFuncParams ¶ms); - bool o3_readData(OpFuncParams ¶ms); - bool o3_writeData(OpFuncParams ¶ms); void o3_wobble(OpGobParams ¶ms); }; @@ -560,33 +479,9 @@ public: virtual ~Inter_v4() {} protected: - typedef void (Inter_v4::*OpcodeDrawProcV4)(); - typedef bool (Inter_v4::*OpcodeFuncProcV4)(OpFuncParams &); - typedef void (Inter_v4::*OpcodeGoblinProcV4)(OpGobParams &); - struct OpcodeDrawEntryV4 { - OpcodeDrawProcV4 proc; - const char *desc; - }; - struct OpcodeFuncEntryV4 { - OpcodeFuncProcV4 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV4 { - OpcodeGoblinProcV4 proc; - const char *desc; - }; - const OpcodeDrawEntryV4 *_opcodesDrawV4; - const OpcodeFuncEntryV4 *_opcodesFuncV4; - const OpcodeGoblinEntryV4 *_opcodesGoblinV4; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void o4_initScreen(); void o4_playVmdOrMusic(); @@ -598,36 +493,12 @@ public: virtual ~Inter_v5() {} protected: - typedef void (Inter_v5::*OpcodeDrawProcV5)(); - typedef bool (Inter_v5::*OpcodeFuncProcV5)(OpFuncParams &); - typedef void (Inter_v5::*OpcodeGoblinProcV5)(OpGobParams &); - struct OpcodeDrawEntryV5 { - OpcodeDrawProcV5 proc; - const char *desc; - }; - struct OpcodeFuncEntryV5 { - OpcodeFuncProcV5 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV5 { - OpcodeGoblinProcV5 proc; - const char *desc; - }; - const OpcodeDrawEntryV5 *_opcodesDrawV5; - const OpcodeFuncEntryV5 *_opcodesFuncV5; - const OpcodeGoblinEntryV5 *_opcodesGoblinV5; - static const int _goblinFuncLookUp[][2]; - - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); - byte _gob_97_98_val; + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); + void o5_deleteFile(); void o5_initScreen(); @@ -657,42 +528,18 @@ public: virtual ~Inter_v6() {} protected: - typedef void (Inter_v6::*OpcodeDrawProcV6)(); - typedef bool (Inter_v6::*OpcodeFuncProcV6)(OpFuncParams &); - typedef void (Inter_v6::*OpcodeGoblinProcV6)(OpGobParams &); - struct OpcodeDrawEntryV6 { - OpcodeDrawProcV6 proc; - const char *desc; - }; - struct OpcodeFuncEntryV6 { - OpcodeFuncProcV6 proc; - const char *desc; - }; - struct OpcodeGoblinEntryV6 { - OpcodeGoblinProcV6 proc; - const char *desc; - }; - const OpcodeDrawEntryV6 *_opcodesDrawV6; - const OpcodeFuncEntryV6 *_opcodesFuncV6; - const OpcodeGoblinEntryV6 *_opcodesGoblinV6; - static const int _goblinFuncLookUp[][2]; - bool _gotFirstPalette; - virtual void setupOpcodes(); - virtual void executeDrawOpcode(byte i); - virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms); - virtual void executeGoblinOpcode(int i, OpGobParams ¶ms); - virtual const char *getOpcodeDrawDesc(byte i); - virtual const char *getOpcodeFuncDesc(byte i, byte j); - virtual const char *getOpcodeGoblinDesc(int i); + virtual void setupOpcodesDraw(); + virtual void setupOpcodesFunc(); + virtual void setupOpcodesGob(); void o6_totSub(); void o6_playVmdOrMusic(); void o6_openItk(); bool o6_loadCursor(OpFuncParams ¶ms); - bool o6_evaluateStore(OpFuncParams ¶ms); + bool o6_assign(OpFuncParams ¶ms); bool o6_palLoad(OpFuncParams ¶ms); bool o6_freeCollision(OpFuncParams ¶ms); bool o6_fillRect(OpFuncParams ¶ms); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index c729bf3c4c..12079600c0 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -39,680 +39,36 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_Bargon, x) - -const int Inter_Bargon::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {11, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_Bargon +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_Bargon::Inter_Bargon(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); } -void Inter_Bargon::setupOpcodes() { - static const OpcodeDrawEntryBargon opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o1_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryBargon opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryBargon opcodesGoblin[71] = { - /* 00 */ - OPCODE(oBargon_intro0), - OPCODE(oBargon_intro1), - OPCODE(oBargon_intro2), - OPCODE(oBargon_intro3), - /* 04 */ - OPCODE(oBargon_intro4), - OPCODE(oBargon_intro5), - OPCODE(oBargon_intro6), - OPCODE(oBargon_intro7), - /* 08 */ - OPCODE(oBargon_intro8), - OPCODE(oBargon_intro9), - OPCODE(o_gobNOP), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawBargon = opcodesDraw; - _opcodesFuncBargon = opcodesFunc; - _opcodesGoblinBargon = opcodesGoblin; +void Inter_Bargon::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); } -void Inter_Bargon::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcBargon op = _opcodesDrawBargon[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); +void Inter_Bargon::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); } -bool Inter_Bargon::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); +void Inter_Bargon::setupOpcodesGob() { + OPCODEGOB( 1, oBargon_intro0); + OPCODEGOB( 2, oBargon_intro1); + OPCODEGOB( 3, oBargon_intro2); + OPCODEGOB( 4, oBargon_intro3); - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } + OPCODEGOB( 5, oBargon_intro4); + OPCODEGOB( 6, oBargon_intro5); + OPCODEGOB( 7, oBargon_intro6); + OPCODEGOB( 8, oBargon_intro7); - OpcodeFuncProcBargon op = _opcodesFuncBargon[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_Bargon::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcBargon op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - warning("unimplemented opcodeGob: %d", i); - } else - (this->*op) (params); -} - -const char *Inter_Bargon::getOpcodeDrawDesc(byte i) { - return _opcodesDrawBargon[i].desc; -} - -const char *Inter_Bargon::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncBargon[i*16 + j].desc; -} - -const char *Inter_Bargon::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinBargon[_goblinFuncLookUp[j][1]].desc; - return ""; + OPCODEGOB( 9, oBargon_intro8); + OPCODEGOB(10, oBargon_intro9); + OPCODEGOB(11, o_gobNOP); } void Inter_Bargon::oBargon_intro0(OpGobParams ¶ms) { @@ -734,16 +90,16 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { int16 mouseX; int16 mouseY; int16 buttons; - SurfaceDesc *surface; + SurfaceDescPtr surface; SoundDesc samples[4]; int16 comp[5] = { 0, 1, 2, 3, -1 }; static const char *sndFiles[] = {"1INTROII.snd", "2INTROII.snd", "1INTRO3.snd", "2INTRO3.snd"}; surface = _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, 0); - _vm->_video->drawPackedSprite("2ille.ims", surface); - _vm->_video->drawSprite(surface, _vm->_draw->_frontSurface, 0, 0, 319, 199, 0, 0, 0); - _vm->_video->drawPackedSprite("2ille4.ims", surface); - _vm->_video->drawSprite(surface, _vm->_draw->_frontSurface, 0, 0, 319, 199, 320, 0, 0); + _vm->_video->drawPackedSprite("2ille.ims", *surface); + _vm->_video->drawSprite(*surface, *_vm->_draw->_frontSurface, 0, 0, 319, 199, 0, 0, 0); + _vm->_video->drawPackedSprite("2ille4.ims", *surface); + _vm->_video->drawSprite(*surface, *_vm->_draw->_frontSurface, 0, 0, 319, 199, 320, 0, 0); _vm->_util->setScrollOffset(320, 0); _vm->_video->dirtyRectsAll(); _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); @@ -754,7 +110,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || _vm->shouldQuit()) { _vm->_palAnim->fade(0, -2, 0); - _vm->_video->clearSurf(_vm->_draw->_frontSurface); + _vm->_video->clearSurf(*_vm->_draw->_frontSurface); memset((char *) _vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); WRITE_VAR(0, 0x11B); @@ -766,7 +122,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { _vm->_util->setScrollOffset(0, 0); _vm->_video->dirtyRectsAll(); } - surface = 0; + surface.reset(); if (VAR(57) == ((uint32) -1)) return; @@ -775,7 +131,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { _vm->_sound->blasterPlayComposition(comp, 0, samples, 4); _vm->_sound->blasterWaitEndPlay(true, false); _vm->_palAnim->fade(0, 0, 0); - _vm->_video->clearSurf(_vm->_draw->_frontSurface); + _vm->_video->clearSurf(*_vm->_draw->_frontSurface); } void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { @@ -806,8 +162,8 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { _vm->shouldQuit()) { _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); - _vm->_video->clearSurf(_vm->_draw->_frontSurface); - memset((char *) _vm->_draw->_vgaPalette, 0, 768); + _vm->_video->clearSurf(*_vm->_draw->_frontSurface); + memset(_vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); WRITE_VAR(0, 0x11B); WRITE_VAR(57, (uint32) -1); diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp index 58c3e703ff..3c4713f9eb 100644 --- a/engines/gob/inter_fascin.cpp +++ b/engines/gob/inter_fascin.cpp @@ -31,8 +31,8 @@ #include "gob/util.h" #include "gob/dataio.h" #include "gob/draw.h" -#include "gob/parse.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -40,494 +40,73 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_Fascination, x) - -const int Inter_Fascination::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {11, 10}, - {12, 11}, - {1000, 12}, - {1001, 13}, - {1002, 14} -}; +#define OPCODEVER Inter_Fascination +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_Fascination::Inter_Fascination(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); } -void Inter_Fascination::setupOpcodes() { - static const OpcodeDrawEntryFascination opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o1_freeMultKeys), - OPCODE(oFascin_cdUnknown3), - /* 04 */ - OPCODE(oFascin_cdUnknown4), - OPCODE(oFascin_cdUnknown5), - OPCODE(oFascin_cdUnknown6), - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(oFascin_setRenderFlags), - OPCODE(oFascin_cdUnknown11), - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - {0, ""},//OPCODE(o2_loadMapObjects), - {0, ""},//OPCODE(o2_freeGoblins), - {0, ""},//OPCODE(o2_moveGoblin), - {0, ""},//OPCODE(o2_writeGoblinPos), - /* 54 */ - {0, ""},//OPCODE(o2_stopGoblin), - {0, ""},//OPCODE(o2_setGoblinState), - {0, ""},//OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - {0, ""},//OPCODE(o2_initScreen), - {0, ""},//OPCODE(o2_scroll), - {0, ""},//OPCODE(o2_setScrollOffset), - {0, ""},//OPCODE(o2_playImd), - /* 84 */ - {0, ""},//OPCODE(o2_getImdInfo), - {0, ""},//OPCODE(o2_openItk), - {0, ""},//OPCODE(o2_closeItk), - {0, ""},//OPCODE(o2_setImdFrontSurf), - /* 88 */ - {0, ""},//OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryFascination opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o1_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryFascination opcodesGoblin[15] = { - /* 00 */ - OPCODE(oFascin_geUnknown0), - OPCODE(oFascin_geUnknown1), - OPCODE(oFascin_geUnknown2), - OPCODE(oFascin_geUnknown3), - /* 04 */ - OPCODE(oFascin_geUnknown4), - OPCODE(oFascin_geUnknown5), - OPCODE(oFascin_geUnknown6), - OPCODE(oFascin_geUnknown7), - /* 08 */ - OPCODE(oFascin_geUnknown8), - OPCODE(oFascin_geUnknown9), - OPCODE(oFascin_geUnknown10), - OPCODE(oFascin_geUnknown11), - /* 0C */ - OPCODE(oFascin_geUnknown1000), - OPCODE(oFascin_geUnknown1001), //protrackerPlay doesn't play correctly "mod.extasy" - OPCODE(oFascin_geUnknown1002), //to be replaced by o2_stopProtracker when protrackerPlay is fixed - }; - - _opcodesDrawFascination = opcodesDraw; - _opcodesFuncFascination = opcodesFunc; - _opcodesGoblinFascination = opcodesGoblin; +void Inter_Fascination::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); + + OPCODEDRAW(0x03, oFascin_cdUnknown3); + + OPCODEDRAW(0x04, oFascin_cdUnknown4); + OPCODEDRAW(0x05, oFascin_cdUnknown5); + OPCODEDRAW(0x06, oFascin_cdUnknown6); + + OPCODEDRAW(0x0A, oFascin_setRenderFlags); + OPCODEDRAW(0x0B, oFascin_cdUnknown11); + + CLEAROPCODEDRAW(0x50); + CLEAROPCODEDRAW(0x51); + CLEAROPCODEDRAW(0x52); + CLEAROPCODEDRAW(0x53); + + CLEAROPCODEDRAW(0x54); + CLEAROPCODEDRAW(0x55); + CLEAROPCODEDRAW(0x56); + + CLEAROPCODEDRAW(0x80); + CLEAROPCODEDRAW(0x81); + CLEAROPCODEDRAW(0x82); + CLEAROPCODEDRAW(0x83); + + CLEAROPCODEDRAW(0x84); + CLEAROPCODEDRAW(0x85); + CLEAROPCODEDRAW(0x86); + CLEAROPCODEDRAW(0x87); + + CLEAROPCODEDRAW(0x88); } -void Inter_Fascination::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); +void Inter_Fascination::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); - OpcodeDrawProcFascination op = _opcodesDrawFascination[i].proc; + OPCODEFUNC(0x09, o1_assign); +} + +void Inter_Fascination::setupOpcodesGob() { + OPCODEGOB( 1, oFascin_geUnknown0); + OPCODEGOB( 2, oFascin_geUnknown1); + OPCODEGOB( 3, oFascin_geUnknown2); + OPCODEGOB( 4, oFascin_geUnknown3); + + OPCODEGOB( 5, oFascin_geUnknown4); + OPCODEGOB( 6, oFascin_geUnknown5); + OPCODEGOB( 7, oFascin_geUnknown6); + OPCODEGOB( 8, oFascin_geUnknown7); + + OPCODEGOB( 9, oFascin_geUnknown8); + OPCODEGOB( 10, oFascin_geUnknown9); + OPCODEGOB( 11, oFascin_geUnknown10); + OPCODEGOB( 12, oFascin_geUnknown11); - if (op == 0) - warning("Not yet implemented Fascination opcodeDraw: %d", i); - else - (this->*op) (); + OPCODEGOB(1000, oFascin_geUnknown1000); + OPCODEGOB(1001, oFascin_geUnknown1001); //protrackerPlay doesn't play correctly "mod.extasy" + OPCODEGOB(1002, oFascin_geUnknown1002); //to be replaced by o2_stopProtracker when protrackerPlay is fixed } void Inter_Fascination::oFascin_geUnknown0(OpGobParams ¶ms) { @@ -552,70 +131,58 @@ void Inter_Fascination::oFascin_geUnknown1(OpGobParams ¶ms) { } void Inter_Fascination::oFascin_geUnknown2(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 2"); - warning("funcLoadInstruments with parameter : 'extasy.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'extasy.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("extasy.tbr"); + _vm->_sound->adlibLoadMDY("extasy.mdy"); } void Inter_Fascination::oFascin_geUnknown3(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 3"); - warning("Verify if 'Guess music' is loaded. If yes, call funcPlayMusic. (Guess)"); + _vm->_sound->adlibPlay(); } void Inter_Fascination::oFascin_geUnknown4(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 4"); - warning("Verify if 'Guess music' is loaded. If yes, call funcStopMusic. (Guess)"); + _vm->_sound->adlibStop(); } void Inter_Fascination::oFascin_geUnknown5(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 5"); - warning("Verify if 'instruments' are loaded, If so, call mem_free"); - warning("Verify if 'Guess music' is loaded. If yes, call _cleanupMdy"); - warning("Then set _ptrTbr and _ptrMdy to 0"); + _vm->_sound->adlibUnload(); } void Inter_Fascination::oFascin_geUnknown6(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 6"); - warning("funcLoadInstruments with parameter : 'music1.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music1.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music1.tbr"); + _vm->_sound->adlibLoadMDY("music1.mdy"); } void Inter_Fascination::oFascin_geUnknown7(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 7"); - warning("funcLoadInstruments with parameter : 'music2.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music2.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music2.tbr"); + _vm->_sound->adlibLoadMDY("music2.mdy"); } void Inter_Fascination::oFascin_geUnknown8(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 8"); - warning("funcLoadInstruments with parameter : 'music3.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'music3.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("music3.tbr"); + _vm->_sound->adlibLoadMDY("music3.mdy"); } void Inter_Fascination::oFascin_geUnknown9(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 9"); - warning("funcLoadInstruments with parameter : 'batt1.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt1.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt1.tbr"); + _vm->_sound->adlibLoadMDY("batt1.mdy"); } void Inter_Fascination::oFascin_geUnknown10(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 10"); - warning("funcLoadInstruments with parameter : 'batt2.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt2.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt2.tbr"); + _vm->_sound->adlibLoadMDY("batt2.mdy"); } void Inter_Fascination::oFascin_geUnknown11(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 11"); - warning("funcLoadInstruments with parameter : 'batt3.tbr'. (Guess)"); - warning("funcLoadMusic with parameter : 'batt3.mdy'. (Guess)"); + _vm->_sound->adlibLoadTBR("batt3.tbr"); + _vm->_sound->adlibLoadMDY("batt3.mdy"); } void Inter_Fascination::oFascin_geUnknown1000(OpGobParams ¶ms) { - warning("Fascination Unknown GE Function 1000 - Load music ?"); + warning("Fascination Unknown GE Function 1000 - Load MOD music"); } void Inter_Fascination::oFascin_geUnknown1001(OpGobParams ¶ms) { - warning("Fascination oFascin_playProtracker - MOD not compatible, ToBeFixed"); + warning("Fascination oFascin_playProtracker - MOD not compatible (sample > 32768), To Be Fixed"); } void Inter_Fascination::oFascin_geUnknown1002(OpGobParams ¶ms) { @@ -638,15 +205,15 @@ void Inter_Fascination::oFascin_cdUnknown3() { warning("Fascination oFascin_cdUnknown3 - Variables initialisations"); - resVar = (uint16) load16(); - resVar2 = (uint16) load16(); - retVal1 = _vm->_parse->parseVarIndex(); - retVal2 = _vm->_parse->parseVarIndex(); - retVal3 = _vm->_parse->parseVarIndex(); - retVal4 = _vm->_parse->parseVarIndex(); - retVal5 = _vm->_parse->parseVarIndex(); - retVal6 = _vm->_parse->parseVarIndex(); - retVal7 = _vm->_parse->parseVarIndex(); + resVar = _vm->_game->_script->readUint16(); + resVar2 = _vm->_game->_script->readUint16(); + retVal1 = _vm->_game->_script->readVarIndex(); + retVal2 = _vm->_game->_script->readVarIndex(); + retVal3 = _vm->_game->_script->readVarIndex(); + retVal4 = _vm->_game->_script->readVarIndex(); + retVal5 = _vm->_game->_script->readVarIndex(); + retVal6 = _vm->_game->_script->readVarIndex(); + retVal7 = _vm->_game->_script->readVarIndex(); warning ("Width? :%d Height? :%d",resVar, resVar2); warning ("Fetched variables 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d", retVal1, retVal2, retVal3, retVal4, retVal5, retVal6, retVal7); } @@ -654,98 +221,37 @@ void Inter_Fascination::oFascin_cdUnknown3() { void Inter_Fascination::oFascin_cdUnknown4() { int16 expr; warning("Fascination oFascin_cdUnknown4"); - evalExpr(&expr); - warning ("evalExpr: %d, the rest is not yet implemented",expr); + _vm->_game->_script->evalExpr(&expr); + warning ("_vm->_game->_script->evalExpr: %d, the rest is not yet implemented",expr); } void Inter_Fascination::oFascin_cdUnknown5() { int16 retVal1,expr; warning("Fascination oFascin_cdUnknown5"); - evalExpr(&expr); - retVal1 = _vm->_parse->parseVarIndex(); - warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); + _vm->_game->_script->evalExpr(&expr); + retVal1 = _vm->_game->_script->readVarIndex(); + warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); } void Inter_Fascination::oFascin_cdUnknown6() { int16 retVal1,expr; warning("Fascination oFascin_cdUnknown6"); - evalExpr(&expr); - retVal1 = _vm->_parse->parseVarIndex(); - warning ("evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); + _vm->_game->_script->evalExpr(&expr); + retVal1 = _vm->_game->_script->readVarIndex(); + warning ("_vm->_game->_script->evalExpr: %d Variable index %d, the rest is not yet implemented",expr, retVal1); } void Inter_Fascination::oFascin_setRenderFlags() { int16 expr; // warning("Fascination oFascin_cdUnknown10 (set render flags)"); - evalExpr(&expr); + _vm->_game->_script->evalExpr(&expr); warning("_draw_renderFlags <- %d",expr); _vm->_draw->_renderFlags = expr; } void Inter_Fascination::oFascin_cdUnknown11() { // warning("Fascination oFascin_cdUnknown11 (set variable)"); - evalExpr(0); -} - -bool Inter_Fascination::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 16)) { - warning("Invalid opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcFascination op = _opcodesFuncFascination[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_Fascination::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcFascination op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - warning("unimplemented opcodeGob: %d", i); - } else - (this->*op) (params); -} - -const char *Inter_Fascination::getOpcodeDrawDesc(byte i) { - return _opcodesDrawFascination[i].desc; -} - -const char *Inter_Fascination::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncFascination[i*16 + j].desc; -} - -const char *Inter_Fascination::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinFascination[_goblinFuncLookUp[j][1]].desc; - warning("Error in getOpcodeGoblinDesc %d",i); - return ""; + _vm->_game->_script->evalExpr(0); } void Inter_Fascination::oFascin_playProtracker(OpGobParams ¶ms) { diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 37e31b95e8..96ecfc6b25 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -34,692 +34,214 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/sound/sound.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v1, x) - -const int Inter_v1::_goblinFuncLookUp[][2] = { - {1, 0}, - {2, 1}, - {3, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {150, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v1 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v1::Inter_v1(GobEngine *vm) : Inter(vm) { - setupOpcodes(); -} - -void Inter_v1::setupOpcodes() { - static const OpcodeDrawEntryV1 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o1_playMult), - OPCODE(o1_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o1_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - {0, ""}, - /* 14 */ - OPCODE(o1_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o1_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o1_renderStatic), - OPCODE(o1_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o1_playCDTrack), - OPCODE(o1_getCDTrackPos), - OPCODE(o1_stopCD), - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 54 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 84 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 88 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV1 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o1_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o1_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o1_animPalInit), - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o1_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o1_stopSound), - OPCODE(o1_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o1_getFreeMem), - OPCODE(o1_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o1_readData), - OPCODE(o1_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV1 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o1_setState), - OPCODE(o1_setCurFrame), - OPCODE(o1_setNextState), - OPCODE(o1_setMultState), - /* 04 */ - OPCODE(o1_setOrder), - OPCODE(o1_setActionStartState), - OPCODE(o1_setCurLookDir), - OPCODE(o1_setType), - /* 08 */ - OPCODE(o1_setNoTick), - OPCODE(o1_setPickable), - OPCODE(o1_setXPos), - OPCODE(o1_setYPos), - /* 0C */ - OPCODE(o1_setDoAnim), - OPCODE(o1_setRelaxTime), - OPCODE(o1_setMaxTick), - OPCODE(o1_getState), - /* 10 */ - OPCODE(o1_getCurFrame), - OPCODE(o1_getNextState), - OPCODE(o1_getMultState), - OPCODE(o1_getOrder), - /* 14 */ - OPCODE(o1_getActionStartState), - OPCODE(o1_getCurLookDir), - OPCODE(o1_getType), - OPCODE(o1_getNoTick), - /* 18 */ - OPCODE(o1_getPickable), - OPCODE(o1_getObjMaxFrame), - OPCODE(o1_getXPos), - OPCODE(o1_getYPos), - /* 1C */ - OPCODE(o1_getDoAnim), - OPCODE(o1_getRelaxTime), - OPCODE(o1_getMaxTick), - OPCODE(o1_manipulateMap), - /* 20 */ - OPCODE(o1_getItem), - OPCODE(o1_manipulateMapIndirect), - OPCODE(o1_getItemIndirect), - OPCODE(o1_setPassMap), - /* 24 */ - OPCODE(o1_setGoblinPosH), - OPCODE(o1_getGoblinPosXH), - OPCODE(o1_getGoblinPosYH), - OPCODE(o1_setGoblinMultState), - /* 28 */ - OPCODE(o1_setGoblinUnk14), - OPCODE(o1_setItemIdInPocket), - OPCODE(o1_setItemIndInPocket), - OPCODE(o1_getItemIdInPocket), - /* 2C */ - OPCODE(o1_getItemIndInPocket), - OPCODE(o1_setItemPos), - OPCODE(o1_setGoblinPos), - OPCODE(o1_setGoblinState), - /* 30 */ - OPCODE(o1_setGoblinStateRedraw), - OPCODE(o1_decRelaxTime), - OPCODE(o1_getGoblinPosX), - OPCODE(o1_getGoblinPosY), - /* 34 */ - OPCODE(o1_clearPathExistence), - OPCODE(o1_setGoblinVisible), - OPCODE(o1_setGoblinInvisible), - OPCODE(o1_getObjectIntersect), - /* 38 */ - OPCODE(o1_getGoblinIntersect), - OPCODE(o1_setItemPos), - OPCODE(o1_loadObjects), - OPCODE(o1_freeObjects), - /* 3C */ - OPCODE(o1_animateObjects), - OPCODE(o1_drawObjects), - OPCODE(o1_loadMap), - OPCODE(o1_moveGoblin), - /* 40 */ - OPCODE(o1_switchGoblin), - OPCODE(o1_loadGoblin), - OPCODE(o1_writeTreatItem), - OPCODE(o1_moveGoblin0), - /* 44 */ - OPCODE(o1_setGoblinTarget), - OPCODE(o1_setGoblinObjectsPos), - OPCODE(o1_initGoblin) - }; - - _opcodesDrawV1 = opcodesDraw; - _opcodesFuncV1 = opcodesFunc; - _opcodesGoblinV1 = opcodesGoblin; -} - -void Inter_v1::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV1 op = _opcodesDrawV1[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v1::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV1 op = _opcodesFuncV1[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - return false; } -void Inter_v1::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); +void Inter_v1::setupOpcodesDraw() { + OPCODEDRAW(0x00, o1_loadMult); + OPCODEDRAW(0x01, o1_playMult); + OPCODEDRAW(0x02, o1_freeMultKeys); - OpcodeGoblinProcV1 op = 0; + OPCODEDRAW(0x07, o1_initCursor); + + OPCODEDRAW(0x08, o1_initCursorAnim); + OPCODEDRAW(0x09, o1_clearCursorAnim); + OPCODEDRAW(0x0A, o1_setRenderFlags); - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV1[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - _vm->_global->_inter_execPtr -= 2; - int16 cmd = load16(); - _vm->_global->_inter_execPtr += cmd * 2; - } else - (this->*op) (params); -} - -const char *Inter_v1::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV1[i].desc; -} - -const char *Inter_v1::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV1[i*16 + j].desc; -} - -const char *Inter_v1::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV1[_goblinFuncLookUp[j][1]].desc; - return ""; -} - -void Inter_v1::checkSwitchTable(byte **ppExec) { + OPCODEDRAW(0x10, o1_loadAnim); + OPCODEDRAW(0x11, o1_freeAnim); + OPCODEDRAW(0x12, o1_updateAnim); + + OPCODEDRAW(0x14, o1_initMult); + OPCODEDRAW(0x15, o1_freeMult); + OPCODEDRAW(0x16, o1_animate); + OPCODEDRAW(0x17, o1_loadMultObject); + + OPCODEDRAW(0x18, o1_getAnimLayerInfo); + OPCODEDRAW(0x19, o1_getObjAnimSize); + OPCODEDRAW(0x1A, o1_loadStatic); + OPCODEDRAW(0x1B, o1_freeStatic); + + OPCODEDRAW(0x1C, o1_renderStatic); + OPCODEDRAW(0x1D, o1_loadCurLayer); + + OPCODEDRAW(0x20, o1_playCDTrack); + OPCODEDRAW(0x21, o1_getCDTrackPos); + OPCODEDRAW(0x22, o1_stopCD); + + OPCODEDRAW(0x30, o1_loadFontToSprite); + OPCODEDRAW(0x31, o1_freeFontToSprite); +} + +void Inter_v1::setupOpcodesFunc() { + OPCODEFUNC(0x00, o1_callSub); + OPCODEFUNC(0x01, o1_callSub); + OPCODEFUNC(0x02, o1_printTotText); + OPCODEFUNC(0x03, o1_loadCursor); + + OPCODEFUNC(0x05, o1_switch); + OPCODEFUNC(0x06, o1_repeatUntil); + OPCODEFUNC(0x07, o1_whileDo); + + OPCODEFUNC(0x08, o1_if); + OPCODEFUNC(0x09, o1_assign); + OPCODEFUNC(0x0A, o1_loadSpriteToPos); + OPCODEFUNC(0x11, o1_printText); + OPCODEFUNC(0x12, o1_loadTot); + OPCODEFUNC(0x13, o1_palLoad); + + OPCODEFUNC(0x14, o1_keyFunc); + OPCODEFUNC(0x15, o1_capturePush); + OPCODEFUNC(0x16, o1_capturePop); + OPCODEFUNC(0x17, o1_animPalInit); + + OPCODEFUNC(0x1E, o1_drawOperations); + OPCODEFUNC(0x1F, o1_setcmdCount); + + OPCODEFUNC(0x20, o1_return); + OPCODEFUNC(0x21, o1_renewTimeInVars); + OPCODEFUNC(0x22, o1_speakerOn); + OPCODEFUNC(0x23, o1_speakerOff); + + OPCODEFUNC(0x24, o1_putPixel); + OPCODEFUNC(0x25, o1_goblinFunc); + OPCODEFUNC(0x26, o1_createSprite); + OPCODEFUNC(0x27, o1_freeSprite); + + OPCODEFUNC(0x30, o1_returnTo); + OPCODEFUNC(0x31, o1_loadSpriteContent); + OPCODEFUNC(0x32, o1_copySprite); + OPCODEFUNC(0x33, o1_fillRect); + + OPCODEFUNC(0x34, o1_drawLine); + OPCODEFUNC(0x35, o1_strToLong); + OPCODEFUNC(0x36, o1_invalidate); + OPCODEFUNC(0x37, o1_setBackDelta); + + OPCODEFUNC(0x38, o1_playSound); + OPCODEFUNC(0x39, o1_stopSound); + OPCODEFUNC(0x3A, o1_loadSound); + OPCODEFUNC(0x3B, o1_freeSoundSlot); + + OPCODEFUNC(0x3C, o1_waitEndPlay); + OPCODEFUNC(0x3D, o1_playComposition); + OPCODEFUNC(0x3E, o1_getFreeMem); + OPCODEFUNC(0x3F, o1_checkData); + + OPCODEFUNC(0x41, o1_prepareStr); + OPCODEFUNC(0x42, o1_insertStr); + OPCODEFUNC(0x43, o1_cutStr); + + OPCODEFUNC(0x44, o1_strstr); + OPCODEFUNC(0x45, o1_istrlen); + OPCODEFUNC(0x46, o1_setMousePos); + OPCODEFUNC(0x47, o1_setFrameRate); + + OPCODEFUNC(0x48, o1_animatePalette); + OPCODEFUNC(0x49, o1_animateCursor); + OPCODEFUNC(0x4A, o1_blitCursor); + OPCODEFUNC(0x4B, o1_loadFont); + + OPCODEFUNC(0x4C, o1_freeFont); + OPCODEFUNC(0x4D, o1_readData); + OPCODEFUNC(0x4E, o1_writeData); + OPCODEFUNC(0x4F, o1_manageDataFile); +} + +void Inter_v1::setupOpcodesGob() { + OPCODEGOB( 1, o1_setState); + OPCODEGOB( 2, o1_setCurFrame); + OPCODEGOB( 3, o1_setNextState); + OPCODEGOB( 4, o1_setMultState); + OPCODEGOB( 5, o1_setOrder); + OPCODEGOB( 6, o1_setActionStartState); + OPCODEGOB( 7, o1_setCurLookDir); + OPCODEGOB( 8, o1_setType); + OPCODEGOB( 9, o1_setNoTick); + OPCODEGOB( 10, o1_setPickable); + OPCODEGOB( 12, o1_setXPos); + OPCODEGOB( 13, o1_setYPos); + OPCODEGOB( 14, o1_setDoAnim); + OPCODEGOB( 15, o1_setRelaxTime); + OPCODEGOB( 16, o1_setMaxTick); + OPCODEGOB( 21, o1_getState); + OPCODEGOB( 22, o1_getCurFrame); + OPCODEGOB( 23, o1_getNextState); + OPCODEGOB( 24, o1_getMultState); + OPCODEGOB( 25, o1_getOrder); + OPCODEGOB( 26, o1_getActionStartState); + OPCODEGOB( 27, o1_getCurLookDir); + OPCODEGOB( 28, o1_getType); + OPCODEGOB( 29, o1_getNoTick); + OPCODEGOB( 30, o1_getPickable); + OPCODEGOB( 32, o1_getObjMaxFrame); + OPCODEGOB( 33, o1_getXPos); + OPCODEGOB( 34, o1_getYPos); + OPCODEGOB( 35, o1_getDoAnim); + OPCODEGOB( 36, o1_getRelaxTime); + OPCODEGOB( 37, o1_getMaxTick); + OPCODEGOB( 40, o1_manipulateMap); + OPCODEGOB( 41, o1_getItem); + OPCODEGOB( 42, o1_manipulateMapIndirect); + OPCODEGOB( 43, o1_getItemIndirect); + OPCODEGOB( 44, o1_setPassMap); + OPCODEGOB( 50, o1_setGoblinPosH); + OPCODEGOB( 52, o1_getGoblinPosXH); + OPCODEGOB( 53, o1_getGoblinPosYH); + OPCODEGOB( 150, o1_setGoblinMultState); + OPCODEGOB( 152, o1_setGoblinUnk14); + OPCODEGOB( 200, o1_setItemIdInPocket); + OPCODEGOB( 201, o1_setItemIndInPocket); + OPCODEGOB( 202, o1_getItemIdInPocket); + OPCODEGOB( 203, o1_getItemIndInPocket); + OPCODEGOB( 204, o1_setItemPos); + OPCODEGOB( 250, o1_setGoblinPos); + OPCODEGOB( 251, o1_setGoblinState); + OPCODEGOB( 252, o1_setGoblinStateRedraw); + OPCODEGOB( 500, o1_decRelaxTime); + OPCODEGOB( 502, o1_getGoblinPosX); + OPCODEGOB( 503, o1_getGoblinPosY); + OPCODEGOB( 600, o1_clearPathExistence); + OPCODEGOB( 601, o1_setGoblinVisible); + OPCODEGOB( 602, o1_setGoblinInvisible); + OPCODEGOB( 603, o1_getObjectIntersect); + OPCODEGOB( 604, o1_getGoblinIntersect); + OPCODEGOB( 605, o1_setItemPos); + OPCODEGOB(1000, o1_loadObjects); + OPCODEGOB(1001, o1_freeObjects); + OPCODEGOB(1002, o1_animateObjects); + OPCODEGOB(1003, o1_drawObjects); + OPCODEGOB(1004, o1_loadMap); + OPCODEGOB(1005, o1_moveGoblin); + OPCODEGOB(1006, o1_switchGoblin); + OPCODEGOB(1008, o1_loadGoblin); + OPCODEGOB(1009, o1_writeTreatItem); + OPCODEGOB(1010, o1_moveGoblin0); + OPCODEGOB(1011, o1_setGoblinTarget); + OPCODEGOB(1015, o1_setGoblinObjectsPos); + OPCODEGOB(2005, o1_initGoblin); +} + +void Inter_v1::checkSwitchTable(uint32 &offset) { int16 len; int32 value; bool found; @@ -727,56 +249,54 @@ void Inter_v1::checkSwitchTable(byte **ppExec) { found = false; notFound = true; - *ppExec = 0; - value = VAR_OFFSET(_vm->_parse->parseVarIndex()); + offset = 0; + value = VAR_OFFSET(_vm->_game->_script->readVarIndex()); - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); while (len != -5) { for (int i = 0; i < len; i++) { - evalExpr(0); + _vm->_game->_script->evalExpr(0); if (_terminate) return; - if (_vm->_global->_inter_resVal == value) { + if (_vm->_game->_script->getResultInt() == value) { found = true; notFound = false; } } if (found) - *ppExec = _vm->_global->_inter_execPtr; + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); found = false; - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); } - if ((*_vm->_global->_inter_execPtr >> 4) != 4) + if ((_vm->_game->_script->peekByte() >> 4) != 4) return; - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); if (notFound) - *ppExec = _vm->_global->_inter_execPtr; + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } void Inter_v1::o1_loadMult() { - _vm->_mult->loadMult(load16()); + _vm->_mult->loadMult(_vm->_game->_script->readInt16()); } void Inter_v1::o1_playMult() { int16 checkEscape; - checkEscape = load16(); + checkEscape = _vm->_game->_script->readInt16(); _vm->_mult->playMult(VAR(57), -1, checkEscape, 0); } void Inter_v1::o1_freeMultKeys() { - load16(); + _vm->_game->_script->readInt16(); _vm->_mult->freeMultKeys(); } @@ -785,20 +305,20 @@ void Inter_v1::o1_initCursor() { int16 height; int16 count; - _vm->_draw->_cursorHotspotXVar = _vm->_parse->parseVarIndex() / 4; - _vm->_draw->_cursorHotspotYVar = _vm->_parse->parseVarIndex() / 4; + _vm->_draw->_cursorHotspotXVar = _vm->_game->_script->readVarIndex() / 4; + _vm->_draw->_cursorHotspotYVar = _vm->_game->_script->readVarIndex() / 4; - width = load16(); + width = _vm->_game->_script->readInt16(); if (width < 16) width = 16; - height = load16(); + height = _vm->_game->_script->readInt16(); if (height < 16) height = 16; _vm->_draw->adjustCoords(0, &width, &height); - count = load16(); + count = _vm->_game->_script->readInt16(); if (count < 2) count = 2; @@ -808,9 +328,9 @@ void Inter_v1::o1_initCursor() { (_vm->_draw->_cursorSprites->getWidth() != (width * count))) { _vm->_draw->freeSprite(23); - _vm->_draw->_cursorSprites = 0; - _vm->_draw->_cursorSpritesBack = 0; - _vm->_draw->_scummvmCursor = 0; + _vm->_draw->_cursorSprites.reset(); + _vm->_draw->_cursorSpritesBack.reset(); + _vm->_draw->_scummvmCursor.reset(); _vm->_draw->_cursorWidth = width; _vm->_draw->_cursorHeight = height; @@ -846,24 +366,24 @@ void Inter_v1::o1_initCursorAnim() { int16 ind; _vm->_draw->_showCursor = 3; - ind = _vm->_parse->parseValExpr(); - _vm->_draw->_cursorAnimLow[ind] = load16(); - _vm->_draw->_cursorAnimHigh[ind] = load16(); - _vm->_draw->_cursorAnimDelays[ind] = load16(); + ind = _vm->_game->_script->readValExpr(); + _vm->_draw->_cursorAnimLow[ind] = _vm->_game->_script->readInt16(); + _vm->_draw->_cursorAnimHigh[ind] = _vm->_game->_script->readInt16(); + _vm->_draw->_cursorAnimDelays[ind] = _vm->_game->_script->readInt16(); } void Inter_v1::o1_clearCursorAnim() { int16 ind; _vm->_draw->_showCursor = 0; - ind = _vm->_parse->parseValExpr(); + ind = _vm->_game->_script->readValExpr(); _vm->_draw->_cursorAnimLow[ind] = -1; _vm->_draw->_cursorAnimHigh[ind] = 0; _vm->_draw->_cursorAnimDelays[ind] = 0; } void Inter_v1::o1_setRenderFlags() { - _vm->_draw->_renderFlags = _vm->_parse->parseValExpr(); + _vm->_draw->_renderFlags = _vm->_game->_script->readValExpr(); } void Inter_v1::o1_loadAnim() { @@ -882,12 +402,12 @@ void Inter_v1::o1_updateAnim() { int16 layer; int16 animation; - evalExpr(&deltaX); - evalExpr(&deltaY); - evalExpr(&animation); - evalExpr(&layer); - evalExpr(&frame); - flags = load16(); + _vm->_game->_script->evalExpr(&deltaX); + _vm->_game->_script->evalExpr(&deltaY); + _vm->_game->_script->evalExpr(&animation); + _vm->_game->_script->evalExpr(&layer); + _vm->_game->_script->evalExpr(&frame); + flags = _vm->_game->_script->readInt16(); _vm->_scenery->updateAnim(layer, frame, animation, flags, deltaX, deltaY, 1); } @@ -904,14 +424,14 @@ void Inter_v1::o1_initMult() { oldAnimHeight = _vm->_mult->_animHeight; oldObjCount = _vm->_mult->_objCount; - _vm->_mult->_animLeft = load16(); - _vm->_mult->_animTop = load16(); - _vm->_mult->_animWidth = load16(); - _vm->_mult->_animHeight = load16(); - _vm->_mult->_objCount = load16(); - posXVar = _vm->_parse->parseVarIndex(); - posYVar = _vm->_parse->parseVarIndex(); - animDataVar = _vm->_parse->parseVarIndex(); + _vm->_mult->_animLeft = _vm->_game->_script->readInt16(); + _vm->_mult->_animTop = _vm->_game->_script->readInt16(); + _vm->_mult->_animWidth = _vm->_game->_script->readInt16(); + _vm->_mult->_animHeight = _vm->_game->_script->readInt16(); + _vm->_mult->_objCount = _vm->_game->_script->readInt16(); + posXVar = _vm->_game->_script->readVarIndex(); + posYVar = _vm->_game->_script->readVarIndex(); + animDataVar = _vm->_game->_script->readVarIndex(); if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) { @@ -944,8 +464,8 @@ void Inter_v1::o1_initMult() { uint32 offPosY = i * 4 + (posYVar / 4) * 4; uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize; - _vm->_mult->_objects[i].pPosX = new VariableReference(*_vm->_inter->_variables, offPosX); - _vm->_mult->_objects[i].pPosY = new VariableReference(*_vm->_inter->_variables, offPosY); + _vm->_mult->_objects[i].pPosX = new VariableReference(*_variables, offPosX); + _vm->_mult->_objects[i].pPosY = new VariableReference(*_variables, offPosY); _vm->_mult->_objects[i].pAnimData = (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim); @@ -963,7 +483,7 @@ void Inter_v1::o1_initMult() { ((oldAnimWidth != _vm->_mult->_animWidth) || (oldAnimHeight != _vm->_mult->_animHeight))) { _vm->_draw->freeSprite(22); - _vm->_mult->_animSurf = 0; + _vm->_mult->_animSurf.reset(); } if (!_vm->_mult->_animSurf) { @@ -972,7 +492,7 @@ void Inter_v1::o1_initMult() { _vm->_mult->_animSurf = _vm->_draw->_spritesArray[22]; } - _vm->_video->drawSprite(_vm->_draw->_backSurface, _vm->_mult->_animSurf, + _vm->_video->drawSprite(*_vm->_draw->_backSurface, *_vm->_mult->_animSurf, _vm->_mult->_animLeft, _vm->_mult->_animTop, _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1, _vm->_mult->_animTop + _vm->_mult->_animHeight - 1, 0, 0, 0); @@ -998,21 +518,21 @@ void Inter_v1::o1_loadMultObject() { int16 objIndex; byte *multData; - evalExpr(&objIndex); - evalExpr(&val); + _vm->_game->_script->evalExpr(&objIndex); + _vm->_game->_script->evalExpr(&val); *_vm->_mult->_objects[objIndex].pPosX = val; - evalExpr(&val); + _vm->_game->_script->evalExpr(&val); *_vm->_mult->_objects[objIndex].pPosY = val; debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex); multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData; for (int i = 0; i < 11; i++) { - if (READ_LE_UINT16(_vm->_global->_inter_execPtr) != 99) { - evalExpr(&val); + if (_vm->_game->_script->peekUint16() != 99) { + _vm->_game->_script->evalExpr(&val); multData[i] = val; } else - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } } @@ -1023,13 +543,13 @@ void Inter_v1::o1_getAnimLayerInfo() { int16 varUnk0; int16 varFrames; - evalExpr(&anim); - evalExpr(&layer); + _vm->_game->_script->evalExpr(&anim); + _vm->_game->_script->evalExpr(&layer); - varDX = _vm->_parse->parseVarIndex(); - varDY = _vm->_parse->parseVarIndex(); - varUnk0 = _vm->_parse->parseVarIndex(); - varFrames = _vm->_parse->parseVarIndex(); + varDX = _vm->_game->_script->readVarIndex(); + varDY = _vm->_game->_script->readVarIndex(); + varUnk0 = _vm->_game->_script->readVarIndex(); + varFrames = _vm->_game->_script->readVarIndex(); _vm->_scenery->writeAnimLayerInfo(anim, layer, varDX, varDY, varUnk0, varFrames); @@ -1038,7 +558,7 @@ void Inter_v1::o1_getAnimLayerInfo() { void Inter_v1::o1_getObjAnimSize() { int16 objIndex; - evalExpr(&objIndex); + _vm->_game->_script->evalExpr(&objIndex); Mult::Mult_AnimData &animData = *(_vm->_mult->_objects[objIndex].pAnimData); if (animData.isStatic == 0) @@ -1048,10 +568,10 @@ void Inter_v1::o1_getObjAnimSize() { _vm->_scenery->_toRedrawLeft = MAX(_vm->_scenery->_toRedrawLeft, (int16) 0); _vm->_scenery->_toRedrawTop = MAX(_vm->_scenery->_toRedrawTop, (int16) 0); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawLeft); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawTop); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawRight); - WRITE_VAR_OFFSET(_vm->_parse->parseVarIndex(), _vm->_scenery->_toRedrawBottom); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawLeft); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawTop); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawRight); + WRITE_VAR_OFFSET(_vm->_game->_script->readVarIndex(), _vm->_scenery->_toRedrawBottom); } void Inter_v1::o1_loadStatic() { @@ -1066,20 +586,20 @@ void Inter_v1::o1_renderStatic() { int16 layer; int16 index; - _vm->_inter->evalExpr(&index); - _vm->_inter->evalExpr(&layer); + _vm->_game->_script->evalExpr(&index); + _vm->_game->_script->evalExpr(&layer); _vm->_scenery->renderStatic(index, layer); } void Inter_v1::o1_loadCurLayer() { - evalExpr(&_vm->_scenery->_curStatic); - evalExpr(&_vm->_scenery->_curStaticLayer); + _vm->_game->_script->evalExpr(&_vm->_scenery->_curStatic); + _vm->_game->_script->evalExpr(&_vm->_scenery->_curStaticLayer); } void Inter_v1::o1_playCDTrack() { - evalExpr(0); + _vm->_game->_script->evalExpr(0); _vm->_sound->adlibPlayBgMusic(); // Mac version - _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version + _vm->_sound->cdPlay(_vm->_game->_script->getResultStr()); // PC CD version } void Inter_v1::o1_getCDTrackPos() { @@ -1103,15 +623,15 @@ void Inter_v1::o1_stopCD() { } void Inter_v1::o1_loadFontToSprite() { - int16 i = load16(); - _vm->_draw->_fontToSprite[i].sprite = load16(); - _vm->_draw->_fontToSprite[i].base = load16(); - _vm->_draw->_fontToSprite[i].width = load16(); - _vm->_draw->_fontToSprite[i].height = load16(); + int16 i = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readInt16(); + _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readInt16(); } void Inter_v1::o1_freeFontToSprite() { - int16 i = load16(); + int16 i = _vm->_game->_script->readInt16(); _vm->_draw->_fontToSprite[i].sprite = -1; _vm->_draw->_fontToSprite[i].base = -1; _vm->_draw->_fontToSprite[i].width = -1; @@ -1119,11 +639,7 @@ void Inter_v1::o1_freeFontToSprite() { } bool Inter_v1::o1_callSub(OpFuncParams ¶ms) { - byte *storedIP; - uint16 offset; - - offset = load16(); - storedIP = _vm->_global->_inter_execPtr; + uint16 offset = _vm->_game->_script->readUint16(); debugC(5, kDebugGameFlow, "tot = \"%s\", offset = %d", _vm->_game->_curTotFile, offset); @@ -1147,79 +663,89 @@ bool Inter_v1::o1_callSub(OpFuncParams ¶ms) { return false; } - _vm->_global->_inter_execPtr = _vm->_game->_totFileData + offset; + _vm->_game->_script->call(offset); - if ((params.counter == params.cmdCount) && (params.retFlag == 2)) + if ((params.counter == params.cmdCount) && (params.retFlag == 2)) { + _vm->_game->_script->pop(false); return true; + } callSub(2); - _vm->_global->_inter_execPtr = storedIP; + + _vm->_game->_script->pop(); return false; } bool Inter_v1::o1_printTotText(OpFuncParams ¶ms) { - _vm->_draw->printTotText(load16()); + _vm->_draw->printTotText(_vm->_game->_script->readInt16()); return false; } bool Inter_v1::o1_loadCursor(OpFuncParams ¶ms) { - int16 width, height; - byte *dataBuf; - int16 id; - int8 index; - - id = load16(); - index = (int8) *_vm->_global->_inter_execPtr++; + int16 id = _vm->_game->_script->readInt16(); + int8 index = _vm->_game->_script->readInt8(); if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth()) return false; - dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return false; - _vm->_video->fillRect(_vm->_draw->_cursorSprites, + _vm->_video->fillRect(*_vm->_draw->_cursorSprites, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, - index * _vm->_draw->_cursorWidth, 0, 0, _vm->_draw->_cursorSprites); + _vm->_video->drawPackedSprite(resource->getData(), + resource->getWidth(), resource->getHeight(), + index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites); _vm->_draw->_cursorAnimLow[index] = 0; + delete resource; return false; } bool Inter_v1::o1_switch(OpFuncParams ¶ms) { - byte *callAddr; + uint32 offset; + + checkSwitchTable(offset); - checkSwitchTable(&callAddr); - byte *storedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = callAddr; + _vm->_game->_script->call(offset); - if ((params.counter == params.cmdCount) && (params.retFlag == 2)) + if (offset == 0) + _vm->_game->_script->setFinished(true); + + if ((params.counter == params.cmdCount) && (params.retFlag == 2)) { + _vm->_game->_script->pop(false); return true; + } funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + + _vm->_game->_script->pop(); return false; } bool Inter_v1::o1_repeatUntil(OpFuncParams ¶ms) { - byte *blockPtr; int16 size; bool flag; _nestLevel[0]++; - blockPtr = _vm->_global->_inter_execPtr; + + uint32 blockPos = _vm->_game->_script->pos(); do { - _vm->_global->_inter_execPtr = blockPtr; - size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->seek(blockPos); + size = _vm->_game->_script->peekUint16(2) + 2; funcBlock(1); - _vm->_global->_inter_execPtr = blockPtr + size + 1; - flag = evalBoolResult(); + + _vm->_game->_script->seek(blockPos + size + 1); + + flag = _vm->_game->_script->evalBoolResult(); } while (!flag && !_break && !_terminate && !_vm->shouldQuit()); _nestLevel[0]--; @@ -1232,32 +758,31 @@ bool Inter_v1::o1_repeatUntil(OpFuncParams ¶ms) { } bool Inter_v1::o1_whileDo(OpFuncParams ¶ms) { - byte *blockPtr; - byte *savedIP; bool flag; int16 size; _nestLevel[0]++; do { - savedIP = _vm->_global->_inter_execPtr; - flag = evalBoolResult(); + uint32 startPos = _vm->_game->_script->pos(); + + flag = _vm->_game->_script->evalBoolResult(); if (_terminate) return false; - blockPtr = _vm->_global->_inter_execPtr; + uint32 blockPos = _vm->_game->_script->pos(); - size = READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + size = _vm->_game->_script->peekUint16(2) + 2; if (flag) { funcBlock(1); - _vm->_global->_inter_execPtr = savedIP; + _vm->_game->_script->seek(startPos); } else - _vm->_global->_inter_execPtr += size; + _vm->_game->_script->skip(size); if (_break || _terminate || _vm->shouldQuit()) { - _vm->_global->_inter_execPtr = blockPtr; - _vm->_global->_inter_execPtr += size; + _vm->_game->_script->seek(blockPos); + _vm->_game->_script->skip(size); break; } } while (flag); @@ -1273,76 +798,65 @@ bool Inter_v1::o1_whileDo(OpFuncParams ¶ms) { bool Inter_v1::o1_if(OpFuncParams ¶ms) { byte cmd; bool boolRes; - byte *storedIP; - boolRes = evalBoolResult(); + boolRes = _vm->_game->_script->evalBoolResult(); if (boolRes) { if ((params.counter == params.cmdCount) && (params.retFlag == 2)) return true; - storedIP = _vm->_global->_inter_execPtr; + _vm->_game->_script->push(); funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); - debugC(5, kDebugGameFlow, "cmd = %d", - (int16) *_vm->_global->_inter_execPtr); + debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte()); - cmd = *_vm->_global->_inter_execPtr >> 4; - _vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte() >> 4; if (cmd != 12) return false; - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } else { - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); - debugC(5, kDebugGameFlow, "cmd = %d", - (int16) *_vm->_global->_inter_execPtr); + debugC(5, kDebugGameFlow, "cmd = %d", (int16) _vm->_game->_script->peekByte()); - cmd = *_vm->_global->_inter_execPtr >> 4; - _vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte() >> 4; if (cmd != 12) return false; if ((params.counter == params.cmdCount) && (params.retFlag == 2)) return true; - storedIP = _vm->_global->_inter_execPtr; + _vm->_game->_script->push(); funcBlock(0); - _vm->_global->_inter_execPtr = storedIP; + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } return false; } -bool Inter_v1::o1_evaluateStore(OpFuncParams ¶ms) { - byte *savedPos; - int16 token; +bool Inter_v1::o1_assign(OpFuncParams ¶ms) { + byte destType = _vm->_game->_script->peekByte(); + int16 dest = _vm->_game->_script->readVarIndex(); + int16 result; - int16 varOff; + int16 srcType = _vm->_game->_script->evalExpr(&result); - savedPos = _vm->_global->_inter_execPtr; - varOff = _vm->_parse->parseVarIndex(); - token = evalExpr(&result); - switch (savedPos[0]) { - case 23: - case 26: - WRITE_VAR_OFFSET(varOff, _vm->_global->_inter_resVal); + switch (destType) { + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } @@ -1350,17 +864,17 @@ bool Inter_v1::o1_evaluateStore(OpFuncParams ¶ms) { } bool Inter_v1::o1_loadSpriteToPos(OpFuncParams ¶ms) { - _vm->_draw->_spriteLeft = load16(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_transparency = *_vm->_global->_inter_execPtr & 1; - _vm->_draw->_destSurface = ((int16) (*_vm->_global->_inter_execPtr >> 1)) - 1; + _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1; + _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1; if (_vm->_draw->_destSurface < 0) _vm->_draw->_destSurface = 101; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); _vm->_draw->spriteOperation(DRAW_LOADSPRITE); @@ -1371,12 +885,12 @@ bool Inter_v1::o1_printText(OpFuncParams ¶ms) { char buf[60]; int i; - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); - _vm->_draw->_fontIndex = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr(); _vm->_draw->_destSurface = 21; _vm->_draw->_textToPrint = buf; _vm->_draw->_transparency = 0; @@ -1387,35 +901,35 @@ bool Inter_v1::o1_printText(OpFuncParams ¶ms) { } do { - for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') && - (*_vm->_global->_inter_execPtr != 200); - i++, _vm->_global->_inter_execPtr++) { - buf[i] = (char) *_vm->_global->_inter_execPtr; + for (i = 0; ((_vm->_game->_script->peekChar()) != '.') && + (_vm->_game->_script->peekByte() != 200); + i++, _vm->_game->_script->skip(1)) { + buf[i] = _vm->_game->_script->peekChar(); } - if (*_vm->_global->_inter_execPtr != 200) { - _vm->_global->_inter_execPtr++; - switch (*_vm->_global->_inter_execPtr) { - case 23: - case 26: + if (_vm->_game->_script->peekByte() != 200) { + _vm->_game->_script->skip(1); + switch (_vm->_game->_script->peekByte()) { + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: sprintf(buf + i, "%d", - VAR_OFFSET(_vm->_parse->parseVarIndex())); + VAR_OFFSET(_vm->_game->_script->readVarIndex())); break; - case 25: - case 28: + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: sprintf(buf + i, "%s", - GET_VARO_STR(_vm->_parse->parseVarIndex())); + GET_VARO_STR(_vm->_game->_script->readVarIndex())); break; } - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } else buf[i] = 0; _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - } while (*_vm->_global->_inter_execPtr != 200); + } while (_vm->_game->_script->peekByte() != 200); - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); return false; } @@ -1424,16 +938,14 @@ bool Inter_v1::o1_loadTot(OpFuncParams ¶ms) { char buf[20]; int8 size; - if ((*_vm->_global->_inter_execPtr & 0x80) != 0) { - _vm->_global->_inter_execPtr++; - evalExpr(0); - strncpy0(buf, _vm->_global->_inter_resStr, 15); + if ((_vm->_game->_script->peekByte() & 0x80) != 0) { + _vm->_game->_script->skip(1); + _vm->_game->_script->evalExpr(0); + strncpy0(buf, _vm->_game->_script->getResultStr(), 15); } else { - size = (int8) *_vm->_global->_inter_execPtr++; - for (int i = 0; i < size; i++) - buf[i] = *_vm->_global->_inter_execPtr++; - - buf[size] = 0; + size = _vm->_game->_script->readInt8(); + memcpy(buf, _vm->_game->_script->readString(size), size); + buf[size] = '\0'; } // if (_vm->getGameType() == kGameTypeGeisha) @@ -1450,15 +962,15 @@ bool Inter_v1::o1_loadTot(OpFuncParams ¶ms) { bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { int index1, index2; - byte *palPtr; byte cmd; + Resource *resource; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte(); switch (cmd & 0x7F) { case 48: if ((_vm->_global->_fakeVideoMode < 0x32) || (_vm->_global->_fakeVideoMode > 0x63)) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } break; @@ -1466,35 +978,35 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { case 49: if ((_vm->_global->_fakeVideoMode != 5) && (_vm->_global->_fakeVideoMode != 7)) { - _vm->_global->_inter_execPtr += 18; + _vm->_game->_script->skip(18); return false; } break; case 50: if (_vm->_global->_colorCount == 256) { - _vm->_global->_inter_execPtr += 16; + _vm->_game->_script->skip(16); return false; } break; case 51: if (_vm->_global->_fakeVideoMode < 0x64) { - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); return false; } break; case 52: if (_vm->_global->_colorCount == 256) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } break; case 53: if (_vm->_global->_colorCount != 256) { - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); return false; } break; @@ -1507,14 +1019,14 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { case 61: if (_vm->_global->_fakeVideoMode < 0x13) { - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); return false; } break; } if ((cmd & 0x7F) == 0x30) { - _vm->_global->_inter_execPtr += 48; + _vm->_game->_script->skip(48); return false; } @@ -1525,36 +1037,38 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { bool allZero = true; for (int i = 2; i < 18; i++) { - if (_vm->_global->_inter_execPtr[i] != 0) { + if (_vm->_game->_script->peekByte(i) != 0) { allZero = false; break; } } if (!allZero) { - _vm->_video->clearSurf(_vm->_draw->_frontSurface); + _vm->_video->clearSurf(*_vm->_draw->_frontSurface); _vm->_draw->_noInvalidated57 = true; - _vm->_global->_inter_execPtr += 18; + _vm->_game->_script->skip(48); return false; } _vm->_draw->_noInvalidated57 = false; - for (int i = 0; i < 18; i++, _vm->_global->_inter_execPtr++) { + for (int i = 0; i < 18; i++) { if (i < 2) { if (!_vm->_draw->_applyPal) continue; - _vm->_draw->_unusedPalette1[i] = *_vm->_global->_inter_execPtr; + _vm->_draw->_unusedPalette1[i] = _vm->_game->_script->peekByte(); continue; } - index1 = *_vm->_global->_inter_execPtr >> 4; - index2 = (*_vm->_global->_inter_execPtr & 0xF); + index1 = _vm->_game->_script->peekByte() >> 4; + index2 = _vm->_game->_script->peekByte() & 0xF; _vm->_draw->_unusedPalette1[i] = ((_vm->_draw->_palLoadData1[index1] + _vm->_draw->_palLoadData2[index2]) << 8) + (_vm->_draw->_palLoadData2[index1] + _vm->_draw->_palLoadData1[index2]); + + _vm->_game->_script->skip(1); } _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; @@ -1564,21 +1078,25 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { switch (cmd) { case 50: - for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr++) - _vm->_draw->_unusedPalette2[i] = *_vm->_global->_inter_execPtr; + for (int i = 0; i < 16; i++) + _vm->_draw->_unusedPalette2[i] = _vm->_game->_script->readByte(); break; case 52: - for (int i = 0; i < 16; i++, _vm->_global->_inter_execPtr += 3) { - _vm->_draw->_vgaPalette[i].red = _vm->_global->_inter_execPtr[0]; - _vm->_draw->_vgaPalette[i].green = _vm->_global->_inter_execPtr[1]; - _vm->_draw->_vgaPalette[i].blue = _vm->_global->_inter_execPtr[2]; + for (int i = 0; i < 16; i++) { + _vm->_draw->_vgaPalette[i].red = _vm->_game->_script->readByte(); + _vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte(); + _vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte(); } break; case 53: - palPtr = _vm->_game->loadTotResource(_vm->_inter->load16()); - memcpy((char *) _vm->_draw->_vgaPalette, palPtr, 768); + resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16()); + if (!resource) + break; + + memcpy((char *) _vm->_draw->_vgaPalette, resource->getData(), MIN<int>(768, resource->getSize())); + delete resource; break; case 54: @@ -1586,11 +1104,15 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { break; case 61: - index1 = *_vm->_global->_inter_execPtr++; - index2 = (*_vm->_global->_inter_execPtr++ - index1 + 1) * 3; - palPtr = _vm->_game->loadTotResource(_vm->_inter->load16()); + index1 = _vm->_game->_script->readByte(); + index2 = (_vm->_game->_script->readByte() - index1 + 1) * 3; + resource = _vm->_game->_resources->getResource(_vm->_game->_script->readInt16()); + if (!resource) + break; + memcpy((char *) _vm->_draw->_vgaPalette + index1 * 3, - palPtr + index1 * 3, index2); + resource->getData() + index1 * 3, index2); + delete resource; if (_vm->_draw->_applyPal) { _vm->_draw->_applyPal = false; @@ -1628,7 +1150,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { int16 key; uint32 now; - cmd = load16(); + cmd = _vm->_game->_script->readInt16(); animPalette(); _vm->_draw->blitInvalidated(); @@ -1643,7 +1165,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { // to become 5000. We deliberately slow down busy-waiting, so we shorten // the counting, too. if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) && - ((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) && + (_vm->_game->_script->pos() == 729) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot")) WRITE_VAR(59, 4000); @@ -1689,10 +1211,10 @@ bool Inter_v1::o1_capturePush(OpFuncParams ¶ms) { int16 left, top; int16 width, height; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); if ((width < 0) || (height < 0)) return false; @@ -1711,24 +1233,24 @@ bool Inter_v1::o1_capturePop(OpFuncParams ¶ms) { } bool Inter_v1::o1_animPalInit(OpFuncParams ¶ms) { - _animPalDir[0] = load16(); - _animPalLowIndex[0] = _vm->_parse->parseValExpr(); - _animPalHighIndex[0] = _vm->_parse->parseValExpr(); + _animPalDir[0] = _vm->_game->_script->readInt16(); + _animPalLowIndex[0] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[0] = _vm->_game->_script->readValExpr(); return false; } bool Inter_v1::o1_drawOperations(OpFuncParams ¶ms) { byte cmd; - cmd = *_vm->_global->_inter_execPtr++; + cmd = _vm->_game->_script->readByte(); - executeDrawOpcode(cmd); + executeOpcodeDraw(cmd); return false; } bool Inter_v1::o1_setcmdCount(OpFuncParams ¶ms) { - params.cmdCount = *_vm->_global->_inter_execPtr++; + params.cmdCount = _vm->_game->_script->readByte(); params.counter = 0; return false; } @@ -1737,7 +1259,7 @@ bool Inter_v1::o1_return(OpFuncParams ¶ms) { if (params.retFlag != 2) _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } @@ -1747,7 +1269,7 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams ¶ms) { } bool Inter_v1::o1_speakerOn(OpFuncParams ¶ms) { - _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1); + _vm->_sound->speakerOn(_vm->_game->_script->readValExpr(), -1); return false; } @@ -1757,11 +1279,11 @@ bool Inter_v1::o1_speakerOff(OpFuncParams ¶ms) { } bool Inter_v1::o1_putPixel(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_PUTPIXEL); return false; } @@ -1773,33 +1295,33 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { gobParams.extraData = 0; gobParams.objDesc = 0; - gobParams.retVarPtr.set(*_vm->_inter->_variables, 236); + gobParams.retVarPtr.set(*_variables, 236); - cmd = load16(); - _vm->_global->_inter_execPtr += 2; + cmd = _vm->_game->_script->readInt16(); + _vm->_game->_script->skip(2); if ((cmd > 0) && (cmd < 17)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData]; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); } if ((cmd > 90) && (cmd < 107)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData]; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); cmd -= 90; } if ((cmd > 110) && (cmd < 128)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_goblins[gobParams.extraData]; cmd -= 90; } else if ((cmd > 20) && (cmd < 38)) { objDescSet = true; - gobParams.extraData = load16(); + gobParams.extraData = _vm->_game->_script->readInt16(); gobParams.objDesc = _vm->_goblin->_objects[gobParams.extraData]; } @@ -1815,7 +1337,7 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { if ((cmd < 40) && objDescSet && !gobParams.objDesc) return false; - executeGoblinOpcode(cmd, gobParams); + executeOpcodeGob(cmd, gobParams); return false; } @@ -1825,31 +1347,31 @@ bool Inter_v1::o1_createSprite(OpFuncParams ¶ms) { int16 width, height; int16 flag; - if (_vm->_global->_inter_execPtr[1] == 0) { - index = load16(); - width = load16(); - height = load16(); + if (_vm->_game->_script->peekByte(1) == 0) { + index = _vm->_game->_script->readInt16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); } else { - index = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); } - flag = load16(); + flag = _vm->_game->_script->readInt16(); _vm->_draw->initSpriteSurf(index, width, height, flag ? 2 : 0); return false; } bool Inter_v1::o1_freeSprite(OpFuncParams ¶ms) { - _vm->_draw->freeSprite(load16()); + _vm->_draw->freeSprite(_vm->_game->_script->readInt16()); return false; } bool Inter_v1::o1_returnTo(OpFuncParams ¶ms) { if (params.retFlag == 1) { _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } @@ -1858,14 +1380,14 @@ bool Inter_v1::o1_returnTo(OpFuncParams ¶ms) { *_breakFromLevel = *_nestLevel; _break = true; - _vm->_global->_inter_execPtr = 0; + _vm->_game->_script->setFinished(true); return true; } bool Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) { - _vm->_draw->_spriteLeft = load16(); - _vm->_draw->_destSurface = load16(); - _vm->_draw->_transparency = load16(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); + _vm->_draw->_transparency = _vm->_game->_script->readInt16(); _vm->_draw->_destSpriteX = 0; _vm->_draw->_destSpriteY = 0; @@ -1874,25 +1396,25 @@ bool Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) { } bool Inter_v1::o1_copySprite(OpFuncParams ¶ms) { - if (_vm->_global->_inter_execPtr[1] == 0) - _vm->_draw->_sourceSurface = load16(); + if (_vm->_game->_script->peekByte(1) == 0) + _vm->_draw->_sourceSurface = _vm->_game->_script->readInt16(); else - _vm->_draw->_sourceSurface = _vm->_parse->parseValExpr(); + _vm->_draw->_sourceSurface = _vm->_game->_script->readValExpr(); - if (_vm->_global->_inter_execPtr[1] == 0) - _vm->_draw->_destSurface = load16(); + if (_vm->_game->_script->peekByte(1) == 0) + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); else - _vm->_draw->_destSurface = _vm->_parse->parseValExpr(); + _vm->_draw->_destSurface = _vm->_game->_script->readValExpr(); - _vm->_draw->_spriteLeft = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteTop = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_spriteLeft = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteTop = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_transparency = load16(); + _vm->_draw->_transparency = _vm->_game->_script->readInt16(); _vm->_draw->spriteOperation(DRAW_BLITSURF); return false; @@ -1901,16 +1423,16 @@ bool Inter_v1::o1_copySprite(OpFuncParams ¶ms) { bool Inter_v1::o1_fillRect(OpFuncParams ¶ms) { int16 destSurf; - _vm->_draw->_destSurface = destSurf = load16(); + _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); - if (!_vm->_draw->_spritesArray[(destSurf > 100) ? (destSurf - 80) : destSurf]) + if (!_vm->_draw->_spritesArray[(destSurf >= 100) ? (destSurf - 80) : destSurf]) return false; if (_vm->_draw->_spriteRight < 0) { @@ -1927,14 +1449,14 @@ bool Inter_v1::o1_fillRect(OpFuncParams ¶ms) { } bool Inter_v1::o1_drawLine(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_DRAWLINE); return false; } @@ -1945,28 +1467,28 @@ bool Inter_v1::o1_strToLong(OpFuncParams ¶ms) { int16 destVar; int32 res; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); strncpy0(str, GET_VARO_STR(strVar), 19); res = atoi(str); - destVar = _vm->_parse->parseVarIndex(); + destVar = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(destVar, res); return false; } bool Inter_v1::o1_invalidate(OpFuncParams ¶ms) { - _vm->_draw->_destSurface = load16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); + _vm->_draw->_destSurface = _vm->_game->_script->readInt16(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); _vm->_draw->spriteOperation(DRAW_INVALIDATE); return false; } bool Inter_v1::o1_setBackDelta(OpFuncParams ¶ms) { - _vm->_draw->_backDeltaX = _vm->_parse->parseValExpr(); - _vm->_draw->_backDeltaY = _vm->_parse->parseValExpr(); + _vm->_draw->_backDeltaX = _vm->_game->_script->readValExpr(); + _vm->_draw->_backDeltaY = _vm->_game->_script->readValExpr(); return false; } @@ -1977,9 +1499,9 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { int16 index; int16 endRep; - index = _vm->_parse->parseValExpr(); - repCount = _vm->_parse->parseValExpr(); - frequency = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + repCount = _vm->_game->_script->readValExpr(); + frequency = _vm->_game->_script->readValExpr(); SoundDesc *sample = _vm->_sound->sampleGetBySlot(index); @@ -2002,7 +1524,7 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { } if (sample->getType() == SOUND_ADL) { - _vm->_sound->adlibLoad(sample->getData(), sample->size(), index); + _vm->_sound->adlibLoadADL(sample->getData(), sample->size(), index); _vm->_sound->adlibSetRepeating(repCount - 1); _vm->_sound->adlibPlay(); } else { @@ -2015,7 +1537,7 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { bool Inter_v1::o1_stopSound(OpFuncParams ¶ms) { _vm->_sound->adlibStop(); - _vm->_sound->blasterStop(_vm->_parse->parseValExpr()); + _vm->_sound->blasterStop(_vm->_game->_script->readValExpr()); _soundEndTimeKey = 0; return false; @@ -2041,8 +1563,8 @@ bool Inter_v1::o1_playComposition(OpFuncParams ¶ms) { int16 dataVar; int16 freqVal; - dataVar = _vm->_parse->parseVarIndex(); - freqVal = _vm->_parse->parseValExpr(); + dataVar = _vm->_game->_script->readVarIndex(); + freqVal = _vm->_game->_script->readValExpr(); for (int i = 0; i < 50; i++) composition[i] = (int16) VAR_OFFSET(dataVar + i * 4); @@ -2054,8 +1576,8 @@ bool Inter_v1::o1_getFreeMem(OpFuncParams ¶ms) { int16 freeVar; int16 maxFreeVar; - freeVar = _vm->_parse->parseVarIndex(); - maxFreeVar = _vm->_parse->parseVarIndex(); + freeVar = _vm->_game->_script->readVarIndex(); + maxFreeVar = _vm->_game->_script->readVarIndex(); // HACK WRITE_VAR_OFFSET(freeVar, 1000000); @@ -2067,22 +1589,22 @@ bool Inter_v1::o1_checkData(OpFuncParams ¶ms) { int16 handle; int16 varOff; - evalExpr(0); - varOff = _vm->_parse->parseVarIndex(); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + varOff = _vm->_game->_script->readVarIndex(); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); WRITE_VAR_OFFSET(varOff, handle); if (handle >= 0) _vm->_dataIO->closeData(handle); else - warning("File \"%s\" not found", _vm->_global->_inter_resStr); + warning("File \"%s\" not found", _vm->_game->_script->getResultStr()); return false; } bool Inter_v1::o1_prepareStr(OpFuncParams ¶ms) { int16 strVar; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); _vm->_util->prepareStr(GET_VARO_FSTR(strVar)); return false; } @@ -2091,12 +1613,12 @@ bool Inter_v1::o1_insertStr(OpFuncParams ¶ms) { int16 pos; int16 strVar; - strVar = _vm->_parse->parseVarIndex(); - evalExpr(0); - pos = _vm->_parse->parseValExpr(); + strVar = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->evalExpr(0); + pos = _vm->_game->_script->readValExpr(); char *str = GET_VARO_FSTR(strVar); - _vm->_util->insertStr(_vm->_global->_inter_resStr, str, pos); + _vm->_util->insertStr(_vm->_game->_script->getResultStr(), str, pos); return false; } @@ -2105,9 +1627,9 @@ bool Inter_v1::o1_cutStr(OpFuncParams ¶ms) { int16 pos; int16 size; - strVar = _vm->_parse->parseVarIndex(); - pos = _vm->_parse->parseValExpr(); - size = _vm->_parse->parseValExpr(); + strVar = _vm->_game->_script->readVarIndex(); + pos = _vm->_game->_script->readValExpr(); + size = _vm->_game->_script->readValExpr(); _vm->_util->cutFromStr(GET_VARO_STR(strVar), pos, size); return false; } @@ -2117,11 +1639,11 @@ bool Inter_v1::o1_strstr(OpFuncParams ¶ms) { int16 resVar; int16 pos; - strVar = _vm->_parse->parseVarIndex(); - evalExpr(0); - resVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->evalExpr(0); + resVar = _vm->_game->_script->readVarIndex(); - char *res = strstr(GET_VARO_STR(strVar), _vm->_global->_inter_resStr); + char *res = strstr(GET_VARO_STR(strVar), _vm->_game->_script->getResultStr()); pos = res ? (res - (GET_VARO_STR(strVar))) : -1; WRITE_VAR_OFFSET(resVar, pos); return false; @@ -2131,17 +1653,17 @@ bool Inter_v1::o1_istrlen(OpFuncParams ¶ms) { int16 len; int16 strVar; - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); len = strlen(GET_VARO_STR(strVar)); - strVar = _vm->_parse->parseVarIndex(); + strVar = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(strVar, len); return false; } bool Inter_v1::o1_setMousePos(OpFuncParams ¶ms) { - _vm->_global->_inter_mouseX = _vm->_parse->parseValExpr(); - _vm->_global->_inter_mouseY = _vm->_parse->parseValExpr(); + _vm->_global->_inter_mouseX = _vm->_game->_script->readValExpr(); + _vm->_global->_inter_mouseY = _vm->_game->_script->readValExpr(); _vm->_global->_inter_mouseX -= _vm->_video->_scrollOffsetX; _vm->_global->_inter_mouseY -= _vm->_video->_scrollOffsetY; if (_vm->_global->_useMouse != 0) @@ -2151,7 +1673,7 @@ bool Inter_v1::o1_setMousePos(OpFuncParams ¶ms) { } bool Inter_v1::o1_setFrameRate(OpFuncParams ¶ms) { - _vm->_util->setFrameRate(_vm->_parse->parseValExpr()); + _vm->_util->setFrameRate(_vm->_game->_script->readValExpr()); return false; } @@ -2177,27 +1699,23 @@ bool Inter_v1::o1_blitCursor(OpFuncParams ¶ms) { bool Inter_v1::o1_loadFont(OpFuncParams ¶ms) { int16 index; - evalExpr(0); - index = load16(); + _vm->_game->_script->evalExpr(0); + index = _vm->_game->_script->readInt16(); delete _vm->_draw->_fonts[index]; _vm->_draw->animateCursor(4); - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); _vm->_draw->_fonts[index] = - _vm->_util->loadFont(_vm->_global->_inter_resStr); + _vm->_util->loadFont(_vm->_game->_script->getResultStr()); - if (_vm->_game->_extHandle >= 0) - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); return false; } bool Inter_v1::o1_freeFont(OpFuncParams ¶ms) { int16 index; - index = load16(); + index = _vm->_game->_script->readInt16(); delete _vm->_draw->_fonts[index]; _vm->_draw->_fonts[index] = 0; return false; @@ -2210,17 +1728,14 @@ bool Inter_v1::o1_readData(OpFuncParams ¶ms) { int16 offset; int16 handle; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - offset = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + offset = _vm->_game->_script->readValExpr(); retSize = 0; - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); - WRITE_VAR(1, 1); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); if (handle >= 0) { DataStream *stream = _vm->_dataIO->openAsStream(handle, true); @@ -2241,8 +1756,6 @@ bool Inter_v1::o1_readData(OpFuncParams ¶ms) { delete stream; } - if (_vm->_game->_extHandle >= 0) - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); return false; } @@ -2255,22 +1768,22 @@ bool Inter_v1::o1_writeData(OpFuncParams ¶ms) { // (Gobliiins 1 doesn't use save file), so we just warn should it be // called regardless. - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - offset = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + offset = _vm->_game->_script->readValExpr(); - warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr); + warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr()); WRITE_VAR(1, 0); return false; } bool Inter_v1::o1_manageDataFile(OpFuncParams ¶ms) { - evalExpr(0); + _vm->_game->_script->evalExpr(0); - if (_vm->_global->_inter_resStr[0] != 0) - _vm->_dataIO->openDataFile(_vm->_global->_inter_resStr); + if (_vm->_game->_script->getResultStr()[0] != 0) + _vm->_dataIO->openDataFile(_vm->_game->_script->getResultStr()); else _vm->_dataIO->closeDataFile(); return false; @@ -2434,16 +1947,16 @@ void Inter_v1::o1_getMaxTick(OpGobParams ¶ms) { } void Inter_v1::o1_manipulateMap(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 item = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); manipulateMap(xPos, yPos, item); } void Inter_v1::o1_getItem(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); if ((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) params.retVarPtr = (uint32) ((_vm->_map->getItem(xPos, yPos) & 0xFF00) >> 8); @@ -2452,9 +1965,9 @@ void Inter_v1::o1_getItem(OpGobParams ¶ms) { } void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 item = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); xPos = VAR(xPos); yPos = VAR(yPos); @@ -2464,8 +1977,8 @@ void Inter_v1::o1_manipulateMapIndirect(OpGobParams ¶ms) { } void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); xPos = VAR(xPos); yPos = VAR(yPos); @@ -2477,17 +1990,17 @@ void Inter_v1::o1_getItemIndirect(OpGobParams ¶ms) { } void Inter_v1::o1_setPassMap(OpGobParams ¶ms) { - int16 xPos = load16(); - int16 yPos = load16(); - int16 val = load16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); _vm->_map->setPass(xPos, yPos, val); } void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); _vm->_goblin->_gobPositions[item].x = xPos * 2; _vm->_goblin->_gobPositions[item].y = yPos * 2; @@ -2522,20 +2035,20 @@ void Inter_v1::o1_setGoblinPosH(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinPosXH(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].x >> 1); } void Inter_v1::o1_getGoblinPosYH(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) (_vm->_goblin->_gobPositions[item].y >> 1); } void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[item]; if (yPos == 0) { @@ -2594,18 +2107,18 @@ void Inter_v1::o1_setGoblinMultState(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinUnk14(OpGobParams ¶ms) { - int16 item = load16(); - int16 val = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[item]; params.objDesc->unk14 = val; } void Inter_v1::o1_setItemIdInPocket(OpGobParams ¶ms) { - _vm->_goblin->_itemIdInPocket = load16(); + _vm->_goblin->_itemIdInPocket = _vm->_game->_script->readInt16(); } void Inter_v1::o1_setItemIndInPocket(OpGobParams ¶ms) { - _vm->_goblin->_itemIndInPocket = load16(); + _vm->_goblin->_itemIndInPocket = _vm->_game->_script->readInt16(); } void Inter_v1::o1_getItemIdInPocket(OpGobParams ¶ms) { @@ -2618,9 +2131,9 @@ void Inter_v1::o1_getItemIndInPocket(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); _vm->_goblin->_gobPositions[item].x = xPos; _vm->_goblin->_gobPositions[item].y = yPos; @@ -2655,8 +2168,8 @@ void Inter_v1::o1_setGoblinPos(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 state = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 state = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[item]; params.objDesc->nextState = state; @@ -2680,8 +2193,8 @@ void Inter_v1::o1_setGoblinState(OpGobParams ¶ms) { void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) { int16 layer; - int16 item = load16(); - int16 state = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 state = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[item]; params.objDesc->nextState = state; @@ -2708,7 +2221,7 @@ void Inter_v1::o1_setGoblinStateRedraw(OpGobParams ¶ms) { } void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[params.extraData]; params.objDesc->relaxTime--; @@ -2722,12 +2235,12 @@ void Inter_v1::o1_decRelaxTime(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinPosX(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].x; } void Inter_v1::o1_getGoblinPosY(OpGobParams ¶ms) { - int16 item = load16(); + int16 item = _vm->_game->_script->readInt16(); params.retVarPtr = (uint32) _vm->_goblin->_gobPositions[item].y; } @@ -2736,18 +2249,18 @@ void Inter_v1::o1_clearPathExistence(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinVisible(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->_goblins[params.extraData]->visible = 1; } void Inter_v1::o1_setGoblinInvisible(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->_goblins[params.extraData]->visible = 0; } void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) { - params.extraData = load16(); - int16 item = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_objects[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, @@ -2758,8 +2271,8 @@ void Inter_v1::o1_getObjectIntersect(OpGobParams ¶ms) { } void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { - params.extraData = load16(); - int16 item = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 item = _vm->_game->_script->readInt16(); params.objDesc = _vm->_goblin->_goblins[params.extraData]; if (_vm->_goblin->objIntersected(params.objDesc, @@ -2770,10 +2283,10 @@ void Inter_v1::o1_getGoblinIntersect(OpGobParams ¶ms) { } void Inter_v1::o1_setItemPos(OpGobParams ¶ms) { - int16 item = load16(); - int16 xPos = load16(); - int16 yPos = load16(); - int16 val = load16(); + int16 item = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); + int16 yPos = _vm->_game->_script->readInt16(); + int16 val = _vm->_game->_script->readInt16(); _vm->_map->_itemPoses[item].x = xPos; _vm->_map->_itemPoses[item].y = yPos; @@ -2781,12 +2294,9 @@ void Inter_v1::o1_setItemPos(OpGobParams ¶ms) { } void Inter_v1::o1_loadObjects(OpGobParams ¶ms) { - params.extraData = load16(); - if (_vm->_game->_extHandle >= 0) - _vm->_dataIO->closeData(_vm->_game->_extHandle); + params.extraData = _vm->_game->_script->readInt16(); _vm->_goblin->loadObjects((char *) VAR_ADDRESS(params.extraData)); - _vm->_game->_extHandle = _vm->_dataIO->openData(_vm->_game->_curExtFile); } void Inter_v1::o1_freeObjects(OpGobParams ¶ms) { @@ -2811,8 +2321,8 @@ void Inter_v1::o1_loadMap(OpGobParams ¶ms) { void Inter_v1::o1_moveGoblin(OpGobParams ¶ms) { int16 item; - params.extraData = load16(); - int16 xPos = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); if ((uint16) VAR(xPos) == 0) { item = @@ -2837,9 +2347,9 @@ void Inter_v1::o1_loadGoblin(OpGobParams ¶ms) { } void Inter_v1::o1_writeTreatItem(OpGobParams ¶ms) { - params.extraData = load16(); - int16 cmd = load16(); - int16 xPos = load16(); + params.extraData = _vm->_game->_script->readInt16(); + int16 cmd = _vm->_game->_script->readInt16(); + int16 xPos = _vm->_game->_script->readInt16(); if ((uint16) VAR(xPos) == 0) { WRITE_VAR(cmd, _vm->_goblin->treatItem((uint16) VAR(params.extraData))); @@ -2855,7 +2365,7 @@ void Inter_v1::o1_moveGoblin0(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinTarget(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); if (VAR(params.extraData) != 0) _vm->_goblin->_goesAtTarget = 1; else @@ -2863,11 +2373,11 @@ void Inter_v1::o1_setGoblinTarget(OpGobParams ¶ms) { } void Inter_v1::o1_setGoblinObjectsPos(OpGobParams ¶ms) { - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.extraData = VAR(params.extraData); _vm->_goblin->_objects[10]->xPos = params.extraData; - params.extraData = load16(); + params.extraData = _vm->_game->_script->readInt16(); params.extraData = VAR(params.extraData); _vm->_goblin->_objects[10]->yPos = params.extraData; } @@ -2961,38 +2471,24 @@ void Inter_v1::o1_initGoblin(OpGobParams ¶ms) { } int16 Inter_v1::loadSound(int16 slot) { - byte *dataPtr; - int16 id; - uint32 dataSize; - SoundSource source; - if (slot == -1) - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); - id = load16(); - if (id == -1) { - _vm->_global->_inter_execPtr += 9; + uint16 id = _vm->_game->_script->readUint16(); + if (id == 0xFFFF) { + _vm->_game->_script->skip(9); return 0; } - if (id >= 30000) { - source = SOUND_EXT; - - dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize); - } else { - int16 totSize; - - source = SOUND_TOT; + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return 0; - dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize); - dataSize = (uint32) ((int32) totSize); - } + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + if (!sample) + return 0; - if (dataPtr) { - SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); - if (sample) - sample->load(SOUND_SND, source, dataPtr, dataSize); - } + sample->load(SOUND_SND, resource); return 0; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 2c6a9e373c..82822330b1 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -36,10 +36,12 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/save/saveload.h" @@ -48,673 +50,126 @@ namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v2, x) - -const int Inter_v2::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {500, 40}, - {501, 41} -}; +#define OPCODEVER Inter_v2 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v2::Inter_v2(GobEngine *vm) : Inter_v1(vm) { - setupOpcodes(); } -void Inter_v2::setupOpcodes() { - static const OpcodeDrawEntryV2 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV2 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV2 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o2_loadInfogramesIns), - OPCODE(o2_startInfogrames), - OPCODE(o2_stopInfogrames), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - OPCODE(o2_playInfogrames), - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o2_handleGoblins), - /* 28 */ - OPCODE(o2_playProtracker), - OPCODE(o2_stopProtracker), - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV2 = opcodesDraw; - _opcodesFuncV2 = opcodesFunc; - _opcodesGoblinV2 = opcodesGoblin; -} +void Inter_v2::setupOpcodesDraw() { + Inter_v1::setupOpcodesDraw(); -void Inter_v2::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); + OPCODEDRAW(0x01, o2_playMult); + OPCODEDRAW(0x02, o2_freeMultKeys); - OpcodeDrawProcV2 op = _opcodesDrawV2[i].proc; + OPCODEDRAW(0x0A, o2_setRenderFlags); - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} + OPCODEDRAW(0x13, o2_multSub); -bool Inter_v2::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); + OPCODEDRAW(0x14, o2_initMult); - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } + OPCODEDRAW(0x17, o2_loadMultObject); - OpcodeFuncProcV2 op = _opcodesFuncV2[i*16 + j].proc; + OPCODEDRAW(0x1C, o2_renderStatic); + OPCODEDRAW(0x1D, o2_loadCurLayer); - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); + OPCODEDRAW(0x20, o2_playCDTrack); + OPCODEDRAW(0x21, o2_waitCDTrackEnd); + OPCODEDRAW(0x22, o2_stopCD); + OPCODEDRAW(0x23, o2_readLIC); - return false; -} + OPCODEDRAW(0x24, o2_freeLIC); + OPCODEDRAW(0x25, o2_getCDTrackPos); -void Inter_v2::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); + OPCODEDRAW(0x30, o2_loadFontToSprite); - OpcodeGoblinProcV2 op = 0; + OPCODEDRAW(0x40, o2_totSub); + OPCODEDRAW(0x41, o2_switchTotSub); + OPCODEDRAW(0x42, o2_pushVars); + OPCODEDRAW(0x43, o2_popVars); - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV2[_goblinFuncLookUp[j][1]].proc; - break; - } + OPCODEDRAW(0x50, o2_loadMapObjects); + OPCODEDRAW(0x51, o2_freeGoblins); + OPCODEDRAW(0x52, o2_moveGoblin); + OPCODEDRAW(0x53, o2_writeGoblinPos); - if (op == 0) { - int16 val; + OPCODEDRAW(0x54, o2_stopGoblin); + OPCODEDRAW(0x55, o2_setGoblinState); + OPCODEDRAW(0x56, o2_placeGoblin); - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); -} + OPCODEDRAW(0x80, o2_initScreen); + OPCODEDRAW(0x81, o2_scroll); + OPCODEDRAW(0x82, o2_setScrollOffset); + OPCODEDRAW(0x83, o2_playImd); + + OPCODEDRAW(0x84, o2_getImdInfo); + OPCODEDRAW(0x85, o2_openItk); + OPCODEDRAW(0x86, o2_closeItk); + OPCODEDRAW(0x87, o2_setImdFrontSurf); -const char *Inter_v2::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV2[i].desc; + OPCODEDRAW(0x88, o2_resetImdFrontSurf); } -const char *Inter_v2::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_v2::setupOpcodesFunc() { + Inter_v1::setupOpcodesFunc(); + + OPCODEFUNC(0x09, o2_assign); + + OPCODEFUNC(0x11, o2_printText); + + OPCODEFUNC(0x17, o2_animPalInit); - return _opcodesFuncV2[i*16 + j].desc; + OPCODEFUNC(0x18, o2_addCollision); + OPCODEFUNC(0x19, o2_freeCollision); + + OPCODEFUNC(0x25, o2_goblinFunc); + + OPCODEFUNC(0x39, o2_stopSound); + OPCODEFUNC(0x3A, o2_loadSound); + + OPCODEFUNC(0x3E, o2_getFreeMem); + OPCODEFUNC(0x3F, o2_checkData); + + OPCODEFUNC(0x4D, o2_readData); + OPCODEFUNC(0x4E, o2_writeData); } -const char *Inter_v2::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV2[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v2::setupOpcodesGob() { + OPCODEGOB( 0, o2_loadInfogramesIns); + OPCODEGOB( 1, o2_startInfogrames); + OPCODEGOB( 2, o2_stopInfogrames); + + OPCODEGOB( 10, o2_playInfogrames); + + OPCODEGOB(100, o2_handleGoblins); + + OPCODEGOB(500, o2_playProtracker); + OPCODEGOB(501, o2_stopProtracker); } -void Inter_v2::checkSwitchTable(byte **ppExec) { - byte cmd; +void Inter_v2::checkSwitchTable(uint32 &offset) { + byte type; int16 len; int32 value; bool found; found = false; - *ppExec = 0; + offset = 0; - cmd = *_vm->_global->_inter_execPtr; + type = _vm->_game->_script->peekByte(); - value = _vm->_parse->parseVarIndex(); + value = _vm->_game->_script->readVarIndex(); - switch (cmd) { - case 16: - case 18: + switch (type) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: value = (int8) READ_VARO_UINT8(value); break; - case 23: - case 26: + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: value = READ_VARO_UINT32(value); break; @@ -726,78 +181,74 @@ void Inter_v2::checkSwitchTable(byte **ppExec) { if (_terminate) return; - len = (int8) *_vm->_global->_inter_execPtr++; + len = _vm->_game->_script->readInt8(); while (len != -5) { for (int i = 0; i < len; i++) { - cmd = *_vm->_global->_inter_execPtr; + type = _vm->_game->_script->peekByte(); - switch (cmd) { - case 19: - _vm->_global->_inter_execPtr++; + switch (type) { + case TYPE_IMM_INT32: + _vm->_game->_script->skip(1); if (!found && - (value == - (int32) (READ_LE_UINT32(_vm->_global->_inter_execPtr)))) + (value == _vm->_game->_script->peekInt32())) found = true; - _vm->_global->_inter_execPtr += 5; + _vm->_game->_script->skip(5); break; - case 20: - _vm->_global->_inter_execPtr++; + case TYPE_IMM_INT16: + _vm->_game->_script->skip(1); if (!found && - (value == - (int16) (READ_LE_UINT16(_vm->_global->_inter_execPtr)))) + (value == _vm->_game->_script->peekInt16())) found = true; - _vm->_global->_inter_execPtr += 3; + _vm->_game->_script->skip(3); break; - case 21: - _vm->_global->_inter_execPtr++; - if (!found && (value == (int8) *_vm->_global->_inter_execPtr)) + case TYPE_IMM_INT8: + _vm->_game->_script->skip(1); + if (!found && (value == _vm->_game->_script->peekInt8())) found = true; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; default: if (!found) { - evalExpr(0); - if (value == _vm->_global->_inter_resVal) + _vm->_game->_script->evalExpr(0); + if (value == _vm->_game->_script->getResultInt()) found = true; } else - _vm->_parse->skipExpr(99); + _vm->_game->_script->skipExpr(99); break; } } - if (found && !*ppExec) - *ppExec = _vm->_global->_inter_execPtr; + if (found && (offset == 0)) + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; - len = (int8) *_vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); + len = _vm->_game->_script->readInt8(); } - if ((*_vm->_global->_inter_execPtr >> 4) != 4) + if ((_vm->_game->_script->peekByte() >> 4) != 4) return; - _vm->_global->_inter_execPtr++; - if (!*ppExec) - *ppExec = _vm->_global->_inter_execPtr; + _vm->_game->_script->skip(1); + if (offset == 0) + offset = _vm->_game->_script->pos(); - _vm->_global->_inter_execPtr += - READ_LE_UINT16(_vm->_global->_inter_execPtr + 2) + 2; + _vm->_game->_script->skip(_vm->_game->_script->peekUint16(2) + 2); } void Inter_v2::o2_playMult() { int16 checkEscape; - checkEscape = load16(); + checkEscape = _vm->_game->_script->readInt16(); _vm->_mult->setMultData(checkEscape >> 1); _vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0); } void Inter_v2::o2_freeMultKeys() { - uint16 index = load16(); + uint16 index = _vm->_game->_script->readUint16(); if (!_vm->_mult->hasMultData(index)) return; @@ -810,7 +261,7 @@ void Inter_v2::o2_freeMultKeys() { void Inter_v2::o2_setRenderFlags() { int16 expr; - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); if (expr & 0x8000) { _vm->_draw->_renderFlags |= expr & 0x3FFF; @@ -823,7 +274,7 @@ void Inter_v2::o2_setRenderFlags() { } void Inter_v2::o2_multSub() { - _vm->_mult->multSub(_vm->_parse->parseValExpr()); + _vm->_mult->multSub(_vm->_game->_script->readValExpr()); } void Inter_v2::o2_initMult() { @@ -838,14 +289,14 @@ void Inter_v2::o2_initMult() { oldAnimHeight = _vm->_mult->_animHeight; oldObjCount = _vm->_mult->_objCount; - _vm->_mult->_animLeft = load16(); - _vm->_mult->_animTop = load16(); - _vm->_mult->_animWidth = load16(); - _vm->_mult->_animHeight = load16(); - _vm->_mult->_objCount = load16(); - posXVar = _vm->_parse->parseVarIndex(); - posYVar = _vm->_parse->parseVarIndex(); - animDataVar = _vm->_parse->parseVarIndex(); + _vm->_mult->_animLeft = _vm->_game->_script->readInt16(); + _vm->_mult->_animTop = _vm->_game->_script->readInt16(); + _vm->_mult->_animWidth = _vm->_game->_script->readInt16(); + _vm->_mult->_animHeight = _vm->_game->_script->readInt16(); + _vm->_mult->_objCount = _vm->_game->_script->readInt16(); + posXVar = _vm->_game->_script->readVarIndex(); + posYVar = _vm->_game->_script->readVarIndex(); + animDataVar = _vm->_game->_script->readVarIndex(); if (_vm->_mult->_objects && (oldObjCount != _vm->_mult->_objCount)) { warning("Initializing new objects without having " @@ -907,12 +358,12 @@ void Inter_v2::o2_initMult() { ((oldAnimWidth != _vm->_mult->_animWidth) || (oldAnimHeight != _vm->_mult->_animHeight))) { _vm->_draw->freeSprite(22); - _vm->_mult->_animSurf = 0; + _vm->_mult->_animSurf.reset(); } _vm->_draw->adjustCoords(0, &_vm->_mult->_animWidth, &_vm->_mult->_animHeight); - if (_vm->_mult->_animSurf == 0) { + if (!_vm->_mult->_animSurf) { _vm->_draw->initSpriteSurf(22, _vm->_mult->_animWidth, _vm->_mult->_animHeight, 0); _vm->_mult->_animSurf = _vm->_draw->_spritesArray[22]; @@ -947,20 +398,20 @@ void Inter_v2::o2_loadMultObject() { int16 layer; byte *multData; - objIndex = _vm->_parse->parseValExpr(); - val = _vm->_parse->parseValExpr(); + objIndex = _vm->_game->_script->readValExpr(); + val = _vm->_game->_script->readValExpr(); *_vm->_mult->_objects[objIndex].pPosX = val; - val = _vm->_parse->parseValExpr(); + val = _vm->_game->_script->readValExpr(); *_vm->_mult->_objects[objIndex].pPosY = val; debugC(4, kDebugGameFlow, "Loading mult object %d", objIndex); multData = (byte *) _vm->_mult->_objects[objIndex].pAnimData; for (int i = 0; i < 11; i++) { - if (*_vm->_global->_inter_execPtr != 99) - multData[i] = _vm->_parse->parseValExpr(); + if (_vm->_game->_script->peekByte() != 99) + multData[i] = _vm->_game->_script->readValExpr(); else - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex]; @@ -1043,22 +494,22 @@ void Inter_v2::o2_renderStatic() { int16 layer; int16 index; - index = _vm->_parse->parseValExpr(); - layer = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + layer = _vm->_game->_script->readValExpr(); _vm->_scenery->renderStatic(index, layer); } void Inter_v2::o2_loadCurLayer() { - _vm->_scenery->_curStatic = _vm->_parse->parseValExpr(); - _vm->_scenery->_curStaticLayer = _vm->_parse->parseValExpr(); + _vm->_scenery->_curStatic = _vm->_game->_script->readValExpr(); + _vm->_scenery->_curStaticLayer = _vm->_game->_script->readValExpr(); } void Inter_v2::o2_playCDTrack() { if (!(_vm->_draw->_renderFlags & RENDERFLAG_NOBLITINVALIDATED)) _vm->_draw->blitInvalidated(); - evalExpr(0); - _vm->_sound->cdPlay(_vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + _vm->_sound->cdPlay(_vm->_game->_script->getResultStr()); } void Inter_v2::o2_waitCDTrackEnd() { @@ -1075,8 +526,8 @@ void Inter_v2::o2_stopCD() { void Inter_v2::o2_readLIC() { char path[40]; - evalExpr(0); - strncpy0(path, _vm->_global->_inter_resStr, 35); + _vm->_game->_script->evalExpr(0); + strncpy0(path, _vm->_game->_script->getResultStr(), 35); strcat(path, ".LIC"); _vm->_sound->cdLoadLIC(path); @@ -1092,24 +543,24 @@ void Inter_v2::o2_getCDTrackPos() { _vm->_util->longDelay(1); - varPos = _vm->_parse->parseVarIndex(); - varName = _vm->_parse->parseVarIndex(); + varPos = _vm->_game->_script->readVarIndex(); + varName = _vm->_game->_script->readVarIndex(); WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName))); WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack()); } void Inter_v2::o2_loadFontToSprite() { - int16 i = load16(); - - _vm->_draw->_fontToSprite[i].sprite = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].base = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].width = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; - _vm->_draw->_fontToSprite[i].height = *_vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += 2; + int16 i = _vm->_game->_script->readInt16(); + + _vm->_draw->_fontToSprite[i].sprite = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].base = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].width = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); + _vm->_draw->_fontToSprite[i].height = _vm->_game->_script->readByte(); + _vm->_game->_script->skip(1); } void Inter_v2::o2_totSub() { @@ -1118,16 +569,16 @@ void Inter_v2::o2_totSub() { int flags; int i; - length = *_vm->_global->_inter_execPtr++; + length = _vm->_game->_script->readByte(); if ((length & 0x7F) > 13) error("Length in o2_totSub is greater than 13 (%d)", length); if (length & 0x80) { - evalExpr(0); - strcpy(totFile, _vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + strcpy(totFile, _vm->_game->_script->getResultStr()); } else { for (i = 0; i < length; i++) - totFile[i] = (char) *_vm->_global->_inter_execPtr++; + totFile[i] = _vm->_game->_script->readChar(); totFile[i] = 0; } @@ -1135,7 +586,7 @@ void Inter_v2::o2_totSub() { if (!scumm_stricmp(totFile, "edit")) _vm->_util->forceMouseUp(); - flags = *_vm->_global->_inter_execPtr++; + flags = _vm->_game->_script->readByte(); _vm->_game->totSub(flags, totFile); } @@ -1143,8 +594,8 @@ void Inter_v2::o2_switchTotSub() { int16 index; int16 skipPlay; - index = load16(); - skipPlay = load16(); + index = _vm->_game->_script->readInt16(); + skipPlay = _vm->_game->_script->readInt16(); _vm->_game->switchTotSub(index, skipPlay); } @@ -1153,13 +604,13 @@ void Inter_v2::o2_pushVars() { byte count; int16 varOff; - count = *_vm->_global->_inter_execPtr++; + count = _vm->_game->_script->readByte(); for (int i = 0; i < count; i++, _varStackPos++) { - if ((*_vm->_global->_inter_execPtr == 25) || - (*_vm->_global->_inter_execPtr == 28)) { + if ((_vm->_game->_script->peekByte() == 25) || + (_vm->_game->_script->peekByte() == 28)) { - varOff = _vm->_parse->parseVarIndex(); - _vm->_global->_inter_execPtr++; + varOff = _vm->_game->_script->readVarIndex(); + _vm->_game->_script->skip(1); _variables->copyTo(varOff, _varStack + _varStackPos, _vm->_global->_inter_animDataSize * 4); @@ -1167,10 +618,12 @@ void Inter_v2::o2_pushVars() { _varStack[_varStackPos] = _vm->_global->_inter_animDataSize * 4; } else { - if (evalExpr(&varOff) != 20) - _vm->_global->_inter_resVal = 0; + int32 n = _vm->_game->_script->getResultInt(); + + if (_vm->_game->_script->evalExpr(&varOff) != 20) + n = 0; - memcpy(_varStack + _varStackPos, &_vm->_global->_inter_resVal, 4); + memcpy(_varStack + _varStackPos, &n, 4); _varStackPos += 4; _varStack[_varStackPos] = 4; } @@ -1182,9 +635,9 @@ void Inter_v2::o2_popVars() { int16 varOff; int16 size; - count = *_vm->_global->_inter_execPtr++; + count = _vm->_game->_script->readByte(); for (int i = 0; i < count; i++) { - varOff = _vm->_parse->parseVarIndex(); + varOff = _vm->_game->_script->readVarIndex(); size = _varStack[--_varStackPos]; _varStackPos -= size; @@ -1204,9 +657,9 @@ void Inter_v2::o2_moveGoblin() { int16 destX, destY; int16 index; - destX = _vm->_parse->parseValExpr(); - destY = _vm->_parse->parseValExpr(); - index = _vm->_parse->parseValExpr(); + destX = _vm->_game->_script->readValExpr(); + destY = _vm->_game->_script->readValExpr(); + index = _vm->_game->_script->readValExpr(); _vm->_goblin->move(destX, destY, index); } @@ -1214,15 +667,15 @@ void Inter_v2::o2_writeGoblinPos() { int16 varX, varY; int16 index; - varX = _vm->_parse->parseVarIndex(); - varY = _vm->_parse->parseVarIndex(); - index = _vm->_parse->parseValExpr(); + varX = _vm->_game->_script->readVarIndex(); + varY = _vm->_game->_script->readVarIndex(); + index = _vm->_game->_script->readValExpr(); WRITE_VAR_OFFSET(varX, _vm->_mult->_objects[index].goblinX); WRITE_VAR_OFFSET(varY, _vm->_mult->_objects[index].goblinY); } void Inter_v2::o2_stopGoblin() { - int16 index = _vm->_parse->parseValExpr(); + int16 index = _vm->_game->_script->readValExpr(); _vm->_mult->_objects[index].pAnimData->pathExistence = 4; } @@ -1236,9 +689,9 @@ void Inter_v2::o2_setGoblinState() { int16 deltaX, deltaY; int16 deltaWidth, deltaHeight; - index = _vm->_parse->parseValExpr(); - state = _vm->_parse->parseValExpr(); - type = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + state = _vm->_game->_script->readValExpr(); + type = _vm->_game->_script->readValExpr(); Mult::Mult_Object &obj = _vm->_mult->_objects[index]; Mult::Mult_AnimData &objAnim = *(obj.pAnimData); @@ -1334,10 +787,10 @@ void Inter_v2::o2_placeGoblin() { int16 x, y; int16 state; - index = _vm->_parse->parseValExpr(); - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - state = _vm->_parse->parseValExpr(); + index = _vm->_game->_script->readValExpr(); + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + state = _vm->_game->_script->readValExpr(); _vm->_goblin->placeObject(0, 0, index, x, y, state); } @@ -1347,13 +800,13 @@ void Inter_v2::o2_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); _vm->_video->clearScreen(); @@ -1441,16 +894,16 @@ void Inter_v2::o2_scroll() { int16 curX; int16 curY; - startX = CLIP((int) _vm->_parse->parseValExpr(), 0, + startX = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfWidth - _vm->_width); - startY = CLIP((int) _vm->_parse->parseValExpr(), 0, + startY = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfHeight - _vm->_height); - endX = CLIP((int) _vm->_parse->parseValExpr(), 0, + endX = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfWidth - _vm->_width); - endY = CLIP((int) _vm->_parse->parseValExpr(), 0, + endY = CLIP((int) _vm->_game->_script->readValExpr(), 0, _vm->_video->_surfHeight - _vm->_height); - stepX = _vm->_parse->parseValExpr(); - stepY = _vm->_parse->parseValExpr(); + stepX = _vm->_game->_script->readValExpr(); + stepY = _vm->_game->_script->readValExpr(); curX = startX; curY = startY; @@ -1470,8 +923,8 @@ void Inter_v2::o2_scroll() { void Inter_v2::o2_setScrollOffset() { int16 offsetX, offsetY; - offsetX = _vm->_parse->parseValExpr(); - offsetY = _vm->_parse->parseValExpr(); + offsetX = _vm->_game->_script->readValExpr(); + offsetY = _vm->_game->_script->readValExpr(); if (offsetX == -1) { WRITE_VAR(2, _vm->_draw->_scrollOffsetX); @@ -1506,22 +959,22 @@ void Inter_v2::o2_playImd() { uint16 palCmd; bool close; - evalExpr(0); - _vm->_global->_inter_resStr[8] = 0; - strncpy0(imd, _vm->_global->_inter_resStr, 127); - - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + _vm->_game->_script->getResultStr()[8] = 0; + strncpy0(imd, _vm->_game->_script->getResultStr(), 127); + + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " - "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y, + "paletteCmd %d (%d - %d), flags %X", _vm->_game->_script->getResultStr(), x, y, startFrame, lastFrame, palCmd, palStart, palEnd, flags); if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) { @@ -1550,28 +1003,28 @@ void Inter_v2::o2_getImdInfo() { int16 varFrames; int16 varWidth, varHeight; - evalExpr(0); - varX = _vm->_parse->parseVarIndex(); - varY = _vm->_parse->parseVarIndex(); - varFrames = _vm->_parse->parseVarIndex(); - varWidth = _vm->_parse->parseVarIndex(); - varHeight = _vm->_parse->parseVarIndex(); + _vm->_game->_script->evalExpr(0); + varX = _vm->_game->_script->readVarIndex(); + varY = _vm->_game->_script->readVarIndex(); + varFrames = _vm->_game->_script->readVarIndex(); + varWidth = _vm->_game->_script->readVarIndex(); + varHeight = _vm->_game->_script->readVarIndex(); // WORKAROUND: The nut rolling animation in the administration center // in Woodruff is called "noixroul", but the scripts think it's "noixroule". if ((_vm->getGameType() == kGameTypeWoodruff) && - (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule"))) - strcpy(_vm->_global->_inter_resStr, "noixroul"); + (!scumm_stricmp(_vm->_game->_script->getResultStr(), "noixroule"))) + strcpy(_vm->_game->_script->getResultStr(), "noixroul"); - _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY, + _vm->_vidPlayer->writeVideoInfo(_vm->_game->_script->getResultStr(), varX, varY, varFrames, varWidth, varHeight); } void Inter_v2::o2_openItk() { char fileName[32]; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 27); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -1588,50 +1041,47 @@ void Inter_v2::o2_setImdFrontSurf() { void Inter_v2::o2_resetImdFrontSurf() { } -bool Inter_v2::o2_evaluateStore(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - - savedPos = _vm->_global->_inter_execPtr; - varOff = _vm->_parse->parseVarIndex(); +bool Inter_v2::o2_assign(OpFuncParams ¶ms) { + byte destType = _vm->_game->_script->peekByte(); + int16 dest = _vm->_game->_script->readVarIndex(); - if (*_vm->_global->_inter_execPtr == 99) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + byte loopCount; + if (_vm->_game->_script->peekByte() == 99) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); } else loopCount = 1; for (int i = 0; i < loopCount; i++) { - token = evalExpr(&result); - switch (savedPos[0]) { - case 16: - case 18: - WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal); + int16 result; + int16 srcType = _vm->_game->_script->evalExpr(&result); + + switch (destType) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: + WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt()); break; - case 17: - case 27: - WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal); + case TYPE_VAR_INT16: + case TYPE_ARRAY_INT16: + WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt()); break; - case 23: - case 26: - WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 24: - WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32_AS_INT16: + WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } } @@ -1643,12 +1093,12 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { char buf[60]; int i; - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); - _vm->_draw->_backColor = _vm->_parse->parseValExpr(); - _vm->_draw->_frontColor = _vm->_parse->parseValExpr(); - _vm->_draw->_fontIndex = _vm->_parse->parseValExpr(); + _vm->_draw->_backColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_frontColor = _vm->_game->_script->readValExpr(); + _vm->_draw->_fontIndex = _vm->_game->_script->readValExpr(); _vm->_draw->_destSurface = 21; _vm->_draw->_textToPrint = buf; _vm->_draw->_transparency = 0; @@ -1659,48 +1109,47 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { } do { - for (i = 0; (((char) *_vm->_global->_inter_execPtr) != '.') && - (*_vm->_global->_inter_execPtr != 200); - i++, _vm->_global->_inter_execPtr++) { - buf[i] = (char) *_vm->_global->_inter_execPtr; + for (i = 0; (_vm->_game->_script->peekChar() != '.') && + (_vm->_game->_script->peekByte() != 200); i++) { + buf[i] = _vm->_game->_script->readChar(); } - if (*_vm->_global->_inter_execPtr != 200) { - _vm->_global->_inter_execPtr++; - switch (*_vm->_global->_inter_execPtr) { - case 16: - case 18: + if (_vm->_game->_script->peekByte() != 200) { + _vm->_game->_script->skip(1); + switch (_vm->_game->_script->peekByte()) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: sprintf(buf + i, "%d", - (int8) READ_VARO_UINT8(_vm->_parse->parseVarIndex())); + (int8) READ_VARO_UINT8(_vm->_game->_script->readVarIndex())); break; - case 17: - case 24: - case 27: + case TYPE_VAR_INT16: + case TYPE_VAR_INT32_AS_INT16: + case TYPE_ARRAY_INT16: sprintf(buf + i, "%d", - (int16) READ_VARO_UINT16(_vm->_parse->parseVarIndex())); + (int16) READ_VARO_UINT16(_vm->_game->_script->readVarIndex())); break; - case 23: - case 26: + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: sprintf(buf + i, "%d", - VAR_OFFSET(_vm->_parse->parseVarIndex())); + VAR_OFFSET(_vm->_game->_script->readVarIndex())); break; - case 25: - case 28: + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: sprintf(buf + i, "%s", - GET_VARO_STR(_vm->_parse->parseVarIndex())); + GET_VARO_STR(_vm->_game->_script->readVarIndex())); break; } - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); } else buf[i] = 0; _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - } while (*_vm->_global->_inter_execPtr != 200); + } while (_vm->_game->_script->peekByte() != 200); - _vm->_global->_inter_execPtr++; + _vm->_game->_script->skip(1); return false; } @@ -1708,20 +1157,20 @@ bool Inter_v2::o2_printText(OpFuncParams ¶ms) { bool Inter_v2::o2_animPalInit(OpFuncParams ¶ms) { int16 index; - index = load16(); + index = _vm->_game->_script->readInt16(); if (index > 0) { index--; - _animPalLowIndex[index] = _vm->_parse->parseValExpr(); - _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalLowIndex[index] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[index] = _vm->_game->_script->readValExpr(); _animPalDir[index] = 1; } else if (index == 0) { memset(_animPalDir, 0, 8 * sizeof(int16)); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); } else { index = -index - 1; - _animPalLowIndex[index] = _vm->_parse->parseValExpr(); - _animPalHighIndex[index] = _vm->_parse->parseValExpr(); + _animPalLowIndex[index] = _vm->_game->_script->readValExpr(); + _animPalHighIndex[index] = _vm->_game->_script->readValExpr(); _animPalDir[index] = -1; } return false; @@ -1734,14 +1183,14 @@ bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { int16 key; int16 funcSub; - id = _vm->_parse->parseValExpr(); - funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData; - left = _vm->_parse->parseValExpr(); - top = _vm->_parse->parseValExpr(); - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - key = load16(); + id = _vm->_game->_script->readValExpr(); + funcSub = _vm->_game->_script->pos(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + key = _vm->_game->_script->readInt16(); if (key == 0) key = ABS(id) + 41960; @@ -1775,7 +1224,7 @@ bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { bool Inter_v2::o2_freeCollision(OpFuncParams ¶ms) { int16 id; - id = _vm->_parse->parseValExpr(); + id = _vm->_game->_script->readValExpr(); if (id == -2) { for (int i = 0; i < 150; i++) { if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) @@ -1797,9 +1246,9 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) { // It's not yet implemented, so we fudge our way through // and pretend we've won. if (_vm->getGameType() == kGameTypeInca2) { - _vm->_global->_inter_execPtr += 4; - uint16 resVar = (uint16) load16(); - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); + uint16 resVar = _vm->_game->_script->readUint16(); + _vm->_game->_script->skip(4); WRITE_VAR(resVar, 1); return false; @@ -1808,18 +1257,20 @@ bool Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) { OpGobParams gobParams; int16 cmd; - cmd = load16(); - _vm->_global->_inter_execPtr += 2; + cmd = _vm->_game->_script->readInt16(); + + gobParams.paramCount = _vm->_game->_script->readInt16(); + gobParams.extraData = cmd; if (cmd != 101) - executeGoblinOpcode(cmd, gobParams); + executeOpcodeGob(cmd, gobParams); return false; } bool Inter_v2::o2_stopSound(OpFuncParams ¶ms) { int16 expr; - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); if (expr < 0) { _vm->_sound->adlibStop(); @@ -1839,13 +1290,13 @@ bool Inter_v2::o2_getFreeMem(OpFuncParams ¶ms) { int16 freeVar; int16 maxFreeVar; - freeVar = _vm->_parse->parseVarIndex(); - maxFreeVar = _vm->_parse->parseVarIndex(); + freeVar = _vm->_game->_script->readVarIndex(); + maxFreeVar = _vm->_game->_script->readVarIndex(); // HACK WRITE_VAR_OFFSET(freeVar, 1000000); WRITE_VAR_OFFSET(maxFreeVar, 1000000); - WRITE_VAR(16, READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4); + WRITE_VAR(16, _vm->_game->_script->getVariablesCount() * 4); return false; } @@ -1855,23 +1306,22 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { int32 size; SaveLoad::SaveMode mode; - evalExpr(0); - varOff = _vm->_parse->parseVarIndex(); + _vm->_game->_script->evalExpr(0); + varOff = _vm->_game->_script->readVarIndex(); size = -1; handle = 1; - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeNone) { - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); - if (handle >= 0) { - _vm->_dataIO->closeData(handle); - size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr); - } else - warning("File \"%s\" not found", _vm->_global->_inter_resStr); + if (_vm->_dataIO->existData(_vm->_game->_script->getResultStr())) + size = _vm->_dataIO->getDataSize(_vm->_game->_script->getResultStr()); + else + warning("File \"%s\" not found", _vm->_game->_script->getResultStr()); + } else if (mode == SaveLoad::kSaveModeSave) - size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr); + size = _vm->_saveLoad->getSize(_vm->_game->_script->getResultStr()); else if (mode == SaveLoad::kSaveModeExists) size = 23; @@ -1879,7 +1329,7 @@ bool Inter_v2::o2_checkData(OpFuncParams ¶ms) { handle = -1; debugC(2, kDebugFileIO, "Requested size of file \"%s\": %d", - _vm->_global->_inter_resStr, size); + _vm->_game->_script->getResultStr(), size); WRITE_VAR_OFFSET(varOff, handle); WRITE_VAR(16, (uint32) size); @@ -1896,20 +1346,20 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { byte *buf; SaveLoad::SaveMode mode; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - evalExpr(0); - offset = _vm->_global->_inter_resVal; + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + _vm->_game->_script->evalExpr(0); + offset = _vm->_game->_script->getResultInt(); retSize = 0; debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)", - _vm->_global->_inter_resStr, dataVar, size, offset); + _vm->_game->_script->getResultStr(), dataVar, size, offset); - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeSave) { WRITE_VAR(1, 1); - if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset)) + if (_vm->_saveLoad->load(_vm->_game->_script->getResultStr(), dataVar, size, offset)) WRITE_VAR(1, 0); return false; } else if (mode == SaveLoad::kSaveModeIgnore) @@ -1917,22 +1367,22 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { if (size < 0) { warning("Attempted to read a raw sprite from file \"%s\"", - _vm->_global->_inter_resStr); + _vm->_game->_script->getResultStr()); return false ; } else if (size == 0) { dataVar = 0; - size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4; + size = _vm->_game->_script->getVariablesCount() * 4; } buf = _variables->getAddressOff8(dataVar); - if (_vm->_global->_inter_resStr[0] == 0) { + if (_vm->_game->_script->getResultStr()[0] == 0) { WRITE_VAR(1, size); return false; } WRITE_VAR(1, 1); - handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr); + handle = _vm->_dataIO->openData(_vm->_game->_script->getResultStr()); if (handle < 0) return false; @@ -1967,23 +1417,23 @@ bool Inter_v2::o2_writeData(OpFuncParams ¶ms) { int16 dataVar; SaveLoad::SaveMode mode; - evalExpr(0); - dataVar = _vm->_parse->parseVarIndex(); - size = _vm->_parse->parseValExpr(); - evalExpr(0); - offset = _vm->_global->_inter_resVal; + _vm->_game->_script->evalExpr(0); + dataVar = _vm->_game->_script->readVarIndex(); + size = _vm->_game->_script->readValExpr(); + _vm->_game->_script->evalExpr(0); + offset = _vm->_game->_script->getResultInt(); debugC(2, kDebugFileIO, "Write to file \"%s\" (%d, %d bytes at %d)", - _vm->_global->_inter_resStr, dataVar, size, offset); + _vm->_game->_script->getResultStr(), dataVar, size, offset); WRITE_VAR(1, 1); - mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr); + mode = _vm->_saveLoad->getSaveMode(_vm->_game->_script->getResultStr()); if (mode == SaveLoad::kSaveModeSave) { - if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset)) + if (_vm->_saveLoad->save(_vm->_game->_script->getResultStr(), dataVar, size, offset)) WRITE_VAR(1, 0); } else if (mode == SaveLoad::kSaveModeNone) - warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr); + warning("Attempted to write to file \"%s\"", _vm->_game->_script->getResultStr()); return false; } @@ -1992,7 +1442,7 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams ¶ms) { int16 varName; char fileName[20]; - varName = load16(); + varName = _vm->_game->_script->readInt16(); strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".INS"); @@ -2004,7 +1454,7 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { int16 varName; char fileName[20]; - varName = load16(); + varName = _vm->_game->_script->readInt16(); strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".DUM"); @@ -2014,13 +1464,13 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { } void Inter_v2::o2_startInfogrames(OpGobParams ¶ms) { - load16(); + _vm->_game->_script->readInt16(); _vm->_sound->infogramesPlay(); } void Inter_v2::o2_stopInfogrames(OpGobParams ¶ms) { - load16(); + _vm->_game->_script->readInt16(); _vm->_sound->infogramesStop(); } @@ -2034,12 +1484,12 @@ void Inter_v2::o2_stopProtracker(OpGobParams ¶ms) { } void Inter_v2::o2_handleGoblins(OpGobParams ¶ms) { - _vm->_goblin->_gob1NoTurn = VAR(load16()) != 0; - _vm->_goblin->_gob2NoTurn = VAR(load16()) != 0; - _vm->_goblin->_gob1RelaxTimeVar = load16(); - _vm->_goblin->_gob2RelaxTimeVar = load16(); - _vm->_goblin->_gob1Busy = VAR(load16()) != 0; - _vm->_goblin->_gob2Busy = VAR(load16()) != 0; + _vm->_goblin->_gob1NoTurn = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob2NoTurn = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob1RelaxTimeVar = _vm->_game->_script->readInt16(); + _vm->_goblin->_gob2RelaxTimeVar = _vm->_game->_script->readInt16(); + _vm->_goblin->_gob1Busy = VAR(_vm->_game->_script->readInt16()) != 0; + _vm->_goblin->_gob2Busy = VAR(_vm->_game->_script->readInt16()) != 0; _vm->_goblin->handleGoblins(); } @@ -2050,21 +1500,20 @@ int16 Inter_v2::loadSound(int16 search) { uint16 slotIdMask; uint32 dataSize; SoundType type; - SoundSource source; type = SOUND_SND; slotIdMask = 0; dataSize = 0; if (!search) { - slot = _vm->_parse->parseValExpr(); + slot = _vm->_game->_script->readValExpr(); if (slot < 0) { type = SOUND_ADL; slot = -slot; } - id = load16(); + id = _vm->_game->_script->readInt16(); } else { - id = load16(); + id = _vm->_game->_script->readInt16(); for (slot = 0; slot < Sound::kSoundsCount; slot++) if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) { @@ -2093,37 +1542,37 @@ int16 Inter_v2::loadSound(int16 search) { if (id == -1) { char sndfile[14]; - source = SOUND_FILE; - - strncpy0(sndfile, (const char *) _vm->_global->_inter_execPtr, 9); - _vm->_global->_inter_execPtr += 9; + strncpy0(sndfile, _vm->_game->_script->readString(9), 9); if (type == SOUND_ADL) strcat(sndfile, ".ADL"); else strcat(sndfile, ".SND"); - dataPtr = (byte *) _vm->_dataIO->getData(sndfile); - if (dataPtr) - dataSize = _vm->_dataIO->getDataSize(sndfile); - } else if (id >= 30000) { - source = SOUND_EXT; - - dataPtr = (byte *) _vm->_game->loadExtData(id, 0, 0, &dataSize); - } else { - int16 totSize; + dataPtr = _vm->_dataIO->getData(sndfile); + dataSize = _vm->_dataIO->getDataSize(sndfile); + if (!dataPtr) + return 0; - source = SOUND_TOT; + if (!sample->load(type, dataPtr, dataSize)) { + delete[] dataPtr; + return 0; + } - dataPtr = (byte *) _vm->_game->loadTotResource(id, &totSize); - dataSize = (uint32) ((int32) totSize); + sample->_id = id; + return slot | slotIdMask; } - if (dataPtr) { - sample->load(type, source, dataPtr, dataSize); - sample->_id = id; + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return 0; + + if (!sample->load(type, resource)) { + delete resource; + return 0; } + sample->_id = id; return slot | slotIdMask; } diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp index 000639e784..17ce7feafa 100644 --- a/engines/gob/inter_v3.cpp +++ b/engines/gob/inter_v3.cpp @@ -32,683 +32,38 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v3, x) - -const int Inter_v3::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v3 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v3::Inter_v3(GobEngine *vm) : Inter_v2(vm) { - setupOpcodes(); } -void Inter_v3::setupOpcodes() { - static const OpcodeDrawEntryV3 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o2_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o2_playImd), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV3 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o3_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV3 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o2_loadInfogramesIns), - OPCODE(o2_startInfogrames), - OPCODE(o2_stopInfogrames), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - OPCODE(o2_playInfogrames), - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o3_wobble), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV3 = opcodesDraw; - _opcodesFuncV3 = opcodesFunc; - _opcodesGoblinV3 = opcodesGoblin; +void Inter_v3::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); } -void Inter_v3::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); +void Inter_v3::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); - OpcodeDrawProcV3 op = _opcodesDrawV3[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v3::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV3 op = _opcodesFuncV3[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_v3::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV3 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV3[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); + OPCODEFUNC(0x1A, o3_getTotTextItemPart); + OPCODEFUNC(0x32, o3_copySprite); } -const char *Inter_v3::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV3[i].desc; -} +void Inter_v3::setupOpcodesGob() { + OPCODEGOB( 0, o2_loadInfogramesIns); + OPCODEGOB( 1, o2_startInfogrames); + OPCODEGOB( 2, o2_stopInfogrames); -const char *Inter_v3::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; + OPCODEGOB( 10, o2_playInfogrames); - return _opcodesFuncV3[i*16 + j].desc; -} - -const char *Inter_v3::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV3[_goblinFuncLookUp[j][1]].desc; - return ""; + OPCODEGOB(100, o3_wobble); } bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { @@ -720,18 +75,18 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { uint32 stringStartVar, stringVar; bool end; - totTextItem = load16(); - stringStartVar = _vm->_parse->parseVarIndex(); - part = _vm->_parse->parseValExpr(); + totTextItem = _vm->_game->_script->readInt16(); + stringStartVar = _vm->_game->_script->readVarIndex(); + part = _vm->_game->_script->readValExpr(); stringVar = stringStartVar; WRITE_VARO_UINT8(stringVar, 0); - if (!_vm->_game->_totTextData) + TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem); + if (!textItem) return false; - totData = _vm->_game->_totTextData->dataPtr + - _vm->_game->_totTextData->items[totTextItem].offset; + totData = textItem->getData(); // Skip background rectangles while (((int16) READ_LE_UINT16(totData)) != -1) @@ -782,6 +137,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { if ((n != 0) || (*totData == 1) || (*totData == 6) || (*totData == 7)) { WRITE_VARO_UINT8(stringVar, 0); + delete textItem; return false; } @@ -813,8 +169,9 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { WRITE_VARO_UINT16(stringVar, offX); WRITE_VARO_UINT16(stringVar + 2, offY); WRITE_VARO_UINT16(stringVar + 4, - totData - _vm->_game->_totTextData->dataPtr); + totData - _vm->_game->_resources->getTexts()); WRITE_VARO_UINT8(stringVar + 6, 0); + delete textItem; return false; } @@ -860,8 +217,10 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { if (((*totData != 2) && (*totData != 5)) || (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) { - if (curPart == part) + if (curPart == part) { + delete textItem; return false; + } stringVar = stringStartVar; WRITE_VARO_UINT8(stringVar, 0); @@ -881,6 +240,7 @@ bool Inter_v3::o3_getTotTextItemPart(OpFuncParams ¶ms) { } } + delete textItem; return false; } @@ -894,7 +254,7 @@ bool Inter_v3::o3_copySprite(OpFuncParams ¶ms) { } void Inter_v3::o3_wobble(OpGobParams ¶ms) { - _vm->_draw->wobble(_vm->_draw->_backSurface); + _vm->_draw->wobble(*_vm->_draw->_backSurface); } } // End of namespace Gob diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index 19e813ce1d..48378a5987 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -32,689 +32,32 @@ #include "gob/global.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" #include "gob/videoplayer.h" #include "gob/sound/sound.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v4, x) - -const int Inter_v4::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 1}, - {2, 2}, - {4, 3}, - {5, 4}, - {6, 5}, - {7, 6}, - {8, 7}, - {9, 8}, - {10, 9}, - {12, 10}, - {13, 11}, - {14, 12}, - {15, 13}, - {16, 14}, - {21, 15}, - {22, 16}, - {23, 17}, - {24, 18}, - {25, 19}, - {26, 20}, - {27, 21}, - {28, 22}, - {29, 23}, - {30, 24}, - {32, 25}, - {33, 26}, - {34, 27}, - {35, 28}, - {36, 29}, - {37, 30}, - {40, 31}, - {41, 32}, - {42, 33}, - {43, 34}, - {44, 35}, - {50, 36}, - {52, 37}, - {53, 38}, - {100, 39}, - {152, 40}, - {200, 41}, - {201, 42}, - {202, 43}, - {203, 44}, - {204, 45}, - {250, 46}, - {251, 47}, - {252, 48}, - {500, 49}, - {502, 50}, - {503, 51}, - {600, 52}, - {601, 53}, - {602, 54}, - {603, 55}, - {604, 56}, - {605, 57}, - {1000, 58}, - {1001, 59}, - {1002, 60}, - {1003, 61}, - {1004, 62}, - {1005, 63}, - {1006, 64}, - {1008, 65}, - {1009, 66}, - {1010, 67}, - {1011, 68}, - {1015, 69}, - {2005, 70} -}; +#define OPCODEVER Inter_v4 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v4::Inter_v4(GobEngine *vm) : Inter_v3(vm) { - setupOpcodes(); } -void Inter_v4::setupOpcodes() { - static const OpcodeDrawEntryV4 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o4_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o4_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV4 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o1_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV4 opcodesGoblin[71] = { - /* 00 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV4 = opcodesDraw; - _opcodesFuncV4 = opcodesFunc; - _opcodesGoblinV4 = opcodesGoblin; -} - -void Inter_v4::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV4 op = _opcodesFuncV4[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); +void Inter_v4::setupOpcodesDraw() { + Inter_v3::setupOpcodesDraw(); - return false; + OPCODEDRAW(0x80, o4_initScreen); + OPCODEDRAW(0x83, o4_playVmdOrMusic); } -void Inter_v4::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV4 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV4[_goblinFuncLookUp[j][1]].proc; - break; - } - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 val; - - _vm->_global->_inter_execPtr -= 2; - val = load16(); - _vm->_global->_inter_execPtr += val << 1; - } else - (this->*op) (params); -} - -const char *Inter_v4::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV4[i].desc; -} - -const char *Inter_v4::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV4[i*16 + j].desc; +void Inter_v4::setupOpcodesFunc() { + Inter_v3::setupOpcodesFunc(); } -const char *Inter_v4::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV4[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v4::setupOpcodesGob() { } void Inter_v4::o4_initScreen() { @@ -722,13 +65,13 @@ void Inter_v4::o4_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); _vm->_video->clearScreen(); @@ -772,9 +115,9 @@ void Inter_v4::o4_initScreen() { memset(_vm->_global->_greenPalette, 0, 256); memset(_vm->_global->_bluePalette, 0, 256); - _vm->_video->_splitSurf = 0; - _vm->_draw->_spritesArray[24] = 0; - _vm->_draw->_spritesArray[25] = 0; + _vm->_video->_splitSurf.reset(); + _vm->_draw->_spritesArray[24].reset(); + _vm->_draw->_spritesArray[25].reset(); _vm->_global->_videoMode = videoMode; _vm->_video->initPrimary(videoMode); @@ -791,8 +134,8 @@ void Inter_v4::o4_initScreen() { _vm->_util->setScrollOffset(); if (offY > 0) { - _vm->_draw->_spritesArray[24] = new SurfaceDesc(videoMode, _vm->_width, offY); - _vm->_draw->_spritesArray[25] = new SurfaceDesc(videoMode, _vm->_width, offY); + _vm->_draw->_spritesArray[24] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); + _vm->_draw->_spritesArray[25] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25]; } } @@ -809,8 +152,8 @@ void Inter_v4::o4_playVmdOrMusic() { uint16 palCmd; bool close; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 127); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); // WORKAROUND: The nut rolling animation in the administration center // in Woodruff is called "noixroul", but the scripts think it's "noixroule". @@ -818,14 +161,14 @@ void Inter_v4::o4_playVmdOrMusic() { (!scumm_stricmp(fileName, "noixroule"))) strcpy(fileName, "noixroul"); - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp index 488c2052eb..1c20851c8d 100644 --- a/engines/gob/inter_v5.cpp +++ b/engines/gob/inter_v5.cpp @@ -30,652 +30,73 @@ #include "gob/inter.h" #include "gob/global.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" #include "gob/draw.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v5, x) - -const int Inter_v5::_goblinFuncLookUp[][2] = { - {0, 0}, - {1, 0}, - {3, 0}, - {2, 0}, - {33, 0}, - {80, 1}, - {81, 2}, - {82, 3}, - {83, 4}, - {84, 5}, - {85, 6}, - {86, 7}, - {87, 0}, - {88, 0}, - {89, 0}, - {90, 0}, - {91, 0}, - {92, 8}, - {93, 0}, - {94, 0}, - {95, 9}, - {96, 10}, - {97, 11}, - {98, 12}, - {99, 0}, - {100, 13}, - {200, 14} -}; +#define OPCODEVER Inter_v5 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v5::Inter_v5(GobEngine *vm) : Inter_v4(vm) { - setupOpcodes(); } -void Inter_v5::setupOpcodes() { - static const OpcodeDrawEntryV5 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o2_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - OPCODE(o5_deleteFile), - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o5_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o4_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o2_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV5 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o1_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o2_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o1_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o2_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o1_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o5_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV5 opcodesGoblin[71] = { - /* 00 */ - OPCODE(o5_spaceShooter), - OPCODE(o5_getSystemCDSpeed), - OPCODE(o5_getSystemRAM), - OPCODE(o5_getSystemCPUSpeed), - /* 04 */ - OPCODE(o5_getSystemDrawSpeed), - OPCODE(o5_totalSystemSpecs), - OPCODE(o5_saveSystemSpecs), - OPCODE(o5_loadSystemSpecs), - /* 08 */ - OPCODE(o5_gob92), - OPCODE(o5_gob95), - OPCODE(o5_gob96), - OPCODE(o5_gob97), - /* 0C */ - OPCODE(o5_gob98), - OPCODE(o5_gob100), - OPCODE(o5_gob200), - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV5 = opcodesDraw; - _opcodesFuncV5 = opcodesFunc; - _opcodesGoblinV5 = opcodesGoblin; -} - -void Inter_v5::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV5 op = _opcodesDrawV5[i].proc; +void Inter_v5::setupOpcodesDraw() { + Inter_v4::setupOpcodesDraw(); - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); + OPCODEDRAW(0x61, o5_deleteFile); + OPCODEDRAW(0x80, o5_initScreen); } -bool Inter_v5::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } +void Inter_v5::setupOpcodesFunc() { + Inter_v4::setupOpcodesFunc(); - OpcodeFuncProcV5 op = _opcodesFuncV5[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; -} - -void Inter_v5::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV5 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV5[_goblinFuncLookUp[j][1]].proc; - break; - } - - _vm->_global->_inter_execPtr -= 2; - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 paramCount = load16(); - _vm->_global->_inter_execPtr += paramCount * 2; - } else { - params.extraData = i; - - (this->*op) (params); - } + OPCODEFUNC(0x45, o5_istrlen); } -const char *Inter_v5::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV5[i].desc; -} - -const char *Inter_v5::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; - - return _opcodesFuncV5[i*16 + j].desc; -} - -const char *Inter_v5::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV5[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v5::setupOpcodesGob() { + OPCODEGOB( 0, o5_spaceShooter); + OPCODEGOB( 1, o5_spaceShooter); + OPCODEGOB( 2, o5_spaceShooter); + OPCODEGOB( 3, o5_spaceShooter); + + OPCODEGOB( 33, o5_spaceShooter); + + OPCODEGOB( 80, o5_getSystemCDSpeed); + OPCODEGOB( 81, o5_getSystemRAM); + OPCODEGOB( 82, o5_getSystemCPUSpeed); + OPCODEGOB( 83, o5_getSystemDrawSpeed); + OPCODEGOB( 84, o5_totalSystemSpecs); + + OPCODEGOB( 85, o5_saveSystemSpecs); + OPCODEGOB( 86, o5_loadSystemSpecs); + + OPCODEGOB( 87, o5_spaceShooter); + OPCODEGOB( 88, o5_spaceShooter); + OPCODEGOB( 89, o5_spaceShooter); + OPCODEGOB( 90, o5_spaceShooter); + + OPCODEGOB( 91, o5_spaceShooter); + OPCODEGOB( 92, o5_gob92); + OPCODEGOB( 93, o5_spaceShooter); + OPCODEGOB( 94, o5_spaceShooter); + + OPCODEGOB( 95, o5_gob95); + OPCODEGOB( 96, o5_gob96); + OPCODEGOB( 97, o5_gob97); + OPCODEGOB( 98, o5_gob98); + + OPCODEGOB( 99, o5_spaceShooter); + OPCODEGOB(100, o5_gob100); + OPCODEGOB(200, o5_gob200); } void Inter_v5::o5_deleteFile() { - evalExpr(0); + _vm->_game->_script->evalExpr(0); - warning("Dynasty Stub: deleteFile \"%s\"", _vm->_global->_inter_resStr); + warning("Dynasty Stub: deleteFile \"%s\"", _vm->_game->_script->getResultStr()); } void Inter_v5::o5_initScreen() { @@ -683,13 +104,13 @@ void Inter_v5::o5_initScreen() { int16 videoMode; int16 width, height; - offY = load16(); + offY = _vm->_game->_script->readInt16(); videoMode = offY & 0xFF; offY = (offY >> 8) & 0xFF; - width = _vm->_parse->parseValExpr(); - height = _vm->_parse->parseValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); warning("initScreen: %d, %d, %d, %d", width, height, offY, videoMode); @@ -754,9 +175,9 @@ void Inter_v5::o5_initScreen() { memset(_vm->_global->_greenPalette, 0, 256); memset(_vm->_global->_bluePalette, 0, 256); - _vm->_video->_splitSurf = 0; - _vm->_draw->_spritesArray[24] = 0; - _vm->_draw->_spritesArray[25] = 0; + _vm->_video->_splitSurf.reset(); + _vm->_draw->_spritesArray[24].reset(); + _vm->_draw->_spritesArray[25].reset(); _vm->_global->_videoMode = videoMode; _vm->_video->initPrimary(videoMode); @@ -773,8 +194,8 @@ void Inter_v5::o5_initScreen() { _vm->_util->setScrollOffset(); if (offY > 0) { - _vm->_draw->_spritesArray[24] = new SurfaceDesc(videoMode, _vm->_width, offY); - _vm->_draw->_spritesArray[25] = new SurfaceDesc(videoMode, _vm->_width, offY); + _vm->_draw->_spritesArray[24] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); + _vm->_draw->_spritesArray[25] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25]; } } @@ -784,18 +205,18 @@ bool Inter_v5::o5_istrlen(OpFuncParams ¶ms) { int16 len; uint16 type; - if (*_vm->_global->_inter_execPtr == 0x80) { - _vm->_global->_inter_execPtr++; + if (_vm->_game->_script->peekByte() == 0x80) { + _vm->_game->_script->skip(1); - strVar1 = _vm->_parse->parseVarIndex(); - strVar2 = _vm->_parse->parseVarIndex(0, &type); + strVar1 = _vm->_game->_script->readVarIndex(); + strVar2 = _vm->_game->_script->readVarIndex(0, &type); len = _vm->_draw->stringLength(GET_VARO_STR(strVar1), READ_VARO_UINT16(strVar2)); } else { - strVar1 = _vm->_parse->parseVarIndex(); - strVar2 = _vm->_parse->parseVarIndex(0, &type); + strVar1 = _vm->_game->_script->readVarIndex(); + strVar2 = _vm->_game->_script->readVarIndex(0, &type); if (_vm->_global->_language == 10) { // Extra handling for Japanese strings @@ -814,44 +235,40 @@ bool Inter_v5::o5_istrlen(OpFuncParams ¶ms) { } void Inter_v5::o5_spaceShooter(OpGobParams ¶ms) { - int16 paramCount = load16(); - warning("Dynasty Stub: Space shooter: %d, %d, %s", - params.extraData, paramCount, _vm->_game->_curTotFile); + params.extraData, params.paramCount, _vm->_game->_curTotFile); - if (paramCount < 4) { + if (params.paramCount < 4) { warning("Space shooter variable counter < 4"); - _vm->_global->_inter_execPtr += paramCount * 2; + _vm->_game->_script->skip(params.paramCount * 2); return; } - uint32 var1 = load16() * 4; - uint32 var2 = load16() * 4; + uint32 var1 = _vm->_game->_script->readInt16() * 4; + uint32 var2 = _vm->_game->_script->readInt16() * 4; - load16(); - load16(); + _vm->_game->_script->readInt16(); + _vm->_game->_script->readInt16(); if (params.extraData != 0) { WRITE_VARO_UINT32(var1, 2); WRITE_VARO_UINT32(var2, 0); } else { - if (paramCount < 5) { + if (params.paramCount < 5) { warning("Space shooter variable counter < 5"); return; } - _vm->_global->_inter_execPtr += (paramCount - 4) * 2; + _vm->_game->_script->skip((params.paramCount - 4) * 2); } } void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, _vm->_draw->_backSurface, font); + _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, *_vm->_draw->_backSurface, font); _vm->_draw->forceBlit(); delete font; @@ -859,13 +276,11 @@ void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, _vm->_draw->_backSurface, font); + _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, *_vm->_draw->_backSurface, font); _vm->_draw->forceBlit(); delete font; @@ -873,13 +288,11 @@ void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, _vm->_draw->_backSurface, font); + _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, *_vm->_draw->_backSurface, font); _vm->_draw->forceBlit(); delete font; @@ -887,13 +300,11 @@ void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, _vm->_draw->_backSurface, font); + _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, *_vm->_draw->_backSurface, font); _vm->_draw->forceBlit(); delete font; @@ -901,13 +312,11 @@ void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { } void Inter_v5::o5_totalSystemSpecs(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 100); // Fudging 100% + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% Video::FontDesc *font; if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, _vm->_draw->_backSurface, font); + _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, *_vm->_draw->_backSurface, font); _vm->_draw->forceBlit(); delete font; @@ -917,8 +326,6 @@ void Inter_v5::o5_totalSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_saveSystemSpecs(OpGobParams ¶ms) { warning("Dynasty Stub: Saving system specifications"); - _vm->_global->_inter_execPtr += 2; - /* FILE *f = fopen("SAVE\\SPEED.INF", w); fwrite(&_cdSpeed, sizeof(_cdSpeed), 1, f); @@ -933,8 +340,6 @@ void Inter_v5::o5_saveSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_loadSystemSpecs(OpGobParams ¶ms) { warning("Dynasty Stub: Loading system specifications"); - _vm->_global->_inter_execPtr += 2; - /* FILE *f = fopen("SAVE\\SPEED.INF", r); fread(&_cdSpeed, sizeof(_cdSpeed), 1, f); @@ -971,32 +376,26 @@ void Inter_v5::o5_loadSystemSpecs(OpGobParams ¶ms) { void Inter_v5::o5_gob92(OpGobParams ¶ms) { warning("Dynasty Stub: GobFunc 92"); - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) _gob92_1)) */); } void Inter_v5::o5_gob95(OpGobParams ¶ms) { warning("Dynasty Stub: GobFunc 95"); - _vm->_global->_inter_execPtr += 2; - - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */); - WRITE_VAR_UINT32(load16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle4)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle3)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int8) speedThrottle2)) */); + WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 0 /* (uint32) ((int32) ((int16) speedThrottle1)) */); } void Inter_v5::o5_gob96(OpGobParams ¶ms) { int16 speedThrottle4, speedThrottle1; byte speedThrottle3, speedThrottle2; - _vm->_global->_inter_execPtr += 2; - - speedThrottle4 = READ_VAR_UINT16(load16()); - speedThrottle3 = READ_VAR_UINT8(load16()); - speedThrottle2 = READ_VAR_UINT8(load16()); - speedThrottle1 = READ_VAR_UINT16(load16()); + speedThrottle4 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + speedThrottle3 = READ_VAR_UINT8(_vm->_game->_script->readInt16()); + speedThrottle2 = READ_VAR_UINT8(_vm->_game->_script->readInt16()); + speedThrottle1 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); warning("Dynasty Stub: GobFunc 96: %d, %d, %d, %d", speedThrottle4, speedThrottle3, speedThrottle2, speedThrottle1); @@ -1006,23 +405,17 @@ void Inter_v5::o5_gob96(OpGobParams ¶ms) { void Inter_v5::o5_gob97(OpGobParams ¶ms) { _gob_97_98_val = 1; - - _vm->_global->_inter_execPtr += 2; } void Inter_v5::o5_gob98(OpGobParams ¶ms) { _gob_97_98_val = 0; - - _vm->_global->_inter_execPtr += 2; } void Inter_v5::o5_gob100(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - uint16 var1 = READ_VAR_UINT16(load16()); - uint16 var2 = READ_VAR_UINT16(load16()); - uint16 var3 = READ_VAR_UINT16(load16()); - uint16 var4 = READ_VAR_UINT16(load16()); + uint16 var1 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var2 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var3 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); + uint16 var4 = READ_VAR_UINT16(_vm->_game->_script->readInt16()); warning("Dynasty Stub: GobFunc 100: %d, %d, %d, %d", var1, var2, var3, var4); @@ -1031,11 +424,9 @@ void Inter_v5::o5_gob100(OpGobParams ¶ms) { } void Inter_v5::o5_gob200(OpGobParams ¶ms) { - _vm->_global->_inter_execPtr += 2; - - uint16 var1 = load16(); // index into the spritesArray - uint16 var2 = load16(); - uint16 var3 = load16(); + uint16 var1 = _vm->_game->_script->readUint16(); // index into the spritesArray + uint16 var2 = _vm->_game->_script->readUint16(); + uint16 var3 = _vm->_game->_script->readUint16(); warning("Dynasty Stub: GobFunc 200: %d, %d, %d", var1, var2, var3); } diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index 04db46c643..506de821d4 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -32,626 +32,43 @@ #include "gob/helper.h" #include "gob/global.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/expression.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/draw.h" #include "gob/sound/sound.h" #include "gob/videoplayer.h" namespace Gob { -#define OPCODE(x) _OPCODE(Inter_v6, x) - -const int Inter_v6::_goblinFuncLookUp[][2] = { - {0, 0}, -}; +#define OPCODEVER Inter_v6 +#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x) +#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x) +#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x) Inter_v6::Inter_v6(GobEngine *vm) : Inter_v5(vm) { _gotFirstPalette = false; - - setupOpcodes(); -} - -void Inter_v6::setupOpcodes() { - static const OpcodeDrawEntryV6 opcodesDraw[256] = { - /* 00 */ - OPCODE(o1_loadMult), - OPCODE(o2_playMult), - OPCODE(o2_freeMultKeys), - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - OPCODE(o1_initCursor), - /* 08 */ - OPCODE(o1_initCursorAnim), - OPCODE(o1_clearCursorAnim), - OPCODE(o2_setRenderFlags), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - OPCODE(o1_loadAnim), - OPCODE(o1_freeAnim), - OPCODE(o1_updateAnim), - OPCODE(o2_multSub), - /* 14 */ - OPCODE(o2_initMult), - OPCODE(o1_freeMult), - OPCODE(o1_animate), - OPCODE(o2_loadMultObject), - /* 18 */ - OPCODE(o1_getAnimLayerInfo), - OPCODE(o1_getObjAnimSize), - OPCODE(o1_loadStatic), - OPCODE(o1_freeStatic), - /* 1C */ - OPCODE(o2_renderStatic), - OPCODE(o2_loadCurLayer), - {0, ""}, - {0, ""}, - /* 20 */ - OPCODE(o2_playCDTrack), - OPCODE(o2_waitCDTrackEnd), - OPCODE(o2_stopCD), - OPCODE(o2_readLIC), - /* 24 */ - OPCODE(o2_freeLIC), - OPCODE(o2_getCDTrackPos), - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o2_loadFontToSprite), - OPCODE(o1_freeFontToSprite), - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - OPCODE(o6_totSub), - OPCODE(o2_switchTotSub), - OPCODE(o2_pushVars), - OPCODE(o2_popVars), - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 48 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 4C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 50 */ - OPCODE(o2_loadMapObjects), - OPCODE(o2_freeGoblins), - OPCODE(o2_moveGoblin), - OPCODE(o2_writeGoblinPos), - /* 54 */ - OPCODE(o2_stopGoblin), - OPCODE(o2_setGoblinState), - OPCODE(o2_placeGoblin), - {0, ""}, - /* 58 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 5C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 60 */ - {0, ""}, - OPCODE(o5_deleteFile), - {0, ""}, - {0, ""}, - /* 64 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 68 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 6C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 70 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 74 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 78 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 7C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 80 */ - OPCODE(o5_initScreen), - OPCODE(o2_scroll), - OPCODE(o2_setScrollOffset), - OPCODE(o6_playVmdOrMusic), - /* 84 */ - OPCODE(o2_getImdInfo), - OPCODE(o6_openItk), - OPCODE(o2_closeItk), - OPCODE(o2_setImdFrontSurf), - /* 88 */ - OPCODE(o2_resetImdFrontSurf), - {0, ""}, - {0, ""}, - {0, ""}, - /* 8C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 90 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 94 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 98 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 9C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* A8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* AC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* B8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* BC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* C8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* CC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* D8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* DC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* E8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* EC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F0 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F4 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* F8 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* FC */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - }; - - static const OpcodeFuncEntryV6 opcodesFunc[80] = { - /* 00 */ - OPCODE(o1_callSub), - OPCODE(o1_callSub), - OPCODE(o1_printTotText), - OPCODE(o6_loadCursor), - /* 04 */ - {0, ""}, - OPCODE(o1_switch), - OPCODE(o1_repeatUntil), - OPCODE(o1_whileDo), - /* 08 */ - OPCODE(o1_if), - OPCODE(o6_evaluateStore), - OPCODE(o1_loadSpriteToPos), - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - OPCODE(o2_printText), - OPCODE(o1_loadTot), - OPCODE(o6_palLoad), - /* 14 */ - OPCODE(o1_keyFunc), - OPCODE(o1_capturePush), - OPCODE(o1_capturePop), - OPCODE(o2_animPalInit), - /* 18 */ - OPCODE(o2_addCollision), - OPCODE(o6_freeCollision), - OPCODE(o3_getTotTextItemPart), - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - OPCODE(o1_drawOperations), - OPCODE(o1_setcmdCount), - /* 20 */ - OPCODE(o1_return), - OPCODE(o1_renewTimeInVars), - OPCODE(o1_speakerOn), - OPCODE(o1_speakerOff), - /* 24 */ - OPCODE(o1_putPixel), - OPCODE(o2_goblinFunc), - OPCODE(o1_createSprite), - OPCODE(o1_freeSprite), - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - OPCODE(o1_returnTo), - OPCODE(o1_loadSpriteContent), - OPCODE(o1_copySprite), - OPCODE(o6_fillRect), - /* 34 */ - OPCODE(o1_drawLine), - OPCODE(o1_strToLong), - OPCODE(o1_invalidate), - OPCODE(o1_setBackDelta), - /* 38 */ - OPCODE(o1_playSound), - OPCODE(o2_stopSound), - OPCODE(o2_loadSound), - OPCODE(o1_freeSoundSlot), - /* 3C */ - OPCODE(o1_waitEndPlay), - OPCODE(o1_playComposition), - OPCODE(o2_getFreeMem), - OPCODE(o2_checkData), - /* 40 */ - {0, ""}, - OPCODE(o1_prepareStr), - OPCODE(o1_insertStr), - OPCODE(o1_cutStr), - /* 44 */ - OPCODE(o1_strstr), - OPCODE(o5_istrlen), - OPCODE(o1_setMousePos), - OPCODE(o1_setFrameRate), - /* 48 */ - OPCODE(o1_animatePalette), - OPCODE(o1_animateCursor), - OPCODE(o1_blitCursor), - OPCODE(o1_loadFont), - /* 4C */ - OPCODE(o1_freeFont), - OPCODE(o2_readData), - OPCODE(o2_writeData), - OPCODE(o1_manageDataFile), - }; - - static const OpcodeGoblinEntryV6 opcodesGoblin[71] = { - /* 00 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 04 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 08 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 0C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 10 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 14 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 18 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 1C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 20 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 24 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 28 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 2C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 30 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 34 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 38 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 3C */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 40 */ - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""}, - /* 44 */ - {0, ""}, - {0, ""}, - {0, ""}, - }; - - _opcodesDrawV6 = opcodesDraw; - _opcodesFuncV6 = opcodesFunc; - _opcodesGoblinV6 = opcodesGoblin; -} - -void Inter_v6::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); - - OpcodeDrawProcV6 op = _opcodesDrawV6[i].proc; - - if (op == 0) - warning("unimplemented opcodeDraw: %d", i); - else - (this->*op) (); -} - -bool Inter_v6::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - _vm->_video->_palLUT->buildNext(); - - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d", - i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile, - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData), - (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - OpcodeFuncProcV6 op = _opcodesFuncV6[i*16 + j].proc; - - if (op == 0) - warning("unimplemented opcodeFunc: %d.%d", i, j); - else - return (this->*op) (params); - - return false; } -void Inter_v6::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); - - OpcodeGoblinProcV6 op = 0; - - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) { - op = _opcodesGoblinV6[_goblinFuncLookUp[j][1]].proc; - break; - } - - _vm->_global->_inter_execPtr -= 2; - - if (op == 0) { - warning("unimplemented opcodeGoblin: %d", i); - - int16 paramCount = load16(); - _vm->_global->_inter_execPtr += paramCount * 2; - } else { - params.extraData = i; +void Inter_v6::setupOpcodesDraw() { + Inter_v5::setupOpcodesDraw(); - (this->*op) (params); - } -} - -const char *Inter_v6::getOpcodeDrawDesc(byte i) { - return _opcodesDrawV6[i].desc; + OPCODEDRAW(0x40, o6_totSub); + OPCODEDRAW(0x83, o6_playVmdOrMusic); + OPCODEDRAW(0x85, o6_openItk); } -const char *Inter_v6::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_v6::setupOpcodesFunc() { + Inter_v5::setupOpcodesFunc(); - return _opcodesFuncV6[i*16 + j].desc; + OPCODEFUNC(0x03, o6_loadCursor); + OPCODEFUNC(0x09, o6_assign); + OPCODEFUNC(0x13, o6_palLoad); + OPCODEFUNC(0x19, o6_freeCollision); + OPCODEFUNC(0x33, o6_fillRect); } -const char *Inter_v6::getOpcodeGoblinDesc(int i) { - for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++) - if (_goblinFuncLookUp[j][0] == i) - return _opcodesGoblinV6[_goblinFuncLookUp[j][1]].desc; - return ""; +void Inter_v6::setupOpcodesGob() { } void Inter_v6::o6_totSub() { @@ -660,20 +77,20 @@ void Inter_v6::o6_totSub() { int flags; int i; - length = *_vm->_global->_inter_execPtr++; + length = _vm->_game->_script->readByte(); if ((length & 0x7F) > 13) error("Length in o2_totSub is greater than 13 (%d)", length); if (length & 0x80) { - evalExpr(0); - strcpy(totFile, _vm->_global->_inter_resStr); + _vm->_game->_script->evalExpr(0); + strcpy(totFile, _vm->_game->_script->getResultStr()); } else { for (i = 0; i < length; i++) - totFile[i] = (char) *_vm->_global->_inter_execPtr++; + totFile[i] = _vm->_game->_script->readChar(); totFile[i] = 0; } - flags = *_vm->_global->_inter_execPtr++; + flags = _vm->_game->_script->readByte(); if (flags & 0x40) warning("Urban Stub: o6_totSub(), flags & 0x40"); @@ -693,17 +110,17 @@ void Inter_v6::o6_playVmdOrMusic() { uint16 palCmd; bool close; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 127); - - x = _vm->_parse->parseValExpr(); - y = _vm->_parse->parseValExpr(); - startFrame = _vm->_parse->parseValExpr(); - lastFrame = _vm->_parse->parseValExpr(); - breakKey = _vm->_parse->parseValExpr(); - flags = _vm->_parse->parseValExpr(); - palStart = _vm->_parse->parseValExpr(); - palEnd = _vm->_parse->parseValExpr(); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); + + x = _vm->_game->_script->readValExpr(); + y = _vm->_game->_script->readValExpr(); + startFrame = _vm->_game->_script->readValExpr(); + lastFrame = _vm->_game->_script->readValExpr(); + breakKey = _vm->_game->_script->readValExpr(); + flags = _vm->_game->_script->readValExpr(); + palStart = _vm->_game->_script->readValExpr(); + palEnd = _vm->_game->_script->readValExpr(); palCmd = 1 << (flags & 0x3F); debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, " @@ -759,8 +176,8 @@ void Inter_v6::o6_playVmdOrMusic() { void Inter_v6::o6_openItk() { char fileName[32]; - evalExpr(0); - strncpy0(fileName, _vm->_global->_inter_resStr, 27); + _vm->_game->_script->evalExpr(0); + strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -778,21 +195,21 @@ void Inter_v6::o6_openItk() { } bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { - int16 id = load16(); + int16 id = _vm->_game->_script->readInt16(); if ((id == -1) || (id == -2)) { char file[10]; if (id == -1) { for (int i = 0; i < 9; i++) - file[i] = *_vm->_global->_inter_execPtr++; + file[i] = _vm->_game->_script->readChar(); } else - strncpy(file, GET_VAR_STR(load16()), 10); + strncpy(file, GET_VAR_STR(_vm->_game->_script->readInt16()), 10); file[9] = '\0'; - uint16 start = load16(); - int8 index = (int8) *_vm->_global->_inter_execPtr++; + uint16 start = _vm->_game->_script->readUint16(); + int8 index = _vm->_game->_script->readInt8(); int vmdSlot = _vm->_vidPlayer->slotOpen(file); @@ -820,101 +237,102 @@ bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { return false; } - int8 index = (int8) *_vm->_global->_inter_execPtr++; + int8 index = _vm->_game->_script->readInt8(); if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth()) return false; - int16 width, height; - byte *dataBuf = _vm->_game->loadTotResource(id, 0, &width, &height); + Resource *resource = _vm->_game->_resources->getResource((uint16) id); + if (!resource) + return false; - _vm->_video->fillRect(_vm->_draw->_cursorSprites, + _vm->_video->fillRect(*_vm->_draw->_cursorSprites, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, - index * _vm->_draw->_cursorWidth, 0, 0, _vm->_draw->_cursorSprites); + _vm->_video->drawPackedSprite(resource->getData(), + resource->getWidth(), resource->getHeight(), + index * _vm->_draw->_cursorWidth, 0, 0, *_vm->_draw->_cursorSprites); _vm->_draw->_cursorAnimLow[index] = 0; + delete resource; return false; } -bool Inter_v6::o6_evaluateStore(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - uint16 var_6, var_A; +bool Inter_v6::o6_assign(OpFuncParams ¶ms) { + uint16 size, destType; + int16 dest = _vm->_game->_script->readVarIndex(&size, &destType); - varOff = _vm->_parse->parseVarIndex(&var_6, &var_A); + if (size != 0) { + int16 src; - if (var_6 != 0) { - int16 var_4; + _vm->_game->_script->push(); - savedPos = _vm->_global->_inter_execPtr; + src = _vm->_game->_script->readVarIndex(&size, 0); - var_4 = _vm->_parse->parseVarIndex(&var_6, 0); + memcpy(_vm->_inter->_variables->getAddressOff8(dest), + _vm->_inter->_variables->getAddressOff8(src), size * 4); - memcpy(_vm->_inter->_variables->getAddressOff8(varOff), - _vm->_inter->_variables->getAddressOff8(var_4), var_6 * 4); + _vm->_game->_script->pop(); - _vm->_global->_inter_execPtr = savedPos; - evalExpr(&var_4); + _vm->_game->_script->evalExpr(&src); return false; } - if (*_vm->_global->_inter_execPtr == 98) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + byte loopCount; + if (_vm->_game->_script->peekByte() == 98) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); for (int i = 0; i < loopCount; i++) { - uint8 c = *_vm->_global->_inter_execPtr++; - uint16 n = load16(); + uint8 c = _vm->_game->_script->readByte(); + uint16 n = _vm->_game->_script->readUint16(); - memset(_vm->_inter->_variables->getAddressOff8(varOff), c, n); + memset(_vm->_inter->_variables->getAddressOff8(dest), c, n); - varOff += n; + dest += n; } return false; - } else if (*_vm->_global->_inter_execPtr == 99) { - _vm->_global->_inter_execPtr++; - loopCount = *_vm->_global->_inter_execPtr++; + } else if (_vm->_game->_script->peekByte() == 99) { + _vm->_game->_script->skip(1); + loopCount = _vm->_game->_script->readByte(); } else loopCount = 1; for (int i = 0; i < loopCount; i++) { - token = evalExpr(&result); - switch (var_A) { - case 16: - case 18: - WRITE_VARO_UINT8(varOff + i, _vm->_global->_inter_resVal); + int16 result; + int16 srcType = _vm->_game->_script->evalExpr(&result); + + switch (destType) { + case TYPE_VAR_INT8: + case TYPE_ARRAY_INT8: + WRITE_VARO_UINT8(dest + i, _vm->_game->_script->getResultInt()); break; - case 17: - case 27: - WRITE_VARO_UINT16(varOff + i * 2, _vm->_global->_inter_resVal); + case TYPE_VAR_INT16: + case TYPE_ARRAY_INT16: + WRITE_VARO_UINT16(dest + i * 2, _vm->_game->_script->getResultInt()); break; - case 23: - case 26: - WRITE_VAR_OFFSET(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32: + case TYPE_ARRAY_INT32: + WRITE_VAR_OFFSET(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 24: - WRITE_VARO_UINT16(varOff + i * 4, _vm->_global->_inter_resVal); + case TYPE_VAR_INT32_AS_INT16: + WRITE_VARO_UINT16(dest + i * 4, _vm->_game->_script->getResultInt()); break; - case 25: - case 28: - if (token == 20) - WRITE_VARO_UINT8(varOff, result); + case TYPE_VAR_STR: + case TYPE_ARRAY_STR: + if (srcType == TYPE_IMM_INT16) + WRITE_VARO_UINT8(dest, result); else - WRITE_VARO_STR(varOff, _vm->_global->_inter_resStr); + WRITE_VARO_STR(dest, _vm->_game->_script->getResultStr()); break; } } @@ -936,7 +354,7 @@ bool Inter_v6::o6_palLoad(OpFuncParams ¶ms) { bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { int16 id; - id = _vm->_parse->parseValExpr(); + id = _vm->_game->_script->readValExpr(); switch (id + 5) { case 0: @@ -972,17 +390,17 @@ bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { bool Inter_v6::o6_fillRect(OpFuncParams ¶ms) { int16 destSurf; - _vm->_draw->_destSurface = destSurf = load16(); + _vm->_draw->_destSurface = destSurf = _vm->_game->_script->readInt16(); - _vm->_draw->_destSpriteX = _vm->_parse->parseValExpr(); - _vm->_draw->_destSpriteY = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteRight = _vm->_parse->parseValExpr(); - _vm->_draw->_spriteBottom = _vm->_parse->parseValExpr(); + _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteRight = _vm->_game->_script->readValExpr(); + _vm->_draw->_spriteBottom = _vm->_game->_script->readValExpr(); - evalExpr(0); + _vm->_game->_script->evalExpr(0); - _vm->_draw->_backColor = _vm->_global->_inter_resVal & 0xFFFF; - uint16 extraVar = _vm->_global->_inter_resVal >> 16; + _vm->_draw->_backColor = _vm->_game->_script->getResultInt() & 0xFFFF; + uint16 extraVar = _vm->_game->_script->getResultInt() >> 16; if (extraVar != 0) warning("Urban Stub: o6_fillRect(), extraVar = %d", extraVar); @@ -1019,11 +437,8 @@ void Inter_v6::probe16bitMusic(char *fileName) { fileName[len - 1] = 'V'; - int16 handle; - if ((handle = _vm->_dataIO->openData(fileName)) >= 0) { - _vm->_dataIO->closeData(handle); + if (_vm->_dataIO->existData(fileName)) return; - } fileName[len - 1] = '8'; } diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index 2c94b3fb24..dacc72d6c7 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -64,7 +64,6 @@ void Map_v1::init(void) { void Map_v1::loadMapObjects(const char *avjFile) { char avoName[128]; byte *dataBuf; - int16 handle; int16 tmp; int32 flag; int16 gobDataCount; @@ -75,15 +74,14 @@ void Map_v1::loadMapObjects(const char *avjFile) { strcpy(avoName, _sourceFile); strcat(avoName, ".avo"); - handle = _vm->_dataIO->openData(avoName); - if (handle >= 0) { + if (_vm->_dataIO->existData(avoName)) { _loadFromAvo = true; - _vm->_dataIO->closeData(handle); dataBuf = _vm->_dataIO->getData(avoName); } else { _loadFromAvo = false; dataBuf = _vm->_dataIO->getData(avjFile); } + Common::MemoryReadStream mapData(dataBuf, 4294967295U); init(); @@ -146,7 +144,6 @@ void Map_v1::loadMapObjects(const char *avjFile) { void Map_v1::loadSounds(Common::SeekableReadStream &data) { int16 count; - int16 handle; char buf[19]; char sndNames[20][14]; @@ -162,11 +159,9 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], SOUND_SND, "diamant1.snd"); for (int i = 0; i < count; i++) { - handle = _vm->_dataIO->openData(sndNames[i]); - if (handle < 0) + if (!_vm->_dataIO->existData(sndNames[i])) continue; - _vm->_dataIO->closeData(handle); _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], SOUND_SND, sndNames[i]); } } diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index db4f2075e1..6ceda7ab44 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -31,7 +31,8 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/mult.h" namespace Gob { @@ -51,22 +52,24 @@ void Map_v2::loadMapObjects(const char *avjFile) { int16 mapWidth, mapHeight; int16 tmp; byte *variables; - byte *extData; uint32 tmpPos; uint32 passPos; - var = _vm->_parse->parseVarIndex(); + var = _vm->_game->_script->readVarIndex(); variables = _vm->_inter->_variables->getAddressOff8(var); - id = _vm->_inter->load16(); + id = _vm->_game->_script->readInt16(); if (id == -1) { _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var); return; } - extData = _vm->_game->loadExtData(id, 0, 0); - Common::MemoryReadStream mapData(extData, 4294967295U); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return; + + Common::SeekableReadStream &mapData = *resource->stream(); if (mapData.readByte() == 3) { _screenWidth = 640; @@ -88,7 +91,7 @@ void Map_v2::loadMapObjects(const char *avjFile) { passPos = mapData.pos(); mapData.skip(_mapWidth * _mapHeight); - if (*extData == 1) + if (resource->getData()[0] == 1) wayPointsCount = _wayPointsCount = 40; else wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; @@ -130,11 +133,11 @@ void Map_v2::loadMapObjects(const char *avjFile) { for (int i = 0; i < _vm->_goblin->_gobsCount; i++) loadGoblinStates(mapData, i); - _vm->_goblin->_soundSlotsCount = _vm->_inter->load16(); + _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16(); for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++) _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); - delete[] extData; + delete resource; } void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) { diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp index 858e7972bc..1db3d6a3f8 100644 --- a/engines/gob/map_v4.cpp +++ b/engines/gob/map_v4.cpp @@ -31,7 +31,8 @@ #include "gob/goblin.h" #include "gob/inter.h" #include "gob/game.h" -#include "gob/parse.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/mult.h" namespace Gob { @@ -49,14 +50,13 @@ void Map_v4::loadMapObjects(const char *avjFile) { int16 mapWidth, mapHeight; int16 tmp; byte *variables; - byte *extData; uint32 tmpPos; uint32 passPos; - var = _vm->_parse->parseVarIndex(); + var = _vm->_game->_script->readVarIndex(); variables = _vm->_inter->_variables->getAddressOff8(var); - id = _vm->_inter->load16(); + id = _vm->_game->_script->readInt16(); if (((uint16) id) >= 65520) { warning("Woodruff Stub: loadMapObjects ID >= 65520"); @@ -66,8 +66,11 @@ void Map_v4::loadMapObjects(const char *avjFile) { return; } - extData = _vm->_game->loadExtData(id, 0, 0); - Common::MemoryReadStream mapData(extData, 4294967295U); + Resource *resource = _vm->_game->_resources->getResource(id); + if (!resource) + return; + + Common::SeekableReadStream &mapData = *resource->stream(); _widthByte = mapData.readByte(); if (_widthByte == 4) { @@ -99,7 +102,7 @@ void Map_v4::loadMapObjects(const char *avjFile) { passPos = mapData.pos(); mapData.skip(_mapWidth * _mapHeight); - if (*extData == 1) + if (resource->getData()[0] == 1) wayPointsCount = _wayPointsCount = 40; else wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; @@ -146,11 +149,11 @@ void Map_v4::loadMapObjects(const char *avjFile) { for (int i = 0; i < _vm->_goblin->_gobsCount; i++) loadGoblinStates(mapData, i); - _vm->_goblin->_soundSlotsCount = _vm->_inter->load16(); + _vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16(); for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++) _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1); - delete[] extData; + delete resource; } } // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 9111db9121..695976da61 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -9,6 +9,7 @@ MODULE_OBJS := \ draw_bargon.o \ draw_fascin.o \ driver_vga.o \ + expression.o \ game.o \ game_v1.o \ game_v2.o \ @@ -43,12 +44,12 @@ MODULE_OBJS := \ mult_v1.o \ mult_v2.o \ palanim.o \ - parse.o \ - parse_v1.o \ - parse_v2.o \ + resources.o \ scenery.o \ scenery_v1.o \ scenery_v2.o \ + script.o \ + totfile.o \ util.o \ variables.o \ video.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 11ef43280f..5aec5ff76e 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -31,6 +31,7 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" #include "gob/palanim.h" #include "gob/scenery.h" #include "gob/video.h" @@ -85,7 +86,6 @@ Mult::Mult(GobEngine *vm) : _vm(vm) { _palFadingGreen = 0; _palFadingBlue = 0; - _animSurf = 0; _animLeft = 0; _animTop = 0; _animWidth = 0; @@ -111,7 +111,7 @@ Mult::~Mult() { void Mult::initAll(void) { _objects = 0; - _animSurf = 0; + _animSurf.reset(); _renderData = 0; _vm->_scenery->init(); @@ -145,7 +145,7 @@ void Mult::freeMult() { _renderObjs = 0; _orderArray = 0; - _animSurf = 0; + _animSurf.reset(); _vm->_draw->freeSprite(22); } @@ -237,7 +237,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, _animArrayData = 0; _orderArray = 0; - _animSurf = 0; + _animSurf.reset(); _vm->_draw->freeSprite(22); _animDataAllocated = false; @@ -252,8 +252,6 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, } void Mult::drawText(bool &stop, bool &stopNoClear) { - byte *savedIP; - int16 cmd; for (_index = 0; _index < _multData->textKeysCount; _index++) { if (_multData->textKeys[_index].frame != _frame) @@ -266,9 +264,10 @@ void Mult::drawText(bool &stop, bool &stopNoClear) { stopNoClear = true; _multData->frameStart = 0; } else if (cmd == 3) { + warning("Mult::drawText, cmd == 3"); stop = false; - savedIP = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr = _multData->textKeys[_index].script; +// uint32 startPos = _vm->_game->_script->pos(); +// _vm->_global->_inter_execPtr = _multData->textKeys[_index].script; } } } diff --git a/engines/gob/mult.h b/engines/gob/mult.h index 3bb3af17b3..7766508922 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -232,7 +232,7 @@ public: int8 *_orderArray; - SurfaceDesc::Ptr _animSurf; + SurfaceDescPtr _animSurf; int16 _animLeft; int16 _animTop; int16 _animWidth; diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index a369e7d297..1bb162c789 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -1,4 +1,4 @@ -/* ScummVM - Graphic Adventure Engine +/* 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 @@ -32,6 +32,8 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/scenery.h" @@ -41,9 +43,6 @@ Mult_v1::Mult_v1(GobEngine *vm) : Mult(vm) { } void Mult_v1::loadMult(int16 resId) { - uint32 dataSize; - byte *extData; - debugC(4, kDebugGameFlow, "Loading mult"); _multData = new Mult_Data; @@ -52,8 +51,11 @@ void Mult_v1::loadMult(int16 resId) { _multData->sndSlotsCount = 0; _multData->frameStart = 0; - extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize); - Common::MemoryReadStream data(extData, dataSize); + Resource *resource = _vm->_game->_resources->getResource(resId); + if (!resource) + return; + + Common::SeekableReadStream &data = *resource->stream(); _multData->staticCount = data.readSByte() + 1; _multData->animCount = data.readSByte() + 1; @@ -157,15 +159,14 @@ void Mult_v1::loadMult(int16 resId) { switch (_multData->sndKeys[i].cmd) { case 1: case 4: - _multData->sndKeys[i].resId = - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16(); for (j = 0; j < i; j++) { if (_multData->sndKeys[i].resId == _multData->sndKeys[j].resId) { _multData->sndKeys[i].soundIndex = _multData->sndKeys[j].soundIndex; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; } } @@ -178,16 +179,16 @@ void Mult_v1::loadMult(int16 resId) { break; case 3: - _vm->_global->_inter_execPtr += 6; + _vm->_game->_script->skip(6); break; case 5: - _vm->_global->_inter_execPtr += _multData->sndKeys[i].freq * 2; + _vm->_game->_script->skip(_multData->sndKeys[i].freq * 2); break; } } - delete[] extData; + delete resource; } void Mult_v1::freeMultKeys() { @@ -234,7 +235,7 @@ void Mult_v1::freeMultKeys() { _animArrayY = 0; _animArrayData = 0; - _animSurf = 0; + _animSurf.reset(); _vm->_draw->freeSprite(22); _animDataAllocated = false; @@ -319,8 +320,8 @@ void Mult_v1::playMultInit() { 320, 200, 0); _vm->_draw->_spritesArray[22] = _animSurf; - _vm->_video->drawSprite(_vm->_draw->_backSurface, - _animSurf, 0, 0, 319, 199, 0, 0, 0); + _vm->_video->drawSprite(*_vm->_draw->_backSurface, + *_animSurf, 0, 0, 319, 199, 0, 0, 0); _animDataAllocated = true; } else @@ -349,7 +350,7 @@ void Mult_v1::drawStatics(bool &stop) { _vm->_scenery->_curStatic = _multData->staticIndices[_vm->_scenery->_curStatic]; _vm->_scenery->renderStatic(_vm->_scenery->_curStatic, _vm->_scenery->_curStaticLayer); - _vm->_video->drawSprite(_vm->_draw->_backSurface, _animSurf, + _vm->_video->drawSprite(*_vm->_draw->_backSurface, *_animSurf, 0, 0, 319, 199, 0, 0, 0); } } diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 1181862039..135c50c92c 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -32,9 +32,10 @@ #include "gob/util.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/goblin.h" #include "gob/inter.h" -#include "gob/parse.h" #include "gob/scenery.h" #include "gob/video.h" #include "gob/videoplayer.h" @@ -60,11 +61,9 @@ void Mult_v2::loadMult(int16 resId) { int8 index; uint8 staticCount; uint8 animCount; - uint32 dataSize; - byte *extData; bool hasImds; - index = (resId & 0x8000) ? *_vm->_global->_inter_execPtr++ : 0; + index = (resId & 0x8000) ? _vm->_game->_script->readByte() : 0; resId &= 0x7FFF; debugC(4, kDebugGameFlow, "Loading mult %d", index); @@ -80,8 +79,11 @@ void Mult_v2::loadMult(int16 resId) { _multData->sndSlotsCount = 0; _multData->frameStart = 0; - extData = (byte *) _vm->_game->loadExtData(resId, 0, 0, &dataSize); - Common::MemoryReadStream data(extData, dataSize); + Resource *resource = _vm->_game->_resources->getResource(resId); + if (!resource) + return; + + Common::SeekableReadStream &data = *resource->stream(); _multData->staticCount = staticCount = data.readSByte(); _multData->animCount = animCount = data.readSByte(); @@ -206,14 +208,13 @@ void Mult_v2::loadMult(int16 resId) { switch (_multData->sndKeys[i].cmd) { case 1: case 4: - _multData->sndKeys[i].resId = - READ_LE_UINT16(_vm->_global->_inter_execPtr); + _multData->sndKeys[i].resId = _vm->_game->_script->peekUint16(); for (j = 0; j < i; j++) { if (_multData->sndKeys[j].resId == _multData->sndKeys[i].resId) { _multData->sndKeys[i].soundIndex = _multData->sndKeys[j].soundIndex; - _vm->_global->_inter_execPtr += 2; + _vm->_game->_script->skip(2); break; } } @@ -226,7 +227,7 @@ void Mult_v2::loadMult(int16 resId) { } break; case 3: - _vm->_global->_inter_execPtr += 4; + _vm->_game->_script->skip(4); break; case -1: @@ -244,17 +245,17 @@ void Mult_v2::loadMult(int16 resId) { if (hasImds) loadImds(data); - delete[] extData; + delete resource; } void Mult_v2::loadImds(Common::SeekableReadStream &data) { int16 size; - size = _vm->_inter->load16(); - _multData->execPtr = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += size * 2; + size = _vm->_game->_script->readInt16(); + _multData->execPtr = _vm->_game->_script->getData() + _vm->_game->_script->pos(); + _vm->_game->_script->skip(size * 2); - if (_vm->_game->_totFileData[0x29] < 51) + if (_vm->_game->_script->getVersionMinor() < 3) return; size = data.readSint16LE(); @@ -263,13 +264,27 @@ void Mult_v2::loadImds(Common::SeekableReadStream &data) { data.read(_multData->somepointer10, size * 20); } - size = _vm->_inter->load16(); + size = _vm->_game->_script->readInt16(); if (size <= 0) return; _multData->imdFiles = new char[size * 14]; - memcpy(_multData->imdFiles, _vm->_global->_inter_execPtr, size * 14); - _vm->_global->_inter_execPtr += size * 14; + memcpy(_multData->imdFiles, + _vm->_game->_script->getData() + _vm->_game->_script->pos(), size * 14); + + // WORKAROUND: The Windows version of Lost in Time has VMD not IMD files, + // but they are still referenced as IMD. + if ((_vm->getGameType() == kGameTypeLostInTime) && + (_vm->getPlatform() == Common::kPlatformWindows)) { + + for (int i = 0; i < size; i++) { + char *dot = strrchr(_multData->imdFiles + (i * 14), '.'); + if (dot) + *dot = '\0'; + } + } + + _vm->_game->_script->skip(size * 14); data.seek(2, SEEK_CUR); for (int i = 0; i < 4; i++) { _multData->imdKeysCount[i] = data.readSint16LE(); @@ -382,14 +397,16 @@ void Mult_v2::multSub(uint16 multIndex) { if (multIndex > 7) error("Multindex out of range"); + _vm->_util->notifyNewAnim(); + debugC(4, kDebugGameFlow, "Sub mult %d", multIndex); _multData = _multDatas[multIndex]; if (!_multData) { - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); - _vm->_parse->parseValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); + _vm->_game->_script->readValExpr(); return; } @@ -412,9 +429,9 @@ void Mult_v2::multSub(uint16 multIndex) { _multData->animObjs[index][0] = flags; for (int i = 1; i < 4; i++) - _multData->animObjs[index][i] = _vm->_parse->parseValExpr(); + _multData->animObjs[index][i] = _vm->_game->_script->readValExpr(); - expr = _vm->_parse->parseValExpr(); + expr = _vm->_game->_script->readValExpr(); _multData->animKeysFrames[index] = expr; _multData->animKeysStartFrames[index] = expr; @@ -565,8 +582,8 @@ void Mult_v2::playMultInit() { _vm->_draw->initSpriteSurf(22, width, height, 0); _animSurf = _vm->_draw->_spritesArray[22]; - _vm->_video->drawSprite(_vm->_draw->_spritesArray[21], - _vm->_draw->_spritesArray[22], 0, 0, + _vm->_video->drawSprite(*_vm->_draw->_spritesArray[21], + *_vm->_draw->_spritesArray[22], 0, 0, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0); for (_counter = 0; _counter < _objCount; _counter++) @@ -622,8 +639,8 @@ void Mult_v2::drawStatics(bool &stop) { _vm->_scenery->_curStatic = -1; } - _vm->_video->drawSprite(_vm->_draw->_spritesArray[21], - _vm->_draw->_spritesArray[22], 0, 0, + _vm->_video->drawSprite(*_vm->_draw->_spritesArray[21], + *_vm->_draw->_spritesArray[22], 0, 0, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0); } } @@ -856,7 +873,7 @@ void Mult_v2::animate() { animObj.newBottom = MAX(animObj.lastBottom, _vm->_scenery->_toRedrawBottom); - if ((_vm->_game->_totFileData[0x29] > 50) && + if ((_vm->_game->_script->getVersionMinor() > 2) && (animObj.newLeft == animObj.lastLeft) && (animObj.newTop == animObj.lastTop) && (animObj.newRight == animObj.lastRight) && diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp deleted file mode 100644 index 81a7da6389..0000000000 --- a/engines/gob/parse.cpp +++ /dev/null @@ -1,476 +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. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/parse.h" -#include "gob/global.h" -#include "gob/game.h" -#include "gob/inter.h" - -namespace Gob { - -Parse::Parse(GobEngine *vm) : _vm(vm) { -} - -int32 Parse::encodePtr(byte *ptr, int type) { - int32 offset = 0; - - switch (type) { - case kExecPtr: - offset = ptr - _vm->_game->_totFileData; - break; - case kInterVar: - offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0)); - break; - case kResStr: - offset = ptr - ((byte *) _vm->_global->_inter_resStr); - break; - default: - error("Parse::encodePtr(): Unknown pointer type"); - } - assert((offset & 0xF0000000) == 0); - return (type << 28) | offset; -} - -byte *Parse::decodePtr(int32 n) { - byte *ptr; - - switch (n >> 28) { - case kExecPtr: - ptr = _vm->_game->_totFileData; - break; - case kInterVar: - ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0); - break; - case kResStr: - ptr = (byte *) _vm->_global->_inter_resStr; - break; - default: - error("Parse::decodePtr(): Unknown pointer type"); - } - return ptr + (n & 0x0FFFFFFF); -} - -void Parse::skipExpr(char stopToken) { - int16 dimCount; - byte operation; - int16 num; - int16 dim; - - num = 0; - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - if ((operation >= 14) && (operation <= OP_FUNC)) { - switch (operation) { - case 14: - _vm->_global->_inter_execPtr += 4; - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - break; - - case OP_LOAD_VAR_INT16: - case OP_LOAD_VAR_INT8: - case OP_LOAD_IMM_INT16: - case 23: - case 24: - _vm->_global->_inter_execPtr += 2; - break; - - case OP_LOAD_IMM_INT32: - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT8: - _vm->_global->_inter_execPtr += 1; - break; - - case OP_LOAD_IMM_STR: - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case OP_LOAD_VAR_STR: - _vm->_global->_inter_execPtr += 2; - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_MARKER); - } - break; - - case 15: - _vm->_global->_inter_execPtr += 2; - - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - dimCount = _vm->_global->_inter_execPtr[2]; - // skip header and dimensions - _vm->_global->_inter_execPtr += 3 + dimCount; - // skip indices - for (dim = 0; dim < dimCount; dim++) - skipExpr(OP_END_MARKER); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_MARKER); - } - break; - - case OP_FUNC: - _vm->_global->_inter_execPtr++; - skipExpr(OP_END_EXPR); - } - continue; - } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) - - if (operation == OP_BEGIN_EXPR) { - num++; - continue; - } - - if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) - continue; - - if ((operation >= OP_OR) && (operation <= OP_NEQ)) - continue; - - if (operation == OP_END_EXPR) - num--; - - if (operation != stopToken) - continue; - - if ((stopToken != OP_END_EXPR) || (num < 0)) - return; - } -} - -void Parse::printExpr(char stopToken) { - // Expression printing disabled by default - return; - - byte *savedPos = _vm->_global->_inter_execPtr; - printExpr_internal(stopToken); - - // restore IP to start of expression - _vm->_global->_inter_execPtr = savedPos; -} - -void Parse::printExpr_internal(char stopToken) { - int16 dimCount; - byte operation; - int16 num; - int16 dim; - byte *arrDesc; - byte func; - - num = 0; - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - // operands - - switch (operation) { - case OP_LOAD_VAR_INT16: // int16 variable load - debugN(5, "var16_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_VAR_INT8: // int8 variable load: - debugN(5, "var8_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: // int32/uint32 immediate - debugN(5, "%d", READ_LE_UINT32(_vm->_global->_inter_execPtr)); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: // int16 immediate - debugN(5, "%d", _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT8: // int8 immediate - debugN(5, "%d", (int8) *_vm->_global->_inter_execPtr++); - break; - - case OP_LOAD_IMM_STR: // string immediate - debugN(5, "\42%s\42", _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case 23: // uint32 variable load - case 24: // uint32 variable load as uint16 - debugN(5, "var_%d", _vm->_inter->load16()); - break; - - case OP_LOAD_VAR_STR: // string variable load - debugN(5, "(&var_%d)", _vm->_inter->load16()); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - debugN(5, "{"); - printExpr_internal(OP_END_MARKER); // this also prints the closing } - } - break; - - case OP_ARRAY_UINT8: // uint8 array access - case OP_ARRAY_UINT32: // uint32 array access - case OP_ARRAY_UINT16: // uint16 array access - case OP_ARRAY_STR: // string array access - debugN(5, "\n"); - if (operation == OP_ARRAY_STR) - debugN(5, "(&"); - - debugN(5, "var_%d[", _vm->_inter->load16()); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - for (dim = 0; dim < dimCount; dim++) { - printExpr_internal(OP_END_MARKER); - debugN(5, " of %d", (int16) arrDesc[dim]); - if (dim != dimCount - 1) - debugN(5, ","); - } - debugN(5, "]"); - if (operation == OP_ARRAY_STR) - debugN(5, ")"); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "{"); - printExpr_internal(OP_END_MARKER); // this also prints the closing } - } - break; - - case OP_FUNC: // function - func = *_vm->_global->_inter_execPtr++; - if (func == FUNC_SQR) - debugN(5, "sqr("); - else if (func == FUNC_RAND) - debugN(5, "rand("); - else if (func == FUNC_ABS) - debugN(5, "abs("); - else if ((func == FUNC_SQRT1) || (func == FUNC_SQRT2) || (func == FUNC_SQRT3)) - debugN(5, "sqrt("); - else - debugN(5, "id("); - printExpr_internal(OP_END_EXPR); - break; - } - continue; - } // if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) - - // operators - switch (operation) { - case OP_BEGIN_EXPR: - debugN(5, "("); - break; - - case OP_NOT: - debugN(5, "!"); - break; - - case OP_END_EXPR: - debugN(5, ")"); - break; - - case OP_NEG: - debugN(5, "-"); - break; - - case OP_ADD: - debugN(5, "+"); - break; - - case OP_SUB: - debugN(5, "-"); - break; - - case OP_BITOR: - debugN(5, "|"); - break; - - case OP_MUL: - debugN(5, "*"); - break; - - case OP_DIV: - debugN(5, "/"); - break; - - case OP_MOD: - debugN(5, "%%"); - break; - - case OP_BITAND: - debugN(5, "&"); - break; - - case OP_OR: - debugN(5, "||"); - break; - - case 31: - debugN(5, "&&"); - break; - - case OP_LESS: - debugN(5, "<"); - break; - - case OP_LEQ: - debugN(5, "<="); - break; - - case OP_GREATER: - debugN(5, ">"); - break; - - case OP_GEQ: - debugN(5, ">="); - break; - - case OP_EQ: - debugN(5, "=="); - break; - - case OP_NEQ: - debugN(5, "!="); - break; - - case 99: - debugN(5, "\n"); - break; - - case OP_END_MARKER: - debugN(5, "}"); - if (stopToken != OP_END_MARKER) { - debugN(5, "Closing paren without opening?"); - } - break; - - default: - debugN(5, "<%d>", (int16) operation); - error("Parse::printExpr(): invalid operator in expression"); - break; - } - - if (operation == OP_BEGIN_EXPR) { - num++; - continue; - } - - if ((operation == OP_NOT) || ((operation >= OP_NEG) && (operation <= 8))) - continue; - - if ((operation >= OP_OR) && (operation <= OP_NEQ)) - continue; - - if (operation == OP_END_EXPR) - num--; - - if (operation == stopToken) { - if ((stopToken != OP_END_EXPR) || (num < 0)) { - return; - } - } - } -} - - -void Parse::printVarIndex() { - byte *arrDesc; - int16 dim; - int16 dimCount; - int16 operation; - int16 temp; - - byte *pos = _vm->_global->_inter_execPtr; - - operation = *_vm->_global->_inter_execPtr++; - switch (operation) { - case 23: - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - debugN(5, "&var_%d", temp); - if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "+"); - printExpr(OP_END_MARKER); - } - break; - - case OP_ARRAY_UINT32: - case OP_ARRAY_STR: - debugN(5, "&var_%d[", _vm->_inter->load16()); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - for (dim = 0; dim < dimCount; dim++) { - printExpr(OP_END_MARKER); - debugN(5, " of %d", (int16) arrDesc[dim]); - if (dim != dimCount - 1) - debugN(5, ","); - } - debugN(5, "]"); - - if ((operation == OP_ARRAY_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - debugN(5, "+"); - printExpr(OP_END_MARKER); - } - break; - - default: - debugN(5, "var_0"); - break; - } - debugN(5, "\n"); - _vm->_global->_inter_execPtr = pos; - return; -} - -int Parse::cmpHelper(byte *operPtr, int32 *valPtr) { - byte var_C = operPtr[-3]; - int cmpTemp = 0; - if (var_C == OP_LOAD_IMM_INT16) { - cmpTemp = (int)valPtr[-3] - (int)valPtr[-1]; - } else if (var_C == OP_LOAD_IMM_STR) { - if ((char *)decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - cmpTemp = strcmp(_vm->_global->_inter_resStr, (char *)decodePtr(valPtr[-1])); - } - - return cmpTemp; -} - - -} // End of namespace Gob diff --git a/engines/gob/parse.h b/engines/gob/parse.h deleted file mode 100644 index d72b4d5c2b..0000000000 --- a/engines/gob/parse.h +++ /dev/null @@ -1,148 +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. - * - * $URL$ - * $Id$ - * - */ - -#ifndef GOB_PARSE_H -#define GOB_PARSE_H - -namespace Gob { - -enum { - OP_NEG = 1, - OP_ADD = 2, - OP_SUB = 3, - OP_BITOR = 4, - OP_MUL = 5, - OP_DIV = 6, - OP_MOD = 7, - OP_BITAND = 8, - OP_BEGIN_EXPR = 9, - OP_END_EXPR = 10, - OP_NOT = 11, - - OP_END_MARKER = 12, // Marks end of an array or string - - - OP_ARRAY_UINT8 = 16, - - OP_LOAD_VAR_INT16 = 17, - OP_LOAD_VAR_INT8 = 18, - OP_LOAD_IMM_INT32 = 19, - OP_LOAD_IMM_INT16 = 20, - OP_LOAD_IMM_INT8 = 21, - OP_LOAD_IMM_STR = 22, - - OP_LOAD_VAR_UINT32 = 23, // ??? - OP_LOAD_VAR_UINT32_AS_UINT16 = 24, // ??? - OP_LOAD_VAR_STR = 25, - - OP_ARRAY_UINT32 = 26, - OP_ARRAY_UINT16 = 27, - OP_ARRAY_STR = 28, - - OP_FUNC = 29, - - OP_OR = 30, // Logical OR - OP_AND = 31, // Logical AND - OP_LESS = 32, - OP_LEQ = 33, - OP_GREATER = 34, - OP_GEQ = 35, - OP_EQ = 36, - OP_NEQ = 37 -}; - -enum { - FUNC_SQRT1 = 0, - FUNC_SQRT2 = 1, - FUNC_SQRT3 = 6, - - FUNC_SQR = 5, - FUNC_ABS = 7, - FUNC_RAND = 10 -}; - -enum { - // FIXME: The following two 'truth values' are stored inside the list - // of "operators". So they somehow coincide with OP_LOAD_VAR_UINT32 - // and OP_LOAD_VAR_UINT32_AS_UINT16. I haven't yet quite understood - // how, resp. what that means. You have been warned. - GOB_TRUE = 24, - GOB_FALSE = 23 -}; - -class Parse { -public: - void skipExpr(char stopToken); - void printExpr(char stopToken); - void printVarIndex(void); - virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0) = 0; - virtual int16 parseValExpr(byte stopToken = 99) = 0; - virtual int16 parseExpr(byte stopToken, byte *resultPtr) = 0; - - Parse(GobEngine *vm); - virtual ~Parse() {} - -protected: - enum PointerType { - kExecPtr = 0, - kInterVar = 1, - kResStr = 2 - }; - - GobEngine *_vm; - - int32 encodePtr(byte *ptr, int type); - byte *decodePtr(int32 n); - - void printExpr_internal(char stopToken); - - int cmpHelper(byte *operPtr, int32 *valPtr); -}; - -class Parse_v1 : public Parse { -public: - Parse_v1(GobEngine *vm); - virtual ~Parse_v1() {} - - virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0); - virtual int16 parseValExpr(byte stopToken = 99); - virtual int16 parseExpr(byte stopToken, byte *resultPtr); -}; - -class Parse_v2 : public Parse_v1 { -public: - Parse_v2(GobEngine *vm); - virtual ~Parse_v2() {} - - virtual int16 getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9); - - virtual int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0); - virtual int16 parseValExpr(byte stopToken = 99); - virtual int16 parseExpr(byte stopToken, byte *resultPtr); -}; - -} // End of namespace Gob - -#endif // GOB_PARSE_H diff --git a/engines/gob/parse_v1.cpp b/engines/gob/parse_v1.cpp deleted file mode 100644 index c993d6ca70..0000000000 --- a/engines/gob/parse_v1.cpp +++ /dev/null @@ -1,834 +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. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/parse.h" -#include "gob/global.h" -#include "gob/inter.h" - -namespace Gob { - -Parse_v1::Parse_v1(GobEngine *vm) : Parse(vm) { -} - -int16 Parse_v1::parseVarIndex(uint16 *arg_0, uint16 *arg_4) { - int16 temp2; - byte *arrDesc; - int16 dim; - int16 dimCount; - int16 operation; - int16 temp; - int16 offset; - int16 val; - - operation = *_vm->_global->_inter_execPtr++; - debugC(5, kDebugParser, "var parse = %d", operation); - switch (operation) { - case 23: - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - debugC(5, kDebugParser, "oper = %d", - (int16) *_vm->_global->_inter_execPtr); - - if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - val = parseValExpr(OP_END_MARKER); - temp += val; - debugC(5, kDebugParser, "parse subscript = %d", val); - } - return temp; - - case OP_ARRAY_UINT32: - case OP_ARRAY_STR: - temp = _vm->_inter->load16() * 4; - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - offset *= 4; - if (operation != OP_ARRAY_STR) - return temp + offset; - - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - } - return offset * _vm->_global->_inter_animDataSize + temp; - - default: - return 0; - } -} - -int16 Parse_v1::parseValExpr(byte stopToken) { - int16 values[20]; - byte operStack[20]; - int16 *valPtr; - byte *operPtr; - byte *arrDesc; - byte operation; - int16 temp2; - int16 dim; - int16 dimCount; - int16 temp; - int16 offset; - int16 stkPos; - int16 brackPos; - static int16 flag = 0; - int16 oldflag; - - oldflag = flag; - if (flag == 0) { - flag = 1; - printExpr(stopToken); - } - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (true) { - stkPos++; - operPtr++; - valPtr++; - - operation = *_vm->_global->_inter_execPtr++; - if ((operation >= OP_LOAD_IMM_INT32) && (operation <= OP_FUNC)) { - *operPtr = OP_LOAD_IMM_INT16; - switch (operation) { - case OP_LOAD_IMM_INT32: - *valPtr = READ_LE_UINT32(_vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *valPtr = _vm->_inter->load16(); - break; - - case 23: - *valPtr = (uint16) VAR(_vm->_inter->load16()); - break; - - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(temp); - break; - - case OP_ARRAY_UINT32: - case OP_ARRAY_STR: - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - if (operation == OP_ARRAY_UINT32) { - *valPtr = (uint16) VAR(temp + offset); - } else { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(temp * 4 + offset * 4 * - _vm->_global->_inter_animDataSize + temp2); - } - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - if (operation == FUNC_SQR) { - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - } else if (operation == FUNC_ABS) { - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - } else if (operation == FUNC_RAND) { - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - } - *valPtr = _vm->_global->_inter_resVal; - break; - - } // switch - if ((stkPos > 0) && (operPtr[-1] == OP_NEG)) { - stkPos--; - operPtr--; - valPtr--; - operPtr[0] = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } - - if ((stkPos > 0) && (operPtr[-1] >= OP_MUL) && (operPtr[-1] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - switch (operPtr[1]) { - case OP_MUL: - valPtr[0] *= valPtr[2]; - break; - - case OP_DIV: - valPtr[0] /= valPtr[2]; - break; - - case OP_MOD: - valPtr[0] %= valPtr[2]; - break; - - case OP_BITAND: - valPtr[0] &= valPtr[2]; - break; - } - } // if ((stkPos > 0) && (cmdPtr[-1] >= OP_MUL) && (cmdPtr[-1] <= OP_BITAND)) - continue; - } - - if ((operation >= OP_NEG) && (operation <= OP_BEGIN_EXPR)) { - *operPtr = operation; - continue; - } - - while (stkPos >= 2) { - if (operPtr[-2] == OP_BEGIN_EXPR) { - stkPos--; - operPtr--; - valPtr--; - - operPtr[-1] = operPtr[0]; - valPtr[-1] = valPtr[0]; - if ((stkPos > 1) && (operPtr[-2] == OP_NEG)) { - valPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - } - - if ((stkPos > 2) && (operPtr[-2] >= OP_MUL) && (operPtr[-2] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_MUL: - operPtr[-1] *= operPtr[1]; - break; - - case OP_DIV: - operPtr[-1] /= operPtr[1]; - break; - - case OP_MOD: - operPtr[-1] %= operPtr[1]; - break; - - case OP_BITAND: - operPtr[-1] &= operPtr[1]; - break; - } - } - if (operation == OP_END_EXPR) - break; - } // operPtr[-2] == OP_BEGIN_EXPR - - for (brackPos = (stkPos - 2); (brackPos > 0) && - (operStack[brackPos] < OP_OR) && (operStack[brackPos] != OP_BEGIN_EXPR); - brackPos--) - ; - - if ((operStack[brackPos] >= OP_OR) || (operStack[brackPos] == OP_BEGIN_EXPR)) - brackPos++; - - if ((operPtr[-2] < 2) || (operPtr[-2] > 8)) - break; - - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_ADD: - values[brackPos] += valPtr[1]; - continue; - case OP_SUB: - values[brackPos] -= valPtr[1]; - continue; - case OP_BITOR: - values[brackPos] |= valPtr[1]; - continue; - case OP_MUL: - valPtr[-1] *= valPtr[1]; - continue; - case OP_DIV: - valPtr[-1] /= valPtr[1]; - continue; - case OP_MOD: - valPtr[-1] %= valPtr[1]; - continue; - case OP_BITAND: - valPtr[-1] &= valPtr[1]; - continue; - } - } - - if (operation != OP_END_EXPR) { - if (operation != stopToken) - debugC(5, kDebugParser, "stoptoken error: %d != %d", - operation, stopToken); - - flag = oldflag; - return values[0]; - } - - stkPos--; - operPtr--; - valPtr--; - } -} - -int16 Parse_v1::parseExpr(byte stopToken, byte *arg_2) { - int32 values[20]; - byte operStack[20]; - int32 prevPrevVal; - int32 prevVal; - int32 curVal; - int32 *valPtr; - byte *operPtr; - byte *arrDescPtr; - byte operation; - int16 dimCount; - int16 temp; - int16 temp2; - uint16 offset; - int16 dim; - bool var_1A; - int16 stkPos; - int16 brackStart; - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (true) { - stkPos++; - operPtr++; - valPtr++; - operation = *_vm->_global->_inter_execPtr++; - if ((operation >= OP_LOAD_IMM_INT32) && (operation <= OP_FUNC)) { - switch (operation) { - case OP_LOAD_IMM_INT32: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_LE_UINT32(_vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_inter->load16(); - break; - - case OP_LOAD_IMM_STR: - *operPtr = OP_LOAD_IMM_STR; - *valPtr = encodePtr(_vm->_global->_inter_execPtr, kExecPtr); - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case 23: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = VAR(_vm->_inter->load16()); - break; - - case OP_LOAD_VAR_STR: - *operPtr = OP_LOAD_IMM_STR; - temp = _vm->_inter->load16() * 4; - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp), - kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(temp); - } - break; - - case OP_ARRAY_UINT32: - case OP_ARRAY_STR: - *operPtr = operation - 6; - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDescPtr = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - dim = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = offset * arrDescPtr[dim] + temp2; - } - - if (operation == OP_ARRAY_UINT32) { - *valPtr = VAR(temp + offset); - break; - } - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8( - temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), - kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(temp * 4 + - offset * 4 * _vm->_global->_inter_animDataSize + temp2); - } - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - switch (operation) { - case FUNC_SQR: - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - break; - - case FUNC_SQRT1: - case FUNC_SQRT2: - case FUNC_SQRT3: - curVal = 1; - prevVal = 1; - - do { - prevPrevVal = prevVal; - prevVal = curVal; - curVal = (curVal + _vm->_global->_inter_resVal / curVal) / 2; - } while ((curVal != prevVal) && (curVal != prevPrevVal)); - _vm->_global->_inter_resVal = curVal; - break; - - case FUNC_RAND: - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - break; - - case FUNC_ABS: - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - break; - } - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_global->_inter_resVal; - } - - if ((stkPos > 0) && ((operPtr[-1] == OP_NEG) || (operPtr[-1] == OP_NOT))) { - stkPos--; - operPtr--; - valPtr--; - - if (*operPtr == OP_NEG) { - *operPtr = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } else if (*operPtr == OP_NOT) { - if (operPtr[1] == GOB_FALSE) - *operPtr = GOB_TRUE; - else - *operPtr = GOB_FALSE; - } - } - - if (stkPos <= 0) - continue; - - switch (operPtr[-1]) { - case OP_ADD: - if (operPtr[-2] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-2]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-2])); - valPtr[-2] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[0])); - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - break; - - case OP_MUL: - valPtr[-2] *= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-2] /= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-2] %= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-2] &= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } - continue; - } // (op >= OP_LOAD_IMM_INT32) && (op <= OP_FUNC) - - if ((operation == stopToken) || (operation == OP_OR) || - (operation == OP_AND) || (operation == OP_END_EXPR)) { - while (stkPos >= 2) { - var_1A = false; - if ((operPtr[-2] == OP_BEGIN_EXPR) && - ((operation == OP_END_EXPR) || (operation == stopToken))) { - operPtr[-2] = operPtr[-1]; - if ((operPtr[-2] == OP_LOAD_IMM_INT16) || (operPtr[-2] == OP_LOAD_IMM_STR)) - valPtr[-2] = valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - - if (stkPos > 1) { - if (operPtr[-2] == OP_NEG) { - operPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - stkPos--; - operPtr--; - valPtr--; - } else if (operPtr[-2] == OP_NOT) { - if (operPtr[-1] == GOB_FALSE) - operPtr[-2] = GOB_TRUE; - else - operPtr[-2] = GOB_FALSE; - - stkPos--; - operPtr--; - valPtr--; - } - } // stkPos > 1 - - if (stkPos > 2) { - switch (operPtr[-2]) { - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } // switch - } // stkPos > 2 - - if (operation != stopToken) - break; - } // if ((operPtr[-2] == OP_BEGIN_EXPR) && ...) - - for (brackStart = (stkPos - 2); (brackStart > 0) && - (operStack[brackStart] < OP_OR) && (operStack[brackStart] != OP_BEGIN_EXPR); - brackStart--) - ; - - if ((operStack[brackStart] >= OP_OR) || (operStack[brackStart] == OP_BEGIN_EXPR)) - brackStart++; - - switch (operPtr[-2]) { - case OP_ADD: - if (operStack[brackStart] == OP_LOAD_IMM_INT16) { - values[brackStart] += valPtr[-1]; - } else if (operStack[brackStart] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(values[brackStart]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[brackStart])); - values[brackStart] = - encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_SUB: - values[brackStart] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_BITOR: - values[brackStart] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_OR: - // (x OR false) == x - // (x OR true) == true - if (operPtr[-3] == GOB_FALSE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_AND: - // (x AND false) == false - // (x AND true) == x - if (operPtr[-3] == GOB_TRUE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LESS: - operPtr[-3] = (cmpHelper(operPtr, valPtr) < 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) <= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GREATER: - operPtr[-3] = (cmpHelper(operPtr, valPtr) > 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) >= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_EQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) == 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_NEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) != 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - default: - var_1A = true; - break; - } // switch - - if (var_1A) - break; - } // while (stkPos >= 2) - - if ((operation == OP_OR) || (operation == OP_AND)) { - if (operPtr[-1] == OP_LOAD_IMM_INT16) { - if (valPtr[-1] != 0) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - } - - if (((operation == OP_OR) && (operPtr[-1] == GOB_TRUE)) || - ((operation == OP_AND) && (operPtr[-1] == GOB_FALSE))) { - if ((stkPos > 1) && (operPtr[-2] == OP_BEGIN_EXPR)) { - skipExpr(OP_END_EXPR); - operPtr[-2] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else - skipExpr(stopToken); - - operation = _vm->_global->_inter_execPtr[-1]; - if ((stkPos > 0) && (operPtr[-1] == OP_NOT)) { - if (operPtr[0] == GOB_FALSE) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - - stkPos--; - operPtr--; - valPtr--; - } - } else - operPtr[0] = operation; - } else { - stkPos--; - operPtr--; - valPtr--; - } - - if (operation != stopToken) - continue; - - if (arg_2 != 0) - *arg_2 = operStack[0]; - - switch (operStack[0]) { - case OP_LOAD_IMM_INT16: - _vm->_global->_inter_resVal = values[0]; - break; - - case OP_LOAD_IMM_STR: - if ((char *) decodePtr(values[0]) != _vm->_global->_inter_resStr) - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[0])); - break; - - case OP_NOT: - if (arg_2 != 0) - *arg_2 ^= 1; - break; - - case 23: - case 24: - break; - - default: - _vm->_global->_inter_resVal = 0; - if (arg_2 != 0) - *arg_2 = OP_LOAD_IMM_INT16; - break; - } - return 0; - } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) - - if (operation < OP_NEG || operation > OP_NOT) { - if (operation < OP_LESS || operation > OP_NEQ) - continue; - - if (stkPos > 2) { - if (operPtr[-2] == OP_ADD) { - if (operPtr[-3] == OP_LOAD_IMM_INT16) { - valPtr[-3] += valPtr[-1]; - } else if (operPtr[-3] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - } else if (operPtr[-2] == OP_SUB) { - valPtr[-3] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else if (operPtr[-2] == OP_BITOR) { - valPtr[-3] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - } - } - *operPtr = operation; - } -} - -} // End of namespace Gob diff --git a/engines/gob/parse_v2.cpp b/engines/gob/parse_v2.cpp deleted file mode 100644 index e7f91650b5..0000000000 --- a/engines/gob/parse_v2.cpp +++ /dev/null @@ -1,1062 +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. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/parse.h" -#include "gob/global.h" -#include "gob/inter.h" - -namespace Gob { - -Parse_v2::Parse_v2(GobEngine *vm) : Parse_v1(vm) { -} - -int16 Parse_v2::parseVarIndex(uint16 *arg_0, uint16 *arg_4) { - int16 temp2; - byte *arrDesc; - int16 dim; - int16 dimCount; - int16 operation; - int16 temp; - int16 offset; - int16 val; - uint32 varPos = 0; - - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - if (arg_0) - *arg_0 = READ_LE_UINT16(_vm->_global->_inter_execPtr); - if (arg_4) - *arg_4 = 14; - - _vm->_global->_inter_execPtr += 2; - - debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation); - - if (*_vm->_global->_inter_execPtr != 97) - return varPos; - - _vm->_global->_inter_execPtr++; - - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - if (arg_0) - *arg_0 = var_0C; - if (arg_4) - *arg_4 = 15; - - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - debugC(2, kDebugParser, "parseVarIndex: Prefix %d (%d)", varPos, operation); - - if (*_vm->_global->_inter_execPtr != 97) - return varPos; - - _vm->_global->_inter_execPtr++; - } - - operation = *_vm->_global->_inter_execPtr++; - } - - if (arg_0) - *arg_0 = 0; - if (arg_4) - *arg_4 = operation; - - debugC(5, kDebugParser, "var parse = %d", operation); - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - if (operation == OP_ARRAY_UINT8) - return varPos + temp + offset; - if (operation == OP_ARRAY_UINT32) - return varPos + (temp + offset) * 4; - if (operation == OP_ARRAY_UINT16) - return varPos + (temp + offset) * 2; - temp *= 4; - offset *= 4; - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - } - return varPos + offset * _vm->_global->_inter_animDataSize + temp; - - case OP_LOAD_VAR_INT16: - return varPos + _vm->_inter->load16() * 2; - - case OP_LOAD_VAR_INT8: - return varPos + _vm->_inter->load16(); - - case 23: - case 24: - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - debugC(5, kDebugParser, "oper = %d", - (int16) *_vm->_global->_inter_execPtr); - if ((operation == OP_LOAD_VAR_STR) && (*_vm->_global->_inter_execPtr == 13)) { - _vm->_global->_inter_execPtr++; - val = parseValExpr(OP_END_MARKER); - temp += val; - debugC(5, kDebugParser, "parse subscript = %d", val); - } - return varPos + temp; - - default: - return 0; - } -} - -int16 Parse_v2::parseValExpr(byte stopToken) { - int16 values[20]; - byte operStack[20]; - int16 *valPtr; - byte *operPtr; - byte *arrDesc; - byte operation; - int16 temp2; - int16 dim; - int16 dimCount; - int16 temp; - int16 offset; - int16 stkPos; - int16 brackPos; - static int16 flag = 0; - int16 oldflag; - uint32 varPos = 0; - - memset(values, 0, 20 * sizeof(int16)); - - oldflag = flag; - if (flag == 0) { - flag = 1; - printExpr(stopToken); - } - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (1) { - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - _vm->_global->_inter_execPtr += 3; - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - _vm->_global->_inter_execPtr++; - } - - debugC(2, kDebugParser, "parseValExpr: Prefix %d (%d)", varPos, operation); - - operation = *_vm->_global->_inter_execPtr++; - } - - stkPos++; - operPtr++; - valPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - *operPtr = OP_LOAD_IMM_INT16; - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDesc = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = arrDesc[dim] * offset + temp2; - } - if (operation == OP_ARRAY_UINT8) - *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset); - else if (operation == OP_ARRAY_UINT32) - *valPtr = (uint16) READ_VARO_UINT32(varPos + temp * 4 + offset * 4); - else if (operation == OP_ARRAY_UINT16) - *valPtr = READ_VARO_UINT16(varPos + temp * 2 + offset * 2); - else if (operation == OP_ARRAY_STR) { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(varPos + temp * 4 + - offset * 4 * _vm->_global->_inter_animDataSize + temp2); - } - break; - - case OP_LOAD_VAR_INT16: - *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2); - break; - - case OP_LOAD_VAR_INT8: - *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: - *valPtr = (uint16) READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *valPtr = _vm->_inter->load16(); - break; - - case OP_LOAD_IMM_INT8: - *valPtr = (int8) *_vm->_global->_inter_execPtr++; - break; - - case 23: - *valPtr = (uint16) READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4); - break; - - case 24: - *valPtr = READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4); - break; - - case OP_LOAD_VAR_STR: - temp = _vm->_inter->load16() * 4; - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *valPtr = READ_VARO_UINT8(varPos + temp); - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - if (operation == FUNC_SQR) { - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - } else if (operation == FUNC_ABS) { - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - } else if (operation == FUNC_RAND) { - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - } - *valPtr = _vm->_global->_inter_resVal; - break; - - } // switch - if ((stkPos > 0) && (operPtr[-1] == OP_NEG)) { - stkPos--; - operPtr--; - valPtr--; - operPtr[0] = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } - - if ((stkPos > 0) && (operPtr[-1] >= OP_MUL) && (operPtr[-1] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - switch (operPtr[1]) { - case OP_MUL: - valPtr[0] *= valPtr[2]; - break; - - case OP_DIV: - valPtr[0] /= valPtr[2]; - break; - - case OP_MOD: - valPtr[0] %= valPtr[2]; - break; - - case OP_BITAND: - valPtr[0] &= valPtr[2]; - break; - } - } // if ((stkPos > 0) && (cmdPtr[-1] >= OP_MUL) && (cmdPtr[-1] <= OP_BITAND)) - varPos = 0; - continue; - } - - if ((operation >= OP_NEG) && (operation <= OP_BEGIN_EXPR)) { - *operPtr = operation; - continue; - } - - while (stkPos >= 2) { - if (operPtr[-2] == OP_BEGIN_EXPR) { - stkPos--; - operPtr--; - valPtr--; - - operPtr[-1] = operPtr[0]; - valPtr[-1] = valPtr[0]; - if ((stkPos > 1) && (operPtr[-2] == OP_NEG)) { - operPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - } - - if ((stkPos > 2) && (operPtr[-2] >= OP_MUL) && (operPtr[-2] <= OP_BITAND)) { - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_MUL: - valPtr[-1] *= valPtr[1]; - break; - - case OP_DIV: - valPtr[-1] /= valPtr[1]; - break; - - case OP_MOD: - valPtr[-1] %= valPtr[1]; - break; - - case OP_BITAND: - valPtr[-1] &= valPtr[1]; - break; - } - } - if (operation == OP_END_EXPR) - break; - } // operPtr[-2] == OP_BEGIN_EXPR - - for (brackPos = (stkPos - 2); (brackPos > 0) && - (operStack[brackPos] < OP_OR) && (operStack[brackPos] != OP_BEGIN_EXPR); - brackPos--) - ; - - if ((operStack[brackPos] >= OP_OR) || (operStack[brackPos] == OP_BEGIN_EXPR)) - brackPos++; - - if ((operPtr[-2] < 2) || (operPtr[-2] > 8)) - break; - - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - switch (operPtr[0]) { - case OP_ADD: - values[brackPos] += valPtr[1]; - continue; - case OP_SUB: - values[brackPos] -= valPtr[1]; - continue; - case OP_BITOR: - values[brackPos] |= valPtr[1]; - continue; - case OP_MUL: - valPtr[-1] *= valPtr[1]; - continue; - case OP_DIV: - valPtr[-1] /= valPtr[1]; - continue; - case OP_MOD: - valPtr[-1] %= valPtr[1]; - continue; - case OP_BITAND: - valPtr[-1] &= valPtr[1]; - continue; - } - } - - if (operation != OP_END_EXPR) { - if (operation != stopToken) { - debugC(5, kDebugParser, "stoptoken error: %d != %d", - operation, stopToken); - } - flag = oldflag; - return values[0]; - } - - stkPos--; - operPtr--; - valPtr--; - } -} - -int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) { - int32 values[20]; - byte operStack[20]; - int32 prevPrevVal; - int32 prevVal; - int32 curVal; - int32 *valPtr; - byte *operPtr; - byte *arrDescPtr; - byte operation; - int16 dimCount; - int16 temp; - int16 temp2; - int16 offset; - int16 dim; - bool var_1A; - int16 stkPos; - int16 brackStart; - uint32 varPos = 0; - - memset(operStack, 0, 20); - - stkPos = -1; - operPtr = operStack - 1; - valPtr = values - 1; - - while (true) { - operation = *_vm->_global->_inter_execPtr++; - - while ((operation == 14) || (operation == 15)) { - if (operation == 14) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - _vm->_global->_inter_execPtr += 2; - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - } else if (operation == 15) { - uint16 n = _vm->_inter->load16(); - varPos += n * 4; - - uint16 var_0C = _vm->_inter->load16(); - uint8 var_A = *_vm->_global->_inter_execPtr++; - - byte *var_12 = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += var_A; - - uint16 var_6 = 0; - - for (int i = 0; i < var_A; i++) { - temp2 = parseValExpr(OP_END_MARKER); - - int16 ax = getOffset(temp2, var_12[i], varPos, 0, 0); - - var_6 = var_6 * var_12[i] + ax; - } - - varPos += var_6 * var_0C * 4; - - if (*_vm->_global->_inter_execPtr == 97) - _vm->_global->_inter_execPtr++; - } - - debugC(2, kDebugParser, "parseExpr: Prefix %d (%d)", varPos, operation); - - operation = *_vm->_global->_inter_execPtr++; - } - - stkPos++; - operPtr++; - valPtr++; - - if ((operation >= OP_ARRAY_UINT8) && (operation <= OP_FUNC)) { - switch (operation) { - case OP_ARRAY_UINT8: - case OP_ARRAY_UINT32: - case OP_ARRAY_UINT16: - case OP_ARRAY_STR: - *operPtr = (operation == OP_ARRAY_STR) ? OP_LOAD_IMM_STR : OP_LOAD_IMM_INT16; - temp = _vm->_inter->load16(); - dimCount = *_vm->_global->_inter_execPtr++; - arrDescPtr = _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += dimCount; - offset = 0; - for (dim = 0; dim < dimCount; dim++) { - temp2 = parseValExpr(OP_END_MARKER); - offset = offset * arrDescPtr[dim] + temp2; - } - if (operation == OP_ARRAY_UINT8) - *valPtr = (int8) READ_VARO_UINT8(varPos + temp + offset); - else if (operation == OP_ARRAY_UINT32) - *valPtr = READ_VARO_UINT32(varPos + temp * 4 + offset * 4); - else if (operation == OP_ARRAY_UINT16) - *valPtr = (int16) READ_VARO_UINT16(varPos + temp * 2 + offset * 2); - else if (operation == OP_ARRAY_STR) { - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8( - varPos + temp * 4 + offset * _vm->_global->_inter_animDataSize * 4), - kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp2 = parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(varPos + temp * 4 + - offset * 4 * _vm->_global->_inter_animDataSize + temp2); - } - } - break; - - case OP_LOAD_VAR_INT16: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 2); - break; - - case OP_LOAD_VAR_INT8: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int8) READ_VARO_UINT8(varPos + _vm->_inter->load16()); - break; - - case OP_LOAD_IMM_INT32: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_LE_UINT32(varPos + _vm->_global->_inter_execPtr); - _vm->_global->_inter_execPtr += 4; - break; - - case OP_LOAD_IMM_INT16: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_inter->load16(); - break; - - case OP_LOAD_IMM_INT8: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int8) *_vm->_global->_inter_execPtr++; - break; - - case OP_LOAD_IMM_STR: - *operPtr = OP_LOAD_IMM_STR; - *valPtr = encodePtr(_vm->_global->_inter_execPtr, kExecPtr); - _vm->_global->_inter_execPtr += - strlen((char *) _vm->_global->_inter_execPtr) + 1; - break; - - case 23: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT32(varPos + _vm->_inter->load16() * 4); - break; - - case 24: - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = (int16) READ_VARO_UINT16(varPos + _vm->_inter->load16() * 4); - break; - - case OP_LOAD_VAR_STR: - *operPtr = OP_LOAD_IMM_STR; - temp = _vm->_inter->load16() * 4; - *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(varPos + temp), kInterVar); - if (*_vm->_global->_inter_execPtr == 13) { - _vm->_global->_inter_execPtr++; - temp += parseValExpr(OP_END_MARKER); - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = READ_VARO_UINT8(varPos + temp); - } - break; - - case OP_FUNC: - operation = *_vm->_global->_inter_execPtr++; - parseExpr(OP_END_EXPR, 0); - - switch (operation) { - case FUNC_SQRT1: - case FUNC_SQRT2: - case FUNC_SQRT3: - curVal = 1; - prevVal = 1; - - do { - prevPrevVal = prevVal; - prevVal = curVal; - curVal = (curVal + _vm->_global->_inter_resVal / curVal) / 2; - } while ((curVal != prevVal) && (curVal != prevPrevVal)); - _vm->_global->_inter_resVal = curVal; - break; - - case FUNC_SQR: - _vm->_global->_inter_resVal = - _vm->_global->_inter_resVal * _vm->_global->_inter_resVal; - break; - - case FUNC_ABS: - if (_vm->_global->_inter_resVal < 0) - _vm->_global->_inter_resVal = -_vm->_global->_inter_resVal; - break; - - case FUNC_RAND: - _vm->_global->_inter_resVal = - _vm->_util->getRandom(_vm->_global->_inter_resVal); - break; - } - - *operPtr = OP_LOAD_IMM_INT16; - *valPtr = _vm->_global->_inter_resVal; - break; - } - - if ((stkPos > 0) && ((operPtr[-1] == OP_NEG) || (operPtr[-1] == OP_NOT))) { - stkPos--; - operPtr--; - valPtr--; - - if (*operPtr == OP_NEG) { - *operPtr = OP_LOAD_IMM_INT16; - valPtr[0] = -valPtr[1]; - } else - *operPtr = (operPtr[1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; - } - - if (stkPos <= 0) { - varPos = 0; - continue; - } - - switch (operPtr[-1]) { - case OP_ADD: - if (operPtr[-2] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-2]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-2])); - valPtr[-2] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[0])); - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - break; - - case OP_MUL: - valPtr[-2] *= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-2] /= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-2] %= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-2] &= valPtr[0]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } - varPos = 0; - continue; - } // (op >= OP_ARRAY_UINT8) && (op <= OP_FUNC) - - if ((operation == stopToken) || (operation == OP_OR) || - (operation == OP_AND) || (operation == OP_END_EXPR)) { - while (stkPos >= 2) { - var_1A = false; - if ((operPtr[-2] == OP_BEGIN_EXPR) && - ((operation == OP_END_EXPR) || (operation == stopToken))) { - operPtr[-2] = operPtr[-1]; - if ((operPtr[-2] == OP_LOAD_IMM_INT16) || (operPtr[-2] == OP_LOAD_IMM_STR)) - valPtr[-2] = valPtr[-1]; - - stkPos--; - operPtr--; - valPtr--; - - if (stkPos > 1) { - if (operPtr[-2] == OP_NEG) { - operPtr[-2] = OP_LOAD_IMM_INT16; - valPtr[-2] = -valPtr[-1]; - stkPos--; - operPtr--; - valPtr--; - } else if (operPtr[-2] == OP_NOT) { - operPtr[-2] = (operPtr[-1] == GOB_FALSE) ? GOB_TRUE : GOB_FALSE; - stkPos--; - operPtr--; - valPtr--; - } - } // stkPos > 1 - - if (stkPos > 2) { - switch (operPtr[-2]) { - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } // switch - } // stkPos > 2 - - if (operation != stopToken) - break; - } // if ((operPtr[-2] == OP_BEGIN_EXPR) && ...) - - for (brackStart = (stkPos - 2); (brackStart > 0) && - (operStack[brackStart] < OP_OR) && (operStack[brackStart] != OP_BEGIN_EXPR); - brackStart--) - ; - - if ((operStack[brackStart] >= OP_OR) || (operStack[brackStart] == OP_BEGIN_EXPR)) - brackStart++; - - switch (operPtr[-2]) { - case OP_ADD: - if (operStack[brackStart] == OP_LOAD_IMM_INT16) { - values[brackStart] += valPtr[-1]; - } else if (operStack[brackStart] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(values[brackStart]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[brackStart])); - values[brackStart] = - encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_SUB: - values[brackStart] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_BITOR: - values[brackStart] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - continue; - - case OP_MUL: - valPtr[-3] *= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_DIV: - valPtr[-3] /= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_MOD: - valPtr[-3] %= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_BITAND: - valPtr[-3] &= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_OR: - // (x OR false) == x - // (x OR true) == true - if (operPtr[-3] == GOB_FALSE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_AND: - // (x AND false) == false - // (x AND true) == x - if (operPtr[-3] == GOB_TRUE) - operPtr[-3] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LESS: - operPtr[-3] = (cmpHelper(operPtr, valPtr) < 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_LEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) <= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GREATER: - operPtr[-3] = (cmpHelper(operPtr, valPtr) > 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_GEQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) >= 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_EQ: - operPtr[-3] = (cmpHelper(operPtr, valPtr) == 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - - case OP_NEQ: { - int cmpTemp = 0; - - if (operPtr[-3] == OP_LOAD_IMM_INT16) { - cmpTemp = valPtr[-3] - valPtr[-1]; - } else if (operPtr[-3] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - // FIXME: Why scumm_stricmp here and strcmp everywhere else? - cmpTemp = scumm_stricmp(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - operPtr[-3] = (cmpTemp != 0) ? GOB_TRUE : GOB_FALSE; - //operPtr[-3] = (cmpHelper(operPtr, valPtr) != 0) ? GOB_TRUE : GOB_FALSE; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - break; - } - - default: - var_1A = true; - break; - } // switch - - if (var_1A) - break; - } // while (stkPos >= 2) - - if ((operation == OP_OR) || (operation == OP_AND)) { - if (operPtr[-1] == OP_LOAD_IMM_INT16) { - if (valPtr[-1] != 0) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - } - - if (((operation == OP_OR) && (operPtr[-1] == GOB_TRUE)) || - ((operation == OP_AND) && (operPtr[-1] == GOB_FALSE))) { - if ((stkPos > 1) && (operPtr[-2] == OP_BEGIN_EXPR)) { - skipExpr(OP_END_EXPR); - operPtr[-2] = operPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else { - skipExpr(stopToken); - } - operation = _vm->_global->_inter_execPtr[-1]; - if ((stkPos > 0) && (operPtr[-1] == OP_NOT)) { - if (operPtr[0] == GOB_FALSE) - operPtr[-1] = GOB_TRUE; - else - operPtr[-1] = GOB_FALSE; - - stkPos--; - operPtr--; - valPtr--; - } - } else - operPtr[0] = operation; - } else { - stkPos--; - operPtr--; - valPtr--; - } - - if (operation != stopToken) - continue; - - if (arg_2 != 0) - *arg_2 = operStack[0]; - - switch (operStack[0]) { - case OP_NOT: - if (arg_2 != 0) - *arg_2 ^= 1; - break; - - case OP_LOAD_IMM_INT16: - _vm->_global->_inter_resVal = values[0]; - break; - - case OP_LOAD_IMM_STR: - if ((char *) decodePtr(values[0]) != _vm->_global->_inter_resStr) - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(values[0])); - break; - - case 23: - case 24: - break; - - default: - _vm->_global->_inter_resVal = 0; - if (arg_2 != 0) - *arg_2 = OP_LOAD_IMM_INT16; - break; - } - return 0; - } // (operation == stopToken) || (operation == OP_OR) || (operation == OP_AND) || (operation == OP_END_EXPR) - - if ((operation < OP_NEG) || (operation > OP_NOT)) { - if ((operation < OP_LESS) || (operation > OP_NEQ)) - continue; - - if (stkPos > 2) { - if (operPtr[-2] == OP_ADD) { - if (operPtr[-3] == OP_LOAD_IMM_INT16) { - valPtr[-3] += valPtr[-1]; - } else if (operPtr[-3] == OP_LOAD_IMM_STR) { - if ((char *) decodePtr(valPtr[-3]) != _vm->_global->_inter_resStr) { - strcpy(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-3])); - valPtr[-3] = encodePtr((byte *) _vm->_global->_inter_resStr, kResStr); - } - strcat(_vm->_global->_inter_resStr, (char *) decodePtr(valPtr[-1])); - } - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - - } else if (operPtr[-2] == OP_SUB) { - valPtr[-3] -= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } else if (operPtr[-2] == OP_BITOR) { - valPtr[-3] |= valPtr[-1]; - stkPos -= 2; - operPtr -= 2; - valPtr -= 2; - } - } - } - *operPtr = operation; - } -} - -int16 Parse_v2::getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9) { - if (arg_0 < 0) - return 0; - - if (arg_2 > arg_0) - return arg_0; - - return arg_2 - 1; -} - -} // End of namespace Gob diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp new file mode 100644 index 0000000000..20427e547b --- /dev/null +++ b/engines/gob/resources.cpp @@ -0,0 +1,706 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/endian.h" +#include "common/stream.h" + +#include "gob/gob.h" +#include "gob/resources.h" +#include "gob/totfile.h" +#include "gob/dataio.h" +#include "gob/game.h" +#include "gob/global.h" + +namespace Gob { + +Resource::Resource(byte *data, int32 size, bool needFree, + int16 width, int16 height) { + + _data = data; + _size = size; + _width = width; + _height = height; + _needFree = needFree; + + _stream = new Common::MemoryReadStream(data, size); +} + +Resource::~Resource() { + delete _stream; + + if (_needFree) + delete[] _data; +} + +byte *Resource::getData() const { + return _data; +} + +int32 Resource::getSize() const { + return _size; +} + +int16 Resource::getWidth() const { + return _width; +} + +int16 Resource::getHeight() const { + return _height; +} + +Common::MemoryReadStream *Resource::stream() const { + return _stream; +} + + +TextItem::TextItem(byte *data, int32 size) { + _data = data; + _size = size; + + _stream = new Common::MemoryReadStream(data, size); +} + +TextItem::~TextItem() { + delete _stream; +} + +byte *TextItem::getData() const { + return _data; +} + +int32 TextItem::getSize() const { + return _size; +} + +Common::MemoryReadStream *TextItem::stream() const { + return _stream; +} + + +Resources::TOTResourceTable::TOTResourceTable() { + items = 0; +} + +Resources::TOTResourceTable::~TOTResourceTable() { + delete[] items; +} + + +Resources::EXTResourceTable::EXTResourceTable() { + itemsCount = 0; + unknown = 0; + items = 0; +} + +Resources::EXTResourceTable::~EXTResourceTable() { + delete[] items; +} + + +Resources::TOTTextTable::TOTTextTable() { + items = 0; + data = 0; + needFree = false; +} + +Resources::TOTTextTable::~TOTTextTable() { + delete[] items; + if (needFree) + delete[] data; +} + + +Resources::Resources(GobEngine *vm) : _vm(vm) { + unload(false); +} + +Resources::~Resources() { + unload(); +} + +bool Resources::load(const Common::String &fileName) { + unload(); + + Common::String fileBase; + + _totFile = TOTFile::createFileName(fileName, _hasLOM); + + if (_hasLOM) { + warning("Stub: Resources::load(%s)", fileName.c_str()); + unload(); + return false; + } + + fileBase = TOTFile::getFileBase(fileName); + + _extFile = fileBase + ".ext"; + + if (!loadTOTResourceTable()) { + unload(); + return false; + } + + if (!loadEXTResourceTable()) { + unload(); + return false; + } + + if (!loadTOTTextTable(fileBase)) { + unload(); + return false; + } + + if (!loadIMFile()) { + unload(); + return false; + } + + if (!loadEXFile()) { + unload(); + return false; + } + + return true; +} + +void Resources::unload(bool del) { + if (del) { + delete _totResourceTable; + delete _extResourceTable; + delete _totTextTable; + + delete[] _totData; + delete[] _imData; + + _totFile.clear(); + _extFile.clear(); + _exFile.clear(); + } + + _totResourceTable = 0; + _extResourceTable = 0; + _totTextTable = 0; + _totData = 0; + _totSize = 0; + _imData = 0; + _imSize = 0; +} + +bool Resources::isLoaded() const { + return (_totResourceTable != 0); +} + +bool Resources::loadTOTResourceTable() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if ((totProps.resourcesOffset == 0xFFFFFFFF) || + (totProps.resourcesOffset == 0)) + // No resources here + return false; + + _totResourceTable = new TOTResourceTable; + + stream->seek(totProps.resourcesOffset); + _totResourceTable->itemsCount = stream->readSint16LE(); + + _totResourceTable->dataOffset = totProps.resourcesOffset + kTOTResTableSize + + _totResourceTable->itemsCount * kTOTResItemSize; + + + uint32 resSize = _totResourceTable->itemsCount * kTOTResItemSize + + kTOTResTableSize; + + // Would the table actually fit into the TOT? + if ((totProps.resourcesOffset + resSize) > ((uint32) stream->size())) + return false; + + _totResourceTable->unknown = stream->readByte(); + _totResourceTable->items = new TOTResourceItem[_totResourceTable->itemsCount]; + + for (int i = 0; i < _totResourceTable->itemsCount; ++i) { + TOTResourceItem &item = _totResourceTable->items[i]; + + item.offset = stream->readSint32LE(); + item.size = stream->readSint16LE(); + item.width = stream->readSint16LE(); + item.height = stream->readSint16LE(); + + if (item.offset < 0) { + item.type = kResourceIM; + item.index = -item.offset - 1; + } else + item.type = kResourceTOT; + } + + _totResStart = totProps.scriptEnd; + _totSize = stream->size() - _totResStart; + if (_totSize <= 0) + return false; + + if (!stream->seek(totProps.scriptEnd)) + return false; + + _totData = new byte[_totSize]; + if (stream->read(_totData, _totSize) != _totSize) + return false; + + return !stream->err(); +} + +bool Resources::loadEXTResourceTable() { + _extResourceTable = new EXTResourceTable; + + DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str()); + if (!stream) + return true; + + _extResourceTable->itemsCount = stream->readSint16LE(); + _extResourceTable->unknown = stream->readByte(); + + if (_extResourceTable->itemsCount > 0) + _extResourceTable->items = new EXTResourceItem[_extResourceTable->itemsCount]; + + for (int i = 0; i < _extResourceTable->itemsCount; i++) { + EXTResourceItem &item = _extResourceTable->items[i]; + + item.offset = stream->readUint32LE(); + item.size = stream->readUint16LE(); + item.width = stream->readUint16LE(); + item.height = stream->readUint16LE(); + + if (item.offset < 0) { + item.type = kResourceEX; + item.offset = -item.offset - 1; + } else { + item.type = kResourceEXT; + item.offset += kEXTResTableSize + + kEXTResItemSize * _extResourceTable->itemsCount; + } + + item.packed = (item.width & 0x8000) != 0; + + item.width &= 0x7FFF; + } + + delete stream; + return true; +} + +bool Resources::loadTOTTextTable(const Common::String &fileBase) { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if (totProps.textsOffset == ((uint32) -1)) + // No texts + return true; + + _totTextTable = new TOTTextTable; + + bool fromTOT; + if (totProps.textsOffset == 0) { + fromTOT = false; + _totTextTable->data = loadTOTLocTexts(fileBase, _totTextTable->size); + _totTextTable->needFree = true; + } else { + fromTOT = true; + _totTextTable->data = _totData + totProps.textsOffset - _totResStart; + _totTextTable->needFree = false; + _totTextTable->size = _totSize - totProps.textsOffset; + } + + if (_totTextTable->data) { + Common::MemoryReadStream totTextTable(_totTextTable->data, _totTextTable->size); + _totTextTable->itemsCount = totTextTable.readSint16LE() & 0x3FFF; + + _totTextTable->items = new TOTTextItem[_totTextTable->itemsCount]; + for (int i = 0; i < _totTextTable->itemsCount; ++i) { + TOTTextItem &item = _totTextTable->items[i]; + + item.offset = totTextTable.readSint16LE(); + item.size = totTextTable.readSint16LE(); + + if (fromTOT) + item.offset -= (totProps.textsOffset - _totResStart); + } + } + + return true; +} + +bool Resources::loadIMFile() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + if ((totProps.communHandling != 0) && (totProps.imFileNumber == 0)) + // No IM file + return true; + + Common::String imFile = "commun.im"; + + char num = totProps.imFileNumber + '0'; + if (num == '0') + num = '1'; + + imFile += num; + + DataStream *stream = _vm->_dataIO->getDataStream(imFile.c_str()); + if (!stream) + return true; + + _imSize = stream->size(); + if (_imSize <= 0) { + _imSize = 0; + delete stream; + return true; + } + + _imData = new byte[_imSize]; + if (stream->read(_imData, _imSize) != _imSize) { + delete[] _imData; + _imData = 0; + _imSize = 0; + } + + delete stream; + return true; +} + +bool Resources::loadEXFile() { + TOTFile totFile(_vm); + + if (!totFile.load(_totFile)) + return false; + + TOTFile::Properties totProps; + if (!totFile.getProperties(totProps)) + return false; + + _exFile = "commun.ex"; + _exFile += totProps.exFileNumber + '0'; + + if (!_vm->_dataIO->existData(_exFile.c_str())) { + _exFile.clear(); + return true; + } + + return true; +} + +Common::String Resources::getLocTextFile(const Common::String &fileBase, + int language) { + + Common::String locTextFile = fileBase + "."; + switch (language) { + case kLanguageFrench: + locTextFile += "dat"; + break; + case kLanguageGerman: + locTextFile += "all"; + break; + case kLanguageSpanish: + locTextFile += "esp"; + break; + case kLanguageItalian: + locTextFile += "ita"; + break; + case kLanguageAmerican: + locTextFile += "usa"; + break; + case kLanguageDutch: + locTextFile += "ndl"; + break; + case kLanguageKorean: + locTextFile += "kor"; + break; + case kLanguageHebrew: + locTextFile += "isr"; + break; + default: + locTextFile += "ang"; + break; + } + + if (!_vm->_dataIO->existData(locTextFile.c_str())) + locTextFile.clear(); + + return locTextFile; +} + +byte *Resources::loadTOTLocTexts(const Common::String &fileBase, int32 &size) { + Common::String locTextFile; + + locTextFile = getLocTextFile(fileBase, _vm->_global->_languageWanted); + + if (!locTextFile.empty()) { + + _vm->_global->_foundLanguage = true; + _vm->_global->_language = _vm->_global->_languageWanted; + + } else if (!_vm->_global->_foundLanguage) { + + // Trying US for GB and vice versa + if (_vm->_global->_languageWanted == kLanguageBritish) { + + locTextFile = getLocTextFile(fileBase, kLanguageAmerican); + if (!locTextFile.empty()) + _vm->_global->_language = kLanguageAmerican; + + } else if (_vm->_global->_languageWanted == kLanguageAmerican) { + + locTextFile = getLocTextFile(fileBase, kLanguageBritish); + if (!locTextFile.empty()) + _vm->_global->_language = kLanguageBritish; + + } + + if (locTextFile.empty()) { + // Looking for the first existing language + for (int i = 0; i < 10; i++) { + locTextFile = getLocTextFile(fileBase, i); + if (!locTextFile.empty()) { + _vm->_global->_language = i; + break; + } + } + } + + } + + debugC(1, kDebugFileIO, "Using language %d for %s", + _vm->_global->_language, _totFile.c_str()); + + if (locTextFile.empty()) + return 0; + + size = _vm->_dataIO->getDataSize(locTextFile.c_str()); + return _vm->_dataIO->getData(locTextFile.c_str()); +} + +Resource *Resources::getResource(uint16 id, int16 *width, int16 *height) const { + if (_hasLOM) { + warning("Stub: Resources::getResource(): Has LOM"); + return 0; + } + + Resource *resource = 0; + if (id >= 30000) + resource = getEXTResource(id - 30000); + else + resource = getTOTResource(id); + + if (!resource) + return 0; + + if (width) + *width = resource->getWidth(); + if (height) + *height = resource->getHeight(); + + return resource; +} + +TextItem *Resources::getTextItem(uint16 id) const { + if (!_totTextTable || !_totTextTable->data) + return 0; + + if (id >= _totTextTable->itemsCount) + return 0; + + TOTTextItem &totItem = _totTextTable->items[id]; + + if ((totItem.offset == 0xFFFF) || (totItem.size == 0)) + return 0; + if ((totItem.offset + totItem.size) > (_totTextTable->size)) + return 0; + + return new TextItem(_totTextTable->data + totItem.offset, totItem.size); +} + +byte *Resources::getTexts() const { + if (!_totTextTable) + return 0; + + return _totTextTable->data; +} + +Resource *Resources::getTOTResource(uint16 id) const { + if (id >= _totResourceTable->itemsCount) { + warning("Trying to load non-existent TOT resource (%s, %d/%d)", + _totFile.c_str(), id, _totResourceTable->itemsCount - 1); + return 0; + } + + TOTResourceItem &totItem = _totResourceTable->items[id]; + + byte *data = 0; + if (totItem.type == kResourceIM) + data = getIMData(totItem); + if (totItem.type == kResourceTOT) + data = getTOTData(totItem); + + if (!data) + return 0; + + return new Resource(data, totItem.size, false, totItem.width, totItem.height); +} + +Resource *Resources::getEXTResource(uint16 id) const { + if (!_extResourceTable || (id > _extResourceTable->itemsCount)) + return 0; + + EXTResourceItem &extItem = _extResourceTable->items[id]; + + uint32 size = extItem.size; + + if (extItem.width & 0x4000) + size += 1 << 16; + if (extItem.width & 0x2000) + size += 2 << 16; + if (extItem.width & 0x1000) + size += 4 << 16; + if (extItem.height == 0) + size += extItem.width << 16; + + byte *data = 0; + if (extItem.type == kResourceEXT) + data = getEXTData(extItem, size); + if (extItem.type == kResourceEX) + data = getEXData(extItem, size); + + if (!data) + return 0; + + if (extItem.packed) { + byte *packedData = data; + + size = READ_LE_UINT32(packedData); + data = new byte[size]; + + _vm->_dataIO->unpackData(packedData, data); + + delete[] packedData; + } + + return new Resource(data, size, true, extItem.width & 0xFFF, extItem.height); +} + +byte *Resources::getTOTData(TOTResourceItem &totItem) const { + if (totItem.size < 0) + return 0; + + int32 offset = _totResourceTable->dataOffset + totItem.offset - _totResStart; + + if ((offset < 0) || (((uint32) (offset + totItem.size)) > _totSize)) + return 0; + + return _totData + offset; +} + +byte *Resources::getIMData(TOTResourceItem &totItem) const { + if (totItem.size < 0) + return 0; + + int32 indexOffset = totItem.index * 4; + if ((indexOffset < 0) || (((uint32) indexOffset) >= _imSize)) + return 0; + + uint32 offset = READ_LE_UINT32(_imData + indexOffset); + if ((offset + totItem.size) > _imSize) + return 0; + + return _imData + offset; +} + +byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const { + DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str()); + if (!stream) + return 0; + + if (!stream->seek(extItem.offset)) { + delete stream; + return 0; + } + + byte *data = new byte[extItem.packed ? (size + 2) : size]; + if (stream->read(data, size) != size) { + delete[] data; + delete stream; + return 0; + } + + delete stream; + return data; +} + +byte *Resources::getEXData(EXTResourceItem &extItem, uint32 size) const { + DataStream *stream = _vm->_dataIO->getDataStream(_exFile.c_str()); + if (!stream) + return 0; + + if (!stream->seek(extItem.offset)) { + delete stream; + return 0; + } + + byte *data = new byte[extItem.packed ? (size + 2) : size]; + if (stream->read(data, size) != size) { + delete[] data; + delete stream; + return 0; + } + + delete stream; + return data; +} + +} // End of namespace Gob diff --git a/engines/gob/resources.h b/engines/gob/resources.h new file mode 100644 index 0000000000..80acef645c --- /dev/null +++ b/engines/gob/resources.h @@ -0,0 +1,207 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_RESOURCES_H +#define GOB_RESOURCES_H + +#include "common/str.h" + +namespace Common { + class MemoryReadStream; +} + +namespace Gob { + +class GobEngine; + +class Resource { +public: + Resource(byte *data, int32 size, bool needFree = true, + int16 width = 0, int16 height = 0); + ~Resource(); + + byte *getData () const; + int32 getSize () const; + int16 getWidth () const; + int16 getHeight() const; + + Common::MemoryReadStream *stream() const; + +private: + byte *_data; + int32 _size; + int16 _width; + int16 _height; + bool _needFree; + + Common::MemoryReadStream *_stream; +}; + +class TextItem { +public: + TextItem(byte *data, int32 size); + ~TextItem(); + + byte *getData() const; + int32 getSize() const; + + Common::MemoryReadStream *stream() const; + +private: + byte *_data; + int32 _size; + + Common::MemoryReadStream *_stream; +}; + +class Resources { +public: + Resources(GobEngine *vm); + ~Resources(); + + bool load(const Common::String &fileName); + void unload(bool del = true); + + bool isLoaded() const; + + Resource *getResource(uint16 id, int16 *width = 0, int16 *height = 0) const; + TextItem *getTextItem(uint16 id) const; + + byte *getTexts() const; + +private: + // Structure sizes in the files + static const int kTOTResItemSize = 4 + 2 + 2 + 2; + static const int kTOTResTableSize = 2 + 1; + static const int kEXTResItemSize = 4 + 2 + 2 + 2; + static const int kEXTResTableSize = 2 + 1; + static const int kTOTTextTableSize = 2; + static const int kTOTTextItemSize = 2 + 2; + + enum ResourceType { + kResourceTOT, + kResourceIM, + kResourceEXT, + kResourceEX + }; + + struct TOTResourceItem { + ResourceType type; + int16 size; + int16 width; + int16 height; + union { + int32 offset; + int32 index; + }; + }; + + struct TOTResourceTable { + int16 itemsCount; + byte unknown; + TOTResourceItem *items; + uint32 dataOffset; + + TOTResourceTable(); + ~TOTResourceTable(); + }; + + struct EXTResourceItem { + ResourceType type; + int32 offset; + uint16 size; + int16 width; + int16 height; + bool packed; + }; + + struct EXTResourceTable { + int16 itemsCount; + byte unknown; + EXTResourceItem *items; + + EXTResourceTable(); + ~EXTResourceTable(); + }; + + struct TOTTextItem { + uint16 offset; + int16 size; + }; + + struct TOTTextTable { + bool needFree; + int16 itemsCount; + + byte *data; + int32 size; + + TOTTextItem *items; + + TOTTextTable(); + ~TOTTextTable(); + }; + + GobEngine *_vm; + + Common::String _totFile; + Common::String _extFile; + Common::String _exFile; + + byte *_totData; + uint32 _totSize; + + byte *_imData; + uint32 _imSize; + + bool _hasLOM; + int32 _totResStart; + + TOTResourceTable *_totResourceTable; + EXTResourceTable *_extResourceTable; + TOTTextTable *_totTextTable; + + bool loadTOTResourceTable(); + bool loadEXTResourceTable(); + bool loadTOTTextTable(const Common::String &fileBase); + bool loadIMFile(); + bool loadEXFile(); + + byte *loadTOTLocTexts(const Common::String &fileBase, int32 &size); + bool getLocTextFile(char *locTextFile, int language); + Common::String getLocTextFile(const Common::String &fileBase, int language); + + Resource *getTOTResource(uint16 id) const; + Resource *getEXTResource(uint16 id) const; + + byte *getTOTData(TOTResourceItem &totItem) const; + byte *getIMData(TOTResourceItem &totItem) const; + byte *getEXTData(EXTResourceItem &extItem, uint32 size) const; + byte *getEXData(EXTResourceItem &extItem, uint32 size) const; +}; + +} // End of namespace Gob + +#endif // GOB_RESOURCES_H diff --git a/engines/gob/save/savefile.cpp b/engines/gob/save/savefile.cpp index b3b545548f..e1c4c62b12 100644 --- a/engines/gob/save/savefile.cpp +++ b/engines/gob/save/savefile.cpp @@ -331,17 +331,14 @@ bool SavePartSprite::readPalette(const byte *palette) { return true; } -bool SavePartSprite::readSprite(const SurfaceDesc *sprite) { - if (!sprite) - return false; - +bool SavePartSprite::readSprite(const SurfaceDesc &sprite) { // The sprite's dimensions have to fit - if (((uint32) sprite->getWidth()) != _width) + if (((uint32)sprite.getWidth()) != _width) return false; - if (((uint32) sprite->getHeight()) != _height) + if (((uint32)sprite.getHeight()) != _height) return false; - memcpy(_dataSprite, sprite->getVidMem(), _width * _height); + memcpy(_dataSprite, sprite.getVidMem(), _width * _height); return true; } @@ -360,17 +357,14 @@ bool SavePartSprite::writePalette(byte *palette) const { return true; } -bool SavePartSprite::writeSprite(SurfaceDesc *sprite) const { - if (!sprite) - return false; - +bool SavePartSprite::writeSprite(SurfaceDesc &sprite) const { // The sprite's dimensions have to fit - if (((uint32) sprite->getWidth()) != _width) + if (((uint32)sprite.getWidth()) != _width) return false; - if (((uint32) sprite->getHeight()) != _height) + if (((uint32)sprite.getHeight()) != _height) return false; - memcpy(sprite->getVidMem(), _dataSprite, _width * _height); + memcpy(sprite.getVidMem(), _dataSprite, _width * _height); return true; } diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h index 6c211c1d5c..615be8e0f2 100644 --- a/engines/gob/save/savefile.h +++ b/engines/gob/save/savefile.h @@ -162,15 +162,15 @@ public: /** Read a palette into the part. */ bool readPalette(const byte *palette); /** Read a sprite into the part. */ - bool readSprite(const SurfaceDesc *sprite); - + bool readSprite(const SurfaceDesc &sprite); + /** Read size bytes of raw data into the sprite. */ bool readSpriteRaw(const byte *data, uint32 size); /** Write a palette out of the part. */ bool writePalette(byte *palette) const; /** Write a sprite out of the part. */ - bool writeSprite(SurfaceDesc *sprite) const; + bool writeSprite(SurfaceDesc &sprite) const; private: uint32 _width; diff --git a/engines/gob/save/savehandler.cpp b/engines/gob/save/savehandler.cpp index 74b878f0a1..4e2c09bdca 100644 --- a/engines/gob/save/savehandler.cpp +++ b/engines/gob/save/savehandler.cpp @@ -242,14 +242,14 @@ bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) { if ((index < 0) || (index >= SPRITES_COUNT)) return false; - SurfaceDesc *sprite = _vm->_draw->_spritesArray[index]; + SurfaceDescPtr sprite = _vm->_draw->_spritesArray[index]; // Target sprite exists? if (!sprite) return false; // Load the sprite - if (!_sprite->writeSprite(sprite)) + if (!_sprite->writeSprite(*sprite)) return false; // Handle palette @@ -272,13 +272,13 @@ bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) { } bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) { - SurfaceDesc *sprite; + SurfaceDescPtr sprite; if (!createSprite(dataVar, size, offset, &sprite)) return false; // Save the sprite - if (!_sprite->readSprite(sprite)) + if (!_sprite->readSprite(*sprite)) return false; // Handle palette @@ -291,7 +291,7 @@ bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) { } bool TempSpriteHandler::createSprite(int16 dataVar, int32 size, - int32 offset, SurfaceDesc **sprite) { + int32 offset, SurfaceDescPtr *sprite) { delete _sprite; _sprite = 0; @@ -305,7 +305,7 @@ bool TempSpriteHandler::createSprite(int16 dataVar, int32 size, if ((index < 0) || (index >= SPRITES_COUNT)) return false; - SurfaceDesc *sprt = _vm->_draw->_spritesArray[index]; + SurfaceDescPtr sprt = _vm->_draw->_spritesArray[index]; // Sprite exists? if (!sprt) diff --git a/engines/gob/save/savehandler.h b/engines/gob/save/savehandler.h index cb984f7abb..55505d1b9a 100644 --- a/engines/gob/save/savehandler.h +++ b/engines/gob/save/savehandler.h @@ -27,11 +27,11 @@ #define GOB_SAVE_SAVEHANDLER_H #include "common/savefile.h" +#include "engines/gob/video.h" // for SurfaceDescPtr namespace Gob { class GobEngine; -class SurfaceDesc; class SavePartInfo; class SavePartVars; class SavePartSprite; @@ -139,7 +139,7 @@ public: /** Create a fitting sprite. */ bool createSprite(int16 dataVar, int32 size, - int32 offset, SurfaceDesc **sprite = 0); + int32 offset, SurfaceDescPtr *sprite = 0); protected: SavePartSprite *_sprite; diff --git a/engines/gob/save/saveload.cpp b/engines/gob/save/saveload.cpp index abda2f8a65..81239f07dc 100644 --- a/engines/gob/save/saveload.cpp +++ b/engines/gob/save/saveload.cpp @@ -61,7 +61,7 @@ int32 SaveLoad::getSize(const char *fileName) { int32 size = handler->getSize(); debugC(4, kDebugSaveLoad, "Size is %d", size); - + return size; } diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp index 2f89644ee0..58232e6991 100644 --- a/engines/gob/save/saveload_v3.cpp +++ b/engines/gob/save/saveload_v3.cpp @@ -302,7 +302,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) { if (!_reader || (_reader->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -319,7 +319,7 @@ bool SaveLoad_v3::GameHandler::createReader(int slot) { } else _reader = new SaveReader(_usesScreenshots ? 3 : 2, slot, slotFile); - + if (!_reader->load()) { delete _reader; _reader = 0; @@ -337,7 +337,7 @@ bool SaveLoad_v3::GameHandler::createWriter(int slot) { if (!_writer || (_writer->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -495,7 +495,7 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName, ScreenshotType s _gameHandler = new GameHandler(vm, targetName, true); _screenshotHandler = new ScreenshotHandler(vm, _gameHandler, sShotType); } - + _tempSpriteHandler = new TempSpriteHandler(vm); _notesHandler = new NotesHandler(2560, vm, targetName); diff --git a/engines/gob/save/saveload_v4.cpp b/engines/gob/save/saveload_v4.cpp index 6e1d5208ff..06280af2a6 100644 --- a/engines/gob/save/saveload_v4.cpp +++ b/engines/gob/save/saveload_v4.cpp @@ -317,7 +317,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) { if (!_reader || (_reader->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; @@ -334,7 +334,7 @@ bool SaveLoad_v4::GameHandler::createReader(int slot) { } else _reader = new SaveReader(3, slot, slotFile); - + if (!_reader->load()) { delete _reader; _reader = 0; @@ -352,7 +352,7 @@ bool SaveLoad_v4::GameHandler::createWriter(int slot) { if (!_writer || (_writer->getSlot() != ((uint32) slot))) { Common::String slotFile = _slotFile->build(slot); - + if (slotFile.empty()) return false; diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 16c6079f45..7a4b8ad868 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -31,6 +31,8 @@ #include "gob/global.h" #include "gob/draw.h" #include "gob/game.h" +#include "gob/script.h" +#include "gob/resources.h" #include "gob/inter.h" #include "gob/map.h" #include "gob/videoplayer.h" @@ -39,33 +41,33 @@ namespace Gob { Scenery::Scenery(GobEngine *vm) : _vm(vm) { for (int i = 0; i < 20; i++) { - _spriteRefs[i] = 0; + _spriteRefs[i] = 0; _spriteResId[i] = 0; } for (int i = 0; i < 10; i++) { _staticPictCount[i] = 0; - _staticResId[i] = 0; - _animPictCount[i] = 0; - _animResId[i] = 0; + _staticResId[i] = 0; + _animPictCount[i] = 0; + _animResId[i] = 0; } - _curStatic = 0; + _curStatic = 0; _curStaticLayer = 0; - _toRedrawLeft = 0; - _toRedrawRight = 0; - _toRedrawTop = 0; + _toRedrawLeft = 0; + _toRedrawRight = 0; + _toRedrawTop = 0; _toRedrawBottom = 0; - _animTop = 0; + _animTop = 0; _animLeft = 0; _pCaptureCounter = 0; for (int i = 0; i < 70; i++ ) { _staticPictToSprite[i] = 0; - _animPictToSprite[i] = 0; + _animPictToSprite[i] = 0; } } @@ -78,17 +80,17 @@ Scenery::~Scenery() { void Scenery::init() { for (int i = 0; i < 10; i++) { - _animPictCount[i] = 0; + _animPictCount[i] = 0; _staticPictCount[i] = -1; } for (int i = 0; i < 20; i++) { - _spriteRefs[i] = 0; + _spriteRefs[i] = 0; _spriteResId[i] = -1; } _curStaticLayer = -1; - _curStatic = -1; + _curStatic = -1; } int16 Scenery::loadStatic(char search) { @@ -97,28 +99,26 @@ int16 Scenery::loadStatic(char search) { int16 picsCount; int16 resId; int16 sceneryIndex; - byte *extData = 0; - byte *dataPtr; Static *ptr; int16 width; int16 height; int16 sprResId; int16 sprIndex; - _vm->_inter->evalExpr(&sceneryIndex); + _vm->_game->_script->evalExpr(&sceneryIndex); - size = _vm->_inter->load16(); - backsPtr = (int16 *) _vm->_global->_inter_execPtr; - _vm->_global->_inter_execPtr += size * 2; - picsCount = _vm->_inter->load16(); - resId = _vm->_inter->load16(); + size = _vm->_game->_script->readInt16(); + backsPtr = (int16 *) (_vm->_game->_script->getData() + _vm->_game->_script->pos()); + _vm->_game->_script->skip(size * 2); + picsCount = _vm->_game->_script->readInt16(); + resId = _vm->_game->_script->readInt16(); if (search) { int i; for (i = 0; i < 10; i++) { if ((_staticPictCount[i] != -1) && (_staticResId[i] == resId)) { - _vm->_global->_inter_execPtr += 8 * _staticPictCount[i]; + _vm->_game->_script->skip(8 * _staticPictCount[i]); return i; } @@ -128,52 +128,54 @@ int16 Scenery::loadStatic(char search) { } _staticPictCount[sceneryIndex] = picsCount; - _staticResId[sceneryIndex] = resId; + _staticResId[sceneryIndex] = resId; - if (resId >= 30000) { - extData = _vm->_game->loadExtData(resId, 0, 0); - dataPtr = extData; - } else - dataPtr = _vm->_game->loadTotResource(resId); + Resource *resource = _vm->_game->_resources->getResource((uint16) resId); + if (!resource) + return 0; ptr = &_statics[sceneryIndex]; - ptr->layersCount = (int16) READ_LE_UINT16(dataPtr); - dataPtr += 2; + ptr->layersCount = resource->stream()->readSint16LE(); ptr->layers = new StaticLayer[ptr->layersCount]; for (int i = 0; i < ptr->layersCount; i++) { - int16 offset = READ_LE_UINT16(dataPtr + i * 2); - Common::MemoryReadStream layerData(dataPtr + offset, 4294967295U); + Common::SeekableReadStream &layerData = *resource->stream(); - ptr->layers[i].planeCount = layerData.readSint16LE(); + layerData.seek(2 + i * 2); + layerData.seek(layerData.readUint16LE()); - ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount]; - for (int j = 0; j < ptr->layers[i].planeCount; ++j) { - ptr->layers[i].planes[j].pictIndex = layerData.readByte(); - ptr->layers[i].planes[j].pieceIndex = layerData.readByte(); - ptr->layers[i].planes[j].drawOrder = layerData.readByte(); - ptr->layers[i].planes[j].destX = layerData.readSint16LE(); - ptr->layers[i].planes[j].destY = layerData.readSint16LE(); - ptr->layers[i].planes[j].transp = layerData.readSByte(); - } + ptr->layers[i].backResId = layerData.readSint16LE(); + ptr->layers[i].planeCount = layerData.readSint16LE(); + if (ptr->layers[i].planeCount > 0) { + ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount]; + for (int j = 0; j < ptr->layers[i].planeCount; j++) { + ptr->layers[i].planes[j].pictIndex = layerData.readByte(); + ptr->layers[i].planes[j].pieceIndex = layerData.readByte(); + ptr->layers[i].planes[j].drawOrder = layerData.readByte(); + ptr->layers[i].planes[j].destX = layerData.readSint16LE(); + ptr->layers[i].planes[j].destY = layerData.readSint16LE(); + ptr->layers[i].planes[j].transp = layerData.readSByte(); + } + } else + ptr->layers[i].planes = 0; ptr->layers[i].backResId = (int16) READ_LE_UINT16(backsPtr); backsPtr++; } - ptr->pieces = new PieceDesc*[picsCount]; + ptr->pieces = new PieceDesc*[picsCount]; ptr->piecesCount = new uint32[picsCount]; for (int i = 0; i < picsCount; i++) { - int16 pictDescId = _vm->_inter->load16(); + int16 pictDescId = _vm->_game->_script->readInt16(); loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); - sprResId = _vm->_inter->load16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); + sprResId = _vm->_game->_script->readInt16(); for (sprIndex = 0; sprIndex < 20; sprIndex++) { if (_spriteResId[sprIndex] == sprResId) break; @@ -183,27 +185,24 @@ int16 Scenery::loadStatic(char search) { _staticPictToSprite[7 * sceneryIndex + i] = sprIndex; _spriteRefs[sprIndex]++; } else { - for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; - sprIndex--) - ; + for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; sprIndex--); _staticPictToSprite[7 * sceneryIndex + i] = sprIndex; _spriteRefs[sprIndex] = 1; _spriteResId[sprIndex] = sprResId; _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); - _vm->_video->clearSurf(_vm->_draw->_spritesArray[sprIndex]); - _vm->_draw->_destSurface = sprIndex; - _vm->_draw->_spriteLeft = sprResId; + _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); + _vm->_draw->_destSurface = sprIndex; + _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } } - delete[] extData; - + delete resource; return sceneryIndex + 100; } @@ -211,7 +210,7 @@ void Scenery::freeStatic(int16 index) { int16 spr; if (index == -1) - _vm->_inter->evalExpr(&index); + _vm->_game->_script->evalExpr(&index); if (_staticPictCount[index] == -1) return; @@ -229,12 +228,13 @@ void Scenery::freeStatic(int16 index) { for (int i = 0; i < _statics[index].layersCount; i++) delete[] _statics[index].layers[i].planes; + delete[] _statics[index].layers; delete[] _statics[index].pieces; delete[] _statics[index].piecesCount; _statics[index].layersCount = 0; - _staticPictCount[index] = -1; + _staticPictCount[index] = -1; } void Scenery::renderStatic(int16 scenery, int16 layer) { @@ -261,22 +261,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { _vm->_draw->_spriteLeft = layerPtr->backResId; if (_vm->_draw->_spriteLeft != -1) { - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; - _vm->_draw->_destSurface = 21; - _vm->_draw->_transparency = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_transparency = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } planeCount = layerPtr->planeCount; for (order = 0; order < 100; order++) { - for (plane = 0, planePtr = layerPtr->planes; - plane < planeCount; plane++, planePtr++) { + for (plane = 0, planePtr = layerPtr->planes; plane < planeCount; plane++, planePtr++) { if (planePtr->drawOrder != order) continue; pieceIndex = planePtr->pieceIndex; - pictIndex = planePtr->pictIndex - 1; + pictIndex = planePtr->pictIndex - 1; if (pictIndex >= _staticPictCount[scenery]) continue; @@ -289,19 +288,19 @@ void Scenery::renderStatic(int16 scenery, int16 layer) { _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = ptr->pieces[pictIndex][pieceIndex].left; - right = ptr->pieces[pictIndex][pieceIndex].right; - top = ptr->pieces[pictIndex][pieceIndex].top; + left = ptr->pieces[pictIndex][pieceIndex].left; + right = ptr->pieces[pictIndex][pieceIndex].right; + top = ptr->pieces[pictIndex][pieceIndex].top; bottom = ptr->pieces[pictIndex][pieceIndex].bottom; _vm->_draw->_sourceSurface = _staticPictToSprite[scenery * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_transparency = planePtr->transp ? 3 : 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_transparency = planePtr->transp ? 3 : 0; _vm->_draw->spriteOperation(DRAW_BLITSURF); } } @@ -337,7 +336,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { continue; pieceIndex = planePtr->pieceIndex; - pictIndex = planePtr->pictIndex - 1; + pictIndex = planePtr->pictIndex - 1; if (pictIndex >= _staticPictCount[index]) continue; @@ -351,9 +350,9 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_destSpriteX = planePtr->destX; _vm->_draw->_destSpriteY = planePtr->destY; - left = pictPtr[pictIndex][pieceIndex].left; - right = pictPtr[pictIndex][pieceIndex].right; - top = pictPtr[pictIndex][pieceIndex].top; + left = pictPtr[pictIndex][pieceIndex].left; + right = pictPtr[pictIndex][pieceIndex].right; + top = pictPtr[pictIndex][pieceIndex].top; bottom = pictPtr[pictIndex][pieceIndex].bottom; if (_vm->_draw->_destSpriteX > _toRedrawRight) @@ -372,10 +371,10 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_destSpriteY = _toRedrawTop; } - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; if ((_vm->_draw->_spriteRight <= 0) || (_vm->_draw->_spriteBottom <= 0)) @@ -393,8 +392,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) { _vm->_draw->_sourceSurface = _staticPictToSprite[index * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; - _vm->_draw->_transparency = planePtr->transp ? 3 : 0; + _vm->_draw->_destSurface = 21; + _vm->_draw->_transparency = planePtr->transp ? 3 : 0; _vm->_draw->spriteOperation(DRAW_BLITSURF); } } @@ -422,8 +421,6 @@ int16 Scenery::loadAnim(char search) { int16 j; int16 sceneryIndex; int16 framesCount; - byte *extData; - byte *dataPtr; Animation *ptr; int16 width; int16 height; @@ -431,15 +428,14 @@ int16 Scenery::loadAnim(char search) { int16 sprIndex; uint32 layerPos; - extData = 0; - _vm->_inter->evalExpr(&sceneryIndex); - picsCount = _vm->_inter->load16(); - resId = _vm->_inter->load16(); + _vm->_game->_script->evalExpr(&sceneryIndex); + picsCount = _vm->_game->_script->readInt16(); + resId = _vm->_game->_script->readInt16(); if (search) { for (i = 0; i < 10; i++) { if ((_animPictCount[i] != 0) && (_animResId[i] == resId)) { - _vm->_global->_inter_execPtr += 8 * _animPictCount[i]; + _vm->_game->_script->skip(8 * _animPictCount[i]); return i; } @@ -451,50 +447,50 @@ int16 Scenery::loadAnim(char search) { _animPictCount[sceneryIndex] = picsCount; _animResId[sceneryIndex] = resId; - if (resId >= 30000) { - extData = _vm->_game->loadExtData(resId, 0, 0); - dataPtr = extData; - } else - dataPtr = _vm->_game->loadTotResource(resId); + Resource *resource = _vm->_game->_resources->getResource((uint16) resId); + if (!resource) + return 0; ptr = &_animations[sceneryIndex]; - ptr->layersCount = READ_LE_UINT16(dataPtr); - dataPtr += 2; + ptr->layersCount = resource->stream()->readSint16LE(); ptr->layers = new AnimLayer[ptr->layersCount]; for (i = 0; i < ptr->layersCount; i++) { - int16 offset = READ_LE_UINT16(dataPtr + i * 2); - Common::MemoryReadStream layerData(dataPtr + offset - 2, 4294967295U); - - ptr->layers[i].unknown0 = layerData.readSint16LE(); - ptr->layers[i].posX = layerData.readSint16LE(); - ptr->layers[i].posY = layerData.readSint16LE(); - ptr->layers[i].animDeltaX = layerData.readSint16LE(); - ptr->layers[i].animDeltaY = layerData.readSint16LE(); - ptr->layers[i].transp = layerData.readSByte(); + Common::SeekableReadStream &layerData = *resource->stream(); + + layerData.seek(2 + i * 2); + layerData.seek(layerData.readUint16LE()); + + ptr->layers[i].unknown0 = layerData.readSint16LE(); + ptr->layers[i].posX = layerData.readSint16LE(); + ptr->layers[i].posY = layerData.readSint16LE(); + ptr->layers[i].animDeltaX = layerData.readSint16LE(); + ptr->layers[i].animDeltaY = layerData.readSint16LE(); + ptr->layers[i].transp = layerData.readSByte(); ptr->layers[i].framesCount = layerData.readSint16LE(); + // Going through the AnimFramePiece, finding the end for each layerPos = layerData.pos(); framesCount = 0; - layerData.seek(4, SEEK_CUR); - for (j = 0; j < ptr->layers[i].framesCount; - j++, framesCount++, layerData.seek(4, SEEK_CUR)) { + for (j = 0; j < ptr->layers[i].framesCount; j++) { + layerData.skip(4); // pictIndex, pieceIndex, destX, destY while (layerData.readByte() == 1) { framesCount++; - layerData.seek(4, SEEK_CUR); + layerData.skip(4); // pictIndex, pieceIndex, destX, destY } + framesCount++; } layerData.seek(layerPos); ptr->layers[i].frames = new AnimFramePiece[framesCount]; for (j = 0; j < framesCount; j++) { - ptr->layers[i].frames[j].pictIndex = layerData.readByte(); + ptr->layers[i].frames[j].pictIndex = layerData.readByte(); ptr->layers[i].frames[j].pieceIndex = layerData.readByte(); - ptr->layers[i].frames[j].destX = layerData.readSByte(); - ptr->layers[i].frames[j].destY = layerData.readSByte(); - ptr->layers[i].frames[j].notFinal = layerData.readSByte(); + ptr->layers[i].frames[j].destX = layerData.readSByte(); + ptr->layers[i].frames[j].destY = layerData.readSByte(); + ptr->layers[i].frames[j].notFinal = layerData.readSByte(); } } @@ -502,13 +498,13 @@ int16 Scenery::loadAnim(char search) { ptr->piecesCount = new uint32[picsCount]; for (i = 0; i < picsCount; i++) { - int16 pictDescId = _vm->_inter->load16(); + int16 pictDescId = _vm->_game->_script->readInt16(); loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]); - width = _vm->_inter->load16(); - height = _vm->_inter->load16(); - sprResId = _vm->_inter->load16(); + width = _vm->_game->_script->readInt16(); + height = _vm->_game->_script->readInt16(); + sprResId = _vm->_game->_script->readInt16(); for (sprIndex = 0; sprIndex < 20; sprIndex++) if (_spriteResId[sprIndex] == sprResId) break; @@ -517,27 +513,26 @@ int16 Scenery::loadAnim(char search) { _animPictToSprite[7 * sceneryIndex + i] = sprIndex; _spriteRefs[sprIndex]++; } else { - for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex] != 0; + for (sprIndex = 19; _vm->_draw->_spritesArray[sprIndex]; sprIndex--) ; _animPictToSprite[7 * sceneryIndex + i] = sprIndex; - _spriteRefs[sprIndex] = 1; + _spriteRefs[sprIndex] = 1; _spriteResId[sprIndex] = sprResId; _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); - _vm->_video->clearSurf(_vm->_draw->_spritesArray[sprIndex]); - _vm->_draw->_destSurface = sprIndex; - _vm->_draw->_spriteLeft = sprResId; + _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); + _vm->_draw->_destSurface = sprIndex; + _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; - _vm->_draw->_destSpriteX = 0; - _vm->_draw->_destSpriteY = 0; + _vm->_draw->_destSpriteX = 0; + _vm->_draw->_destSpriteY = 0; _vm->_draw->spriteOperation(DRAW_LOADSPRITE); } } - delete[] extData; - + delete resource; return sceneryIndex + 100; } @@ -545,7 +540,7 @@ void Scenery::freeAnim(int16 index) { int16 spr; if (index == -1) - _vm->_inter->evalExpr(&index); + _vm->_game->_script->evalExpr(&index); if (_animPictCount[index] == 0) return; @@ -563,6 +558,7 @@ void Scenery::freeAnim(int16 index) { for (int i = 0; i < _animations[index].layersCount; i++) delete[] _animations[index].layers[i].frames; + delete[] _animations[index].layers; delete[] _animations[index].pieces; delete[] _animations[index].piecesCount; @@ -607,8 +603,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, return; _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, - _toRedrawRight - _toRedrawLeft + 1, - _toRedrawBottom - _toRedrawTop + 1); + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); *_pCaptureCounter = *_pCaptureCounter + 1; } @@ -628,7 +624,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame) _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); } else { - int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1); + int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1); uint8 frameWrap = curFrame / 256; frame = (frame + 1) % 256; @@ -636,17 +632,17 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); } - destX = 0; - destY = 0; - left = *(obj.pPosX); - top = *(obj.pPosY); - right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1; - bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1; + destX = 0; + destY = 0; + left = *(obj.pPosX); + top = *(obj.pPosY); + right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1; + bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1; if (flags & 2) { if (left < _vm->_mult->_animLeft) { destX += _vm->_mult->_animLeft - left; - left = _vm->_mult->_animLeft; + left = _vm->_mult->_animLeft; } if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) @@ -654,7 +650,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _vm->_mult->_animTop) { destY += _vm->_mult->_animTop - top; - top = _vm->_mult->_animTop; + top = _vm->_mult->_animTop; } if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) @@ -663,7 +659,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, } else if (flags & 4) { if (left < _toRedrawLeft) { destX += _toRedrawLeft - left; - left = _toRedrawLeft; + left = _toRedrawLeft; } if (right > _toRedrawRight) @@ -671,16 +667,16 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _toRedrawTop) { destY += _toRedrawTop - top; - top = _toRedrawTop; + top = _toRedrawTop; } if (bottom > _toRedrawBottom) bottom = _toRedrawBottom; } else { - _toRedrawTop = top; - _toRedrawLeft = left; - _toRedrawRight = right; + _toRedrawTop = top; + _toRedrawLeft = left; + _toRedrawRight = right; _toRedrawBottom = bottom; } @@ -690,7 +686,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (left < _vm->_mult->_animLeft) { destX += _vm->_mult->_animLeft - left; - left = _vm->_mult->_animLeft; + left = _vm->_mult->_animLeft; } if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) @@ -698,40 +694,40 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (top < _vm->_mult->_animTop) { destY += _vm->_mult->_animTop - top; - top = _vm->_mult->_animTop; + top = _vm->_mult->_animTop; } if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1; - _vm->_draw->_spriteLeft = destX; - _vm->_draw->_spriteTop = destY; - _vm->_draw->_spriteRight = right - left + 1; - _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_destSpriteX = left; - _vm->_draw->_destSpriteY = top; + _vm->_draw->_spriteLeft = destX; + _vm->_draw->_spriteTop = destY; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_destSpriteX = left; + _vm->_draw->_destSpriteY = top; _vm->_draw->_transparency = layer; if (layer & 0x80) _vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - (destX + _vm->_draw->_spriteRight); _vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(), - _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, + _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, _vm->_draw->_spriteRight, _vm->_draw->_spriteBottom, _vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, _vm->_draw->_backSurface->getWidth(), (_vm->_draw->_transparency != 0) ? 0 : -1); _vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, - _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1, + _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1, _vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1); } if (!(flags & 4)) { - _animLeft = _toRedrawLeft = left; - _animTop = _toRedrawTop = top; - _animRight = _toRedrawRight = right; + _animLeft = _toRedrawLeft = left; + _animTop = _toRedrawTop = top; + _animRight = _toRedrawRight = right; _animBottom = _toRedrawBottom = bottom; } @@ -757,13 +753,13 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, return; _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, - _toRedrawRight - _toRedrawLeft + 1, - _toRedrawBottom - _toRedrawTop + 1); + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); *_pCaptureCounter = *_pCaptureCounter + 1; } - pictPtr = _animations[animation].pieces; + pictPtr = _animations[animation].pieces; framePtr = layerPtr->frames; for (i = 0; i < frame; i++, framePtr++) @@ -771,9 +767,9 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, framePtr++; if (flags & 4) { - _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft); - _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop); - _toRedrawRight = MIN(_toRedrawRight, + _toRedrawLeft = MAX(_toRedrawLeft, _vm->_mult->_animLeft); + _toRedrawTop = MAX(_toRedrawTop, _vm->_mult->_animTop); + _toRedrawRight = MIN(_toRedrawRight, (int16)(_vm->_mult->_animLeft + _vm->_mult->_animWidth - 1)); _toRedrawBottom = MIN(_toRedrawBottom, (int16)(_vm->_mult->_animTop + _vm->_mult->_animHeight - 1)); @@ -844,7 +840,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, (_vm->_mult->_animLeft + _vm->_mult->_animWidth) + 1; if (destY < _vm->_mult->_animTop) { - top += _vm->_mult->_animTop - destY; + top += _vm->_mult->_animTop - destY; destY = _vm->_mult->_animTop; } @@ -863,7 +859,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, right -= destX + right - left - _toRedrawRight; if (destY < _toRedrawTop) { - top += _toRedrawTop - destY; + top += _toRedrawTop - destY; destY = _toRedrawTop; } @@ -877,33 +873,33 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (doDraw) { _vm->_draw->_sourceSurface = _animPictToSprite[animation * 7 + pictIndex]; - _vm->_draw->_destSurface = 21; + _vm->_draw->_destSurface = 21; - _vm->_draw->_spriteLeft = left; - _vm->_draw->_spriteTop = top; - _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteLeft = left; + _vm->_draw->_spriteTop = top; + _vm->_draw->_spriteRight = right - left + 1; _vm->_draw->_spriteBottom = bottom - top + 1; - _vm->_draw->_destSpriteX = destX; - _vm->_draw->_destSpriteY = destY; + _vm->_draw->_destSpriteX = destX; + _vm->_draw->_destSpriteY = destY; _vm->_draw->_transparency = transp; _vm->_draw->spriteOperation(DRAW_BLITSURF); } if (!(flags & 4)) { if (_toRedrawLeft == -12345) { - _toRedrawLeft = destX; - _animLeft = destX; - _toRedrawTop = destY; - _animTop = destY; - _toRedrawRight = destX + right - left; - _animRight = destX + right - left; + _toRedrawLeft = destX; + _animLeft = destX; + _toRedrawTop = destY; + _animTop = destY; + _toRedrawRight = destX + right - left; + _animRight = destX + right - left; _toRedrawBottom = destY + bottom - top; - _animBottom = destY + bottom - top; + _animBottom = destY + bottom - top; } else { - _toRedrawLeft = MIN(_toRedrawLeft, destX); - _toRedrawTop = MIN(_toRedrawTop, destY); - _toRedrawRight = - MAX(_toRedrawRight, (int16)(destX + right - left)); + _toRedrawLeft = MIN(_toRedrawLeft, destX); + _toRedrawTop = MIN(_toRedrawTop, destY); + _toRedrawRight = + MAX(_toRedrawRight, (int16)(destX + right - left)); _toRedrawBottom = MAX(_toRedrawBottom, (int16)(destY + bottom - top)); } @@ -952,41 +948,23 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) { } void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) { - byte *data; - uint32 size; - bool fromExt = false; - - if (pictDescId >= 30000) { - fromExt = true; - - uint32 eSize; - - data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize); - size = eSize; - } else { - int16 tSize; - - data = _vm->_game->loadTotResource(pictDescId, &tSize); - size = tSize; + Resource *resource = _vm->_game->_resources->getResource(pictDescId); + if (!resource) { + warning("Scenery::loadPieces(): Can't load %d", pictDescId); + return; } - if (!data) - error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId); - - piecesCount = size / 8; + piecesCount = resource->getSize() / 8; pieceDesc = new PieceDesc[piecesCount]; - Common::MemoryReadStream pieceData(data, size); - for (uint32 i = 0; i < piecesCount; i++) { - pieceDesc[i].left = (int16) pieceData.readUint16LE(); - pieceDesc[i].right = (int16) pieceData.readUint16LE(); - pieceDesc[i].top = (int16) pieceData.readUint16LE(); - pieceDesc[i].bottom = (int16) pieceData.readUint16LE(); + pieceDesc[i].left = resource->stream()->readSint16LE(); + pieceDesc[i].right = resource->stream()->readSint16LE(); + pieceDesc[i].top = resource->stream()->readSint16LE(); + pieceDesc[i].bottom = resource->stream()->readSint16LE(); } - if (fromExt) - delete[] data; + delete resource; } } // End of namespace Gob diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp new file mode 100644 index 0000000000..6162e943bf --- /dev/null +++ b/engines/gob/script.cpp @@ -0,0 +1,522 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/script.h" +#include "gob/dataio.h" +#include "gob/expression.h" +#include "gob/videoplayer.h" + +namespace Gob { + +Script::Script(GobEngine *vm) : _vm(vm) { + _expression = new Expression(vm); + + _finished = true; + + _totData = 0; + _totPtr = 0; + _totSize = 0; + + _lomHandle = -1; + + memset(&_totProperties, 0, sizeof(TOTFile::Properties)); +} + +Script::~Script() { + unload(); + + delete _expression; +} + +uint32 Script::read(byte *data, int32 size) { + int32 toRead = MIN<int32>(size, _totSize - (_totPtr - _totData)); + + if (toRead < 1) + return 0; + + memcpy(data, _totPtr, toRead); + _totPtr += toRead; + + return toRead; +} + +uint32 Script::peek(byte *data, int32 size, int32 offset) const { + int32 totOffset = ((_totPtr + offset) - _totData); + + if (totOffset < 1) + return 0; + if (((uint32) totOffset) >= _totSize) + return 0; + + int32 toPeek = MIN<int32>(size, _totSize - totOffset); + if (toPeek < 1) + return 0; + + memcpy(data, _totPtr + offset, toPeek); + + return toPeek; +} + +int32 Script::pos() const { + if (!_totData) + return -1; + + return _totPtr - _totData; +} + +int32 Script::getSize() const { + if (!_totData) + return -1; + + return _totSize; +} + +bool Script::seek(int32 offset, int whence) { + if (!_totData) + return false; + + if (whence == SEEK_CUR) + offset += pos(); + else if (whence == SEEK_END) + offset += _totSize; + + if ((offset < 0) || (((uint32) offset) >= _totSize)) + return false; + + // Cannot seek into the header + if (offset < 128) { + _finished = true; + return false; + } + + // A successful seek means the script file continues to be executed + _finished = false; + + _totPtr = _totData + offset; + + return true; +} + +bool Script::skip(int32 offset) { + return seek(offset, SEEK_CUR); +} + +int32 Script::getOffset(byte *ptr) const { + if (!_totData) + return -1; + + if ((ptr < _totData) || (ptr >= (_totData + _totSize))) + return -1; + + return ptr - _totData; +} + +byte *Script::getData(int32 offset) const { + if (!_totData) + return 0; + if ((offset < 0) || (((uint32) offset) >= _totSize)) + return 0; + + return _totData + offset; +} + +byte *Script::getData() { + return _totData; +} + +byte Script::readByte() { + byte v; + + read(&v, 1); + + return v; +} + +char Script::readChar() { + return (char) readByte(); +} + +uint8 Script::readUint8() { + return (uint8) readByte(); +} + +uint16 Script::readUint16() { + byte v[2]; + + read(v, 2); + + return READ_LE_UINT16(v); +} + +uint32 Script::readUint32() { + byte v[4]; + + read(v, 4); + + return READ_LE_UINT32(v); +} + +int8 Script::readInt8() { + return (int8) readByte(); +} + +int16 Script::readInt16() { + return (int16) readUint16(); +} + +int32 Script::readInt32() { + return (int32) readUint32(); +} + +char *Script::readString(int32 length) { + if (length < 0) { + length = 0; + while (_totPtr[length++] != '\0'); + } + + char *string = (char *) _totPtr; + + _totPtr += length; + + return string; +} + +byte Script::peekByte(int32 offset) { + byte v; + + peek(&v, 1, offset); + + return v; +} + +char Script::peekChar(int32 offset) { + return (char) peekByte(offset); +} + +uint8 Script::peekUint8(int32 offset) { + return (uint8) peekByte(offset); +} + +uint16 Script::peekUint16(int32 offset) { + byte v[2]; + + peek(v, 2, offset); + + return READ_LE_UINT16(v); +} + +uint32 Script::peekUint32(int32 offset) { + byte v[4]; + + peek(v, 4, offset); + + return READ_LE_UINT32(v); +} + +int8 Script::peekInt8(int32 offset) { + return (int8) peekByte(offset); +} + +int16 Script::peekInt16(int32 offset) { + return (int16) peekUint16(offset); +} + +int32 Script::peekInt32(int32 offset) { + return (int32) peekUint32(offset); +} + +char *Script::peekString(int32 offset) { + return (char *) (_totPtr + offset); +} + +int16 Script::readVarIndex(uint16 *size, uint16 *type) { + return _expression->parseVarIndex(size, type); +} + +int16 Script::readValExpr(byte stopToken) { + return _expression->parseValExpr(stopToken); +} + +int16 Script::readExpr(byte stopToken, byte *type) { + return _expression->parseExpr(stopToken, type); +} + +void Script::skipExpr(char stopToken) { + _expression->skipExpr(stopToken); +} + +char Script::evalExpr(int16 *pRes) { + byte type; + + _expression->printExpr(99); + + _expression->parseExpr(99, &type); + if (!pRes) + return type; + + switch (type) { + case TYPE_IMM_INT16: + *pRes = _expression->getResultInt(); + break; + + case TYPE_IMM_STR: + case GOB_FALSE: + *pRes = 0; + break; + + case GOB_TRUE: + *pRes = 1; + break; + } + + return type; +} + +bool Script::evalBoolResult() { + byte type; + + _expression->printExpr(99); + + _expression->parseExpr(99, &type); + if ( (type == GOB_TRUE) || + ((type == TYPE_IMM_INT16) && _expression->getResultInt())) + return true; + else + return false; +} + +int32 Script::getResultInt() const { + return _expression->getResultInt(); +} + +char *Script::getResultStr() const { + return _expression->getResultStr(); +} + +bool Script::load(const Common::String &fileName) { + unload(); + + _finished = false; + + bool isLOM; + + _totFile = TOTFile::createFileName(fileName, isLOM); + + if (isLOM) { + if (!loadLOM(_totFile)) { + unload(); + return false; + } + } else { + if (!loadTOT(_totFile)) { + unload(); + return false; + } + } + + return true; +} + +bool Script::loadTOT(const Common::String &fileName) { + TOTFile totFile(_vm); + + if (!totFile.load(fileName)) + return false; + + Common::SeekableReadStream *stream = totFile.getStream(); + if (!stream) + return false; + + if (!totFile.getProperties(_totProperties)) + return false; + + _totSize = _totProperties.scriptEnd; + if (_totSize <= 0) + return false; + + _totData = new byte[_totSize]; + if (stream->read(_totData, _totSize) != _totSize) + return false; + + return true; +} + +bool Script::loadLOM(const Common::String &fileName) { + warning("Stub: Script::loadLOM(%s)", _totFile.c_str()); + + _lomHandle = _vm->_dataIO->openData(_totFile.c_str()); + if (_lomHandle < 0) + return false; + + DataStream *stream = _vm->_dataIO->openAsStream(_lomHandle); + + stream->seek(48); + _totSize = stream->readUint32LE(); + stream->seek(0); + + _totData = new byte[_totSize]; + stream->read(_totData, _totSize); + + delete stream; + + return false; +} + +void Script::unload() { + unloadTOT(); +} + +void Script::unloadTOT() { + if (_lomHandle >= 0) + _vm->_dataIO->closeData(_lomHandle); + + // Unwind the call stack + while (!_callStack.empty()) + pop(); + + delete[] _totData; + + _totData = 0; + _totSize = 0; + _totPtr = 0; + _lomHandle = -1; + _totFile.clear(); + + _finished = true; +} + +bool Script::isLoaded() const { + return _totData != 0; +} + +void Script::setFinished(bool finished) { + _finished = finished; +} + +bool Script::isFinished() const { + return _finished; +} + +void Script::push() { + if (!isLoaded()) + // Nothing to do + return; + + CallEntry currentCall; + + currentCall.totPtr = _totPtr; + currentCall.finished = _finished; + + _callStack.push(currentCall); +} + +void Script::pop(bool ret) { + if (!isLoaded()) + // Nothing to do + return; + + // Unmatched pop? + assert(!_callStack.empty()); + + CallEntry lastCall = _callStack.pop(); + + if (ret) { + _totPtr = lastCall.totPtr; + _finished = lastCall.finished; + } +} + +void Script::call(uint32 offset) { + if (!isLoaded()) + // Nothing to do + return; + + push(); + seek(offset); +} + +uint8 Script::getVersionMajor() const { + return _totProperties.versionMajor; +} + +uint8 Script::getVersionMinor() const { + return _totProperties.versionMinor; +} + +uint32 Script::getVariablesCount() const { + return _totProperties.variablesCount; +} + +uint32 Script::getTextsOffset() const { + return _totProperties.textsOffset; +} + +uint32 Script::getResourcesOffset() const { + return _totProperties.resourcesOffset; +} + +uint16 Script::getAnimDataSize() const { + return _totProperties.animDataSize; +} + +uint8 Script::getImFileNumber() const { + return _totProperties.imFileNumber; +} + +uint8 Script::getExFileNumber() const { + return _totProperties.exFileNumber; +} + +uint8 Script::getCommunHandling() const { + return _totProperties.communHandling; +} + +uint16 Script::getFunctionOffset(uint8 function) const { + if (!_totData) + return 0; + + // Offsets 100-128, 2 bytes per function + assert(function <= 13); + + return _totProperties.functions[function]; +} + +uint32 Script::getVariablesCount(const char *fileName, GobEngine *vm) { + DataStream *stream = vm->_dataIO->getDataStream(fileName); + if (!stream) + return 0; + + stream->seek(0x2C); + uint32 variablesCount = stream->readUint32LE(); + delete stream; + + return variablesCount; +} + +} // End of namespace Gob diff --git a/engines/gob/script.h b/engines/gob/script.h new file mode 100644 index 0000000000..64a04503b1 --- /dev/null +++ b/engines/gob/script.h @@ -0,0 +1,169 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_SCRIPT_H +#define GOB_SCRIPT_H + +#include "common/str.h" +#include "common/stack.h" + +#include "gob/totfile.h" + +namespace Gob { + +class GobEngine; +class Expression; + +class Script { +public: + Script(GobEngine *vm); + ~Script(); + + /** Read data and move the pointer accordingly. */ + uint32 read(byte *data, int32 size); + /** Read data (from an optional offset) without moving the pointer. */ + uint32 peek(byte *data, int32 size, int32 offset = 0) const; + + // Stream properties + int32 pos() const; + int32 getSize() const; + + // Stream seeking + bool seek(int32 offset, int whence = SEEK_SET); + bool skip(int32 offset); + + // Reading data + byte readByte (); + char readChar (); + uint8 readUint8 (); + uint16 readUint16(); + uint32 readUint32(); + int8 readInt8 (); + int16 readInt16 (); + int32 readInt32 (); + char *readString(int32 length = -1); + + // Peeking data + byte peekByte (int32 offset = 0); + char peekChar (int32 offset = 0); + uint8 peekUint8 (int32 offset = 0); + uint16 peekUint16(int32 offset = 0); + uint32 peekUint32(int32 offset = 0); + int8 peekInt8 (int32 offset = 0); + int16 peekInt16 (int32 offset = 0); + int32 peekInt32 (int32 offset = 0); + char *peekString(int32 offset = 0); + + // Expression parsing functions + int16 readVarIndex(uint16 *size = 0, uint16 *type = 0); + int16 readValExpr(byte stopToken = 99); + int16 readExpr(byte stopToken, byte *type); + void skipExpr(char stopToken); + + // Higher-level expression parsing functions + char evalExpr(int16 *pRes); + bool evalBoolResult(); + + // Accessing the result of expressions + int32 getResultInt() const; + char *getResultStr() const; + + /** Returns the offset the specified pointer is within the script data. */ + int32 getOffset(byte *ptr) const; + /** Returns the data pointer to the offset. */ + byte *getData(int32 offset) const; + + /** Returns the raw data pointer. */ + byte *getData(); + + /** Load a script file. */ + bool load(const Common::String &fileName); + /** Unload the script. */ + void unload(); + /** Was a script loaded? */ + bool isLoaded() const; + + /** Setting the 'finished' property. */ + void setFinished(bool finished); + /** Querying the 'finished' property. */ + bool isFinished() const; + + // Call stack operations + /** Push the current script position onto the call stack. */ + void push(); + /** Pop a script position from the call stack (and return there). */ + void pop(bool ret = true); + /** Push the current script position and branch to the specified offset. */ + void call(uint32 offset); + + // Fixed properties + uint8 getVersionMajor () const; + uint8 getVersionMinor () const; + uint32 getVariablesCount () const; + uint32 getTextsOffset () const; + uint32 getResourcesOffset() const; + uint16 getAnimDataSize () const; + uint8 getImFileNumber () const; + uint8 getExFileNumber () const; + uint8 getCommunHandling () const; + + uint16 getFunctionOffset (uint8 function) const; + + static uint32 getVariablesCount(const char *fileName, GobEngine *vm); + +private: + struct CallEntry { + byte *totPtr; + bool finished; + }; + + GobEngine *_vm; + Expression *_expression; + + bool _finished; + + Common::String _totFile; + byte *_totData; + byte *_totPtr; + uint32 _totSize; + + int16 _lomHandle; + + TOTFile::Properties _totProperties; + + Common::Stack<CallEntry> _callStack; + + /** Loading a TOT file. */ + bool loadTOT(const Common::String &fileName); + /** Loading a LOM file. */ + bool loadLOM(const Common::String &fileName); + + /** Unloading a TOT file. */ + void unloadTOT(); +}; + +} // End of namespace Gob + +#endif // GOB_SCRIPT_H diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp index 07481431b6..7ab8e1f8dd 100644 --- a/engines/gob/sound/adlib.cpp +++ b/engines/gob/sound/adlib.cpp @@ -39,18 +39,33 @@ const unsigned char AdLib::_volRegNums[] = { }; AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { + init(); +} + +AdLib::~AdLib() { + Common::StackLock slock(_mutex); + + _mixer->stopHandle(_handle); + OPLDestroy(_opl); + if (_data && _freeData) + delete[] _data; +} + +void AdLib::init() { _index = -1; _data = 0; _playPos = 0; _dataSize = 0; _rate = _mixer->getOutputRate(); + _opl = makeAdlibOPL(_rate); _first = true; _ended = false; _playing = false; - _needFree = false; + + _freeData = false; _repCount = -1; _samplesTillPoll = 0; @@ -63,15 +78,6 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { this, -1, 255, 0, false, true); } -AdLib::~AdLib() { - Common::StackLock slock(_mutex); - - _mixer->stopHandle(_handle); - OPLDestroy(_opl); - if (_data && _needFree) - delete[] _data; -} - int AdLib::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock slock(_mutex); int samples; @@ -107,7 +113,9 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) { if (_ended) { _first = true; _ended = false; - _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + rewind(); + _samplesTillPoll = 0; if (_repCount == -1) { reset(); @@ -120,7 +128,6 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) { else _playing = false; } - return numSamples; } @@ -173,48 +180,6 @@ void AdLib::reset() { writeOPL(0x01, 0x20); } -void AdLib::setVoices() { - // Definitions of the 9 instruments - for (int i = 0; i < 9; i++) - setVoice(i, i, true); -} - -void AdLib::setVoice(byte voice, byte instr, bool set) { - int i; - int j; - uint16 strct[27]; - byte channel; - byte *dataPtr; - - // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 - // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 - for (i = 0; i < 2; i++) { - dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; - for (j = 0; j < 27; j++) { - strct[j] = READ_LE_UINT16(dataPtr); - dataPtr += 2; - } - channel = _operators[voice] + i * 3; - writeOPL(0xBD, 0x00); - writeOPL(0x08, 0x00); - writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); - if (!i) - writeOPL(0xC0 | voice, - ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); - writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); - writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); - writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | - ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | - ((strct[11] & 1) << 4) | (strct[1] & 0xF)); - if (!i) - writeOPL(0xE0 | channel, (strct[26] & 3)); - else - writeOPL(0xE0 | channel, (strct[14] & 3)); - if (i && set) - writeOPL(0x40 | channel, 0); - } -} - void AdLib::setKey(byte voice, byte note, bool on, bool spec) { short freq = 0; short octa = 0; @@ -278,7 +243,7 @@ void AdLib::setKey(byte voice, byte note, bool on, bool spec) { writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on); if (!freq) - warning("Voice %d, note %02X unknown", voice, note); + warning("AdLib: Voice %d, note %02X unknown", voice, note); } void AdLib::setVolume(byte voice, byte volume) { @@ -287,17 +252,102 @@ void AdLib::setVolume(byte voice, byte volume) { } void AdLib::pollMusic() { + if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { + _ended = true; + return; + } + + interpret(); +} + +void AdLib::unload() { + _playing = false; + _index = -1; + + if (_data && _freeData) + delete[] _data; + + _freeData = false; +} + +bool AdLib::isPlaying() const { + return _playing; +} + +bool AdLib::getRepeating() const { + return _repCount != 0; +} + +void AdLib::setRepeating(int32 repCount) { + _repCount = repCount; +} + +int AdLib::getIndex() const { + return _index; +} + +void AdLib::startPlay() { + if (_data) _playing = true; +} + +void AdLib::stopPlay() { + Common::StackLock slock(_mutex); + _playing = false; +} + +ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer) { +} + +ADLPlayer::~ADLPlayer() { +} + +bool ADLPlayer::load(const char *fileName) { + Common::File song; + + unload(); + song.open(fileName); + if (!song.isOpen()) + return false; + + _freeData = true; + _dataSize = song.size(); + _data = new byte[_dataSize]; + song.read(_data, _dataSize); + song.close(); + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +bool ADLPlayer::load(byte *data, uint32 size, int index) { + unload(); + _repCount = 0; + + _dataSize = size; + _data = data; + _index = index; + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +void ADLPlayer::unload() { + AdLib::unload(); +} + +void ADLPlayer::interpret() { unsigned char instr; byte channel; byte note; byte volume; uint16 tempo; - if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { - _ended = true; - return; - } - // First tempo, we'll ignore it... if (_first) { tempo = *(_playPos++); @@ -352,7 +402,7 @@ void AdLib::pollMusic() { _samplesTillPoll = 0; return; default: - warning("Unknown special command in ADL, stopping playback: %X", + warning("ADLPlayer: Unknown special command %X, stopping playback", instr & 0x0F); _repCount = 0; _ended = true; @@ -360,7 +410,7 @@ void AdLib::pollMusic() { } break; default: - warning("Unknown command in ADL, stopping playback: %X", + warning("ADLPlayer: Unknown command %X, stopping playback", instr & 0xF0); _repCount = 0; _ended = true; @@ -383,75 +433,349 @@ void AdLib::pollMusic() { _samplesTillPoll = tempo * (_rate / 1000); } -bool AdLib::load(const char *fileName) { +void ADLPlayer::reset() { + AdLib::reset(); +} + +void ADLPlayer::rewind() { + _playPos = _data + 3 + (_data[1] + 1) * 0x38; +} + +void ADLPlayer::setVoices() { + // Definitions of the 9 instruments + for (int i = 0; i < 9; i++) + setVoice(i, i, true); +} + +void ADLPlayer::setVoice(byte voice, byte instr, bool set) { + uint16 strct[27]; + byte channel; + byte *dataPtr; + + // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 + // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 + for (int i = 0; i < 2; i++) { + dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; + for (int j = 0; j < 27; j++) { + strct[j] = READ_LE_UINT16(dataPtr); + dataPtr += 2; + } + channel = _operators[voice] + i * 3; + writeOPL(0xBD, 0x00); + writeOPL(0x08, 0x00); + writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); + if (!i) + writeOPL(0xC0 | voice, + ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); + writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); + writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); + writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | + ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | + ((strct[11] & 1) << 4) | (strct[1] & 0xF)); + if (!i) + writeOPL(0xE0 | channel, (strct[26] & 3)); + else + writeOPL(0xE0 | channel, (strct[14] & 3)); + if (i && set) + writeOPL(0x40 | channel, 0); + } +} + + +MDYPlayer::MDYPlayer(Audio::Mixer &mixer) : AdLib(mixer) { + init(); +} + +MDYPlayer::~MDYPlayer() { +} + +void MDYPlayer::init() { + _soundMode = 0; + + _timbres = 0; + _tbrCount = 0; + _tbrStart = 0; + _timbresSize = 0; +} + +bool MDYPlayer::loadMDY(Common::SeekableReadStream &stream) { + unloadMDY(); + + _freeData = true; + + byte mdyHeader[70]; + stream.read(mdyHeader, 70); + + _tickBeat = mdyHeader[36]; + _beatMeasure = mdyHeader[37]; + _totalTick = mdyHeader[38] + (mdyHeader[39] << 8) + (mdyHeader[40] << 16) + (mdyHeader[41] << 24); + _dataSize = mdyHeader[42] + (mdyHeader[43] << 8) + (mdyHeader[44] << 16) + (mdyHeader[45] << 24); + _nrCommand = mdyHeader[46] + (mdyHeader[47] << 8) + (mdyHeader[48] << 16) + (mdyHeader[49] << 24); +// _soundMode is either 0 (melodic) or 1 (percussive) + _soundMode = mdyHeader[58]; + _pitchBendRangeStep = 25*mdyHeader[59]; + _basicTempo = mdyHeader[60] + (mdyHeader[61] << 8); + + if (_pitchBendRangeStep < 25) + _pitchBendRangeStep = 25; + else if (_pitchBendRangeStep > 300) + _pitchBendRangeStep = 300; + + _data = new byte[_dataSize]; + stream.read(_data, _dataSize); + + reset(); + _playPos = _data; + + return true; +} + +bool MDYPlayer::loadMDY(const char *fileName) { Common::File song; - unload(); song.open(fileName); if (!song.isOpen()) return false; - _needFree = true; - _dataSize = song.size(); - _data = new byte[_dataSize]; - song.read(_data, _dataSize); - song.close(); + bool loaded = loadMDY(song); - reset(); - setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; + song.close(); - return true; + return loaded; } -bool AdLib::load(byte *data, uint32 size, int index) { - unload(); - _repCount = 0; +bool MDYPlayer::loadTBR(Common::SeekableReadStream &stream) { + unloadTBR(); - _dataSize = size; - _data = data; - _index = index; + _timbresSize = stream.size(); + + _timbres = new byte[_timbresSize]; + stream.read(_timbres, _timbresSize); reset(); setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; return true; } -void AdLib::unload() { - _playing = false; - _index = -1; +bool MDYPlayer::loadTBR(const char *fileName) { + Common::File timbres; - if (_data && _needFree) - delete[] _data; + timbres.open(fileName); + if (!timbres.isOpen()) + return false; + + bool loaded = loadTBR(timbres); - _needFree = false; + timbres.close(); + + return loaded; } -bool AdLib::isPlaying() const { - return _playing; +void MDYPlayer::unload() { + unloadTBR(); + unloadMDY(); } -bool AdLib::getRepeating() const { - return _repCount != 0; +void MDYPlayer::unloadMDY() { + AdLib::unload(); } -void AdLib::setRepeating(int32 repCount) { - _repCount = repCount; +void MDYPlayer::unloadTBR() { + delete[] _timbres; + + _timbres = 0; + _timbresSize = 0; } -int AdLib::getIndex() const { - return _index; +void MDYPlayer::interpret() { + unsigned char instr; + byte channel; + byte note; + byte volume; + uint8 tempoMult, tempoFrac; + uint8 ctrlByte1, ctrlByte2; + uint8 timbre; + + if (_first) { + for (int i = 0; i < 11; i ++) + setVolume(i, 0); + +// TODO : Set pitch range + + _tempo = _basicTempo; + _wait = *(_playPos++); + _first = false; + } + do { + instr = *_playPos; +// printf("instr 0x%X\n", instr); + switch(instr) { + case 0xF8: + _wait = *(_playPos++); + break; + case 0xFC: + _ended = true; + _samplesTillPoll = 0; + return; + case 0xF0: + _playPos++; + ctrlByte1 = *(_playPos++); + ctrlByte2 = *(_playPos++); + if (ctrlByte1 != 0x7F || ctrlByte2 != 0) { + _playPos -= 2; + while (*(_playPos++) != 0xF7); + } else { + tempoMult = *(_playPos++); + tempoFrac = *(_playPos++); + _tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7); + _playPos++; + } + _wait = *(_playPos++); + break; + default: + if (instr >= 0x80) { + _playPos++; + } + channel = (int)(instr & 0x0f); + + switch(instr & 0xf0) { + case 0x90: + note = *(_playPos++); + volume = *(_playPos++); + _pollNotes[channel] = note; + setVolume(channel, volume); + setKey(channel, note, true, false); + break; + case 0x80: + _playPos += 2; + note = _pollNotes[channel]; + setKey(channel, note, false, false); + break; + case 0xA0: + setVolume(channel, *(_playPos++)); + break; + case 0xC0: + timbre = *(_playPos++); + setVoice(channel, timbre, false); + break; + case 0xE0: + warning("MDYPlayer: Pitch bend not yet implemented"); + + note = *(_playPos)++; + note += (unsigned)(*(_playPos++)) << 7; + + setKey(channel, note, _notOn[channel], true); + + break; + case 0xB0: + _playPos += 2; + break; + case 0xD0: + _playPos++; + break; + default: + warning("MDYPlayer: Bad MIDI instr byte: 0%X", instr); + while ((*_playPos) < 0x80) + _playPos++; + if (*_playPos != 0xF8) + _playPos--; + break; + } //switch instr & 0xF0 + _wait = *(_playPos++); + break; + } //switch instr + } while (_wait == 0); + + if (_wait == 0xF8) { + _wait = 0xF0; + if (*_playPos != 0xF8) + _wait += *(_playPos++); + } +// _playPos++; + _samplesTillPoll = _wait * (_rate / 1000); } -void AdLib::startPlay() { - if (_data) _playing = true; +void MDYPlayer::reset() { + AdLib::reset(); + +// _soundMode 1 : Percussive mode. + if (_soundMode == 1) { + writeOPL(0xA6, 0); + writeOPL(0xB6, 0); + writeOPL(0xA7, 0); + writeOPL(0xB7, 0); + writeOPL(0xA8, 0); + writeOPL(0xB8, 0); + +// TODO set the correct frequency for the last 4 percussive voices + } } -void AdLib::stopPlay() { - Common::StackLock slock(_mutex); - _playing = false; +void MDYPlayer::rewind() { + _playPos = _data; +} + +void MDYPlayer::setVoices() { + byte *timbrePtr; + + timbrePtr = _timbres; + debugC(6, kDebugSound, "TBR version: %X.%X", timbrePtr[0], timbrePtr[1]); + timbrePtr += 2; + + _tbrCount = READ_LE_UINT16(timbrePtr); + debugC(6, kDebugSound, "Timbres counter: %d", _tbrCount); + timbrePtr += 2; + _tbrStart = READ_LE_UINT16(timbrePtr); + + timbrePtr += 2; + for (int i = 0; i < _tbrCount ; i++) + setVoice(i, i, true); +} + +void MDYPlayer::setVoice(byte voice, byte instr, bool set) { + uint16 strct[27]; + byte channel; + byte *timbrePtr; + char timbreName[10]; + + timbreName[9] = '\0'; + for (int j = 0; j < 9; j++) + timbreName[j] = _timbres[6 + j + (instr * 9)]; + debugC(6, kDebugSound, "Loading timbre %s", timbreName); + + // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 + // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 + for (int i = 0; i < 2; i++) { + timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A; + for (int j = 0; j < 27; j++) { + if (timbrePtr >= (_timbres + _timbresSize)) { + warning("MDYPlayer: Instrument %d out of range (%d, %d)", instr, + (uint32) (timbrePtr - _timbres), _timbresSize); + strct[j] = 0; + } else + strct[j] = READ_LE_UINT16(timbrePtr); + timbrePtr += 2; + } + channel = _operators[voice] + i * 3; + writeOPL(0xBD, 0x00); + writeOPL(0x08, 0x00); + writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); + if (!i) + writeOPL(0xC0 | voice, + ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); + writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); + writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); + writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | + ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | + ((strct[11] & 1) << 4) | (strct[1] & 0xF)); + if (!i) + writeOPL(0xE0 | channel, (strct[26] & 3)); + else { + writeOPL(0xE0 | channel, (strct[14] & 3)); + writeOPL(0x40 | channel, 0); + } + } } } // End of namespace Gob diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h index 4cd83d5883..3f7b46643f 100644 --- a/engines/gob/sound/adlib.h +++ b/engines/gob/sound/adlib.h @@ -38,7 +38,7 @@ class GobEngine; class AdLib : public Audio::AudioStream { public: AdLib(Audio::Mixer &mixer); - ~AdLib(); + virtual ~AdLib(); bool isPlaying() const; int getIndex() const; @@ -49,9 +49,7 @@ public: void startPlay(); void stopPlay(); - bool load(const char *fileName); - bool load(byte *data, uint32 size, int index = -1); - void unload(); + virtual void unload(); // AudioStream API int readBuffer(int16 *buffer, const int numSamples); @@ -89,18 +87,88 @@ protected: bool _playing; bool _first; bool _ended; - bool _needFree; + + bool _freeData; int _index; + unsigned char _wait; + uint8 _tickBeat; + uint8 _beatMeasure; + uint32 _totalTick; + uint32 _nrCommand; + uint16 _pitchBendRangeStep; + uint16 _basicTempo, _tempo; + void writeOPL(byte reg, byte val); void setFreqs(); - void reset(); - void setVoices(); - void setVoice(byte voice, byte instr, bool set); void setKey(byte voice, byte note, bool on, bool spec); void setVolume(byte voice, byte volume); void pollMusic(); + + virtual void interpret() = 0; + + virtual void reset(); + virtual void rewind() = 0; + virtual void setVoices() = 0; + +private: + void init(); +}; + +class ADLPlayer : public AdLib { +public: + ADLPlayer(Audio::Mixer &mixer); + ~ADLPlayer(); + + bool load(const char *fileName); + bool load(byte *data, uint32 size, int index = -1); + + void unload(); + +protected: + void interpret(); + + void reset(); + void rewind(); + + void setVoices(); + void setVoice(byte voice, byte instr, bool set); +}; + +class MDYPlayer : public AdLib { +public: + MDYPlayer(Audio::Mixer &mixer); + ~MDYPlayer(); + + bool loadMDY(const char *fileName); + bool loadMDY(Common::SeekableReadStream &stream); + bool loadTBR(const char *fileName); + bool loadTBR(Common::SeekableReadStream &stream); + + void unload(); + +protected: + byte _soundMode; + + byte *_timbres; + uint16 _tbrCount; + uint16 _tbrStart; + uint32 _timbresSize; + + void interpret(); + + void reset(); + void rewind(); + + void setVoices(); + void setVoice(byte voice, byte instr, bool set); + + void unloadTBR(); + void unloadMDY(); + +private: + void init(); }; } // End of namespace Gob diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp index 12ceb031b7..6ce184155e 100644 --- a/engines/gob/sound/bgatmosphere.cpp +++ b/engines/gob/sound/bgatmosphere.cpp @@ -27,6 +27,7 @@ #include "common/events.h" #include "gob/sound/bgatmosphere.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h index 3fa648b94d..aa8cf58e10 100644 --- a/engines/gob/sound/bgatmosphere.h +++ b/engines/gob/sound/bgatmosphere.h @@ -29,11 +29,12 @@ #include "sound/mixer.h" #include "common/mutex.h" -#include "gob/sound/sounddesc.h" #include "gob/sound/soundmixer.h" namespace Gob { +class SoundDesc; + class BackgroundAtmosphere : private SoundMixer { public: enum PlayMode { diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp index ec9b2aaccb..4d6a7ec966 100644 --- a/engines/gob/sound/cdrom.cpp +++ b/engines/gob/sound/cdrom.cpp @@ -30,6 +30,7 @@ #include "gob/gob.h" #include "gob/sound/cdrom.h" #include "gob/helper.h" +#include "gob/dataio.h" namespace Gob { @@ -86,7 +87,7 @@ void CDROM::startTrack(const char *trackName) { byte *matchPtr = getTrackBuffer(trackName); if (!matchPtr) { - warning("Track \"%s\" not found", trackName); + warning("CDROM: Track \"%s\" not found", trackName); return; } diff --git a/engines/gob/sound/cdrom.h b/engines/gob/sound/cdrom.h index 201f7adb75..6f01e6f90a 100644 --- a/engines/gob/sound/cdrom.h +++ b/engines/gob/sound/cdrom.h @@ -26,10 +26,10 @@ #ifndef GOB_SOUND_CDROM_H #define GOB_SOUND_CDROM_H -#include "gob/dataio.h" - namespace Gob { +class DataStream; + class CDROM { public: CDROM(); diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp index 0b46f3485c..c955dba43f 100644 --- a/engines/gob/sound/infogrames.cpp +++ b/engines/gob/sound/infogrames.cpp @@ -55,7 +55,7 @@ bool Infogrames::loadSong(const char *fileName) { _mixer->getOutputRate(), _mixer->getOutputRate() / 75); if (!_song->load(fileName)) { - warning("Couldn't load infogrames music"); + warning("Infogrames: Couldn't load music \"%s\"", fileName); clearSong(); return false; } @@ -92,7 +92,7 @@ void Infogrames::clearSong() { bool Infogrames::loadInst(const char *fileName) { _instruments = new Audio::Infogrames::Instruments; if (!_instruments->load(fileName)) { - warning("Couldn't load instruments file"); + warning("Infogrames: Couldn't load instruments \"%s\"", fileName); clearInstruments(); return false; } diff --git a/engines/gob/sound/protracker.cpp b/engines/gob/sound/protracker.cpp index 891580ef40..3e33cfd494 100644 --- a/engines/gob/sound/protracker.cpp +++ b/engines/gob/sound/protracker.cpp @@ -25,6 +25,8 @@ #include "common/file.h" +#include "sound/mods/protracker.h" + #include "gob/sound/protracker.h" namespace Gob { diff --git a/engines/gob/sound/protracker.h b/engines/gob/sound/protracker.h index 6270530427..73cae0d510 100644 --- a/engines/gob/sound/protracker.h +++ b/engines/gob/sound/protracker.h @@ -28,7 +28,6 @@ #include "sound/mixer.h" #include "sound/audiostream.h" -#include "sound/mods/protracker.h" namespace Gob { diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp index f0cf17b989..d3afc9baa3 100644 --- a/engines/gob/sound/sound.cpp +++ b/engines/gob/sound/sound.cpp @@ -31,20 +31,28 @@ #include "gob/game.h" #include "gob/inter.h" +#include "gob/sound/pcspeaker.h" +#include "gob/sound/soundblaster.h" +#include "gob/sound/adlib.h" +#include "gob/sound/infogrames.h" +#include "gob/sound/protracker.h" +#include "gob/sound/cdrom.h" + namespace Gob { Sound::Sound(GobEngine *vm) : _vm(vm) { _pcspeaker = new PCSpeaker(*_vm->_mixer); _blaster = new SoundBlaster(*_vm->_mixer); - _adlib = 0; + _adlPlayer = 0; + _mdyPlayer = 0; _infogrames = 0; _protracker = 0; _cdrom = 0; _bgatmos = 0; - if (!_vm->_noMusic && _vm->hasAdlib()) - _adlib = new AdLib(*_vm->_mixer); + _hasAdLib = (!_vm->_noMusic && _vm->hasAdlib()); + if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) { _infogrames = new Infogrames(*_vm->_mixer); _protracker = new Protracker(*_vm->_mixer); @@ -62,7 +70,8 @@ Sound::Sound(GobEngine *vm) : _vm(vm) { Sound::~Sound() { delete _pcspeaker; delete _blaster; - delete _adlib; + delete _adlPlayer; + delete _mdyPlayer; delete _infogrames; delete _protracker; delete _cdrom; @@ -105,14 +114,11 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, debugC(2, kDebugSound, "Loading sample \"%s\"", fileName); - int16 handle = _vm->_dataIO->openData(fileName); - if (handle < 0) { + if (!_vm->_dataIO->existData(fileName)) { warning("Can't open sample file \"%s\"", fileName); return false; } - _vm->_dataIO->closeData(handle); - byte *data; uint32 size; @@ -121,7 +127,7 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, return false; size = _vm->_dataIO->getDataSize(fileName); - return sndDesc->load(type, SOUND_FILE, data, size); + return sndDesc->load(type, data, size); } void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { @@ -130,9 +136,14 @@ void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { if (sndDesc->getType() == SOUND_ADL) { - if (_adlib && noteAdlib) - if ((index == -1) || (_adlib->getIndex() == index)) - _adlib->stopPlay(); + if (noteAdlib) { + if (_adlPlayer) + if ((index == -1) || (_adlPlayer->getIndex() == index)) + _adlPlayer->stopPlay(); + if (_mdyPlayer) + if ((index == -1) || (_mdyPlayer->getIndex() == index)) + _mdyPlayer->stopPlay(); + } } else { @@ -223,50 +234,112 @@ void Sound::infogramesStop() { _infogrames->stop(); } -bool Sound::adlibLoad(const char *fileName) { - if (!_adlib) +bool Sound::adlibLoadADL(const char *fileName) { + if (!_hasAdLib) return false; - debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading ADL data (\"%s\")", fileName); - return _adlib->load(fileName); + return _adlPlayer->load(fileName); } -bool Sound::adlibLoad(byte *data, uint32 size, int index) { - if (!_adlib) +bool Sound::adlibLoadADL(byte *data, uint32 size, int index) { + if (!_hasAdLib) return false; - debugC(1, kDebugSound, "Adlib: Loading data (%d)", index); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading ADL data (%d)", index); - return _adlib->load(data, size, index); + return _adlPlayer->load(data, size, index); } void Sound::adlibUnload() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Unloading data"); - _adlib->unload(); + if (_adlPlayer) + _adlPlayer->unload(); + if (_mdyPlayer) + _mdyPlayer->unload(); +} + +bool Sound::adlibLoadMDY(const char *fileName) { + if (!_hasAdLib) + return false; + + if (!_mdyPlayer) + _mdyPlayer = new MDYPlayer(*_vm->_mixer); + + debugC(1, kDebugSound, "Adlib: Loading MDY data (\"%s\")", fileName); + + if (!_vm->_dataIO->existData(fileName)) { + warning("Can't open MDY file \"%s\"", fileName); + return false; + } + + DataStream *stream = _vm->_dataIO->getDataStream(fileName); + + bool loaded = _mdyPlayer->loadMDY(*stream); + + delete stream; + + return loaded; +} + +bool Sound::adlibLoadTBR(const char *fileName) { + if (!_hasAdLib) + return false; + + if (!_mdyPlayer) + _mdyPlayer = new MDYPlayer(*_vm->_mixer); + + if (!_vm->_dataIO->existData(fileName)) { + warning("Can't open TBR file \"%s\"", fileName); + return false; + } + + debugC(1, kDebugSound, "Adlib: Loading MDY instruments (\"%s\")", fileName); + + DataStream *stream = _vm->_dataIO->getDataStream(fileName); + + bool loaded = _mdyPlayer->loadTBR(*stream); + + delete stream; + + return loaded; } void Sound::adlibPlayTrack(const char *trackname) { - if (!_adlib || _adlib->isPlaying()) + if (!_hasAdLib) return; - debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname); + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); - _adlib->unload(); - _adlib->load(trackname); - _adlib->startPlay(); + if (_adlPlayer->isPlaying()) + return; + + debugC(1, kDebugSound, "Adlib: Playing ADL track \"%s\"", trackname); + + _adlPlayer->unload(); + _adlPlayer->load(trackname); + _adlPlayer->startPlay(); } void Sound::adlibPlayBgMusic() { - int track; - - if (!_adlib) + if (!_hasAdLib) return; + if (!_adlPlayer) + _adlPlayer = new ADLPlayer(*_vm->_mixer); + static const char *tracksMac[] = { // "musmac1.adl", // TODO: This track isn't played correctly at all yet "musmac2.adl", @@ -285,58 +358,82 @@ void Sound::adlibPlayBgMusic() { }; if (_vm->getPlatform() == Common::kPlatformWindows) { - track = _vm->_util->getRandom(ARRAYSIZE(tracksWin)); + int track = _vm->_util->getRandom(ARRAYSIZE(tracksWin)); adlibPlayTrack(tracksWin[track]); } else { - track = _vm->_util->getRandom(ARRAYSIZE(tracksMac)); + int track = _vm->_util->getRandom(ARRAYSIZE(tracksMac)); adlibPlayTrack(tracksMac[track]); } } void Sound::adlibPlay() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Starting playback"); - _adlib->startPlay(); + if (_adlPlayer) + _adlPlayer->startPlay(); + if (_mdyPlayer) + _mdyPlayer->startPlay(); } void Sound::adlibStop() { - if (!_adlib) + if (!_hasAdLib) return; debugC(1, kDebugSound, "Adlib: Stopping playback"); - _adlib->stopPlay(); + if (_adlPlayer) + _adlPlayer->stopPlay(); + if (_mdyPlayer) + _mdyPlayer->stopPlay(); } bool Sound::adlibIsPlaying() const { - if (!_adlib) + if (!_hasAdLib) return false; - return _adlib->isPlaying(); + if (_adlPlayer && _adlPlayer->isPlaying()) + return true; + if (_mdyPlayer && _mdyPlayer->isPlaying()) + return true; + + return false; } int Sound::adlibGetIndex() const { - if (!_adlib) + if (!_hasAdLib) return -1; - return _adlib->getIndex(); + if (_adlPlayer) + return _adlPlayer->getIndex(); + if (_mdyPlayer) + return _mdyPlayer->getIndex(); + + return -1; } bool Sound::adlibGetRepeating() const { - if (!_adlib) + if (!_hasAdLib) return false; - return _adlib->getRepeating(); + if (_adlPlayer) + return _adlPlayer->getRepeating(); + if (_mdyPlayer) + return _mdyPlayer->getRepeating(); + + return false; } void Sound::adlibSetRepeating(int32 repCount) { - if (!_adlib) + if (!_hasAdLib) return; - _adlib->setRepeating(repCount); + if (_adlPlayer) + _adlPlayer->setRepeating(repCount); + if (_mdyPlayer) + _mdyPlayer->setRepeating(repCount); } void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount, @@ -425,17 +522,12 @@ void Sound::cdLoadLIC(const char *fname) { debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname); - int handle = _vm->_dataIO->openData(fname); - - if (handle == -1) + if (!_vm->_dataIO->existData(fname)) return; - _vm->_dataIO->closeData(handle); - _vm->_dataIO->getUnpackedData(fname); - handle = _vm->_dataIO->openData(fname); - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); + DataStream *stream = _vm->_dataIO->getDataStream(fname); _cdrom->readLIC(*stream); diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h index dbdd580ec7..6f6c1d0469 100644 --- a/engines/gob/sound/sound.h +++ b/engines/gob/sound/sound.h @@ -27,16 +27,19 @@ #define GOB_SOUND_SOUND_H #include "gob/sound/sounddesc.h" -#include "gob/sound/pcspeaker.h" -#include "gob/sound/soundblaster.h" -#include "gob/sound/adlib.h" -#include "gob/sound/infogrames.h" -#include "gob/sound/protracker.h" -#include "gob/sound/cdrom.h" #include "gob/sound/bgatmosphere.h" namespace Gob { +class GobEngine; +class PCSpeaker; +class SoundBlaster; +class ADLPlayer; +class MDYPlayer; +class Infogrames; +class Protracker; +class CDROM; + class Sound { public: static const int kSoundsCount = 60; @@ -77,8 +80,10 @@ public: // AdLib - bool adlibLoad(const char *fileName); - bool adlibLoad(byte *data, uint32 size, int index = -1); + bool adlibLoadADL(const char *fileName); + bool adlibLoadADL(byte *data, uint32 size, int index = -1); + bool adlibLoadMDY(const char *fileName); + bool adlibLoadTBR(const char *fileName); void adlibUnload(); void adlibPlayTrack(const char *trackname); @@ -139,11 +144,14 @@ public: private: GobEngine *_vm; + bool _hasAdLib; + SoundDesc _sounds[kSoundsCount]; PCSpeaker *_pcspeaker; SoundBlaster *_blaster; - AdLib *_adlib; + ADLPlayer *_adlPlayer; + MDYPlayer *_mdyPlayer; Infogrames *_infogrames; Protracker *_protracker; CDROM *_cdrom; diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp index 23eea90688..69610dc949 100644 --- a/engines/gob/sound/soundblaster.cpp +++ b/engines/gob/sound/soundblaster.cpp @@ -24,6 +24,7 @@ */ #include "gob/sound/soundblaster.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h index c57e4a443e..a2dc87267c 100644 --- a/engines/gob/sound/soundblaster.h +++ b/engines/gob/sound/soundblaster.h @@ -29,11 +29,12 @@ #include "common/mutex.h" #include "sound/mixer.h" -#include "gob/sound/sounddesc.h" #include "gob/sound/soundmixer.h" namespace Gob { +class SoundDesc; + class SoundBlaster : public SoundMixer { public: SoundBlaster(Audio::Mixer &mixer); diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp index c4c78eebbd..b9b327d105 100644 --- a/engines/gob/sound/sounddesc.cpp +++ b/engines/gob/sound/sounddesc.cpp @@ -29,15 +29,17 @@ #include "sound/wave.h" #include "gob/sound/sounddesc.h" +#include "gob/resources.h" namespace Gob { SoundDesc::SoundDesc() { + _resource = 0; + _data = _dataPtr = 0; _size = 0; _type = SOUND_SND; - _source = SOUND_FILE; _repCount = 0; _frequency = 0; @@ -50,23 +52,31 @@ SoundDesc::~SoundDesc() { free(); } -void SoundDesc::set(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - +void SoundDesc::set(SoundType type, byte *data, uint32 dSize) { free(); _type = type; - _source = src; _data = _dataPtr = data; _size = dSize; } -bool SoundDesc::load(SoundType type, SoundSource src, - byte *data, uint32 dSize) { +void SoundDesc::set(SoundType type, Resource *resource) { + byte *data = 0; + uint32 dSize = 0; + + if (resource && (resource->getSize() > 0)) { + data = resource->getData(); + dSize = resource->getSize(); + } + + set(type, data, dSize); + _resource = resource; +} + +bool SoundDesc::load(SoundType type, byte *data, uint32 dSize) { free(); - _source = src; switch (type) { case SOUND_ADL: return loadADL(data, dSize); @@ -79,10 +89,28 @@ bool SoundDesc::load(SoundType type, SoundSource src, return false; } +bool SoundDesc::load(SoundType type, Resource *resource) { + if (!resource || (resource->getSize() <= 0)) + return false; + + if (!load(type, resource->getData(), resource->getSize())) + return false; + + _resource = resource; + return true; +} + void SoundDesc::free() { - if (_source != SOUND_TOT) - delete[] _data; - _data = _dataPtr = 0; + if (_resource) { + delete _resource; + _data = 0; + } + + delete[] _data; + + _resource = 0; + _data = 0; + _dataPtr = 0; _id = 0; } diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h index 83efd61e6d..9e5d20e138 100644 --- a/engines/gob/sound/sounddesc.h +++ b/engines/gob/sound/sounddesc.h @@ -30,18 +30,14 @@ namespace Gob { +class Resource; + enum SoundType { SOUND_SND, SOUND_WAV, SOUND_ADL }; -enum SoundSource { - SOUND_FILE, - SOUND_TOT, - SOUND_EXT -}; - class SoundDesc { public: int16 _repCount; @@ -58,8 +54,11 @@ public: bool isId(int16 id) const { return _dataPtr && (_id == id); } - void set(SoundType type, SoundSource src, byte *data, uint32 dSize); - bool load(SoundType type, SoundSource src, byte *data, uint32 dSize); + void set(SoundType type, byte *data, uint32 dSize); + void set(SoundType type, Resource *resource); + bool load(SoundType type, byte *data, uint32 dSize); + bool load(SoundType type, Resource *resource); + void free(); void convToSigned(); @@ -71,12 +70,12 @@ public: ~SoundDesc(); private: + Resource *_resource; byte *_data; byte *_dataPtr; uint32 _size; SoundType _type; - SoundSource _source; bool loadSND(byte *data, uint32 dSize); bool loadWAV(byte *data, uint32 dSize); diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp index ea1dd2ef82..68a96d3b01 100644 --- a/engines/gob/sound/soundmixer.cpp +++ b/engines/gob/sound/soundmixer.cpp @@ -24,6 +24,7 @@ */ #include "gob/sound/soundmixer.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h index f32beb149f..20376b5152 100644 --- a/engines/gob/sound/soundmixer.h +++ b/engines/gob/sound/soundmixer.h @@ -31,10 +31,10 @@ #include "sound/audiostream.h" #include "sound/mixer.h" -#include "gob/sound/sounddesc.h" - namespace Gob { +class SoundDesc; + class SoundMixer : public Audio::AudioStream { public: SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type); diff --git a/engines/gob/totfile.cpp b/engines/gob/totfile.cpp new file mode 100644 index 0000000000..bbf62c143b --- /dev/null +++ b/engines/gob/totfile.cpp @@ -0,0 +1,135 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/str.h" +#include "common/stream.h" + +#include "gob/gob.h" +#include "gob/totfile.h" +#include "gob/dataio.h" +#include "gob/videoplayer.h" + +namespace Gob { + +TOTFile::TOTFile(GobEngine *vm) : _vm(vm) { + _stream = 0; + + memset(_header, 0, 128); +} + +TOTFile::~TOTFile() { + unload(); +} + +bool TOTFile::load(const Common::String &fileName) { + // Trying to open normally + _stream = _vm->_dataIO->getDataStream(fileName.c_str()); + + if (!_stream) + // Trying to open from video + _stream = _vm->_vidPlayer->getExtraData(fileName.c_str()); + + if (!_stream) + return false; + + if (_stream->read(_header, 128) != 128) + return false; + + _stream->seek(0); + + return true; +} + +void TOTFile::unload() { + delete _stream; + + _stream = 0; +} + +Common::SeekableReadStream *TOTFile::getStream() const { + return _stream; +} + +bool TOTFile::getProperties(Properties &props) const { + if (!_stream) + return false; + + // Offset 39-41: Version in "Major.Minor" string form + if (_header[40] != '.') + return false; + + props.versionMajor = _header[39] - '0'; + props.versionMinor = _header[41] - '0'; + + props.variablesCount = READ_LE_UINT32(_header + 44); + + props.textsOffset = READ_LE_UINT32(_header + 48); + props.resourcesOffset = READ_LE_UINT32(_header + 52); + + props.animDataSize = READ_LE_UINT16(_header + 56); + + props.imFileNumber = _header[59]; + props.exFileNumber = _header[60]; + props.communHandling = _header[61]; + + for (int i = 0; i < 14; i++) + props.functions[i] = READ_LE_UINT16(_header + 100 + i * 2); + + props.scriptEnd = _stream->size(); + if (props.textsOffset > 0) + props.scriptEnd = MIN(props.scriptEnd, props.textsOffset); + if (props.resourcesOffset > 0) + props.scriptEnd = MIN(props.scriptEnd, props.resourcesOffset); + + return true; +} + +Common::String TOTFile::createFileName(const Common::String &base, bool &isLOM) { + isLOM = false; + + const char *dot; + if ((dot = strrchr(base.c_str(), '.'))) { + // fileName includes an extension + + if (!scumm_stricmp(dot + 1, "LOM")) + isLOM = true; + + return base; + } + + return base + ".tot"; +} + +Common::String TOTFile::getFileBase(const Common::String &fileName) { + const char *dot; + if ((dot = strrchr(fileName.c_str(), '.'))) { + // fileName includes an extension + return Common::String(fileName.c_str(), dot); + } + + return fileName; +} + +} // End of namespace Gob diff --git a/engines/gob/totfile.h b/engines/gob/totfile.h new file mode 100644 index 0000000000..00963d36a2 --- /dev/null +++ b/engines/gob/totfile.h @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_TOTFILE_H +#define GOB_TOTFILE_H + +#include "common/str.h" + +namespace Common { + class SeekableReadStream; +} + +namespace Gob { + +class TOTFile { +public: + enum Function { + kFunctionStart = 0, + kFunctionCenter = 13 + }; + + struct Properties { + uint8 versionMajor; + uint8 versionMinor; + uint32 variablesCount; + uint32 textsOffset; + uint32 resourcesOffset; + uint16 animDataSize; + uint8 imFileNumber; + uint8 exFileNumber; + uint8 communHandling; + uint16 functions[14]; + uint32 scriptEnd; + }; + + TOTFile(GobEngine *vm); + ~TOTFile(); + + bool load(const Common::String &fileName); + void unload(); + + Common::SeekableReadStream *getStream() const; + bool getProperties(Properties &props) const; + + static Common::String createFileName(const Common::String &base, bool &isLOM); + static Common::String getFileBase(const Common::String &fileName); + +private: + GobEngine *_vm; + + Common::SeekableReadStream *_stream; + + byte _header[128]; +}; + +} // End of namespace Gob + +#endif // GOB_TOTFILE_H diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 2916caa340..b0e7691c07 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -120,6 +120,8 @@ void Util::processInput(bool scroll) { _fastMode ^= 1; else if (event.kbd.keycode == Common::KEYCODE_g) _fastMode ^= 2; + else if (event.kbd.keycode == Common::KEYCODE_p) + _vm->pauseGame(); break; } addKeyToBuffer(event.kbd); @@ -233,6 +235,17 @@ int16 Util::checkKey(void) { return translateKey(key); } +bool Util::checkKey(int16 &key) { + Common::KeyState keyS; + + if (!getKeyFromBuffer(keyS)) + return false; + + key = translateKey(keyS); + + return true; +} + void Util::getMouseState(int16 *pX, int16 *pY, int16 *pButtons) { Common::Point mouse = g_system->getEventManager()->getMousePos(); *pX = mouse.x + _vm->_video->_scrollOffsetX - _vm->_video->_screenDeltaX; @@ -318,6 +331,12 @@ void Util::setFrameRate(int16 rate) { _frameRate = rate; _frameWaitTime = 1000 / rate; _startFrameTime = getTimeKey(); + _frameWaitLag = 0; +} + +void Util::notifyNewAnim() { + _startFrameTime = getTimeKey(); + _frameWaitLag = 0; } void Util::waitEndFrame() { diff --git a/engines/gob/util.h b/engines/gob/util.h index 19b11801bc..0a76ee40ab 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -64,6 +64,7 @@ public: void clearKeyBuf(void); int16 getKey(void); int16 checkKey(void); + bool checkKey(int16 &key); void getMouseState(int16 *pX, int16 *pY, int16 *pButtons); void setMousePos(int16 x, int16 y); @@ -75,6 +76,7 @@ public: void clearPalette(void); int16 getFrameRate(); void setFrameRate(int16 rate); + void notifyNewAnim(); void waitEndFrame(); void setScrollOffset(int16 x = -1, int16 y = -1); diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 08aabea004..3b4822cc77 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -96,7 +96,6 @@ Video::Video(GobEngine *vm) : _vm(vm) { _scrollOffsetX = 0; _scrollOffsetY = 0; - _splitSurf = 0; _splitHeight1 = 200; _splitHeight2 = 0; _splitStart = 0; @@ -148,9 +147,8 @@ void Video::initPrimary(int16 mode) { } } -SurfaceDesc *Video::initSurfDesc(int16 vidMode, int16 width, int16 height, - int16 flags) { - SurfaceDesc *descPtr = 0; +SurfaceDescPtr Video::initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags) { + SurfaceDescPtr descPtr; if (flags & PRIMARY_SURFACE) assert((width == _surfWidth) && (height == _surfHeight)); @@ -170,7 +168,7 @@ SurfaceDesc *Video::initSurfDesc(int16 vidMode, int16 width, int16 height, if (!(flags & SCUMMVM_CURSOR)) width = (width + 7) & 0xFFF8; - descPtr = new SurfaceDesc(vidMode, width, height); + descPtr = SurfaceDescPtr(new SurfaceDesc(vidMode, width, height)); } return descPtr; } @@ -241,15 +239,15 @@ void Video::sparseRetrace(int max) { _lastSparse = timeKey; } -void Video::putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest) { - if ((x >= dest->getWidth()) || (x < 0) || - (y >= dest->getHeight()) || (y < 0)) +void Video::putPixel(int16 x, int16 y, int16 color, SurfaceDesc &dest) { + if ((x >= dest.getWidth()) || (x < 0) || + (y >= dest.getHeight()) || (y < 0)) return; _videoDriver->putPixel(x, y, color, dest); } -void Video::fillRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, +void Video::fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 color) { if (_doRangeClamp) { @@ -258,20 +256,20 @@ void Video::fillRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, if (top > bottom) SWAP(top, bottom); - if ((left >= dest->getWidth()) || (right < 0) || - (top >= dest->getHeight()) || (bottom < 0)) + if ((left >= dest.getWidth()) || (right < 0) || + (top >= dest.getHeight()) || (bottom < 0)) return; - left = CLIP(left, (int16) 0, (int16) (dest->getWidth() - 1)); - top = CLIP(top, (int16) 0, (int16) (dest->getHeight() - 1)); - right = CLIP(right, (int16) 0, (int16) (dest->getWidth() - 1)); - bottom = CLIP(bottom, (int16) 0, (int16) (dest->getHeight() - 1)); + left = CLIP(left, (int16)0, (int16)(dest.getWidth() - 1)); + top = CLIP(top, (int16)0, (int16)(dest.getHeight() - 1)); + right = CLIP(right, (int16)0, (int16)(dest.getWidth() - 1)); + bottom = CLIP(bottom, (int16)0, (int16)(dest.getHeight() - 1)); } _videoDriver->fillRect(dest, left, top, right, bottom, color); } -void Video::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, +void Video::drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, int16 color) { if ((x0 == x1) || (y0 == y1)) @@ -286,7 +284,7 @@ void Video::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, * version found in the Wikipedia article about the * "Bresenham's line algorithm" instead */ -void Video::drawCircle(SurfaceDesc *dest, int16 x0, int16 y0, +void Video::drawCircle(SurfaceDesc &dest, int16 x0, int16 y0, int16 radius, int16 color) { int16 f = 1 - radius; int16 ddFx = 0; @@ -319,11 +317,11 @@ void Video::drawCircle(SurfaceDesc *dest, int16 x0, int16 y0, } } -void Video::clearSurf(SurfaceDesc *dest) { - Video::fillRect(dest, 0, 0, dest->getWidth() - 1, dest->getHeight() - 1, 0); +void Video::clearSurf(SurfaceDesc &dest) { + Video::fillRect(dest, 0, 0, dest.getWidth() - 1, dest.getHeight() - 1, 0); } -void Video::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, +void Video::drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { int16 destRight; int16 destBottom; @@ -334,8 +332,8 @@ void Video::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, if (top > bottom) SWAP(top, bottom); - if ((left >= source->getWidth()) || (right < 0) || - (top >= source->getHeight()) || (bottom < 0)) + if ((left >= source.getWidth()) || (right < 0) || + (top >= source.getHeight()) || (bottom < 0)) return; if (left < 0) { @@ -346,12 +344,12 @@ void Video::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, y -= top; top = 0; } - right = CLIP(right, (int16) 0, (int16) (source->getWidth() - 1)); - bottom = CLIP(bottom, (int16) 0, (int16) (source->getHeight() - 1)); - if (right - left >= source->getWidth()) - right = left + source->getWidth() - 1; - if (bottom - top >= source->getHeight()) - bottom = top + source->getHeight() - 1; + right = CLIP(right, (int16)0, (int16)(source.getWidth() - 1)); + bottom = CLIP(bottom, (int16)0, (int16)(source.getHeight() - 1)); + if (right - left >= source.getWidth()) + right = left + source.getWidth() - 1; + if (bottom - top >= source.getHeight()) + bottom = top + source.getHeight() - 1; if (x < 0) { left -= x; @@ -361,30 +359,30 @@ void Video::drawSprite(SurfaceDesc *source, SurfaceDesc *dest, top -= y; y = 0; } - if ((x >= dest->getWidth()) || (left > right) || - (y >= dest->getHeight()) || (top > bottom)) + if ((x >= dest.getWidth()) || (left > right) || + (y >= dest.getHeight()) || (top > bottom)) return; destRight = x + right - left; destBottom = y + bottom - top; - if (destRight >= dest->getWidth()) - right -= destRight - dest->getWidth() + 1; + if (destRight >= dest.getWidth()) + right -= destRight - dest.getWidth() + 1; - if (destBottom >= dest->getHeight()) - bottom -= destBottom - dest->getHeight() + 1; + if (destBottom >= dest.getHeight()) + bottom -= destBottom - dest.getHeight() + 1; } _videoDriver->drawSprite(source, dest, left, top, right, bottom, x, y, transp); } -void Video::drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, +void Video::drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { _videoDriver->drawSpriteDouble(source, dest, left, top, right, bottom, x, y, transp); } void Video::drawLetter(int16 item, int16 x, int16 y, FontDesc *fontDesc, - int16 color1, int16 color2, int16 transp, SurfaceDesc *dest) { + int16 color1, int16 color2, int16 transp, SurfaceDesc &dest) { byte *dataPtr; byte *itemData; int16 itemSize; @@ -417,25 +415,25 @@ void Video::drawLetter(int16 item, int16 x, int16 y, FontDesc *fontDesc, item = 0; } - _videoDriver->drawLetter((unsigned char) item, x, y, fontDesc, color1, color2, transp, dest); + _videoDriver->drawLetter((unsigned char)item, x, y, fontDesc, color1, color2, transp, dest); } void Video::drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, int16 transp, SurfaceDesc *dest) { + int16 x, int16 y, int16 transp, SurfaceDesc &dest) { if (spriteUncompressor(sprBuf, width, height, x, y, transp, dest)) return; - _vm->validateVideoMode(dest->_vidMode); + _vm->validateVideoMode(dest._vidMode); _videoDriver->drawPackedSprite(sprBuf, width, height, x, y, transp, dest); } -void Video::drawPackedSprite(const char *path, SurfaceDesc *dest, int width) { +void Video::drawPackedSprite(const char *path, SurfaceDesc &dest, int width) { byte *data; data = _vm->_dataIO->getData(path); - drawPackedSprite(data, width, dest->getHeight(), 0, 0, 0, dest); + drawPackedSprite(data, width, dest.getHeight(), 0, 0, 0, dest); delete[] data; } diff --git a/engines/gob/video.h b/engines/gob/video.h index 4341d05c14..c71a18daa6 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -28,9 +28,9 @@ #include "common/list.h" #include "common/rect.h" +#include "common/ptr.h" #include "gob/gob.h" -#include "gob/helper.h" namespace Graphics { class PaletteLUT; @@ -39,9 +39,9 @@ namespace Graphics { namespace Gob { // Some Surfaces are simultaneous in Draw::spritesArray and discrete -// variables, so it's a references counting class that cleans -// up its own mess -class SurfaceDesc : public ReferenceCounter<SurfaceDesc> { +// variables, so if in doubt you should use a SurfaceDescPtr shared +// pointer object to refer to any SurfaceDesc. +class SurfaceDesc { public: int16 _vidMode; @@ -54,7 +54,6 @@ public: void setVidMem(byte *vidMem); void resize(int16 width, int16 height); void swap(SurfaceDesc &surf); - void swap(SurfaceDesc *surf) { assert(surf); swap(*surf); } SurfaceDesc(int16 vidMode, int16 width, int16 height, byte *vidMem = 0); ~SurfaceDesc() { if (_ownVidMem) delete[] _vidMem; } @@ -66,6 +65,9 @@ private: bool _ownVidMem; }; +typedef Common::SharedPtr<SurfaceDesc> SurfaceDescPtr; + + class Video { public: struct FontDesc { @@ -117,7 +119,7 @@ public: int16 _scrollOffsetX; int16 _scrollOffsetY; - SurfaceDesc::Ptr _splitSurf; + SurfaceDescPtr _splitSurf; int16 _splitHeight1; int16 _splitHeight2; int16 _splitStart; @@ -129,7 +131,7 @@ public: void freeDriver(); void initPrimary(int16 mode); - SurfaceDesc *initSurfDesc(int16 vidMode, int16 width, + SurfaceDescPtr initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags); void setSize(bool defaultTo1XScaler); @@ -139,24 +141,24 @@ public: void waitRetrace(bool mouse = true); void sparseRetrace(int max); - void putPixel(int16 x, int16 y, int16 color, SurfaceDesc *dest); - virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top, + void putPixel(int16 x, int16 y, int16 color, SurfaceDesc &dest); + virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 color); - void drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, int16 y1, + void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, int16 color); - void drawCircle(SurfaceDesc *dest, int16 x0, int16 y0, + void drawCircle(SurfaceDesc &dest, int16 x0, int16 y0, int16 radius, int16 color); - void clearSurf(SurfaceDesc *dest); - void drawSprite(SurfaceDesc *source, SurfaceDesc *dest, + void clearSurf(SurfaceDesc &dest); + void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, + void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); void drawLetter(int16 item, int16 x, int16 y, FontDesc *fontDesc, - int16 color1, int16 color2, int16 transp, SurfaceDesc *dest); + int16 color1, int16 color2, int16 transp, SurfaceDesc &dest); void drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, int16 transp, SurfaceDesc *dest); - void drawPackedSprite(const char *path, SurfaceDesc *dest, + int16 x, int16 y, int16 transp, SurfaceDesc &dest); + void drawPackedSprite(const char *path, SurfaceDesc &dest, int width = 320); void setPalColor(byte *pal, byte red, byte green, byte blue) { @@ -181,7 +183,7 @@ public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 x, int16 y, int16 transp, - SurfaceDesc *destDesc) = 0; + SurfaceDesc &destDesc) = 0; virtual void init() {} @@ -210,7 +212,7 @@ protected: class Video_v1 : public Video { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc); + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); Video_v1(GobEngine *vm); virtual ~Video_v1() {} @@ -219,7 +221,7 @@ public: class Video_v2 : public Video_v1 { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc); + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); Video_v2(GobEngine *vm); virtual ~Video_v2() {} @@ -228,9 +230,9 @@ public: class Video_v6 : public Video_v2 { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc); + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); - virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top, + virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 color); virtual void init(); @@ -245,13 +247,13 @@ private: void buildPalLUT(); - void shadeRect(SurfaceDesc *dest, + void shadeRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength); - void drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc); - void drawYUVData(const byte *srcData, SurfaceDesc *destDesc, + void drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc &surfDesc); + void drawYUVData(const byte *srcData, SurfaceDesc &destDesc, int16 width, int16 height, int16 x, int16 y); - void drawYUV(SurfaceDesc *destDesc, int16 x, int16 y, + void drawYUV(SurfaceDesc &destDesc, int16 x, int16 y, int16 dataWidth, int16 dataHeight, int16 width, int16 height, const byte *dataY, const byte *dataU, const byte *dataV); }; @@ -260,13 +262,13 @@ class VideoDriver { public: VideoDriver() {} virtual ~VideoDriver() {} - virtual void drawSprite(SurfaceDesc *source, SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; - virtual void drawSpriteDouble(SurfaceDesc *source, SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; - virtual void fillRect(SurfaceDesc *dest, int16 left, int16 top, int16 right, int16 bottom, byte color) = 0; - virtual void putPixel(int16 x, int16 y, byte color, SurfaceDesc *dest) = 0; - virtual void drawLetter(unsigned char item, int16 x, int16 y, Video::FontDesc *fontDesc, byte color1, byte color2, byte transp, SurfaceDesc *dest) = 0; - virtual void drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color) = 0; - virtual void drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, byte transp, SurfaceDesc *dest) = 0; + virtual void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; + virtual void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; + virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color) = 0; + virtual void putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest) = 0; + virtual void drawLetter(unsigned char item, int16 x, int16 y, Video::FontDesc *fontDesc, byte color1, byte color2, byte transp, SurfaceDesc &dest) = 0; + virtual void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color) = 0; + virtual void drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, byte transp, SurfaceDesc &dest) = 0; }; } // End of namespace Gob diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp index 3c9627c041..699ac5f934 100644 --- a/engines/gob/video_v1.cpp +++ b/engines/gob/video_v1.cpp @@ -34,7 +34,7 @@ Video_v1::Video_v1(GobEngine *vm) : Video(vm) { } char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { byte *memBuffer; byte *srcPtr, *destPtr, *linePtr; byte temp; @@ -46,10 +46,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 bufPos; int16 strLen; - if (!destDesc) - return 1; - - _vm->validateVideoMode(destDesc->_vidMode); + _vm->validateVideoMode(destDesc._vidMode); if (sprBuf[0] != 1) return 0; @@ -59,7 +56,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, if (sprBuf[2] == 2) { SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3); - Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1, + Video::drawSprite(sourceDesc, destDesc, 0, 0, srcWidth - 1, srcHeight - 1, x, y, transp); return 1; } else { @@ -69,7 +66,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, srcPtr = sprBuf + 3; sourceLeft = READ_LE_UINT16(srcPtr); - destPtr = destDesc->getVidMem() + destDesc->getWidth() * y + x; + destPtr = destDesc.getVidMem() + destDesc.getWidth() * y + x; curWidth = 0; curHeight = 0; @@ -96,7 +93,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, curWidth++; if (curWidth >= srcWidth) { curWidth = 0; - linePtr += destDesc->getWidth(); + linePtr += destDesc.getWidth(); destPtr = linePtr; curHeight++; if (curHeight >= srcHeight) @@ -125,7 +122,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, curWidth++; if (curWidth >= srcWidth) { curWidth = 0; - linePtr += destDesc->getWidth(); + linePtr += destDesc.getWidth(); destPtr = linePtr; curHeight++; if (curHeight >= srcHeight) { diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp index ab0c7e52db..b526b63a37 100644 --- a/engines/gob/video_v2.cpp +++ b/engines/gob/video_v2.cpp @@ -34,7 +34,7 @@ Video_v2::Video_v2(GobEngine *vm) : Video_v1(vm) { } char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { byte *memBuffer; byte *srcPtr, *destPtr, *linePtr; byte temp; @@ -47,10 +47,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 strLen; int16 lenCmd; - if (!destDesc) - return 1; - - _vm->validateVideoMode(destDesc->_vidMode); + _vm->validateVideoMode(destDesc._vidMode); if (sprBuf[0] != 1) return 0; @@ -60,7 +57,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, if (sprBuf[2] == 2) { SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3); - Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1, + Video::drawSprite(sourceDesc, destDesc, 0, 0, srcWidth - 1, srcHeight - 1, x, y, transp); return 1; } else if (sprBuf[2] == 1) { @@ -70,7 +67,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, srcPtr = sprBuf + 3; sourceLeft = READ_LE_UINT32(srcPtr); - destPtr = destDesc->getVidMem() + destDesc->getWidth() * y + x; + destPtr = destDesc.getVidMem() + destDesc.getWidth() * y + x; curWidth = 0; curHeight = 0; @@ -104,7 +101,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, curWidth++; if (curWidth >= srcWidth) { curWidth = 0; - linePtr += destDesc->getWidth(); + linePtr += destDesc.getWidth(); destPtr = linePtr; curHeight++; if (curHeight >= srcHeight) @@ -133,7 +130,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, curWidth++; if (curWidth >= srcWidth) { curWidth = 0; - linePtr += destDesc->getWidth(); + linePtr += destDesc.getWidth(); destPtr = linePtr; curHeight++; if (curHeight >= srcHeight) { diff --git a/engines/gob/video_v6.cpp b/engines/gob/video_v6.cpp index f0d554bd01..983eeea8cf 100644 --- a/engines/gob/video_v6.cpp +++ b/engines/gob/video_v6.cpp @@ -77,11 +77,8 @@ void Video_v6::buildPalLUT() { } char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc *destDesc) { - if (!destDesc) - return 1; - - _vm->validateVideoMode(destDesc->_vidMode); + int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { + _vm->validateVideoMode(destDesc._vidMode); if ((sprBuf[0] == 1) && (sprBuf[1] == 3)) { drawPacked(sprBuf, x, y, destDesc); @@ -93,7 +90,7 @@ char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, return 1; } -void Video_v6::fillRect(SurfaceDesc *dest, +void Video_v6::fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 color) { if (!(color & 0xFF00)) { @@ -112,27 +109,27 @@ void Video_v6::fillRect(SurfaceDesc *dest, if (top > bottom) SWAP(top, bottom); - if ((left >= dest->getWidth()) || (right < 0) || - (top >= dest->getHeight()) || (bottom < 0)) + if ((left >= dest.getWidth()) || (right < 0) || + (top >= dest.getHeight()) || (bottom < 0)) return; - left = CLIP(left, (int16) 0, (int16) (dest->getWidth() - 1)); - top = CLIP(top, (int16) 0, (int16) (dest->getHeight() - 1)); - right = CLIP(right, (int16) 0, (int16) (dest->getWidth() - 1)); - bottom = CLIP(bottom, (int16) 0, (int16) (dest->getHeight() - 1)); + left = CLIP(left, (int16)0, (int16)(dest.getWidth() - 1)); + top = CLIP(top, (int16)0, (int16)(dest.getHeight() - 1)); + right = CLIP(right, (int16)0, (int16)(dest.getWidth() - 1)); + bottom = CLIP(bottom, (int16)0, (int16)(dest.getHeight() - 1)); } byte strength = 16 - (((uint16) color) >> 12); shadeRect(dest, left, top, right, bottom, color, strength); } -void Video_v6::shadeRect(SurfaceDesc *dest, +void Video_v6::shadeRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength) { int width = right - left + 1; int height = bottom - top + 1; - int dWidth = dest->getWidth(); - byte *vidMem = dest->getVidMem() + dWidth * top + left; + int dWidth = dest.getWidth(); + byte *vidMem = dest.getVidMem() + dWidth * top + left; byte sY, sU, sV; _palLUT->getEntry(color, sY, sU, sV); @@ -167,7 +164,7 @@ void Video_v6::shadeRect(SurfaceDesc *dest, delete dither; } -void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc) { +void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc &surfDesc) { const byte *data = sprBuf + 2; int16 width = READ_LE_UINT16(data); @@ -193,7 +190,7 @@ void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *sur delete[] uncBuf; } -void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc *destDesc, +void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc &destDesc, int16 width, int16 height, int16 x, int16 y) { int16 dataWidth = width; @@ -212,16 +209,16 @@ void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc *destDesc, } -void Video_v6::drawYUV(SurfaceDesc *destDesc, int16 x, int16 y, +void Video_v6::drawYUV(SurfaceDesc &destDesc, int16 x, int16 y, int16 dataWidth, int16 dataHeight, int16 width, int16 height, const byte *dataY, const byte *dataU, const byte *dataV) { - byte *vidMem = destDesc->getVidMem() + y * destDesc->getWidth() + x; + byte *vidMem = destDesc.getVidMem() + y * destDesc.getWidth() + x; - if ((x + width - 1) >= destDesc->getWidth()) - width = destDesc->getWidth() - x; - if ((y + height - 1) >= destDesc->getHeight()) - height = destDesc->getHeight() - y; + if ((x + width - 1) >= destDesc.getWidth()) + width = destDesc.getWidth() - x; + if ((y + height - 1) >= destDesc.getHeight()) + height = destDesc.getHeight() - y; Graphics::SierraLight *dither = new Graphics::SierraLight(width, _palLUT); @@ -241,7 +238,7 @@ void Video_v6::drawYUV(SurfaceDesc *destDesc, int16 x, int16 y, } dither->nextLine(); - vidMem += destDesc->getWidth(); + vidMem += destDesc.getWidth(); } delete dither; diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index 88a6cb1a8e..6c07d22333 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -150,8 +150,10 @@ Graphics::CoktelVideo::State VideoPlayer::Video::nextFrame() { return _state; } + VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) { _primaryVideo = new Video(vm); + _ownSurf = false; _backSurf = false; _needBlit = false; _noCursorSwitch = false; @@ -199,15 +201,11 @@ bool VideoPlayer::findFile(char *fileName, Type &which) { int i; for (i = 0; i < ARRAYSIZE(_extensions); i++) { if ((which == kVideoTypeTry) || (which == ((Type) i))) { - int16 handle; - fileName[len] = '.'; fileName[len + 1] = 0; strcat(fileName, _extensions[i]); - handle = _vm->_dataIO->openData(fileName); - if (handle >= 0) { - _vm->_dataIO->closeData(handle); + if (_vm->_dataIO->existData(fileName)) { which = (Type) i; break; } @@ -225,7 +223,7 @@ bool VideoPlayer::findFile(char *fileName, Type &which) { } bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y, - int16 flags, Type which) { + int32 flags, Type which) { char fileName[256]; @@ -251,10 +249,13 @@ bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y, _noCursorSwitch = true; } + _ownSurf = false; + if (!(flags & kFlagNoVideo)) { - SurfaceDesc::Ptr surf; + SurfaceDescPtr surf; if (flags & kFlagOtherSurface) { + _ownSurf = true; _backSurf = false; surf = _vm->_video->initSurfDesc(_vm->_global->_videoMode, @@ -263,6 +264,13 @@ bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y, _vm->_draw->_spritesArray[x] = surf; x = 0; + } else if (flags & kFlagScreenSurface) { + _ownSurf = true; + _backSurf = false; + + surf = _vm->_video->initSurfDesc(_vm->_global->_videoMode, + _vm->_width, _vm->_height, 0); + _vm->_draw->_spritesArray[0] = surf; } else { _backSurf = ((flags & kFlagFrontSurface) == 0); surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20]; @@ -459,13 +467,14 @@ void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) { } void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) { - if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot]) - return; + Video *video = getVideoBySlot(slot); - Graphics::CoktelVideo &video = *(_videoSlots[slot]->getVideo()); + if (video) { + Graphics::CoktelVideo &cVideo = *video->getVideo(); - if (!onlySound || (video.getFeatures() & Graphics::CoktelVideo::kFeaturesSound)) - video.waitEndFrame(); + if (!onlySound || (cVideo.getFeatures() & Graphics::CoktelVideo::kFeaturesSound)) + cVideo.waitEndFrame(); + } } bool VideoPlayer::slotIsOpen(int slot) const { @@ -611,10 +620,24 @@ Common::MemoryReadStream *VideoPlayer::getExtraData(const char *fileName, int sl return 0; } -bool VideoPlayer::doPlay(int16 frame, int16 breakKey, +void VideoPlayer::playFrame(int16 frame, int16 breakKey, uint16 palCmd, int16 palStart, int16 palEnd, int16 palFrame, int16 endFrame) { + if (!_primaryVideo) + return; + + Video &video = *_primaryVideo; + Graphics::CoktelVideo &cVideo = *video.getVideo(); + + if (cVideo.getCurrentFrame() != frame) + cVideo.seekFrame(frame); + if (palFrame < 0) + palFrame = 0; + if (endFrame < 0) + endFrame = cVideo.getFramesCount() - 1; + + bool modifiedPal = false; if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) { @@ -622,7 +645,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_draw->_applyPal = true; if (palCmd >= 4) - copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd); + copyPalette(cVideo, palStart, palEnd); } if (modifiedPal && (palCmd == 8) && !_backSurf) @@ -632,7 +655,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, if (_needBlit) _vm->_draw->forceBlit(); - Graphics::CoktelVideo::State state = _primaryVideo->nextFrame(); + Graphics::CoktelVideo::State state = video.nextFrame(); WRITE_VAR(11, frame); if (_needBlit) @@ -648,7 +671,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, } if ((state.flags & Graphics::CoktelVideo::kStatePalette) && (palCmd > 1)) { - copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd); + copyPalette(cVideo, palStart, palEnd); if (!_backSurf) _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); @@ -660,17 +683,25 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - if (_backSurf) { - _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom); - _vm->_draw->blitInvalidated(); - } else - _vm->_video->dirtyRectsAdd(state.left, state.top, state.right, state.bottom); - _vm->_video->retrace(); + if (!_ownSurf) { + if (_backSurf) { + _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom); + _vm->_draw->blitInvalidated(); + } else + _vm->_video->dirtyRectsAdd(state.left, state.top, state.right, state.bottom); + _vm->_video->retrace(); + } if (modifiedPal && ((palCmd == 2) || (palCmd == 4))) _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); +} + +bool VideoPlayer::doPlay(int16 frame, int16 breakKey, + uint16 palCmd, int16 palStart, int16 palEnd, + int16 palFrame, int16 endFrame) { + playFrame(frame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame); _vm->_util->processInput(); diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index eaa0418b68..842426f90a 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -44,7 +44,8 @@ public: kFlagUseBackSurfaceContent = 0x40, kFlagFrontSurface = 0x80, kFlagNoVideo = 0x100, - kFlagOtherSurface = 0x800 + kFlagOtherSurface = 0x800, + kFlagScreenSurface = 0x400000 }; enum Type { @@ -58,13 +59,17 @@ public: ~VideoPlayer(); bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1, - int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry); + int32 flags = kFlagFrontSurface, Type which = kVideoTypeTry); bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1, int16 endFrame = -1, bool fade = false, int16 reverseTo = -1, bool forceSeek = false); void primaryClose(); + void playFrame(int16 frame, int16 breakKey = 27, + uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, + int16 palFrame = -1 , int16 endFrame = -1); + int slotOpen(const char *videoFile, Type which = kVideoTypeTry); void slotPlay(int slot, int16 frame = -1); void slotClose(int slot); @@ -72,7 +77,7 @@ public: uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, uint16 pitch, int16 transp = -1); void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1); - void slotWaitEndFrame(int slot, bool onlySound = false); + void slotWaitEndFrame(int slot = -1, bool onlySound = false); void slotSetDoubleMode(int slot, bool doubleMode); @@ -140,6 +145,7 @@ private: Common::Array<Video *> _videoSlots; Video *_primaryVideo; + bool _ownSurf; bool _backSurf; bool _needBlit; bool _noCursorSwitch; diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index a2ba4a0aed..14f1c6463c 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -55,7 +55,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -65,7 +65,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("script.grv", "6e30b54b1f3bc2262cdcf7961db2ae67", 17191), - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -79,7 +79,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "intro.gjd", 0, NULL, 31711554}, { NULL, 0, NULL, 0} }, - Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS + Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -90,7 +90,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieV2, 1 }, @@ -100,7 +100,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "Demo", AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70), - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 1 }, @@ -110,7 +110,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "Making Of", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 2 }, @@ -120,7 +120,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "clandestiny", "Trailer", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 3 }, @@ -130,7 +130,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "clandestiny", "", AD_ENTRY1s("disk.1", "f79fc1515174540fef6a34132efc4c53", 76), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -140,7 +140,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "unclehenry", "", AD_ENTRY1s("disk.1", "0e1b1d3cecc4fc7efa62a968844d1f7a", 72), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -150,7 +150,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "tlc", "", AD_ENTRY1s("disk.1", "32a1afa68478f1f9d2b25eeea427f2e3", 84), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -175,7 +175,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - kADFlagUseExtraAsHint + kADFlagUseExtraAsHint, + // Additional GUI options (for every game} + Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX }; diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 4315644ab7..f5db99dd4a 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -277,6 +277,11 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf void GroovieEngine::syncSoundSettings() { _musicPlayer->setUserVolume(ConfMan.getInt("music_volume")); + // VDX videos just contain one digital audio track, which can be used for + // both SFX or Speech, but the engine doesn't know what they contain, so + // we have to use just one volume setting for videos. + // We use "speech" because most users will want to change the videos + // volume when they can't hear the speech because of the music. _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("speech_volume")); } diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index df627e841c..eb53842b91 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -38,7 +38,9 @@ namespace Groovie { -void debugScript(int level, bool nl, const char *s, ...) { +static void debugScript(int level, bool nl, const char *s, ...) GCC_PRINTF(3, 4); + +static void debugScript(int level, bool nl, const char *s, ...) { char buf[STRINGBUFLEN]; va_list va; @@ -511,7 +513,7 @@ void Script::o_videofromref() { // 0x09 } } if (fileref != _videoRef) { - debugScript(1, true, ""); + debugScript(1, false, "\n"); } // Play the video if (!playvideofromref(fileref)) { @@ -569,7 +571,7 @@ bool Script::playvideofromref(uint32 fileref) { _eventKbdChar = 0; // Newline - debugScript(1, true, ""); + debugScript(1, false, "\n"); } // Let the caller know if the video has ended @@ -759,7 +761,7 @@ void Script::o_loadstring() { setVariable(varnum++, readScriptChar(true, true, true)); debugScript(1, false, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_ret() { @@ -840,7 +842,7 @@ void Script::o_xor_obfuscate() { varnum++; } while (!_firstbit); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_vdxtransition() { // 0x1C @@ -1095,7 +1097,7 @@ void Script::o_loadstringvar() { setVariable(varnum++, readScriptChar(true, true, true)); debugScript(1, false, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_chargreatjmp() { diff --git a/engines/igor/detection.cpp b/engines/igor/detection.cpp index 3c2b15377e..c33dc12e96 100644 --- a/engines/igor/detection.cpp +++ b/engines/igor/detection.cpp @@ -36,6 +36,8 @@ struct IgorGameDescription { int gameFlags; }; +using Common::GUIO_NONE; + static const IgorGameDescription igorGameDescriptions[] = { { { @@ -48,7 +50,8 @@ static const IgorGameDescription igorGameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, Igor::kIdEngDemo100, Igor::kFlagDemo | Igor::kFlagFloppy @@ -64,7 +67,8 @@ static const IgorGameDescription igorGameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, Igor::kIdEngDemo110, Igor::kFlagDemo | Igor::kFlagFloppy @@ -80,7 +84,8 @@ static const IgorGameDescription igorGameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, Igor::kIdSpaCD, Igor::kFlagTalkie @@ -101,7 +106,9 @@ static const ADParams igorDetectionParams = { 0, "igor", 0, - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class IgorMetaEngine : public AdvancedMetaEngine { diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp index 0581f6ddc3..6cf7bda33d 100644 --- a/engines/igor/igor.cpp +++ b/engines/igor/igor.cpp @@ -2095,7 +2095,7 @@ int IgorEngine::getHorizontalStepsCount(int minX, int minY, int maxX, int maxY) float r2 = _walkScaleSpeedTable[scale - 1]; debugC(9, kDebugWalk, "getHorizontalStepsCount() maxX - minX = %d r1 = %f r2 = %f", maxX - minX, r1, r2); - int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.)); + int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.0f)); int count = 0; if (steps != 0) { float r3 = (maxY - minY) / (float)steps; diff --git a/engines/igor/staticres.cpp b/engines/igor/staticres.cpp index e5df644c5e..ef19d7033f 100644 --- a/engines/igor/staticres.cpp +++ b/engines/igor/staticres.cpp @@ -230,11 +230,11 @@ const uint8 IgorEngine::_walkWidthScaleTable[] = { }; const float IgorEngine::_walkScaleSpeedTable[] = { - 0.6250, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.1250, 1.3750, 1.6250, 1.6250, - 1.6250, 1.6250, 2.0000, 2.1250, 2.3750, 2.3750, 2.6250, 2.6250, 2.7500, 2.7500, - 2.7500, 3.0000, 3.0000, 3.0000, 3.0000, 3.6250, 3.6250, 3.6250, 3.8750, 3.8750, - 3.8750, 4.0000, 4.0000, 4.3750, 4.3750, 4.6250, 4.6250, 5.0000, 5.0000, 5.0000, - 5.0000, 5.2500, 5.5000, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250 + 0.6250f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 1.1250f, 1.3750f, 1.6250f, 1.6250f, + 1.6250f, 1.6250f, 2.0000f, 2.1250f, 2.3750f, 2.3750f, 2.6250f, 2.6250f, 2.7500f, 2.7500f, + 2.7500f, 3.0000f, 3.0000f, 3.0000f, 3.0000f, 3.6250f, 3.6250f, 3.6250f, 3.8750f, 3.8750f, + 3.8750f, 4.0000f, 4.0000f, 4.3750f, 4.3750f, 4.6250f, 4.6250f, 5.0000f, 5.0000f, 5.0000f, + 5.0000f, 5.2500f, 5.5000f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f }; const uint8 IgorEngine::_walkScaleTable[] = { diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index d7139a9e70..faf1b150a2 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -119,7 +119,7 @@ void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) { flags |= 0x8000; x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd(); y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd(); - _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer); + _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer, 0, 0); } } } diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index a77ffee299..d71f7b8b25 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -69,7 +69,7 @@ bool Debugger::cmd_setScreenDebug(int argc, const char **argv) { } bool Debugger::cmd_loadPalette(int argc, const char **argv) { - uint8 palette[768]; + Palette palette(_vm->screen()->getPalette(0).getNumColors()); if (argc <= 1) { DebugPrintf("Use load_palette <file> [start_col] [end_col]\n"); @@ -80,7 +80,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { uint8 buffer[320*200]; _vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer); _vm->screen()->loadBitmap(argv[1], 5, 5, 0); - memcpy(palette, _vm->screen()->getCPagePtr(5), 768); + palette.copy(_vm->screen()->getCPagePtr(5), 0, 256); _vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer); } else if (!_vm->screen()->loadPalette(argv[1], palette)) { DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); @@ -88,16 +88,16 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { } int startCol = 0; - int endCol = 255; + int endCol = palette.getNumColors(); if (argc > 2) - startCol = MIN(255, MAX(0, atoi(argv[2]))); + startCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[2]))); if (argc > 3) - endCol = MIN(255, MAX(0, atoi(argv[3]))); + endCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[3]))); if (startCol > 0) - memcpy(palette, _vm->screen()->getScreenPalette(), startCol*3); - if (endCol < 255) - memcpy(palette + endCol * 3, _vm->screen()->getScreenPalette() + endCol * 3, (255-endCol)*3); + palette.copy(_vm->screen()->getPalette(0), 0, startCol); + if (endCol < palette.getNumColors()) + palette.copy(_vm->screen()->getPalette(0), endCol); _vm->screen()->setScreenPalette(palette); _vm->screen()->updateScreen(); @@ -465,53 +465,6 @@ bool Debugger_HoF::cmd_passcodes(int argc, const char **argv) { #ifdef ENABLE_LOL Debugger_LoL::Debugger_LoL(LoLEngine *vm) : Debugger(vm), _vm(vm) { } - -bool Debugger_LoL::cmd_listFlags(int argc, const char **argv) { - for (int i = 0, p = 0; i < (int)sizeof(_vm->_gameFlags)*8; ++i, ++p) { - const uint8 index = (i >> 4); - const uint8 offset = i & 0xF; - - DebugPrintf("(%-3i): %-2i", i, (_vm->_gameFlags[index] >> offset) & 1); - if (p == 5) { - DebugPrintf("\n"); - p -= 6; - } - } - DebugPrintf("\n"); - return true; -} - -bool Debugger_LoL::cmd_toggleFlag(int argc, const char **argv) { - if (argc > 1) { - uint flag = atoi(argv[1]); - - const uint8 index = (flag >> 4); - const uint8 offset = flag & 0xF; - - _vm->_gameFlags[index] ^= _vm->_gameFlags[index] & (1 << offset); - - DebugPrintf("Flag %i is now %i\n", flag, (_vm->_gameFlags[index] >> offset) & 1); - } else { - DebugPrintf("Syntax: toggleflag <flag>\n"); - } - - return true; -} - -bool Debugger_LoL::cmd_queryFlag(int argc, const char **argv) { - if (argc > 1) { - uint flag = atoi(argv[1]); - - const uint8 index = (flag >> 4); - const uint8 offset = flag & 0xF; - - DebugPrintf("Flag %i is %i\n", flag, (_vm->_gameFlags[index] >> offset) & 1); - } else { - DebugPrintf("Syntax: queryflag <flag>\n"); - } - - return true; -} #endif // ENABLE_LOL } // End of namespace Kyra diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index b01402f7d5..c9cf6dba2a 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -47,9 +47,9 @@ protected: bool cmd_loadPalette(int argc, const char **argv); bool cmd_showFacings(int argc, const char **argv); bool cmd_gameSpeed(int argc, const char **argv); - virtual bool cmd_listFlags(int argc, const char **argv); - virtual bool cmd_toggleFlag(int argc, const char **argv); - virtual bool cmd_queryFlag(int argc, const char **argv); + bool cmd_listFlags(int argc, const char **argv); + bool cmd_toggleFlag(int argc, const char **argv); + bool cmd_queryFlag(int argc, const char **argv); bool cmd_listTimers(int argc, const char **argv); bool cmd_setTimerCountdown(int argc, const char **argv); }; @@ -106,10 +106,6 @@ public: protected: LoLEngine *_vm; - - bool cmd_listFlags(int argc, const char **argv); - bool cmd_toggleFlag(int argc, const char **argv); - bool cmd_queryFlag(int argc, const char **argv); }; #endif // ENABLE_LOL diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 0da73e2386..3491c54b36 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -83,7 +83,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_CMP_FLAGS }, @@ -95,7 +96,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_CMP_FLAGS }, @@ -108,7 +110,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -119,7 +122,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -130,7 +134,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -141,7 +146,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -152,7 +158,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -163,7 +170,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -174,7 +182,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -185,7 +194,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -197,7 +207,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "2bd1da653eaefd691e050e4a9eb68a64"), Common::EN_ANY, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_AMIGA_FLAGS }, @@ -213,7 +224,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_FLOPPY_FLAGS }, @@ -229,7 +241,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformFMTowns, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_TOWNS_FLAGS }, @@ -244,7 +257,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::JA_JPN, Common::kPlatformFMTowns, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA1_TOWNS_SJIS_FLAGS }, @@ -260,7 +274,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC98, - ADGF_CD + ADGF_CD, + Common::GUIO_NOSPEECH }, KYRA1_TOWNS_FLAGS }, @@ -275,7 +290,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::JA_JPN, Common::kPlatformPC98, - ADGF_CD + ADGF_CD, + Common::GUIO_NOSPEECH }, KYRA1_TOWNS_SJIS_FLAGS }, @@ -287,7 +303,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), Common::EN_ANY, Common::kPlatformPC, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -298,7 +315,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), Common::DE_DEU, Common::kPlatformPC, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -309,7 +327,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), Common::FR_FRA, Common::kPlatformPC, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -321,7 +340,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), Common::IT_ITA, Common::kPlatformPC, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -337,7 +357,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -352,7 +373,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformMacintosh, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -367,7 +389,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformMacintosh, - ADGF_CD + ADGF_CD, + Common::GUIO_NONE }, KYRA1_CD_FLAGS }, @@ -379,7 +402,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + Common::GUIO_NOSPEECH }, KYRA1_DEMO_FLAGS }, @@ -391,7 +415,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_CMP_FLAGS }, @@ -403,7 +428,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_CMP_FLAGS }, @@ -415,7 +441,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_FLAGS }, @@ -427,7 +454,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_FLAGS }, @@ -439,7 +467,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_FLAGS }, @@ -451,7 +480,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_FLOPPY_FLAGS }, @@ -463,7 +493,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FLAGS }, @@ -474,7 +505,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FLAGS }, @@ -485,7 +517,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FLAGS }, @@ -498,7 +531,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), Common::IT_ITA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -509,7 +543,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -520,7 +555,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -532,7 +568,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), Common::IT_ITA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -544,7 +581,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -556,7 +594,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -568,7 +607,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE }, KYRA2_CD_DEMO_FLAGS }, @@ -580,7 +620,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE }, KYRA2_CD_DEMO_FLAGS }, @@ -592,7 +633,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE }, KYRA2_CD_DEMO_FLAGS }, @@ -604,7 +646,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + Common::GUIO_NONE }, KYRA2_DEMO_FLAGS }, @@ -616,7 +659,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), Common::EN_ANY, Common::kPlatformFMTowns, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_TOWNS_FLAGS }, @@ -627,7 +671,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), Common::JA_JPN, Common::kPlatformFMTowns, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, KYRA2_TOWNS_SJIS_FLAGS }, @@ -638,7 +683,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), Common::EN_ANY, Common::kPlatformPC98, - ADGF_CD + ADGF_CD, + Common::GUIO_NOSPEECH }, KYRA2_TOWNS_FLAGS }, @@ -649,7 +695,8 @@ const KYRAGameDescription adGameDescs[] = { AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), Common::JA_JPN, Common::kPlatformPC98, - ADGF_CD + ADGF_CD, + Common::GUIO_NOSPEECH }, KYRA2_TOWNS_SJIS_FLAGS }, @@ -668,7 +715,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FLAGS }, @@ -683,7 +731,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FLAGS }, @@ -698,7 +747,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FLAGS }, @@ -715,7 +765,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -730,7 +781,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -745,7 +797,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -762,7 +815,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -777,7 +831,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -792,7 +847,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_INS_FLAGS }, @@ -809,7 +865,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) }, @@ -824,7 +881,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) }, @@ -839,7 +897,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) }, @@ -856,7 +915,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) }, @@ -871,7 +931,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) }, @@ -886,7 +947,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI }, KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) }, @@ -904,7 +966,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -920,7 +983,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -936,7 +1000,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -952,7 +1017,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -968,7 +1034,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -984,7 +1051,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE }, LOL_CD_FLAGS }, @@ -999,7 +1067,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, LOL_FLOPPY_CMP_FLAGS }, @@ -1014,7 +1083,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, LOL_FLOPPY_CMP_FLAGS }, @@ -1030,7 +1100,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, LOL_FLOPPY_FLAGS }, @@ -1046,7 +1117,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, LOL_FLOPPY_FLAGS }, @@ -1062,7 +1134,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::JA_JPN, Common::kPlatformPC98, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH }, LOL_PC98_SJIS_FLAGS }, @@ -1078,7 +1151,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + Common::GUIO_NONE }, LOL_DEMO_FLAGS }, @@ -1093,7 +1167,8 @@ const KYRAGameDescription adGameDescs[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + Common::GUIO_NOSPEECH }, LOL_KYRA2_DEMO_FLAGS }, @@ -1128,7 +1203,9 @@ const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; } // End of anonymous namespace diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index faea2c9a72..85d974f675 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -83,17 +83,21 @@ void GUI::initMenu(Menu &menu) { int menu_y2 = menu.height + menu.y - 1; _screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bkgdColor); - _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2); + _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra); if (menu.titleX != -1) textX = menu.titleX; else - textX = _text->getCenterStringX(getMenuTitle(menu), menu.x, menu_x2); + textX = getMenuCenterStringX(getMenuTitle(menu), menu.x, menu_x2); textY = menu.y + menu.titleY; - _text->printText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); - _text->printText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9); + } else { + printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); + } int x1, y1, x2, y2; for (int i = 0; i < menu.numberOfItems; ++i) { @@ -114,35 +118,49 @@ void GUI::initMenu(Menu &menu) { menuButtonData->width = menu.item[i].width - 1; menuButtonData->height = menu.item[i].height - 1; menuButtonData->buttonCallback = menu.item[i].callback; - menuButtonData->keyCode = menu.item[i].unk1F; + menuButtonData->keyCode = menu.item[i].keyCode; menuButtonData->keyCode2 = 0; + menuButtonData->arg = menu.item[i].itemId; _menuButtonList = addButtonToList(_menuButtonList, menuButtonData); } _screen->fillRect(x1, y1, x2, y2, menu.item[i].bkgdColor); - _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2); + _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2, _vm->gameFlags().gameID == GI_LOL ? Screen::kShadeTypeLol : Screen::kShadeTypeKyra); if (getMenuItemTitle(menu.item[i])) { if (menu.item[i].titleX != -1) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - - if (i == menu.highlightedItem) - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); - else - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + } } } for (int i = 0; i < menu.numberOfItems; ++i) { if (getMenuItemLabel(menu.item[i])) { - _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + menu.item[i].labelX = menu.item[i].x - 1; + menu.item[i].labelY = menu.item[i].y + 3; + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10); + } else { + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); + } } } @@ -172,8 +190,22 @@ void GUI::initMenu(Menu &menu) { _screen->updateScreen(); } -void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) { +void GUI::processHighlights(Menu &menu) { int x1, y1, x2, y2; + Common::Point p = _vm->getMousePos(); + int mouseX = p.x; + int mouseY = p.y; + + if (_vm->_flags.gameID == GI_LOL && menu.highlightedItem != 255) { + // LoL doesnt't have default highlighted items. + // We use a highlightedItem value of 255 for this. + + // With LoL no highlighting should take place unless the + // mouse cursor moves over a button. The highlighting should end + // when the mouse cursor leaves the button. + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } for (int i = 0; i < menu.numberOfItems; ++i) { if (!menu.item[i].enabled) @@ -188,9 +220,11 @@ void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) { if (mouseX > x1 && mouseX < x2 && mouseY > y1 && mouseY < y2) { - if (menu.highlightedItem != i) { - if (menu.item[menu.highlightedItem].enabled) - redrawText(menu); + if (menu.highlightedItem != i || _vm->_flags.gameID == GI_LOL) { + if (_vm->_flags.gameID != GI_LOL) { + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } menu.highlightedItem = i; redrawHighlight(menu); @@ -212,11 +246,16 @@ void GUI::redrawText(const Menu &menu) { if (menu.item[i].titleX >= 0) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); int textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + } } void GUI::redrawHighlight(const Menu &menu) { @@ -231,11 +270,17 @@ void GUI::redrawHighlight(const Menu &menu) { if (menu.item[i].titleX != -1) textX = x1 + menu.item[i].titleX + 3; else - textX = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); int textY = y1 + 2; - _text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); - _text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + + if (_vm->gameFlags().gameID == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + } else { + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + } } void GUI::updateAllMenuButtons() { @@ -296,7 +341,7 @@ int GUI::redrawShadedButtonCallback(Button *button) { return 0; } -void GUI::updateSaveList() { +void GUI::updateSaveList(bool excludeQuickSaves) { Common::String pattern = _vm->_targetName + ".???"; Common::StringList saveFileList = _vm->_saveFileMan->listSavefiles(pattern); _saveSlots.clear(); @@ -311,6 +356,8 @@ void GUI::updateSaveList() { s1 -= '0'; s2 -= '0'; s3 -= '0'; + if (excludeQuickSaves && s1 == 9 && s2 == 9) + continue; _saveSlots.push_back(s1*100+s2*10+s3); } @@ -383,6 +430,14 @@ void GUI::checkTextfieldInput() { _vm->_system->delayMillis(3); } +void GUI::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) { + _text->printText(str, x, y, c0, c1, c2, font); +} + +int GUI::getMenuCenterStringX(const char *str, int x1, int x2) { + return _text->getCenterStringX(str, x1, x2); +} + #pragma mark - MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(0) { @@ -404,7 +459,7 @@ void MainMenu::updateAnimation() { if (now > _nextUpdate) { _nextUpdate = now + _anim.delay * _vm->tickLength(); - _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0); + _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0, 0, 0, 0); _animIntern.curFrame += _animIntern.direction ; if (_animIntern.curFrame < _anim.startFrame) { _animIntern.curFrame = _anim.startFrame; @@ -421,8 +476,9 @@ void MainMenu::updateAnimation() { bool MainMenu::getInput() { Common::Event event; + Common::EventManager *eventMan = _vm->getEventManager(); - while (_system->getEventManager()->pollEvent(event)) { + while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_LBUTTONUP: return true; diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index f83620c8f9..95df656977 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -114,7 +114,7 @@ struct MenuItem { uint16 labelId; int16 labelX, labelY; - uint16 unk1F; + uint16 keyCode; }; struct Menu { @@ -161,7 +161,7 @@ public: virtual void initMenuLayout(Menu &menu); void initMenu(Menu &menu); - void processHighlights(Menu &menu, int mouseX, int mouseY); + void processHighlights(Menu &menu); // utilities for thumbnail creation virtual void createScreenThumbnail(Graphics::Surface &dst) = 0; @@ -176,6 +176,9 @@ protected: bool _displaySubMenu; bool _cancelSubMenu; + virtual void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font=Screen::FID_8_FNT); + virtual int getMenuCenterStringX(const char *str, int x1, int x2); + Button::Callback _redrawShadedButtonFunctor; Button::Callback _redrawButtonFunctor; @@ -201,7 +204,7 @@ protected: void redrawHighlight(const Menu &menu); Common::Array<int> _saveSlots; - void updateSaveList(); + void updateSaveList(bool excludeQuickSaves = false); int getNextSavegameSlot(); uint32 _lastScreenUpdate; @@ -257,7 +260,7 @@ private: void drawBox(int x, int y, int w, int h, int fill); bool getInput(); - void printString(const char *string, int x, int y, int col1, int col2, int flags, ...); + void printString(const char *string, int x, int y, int col1, int col2, int flags, ...) GCC_PRINTF(2, 8); }; } // end of namesapce Kyra diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index a37ac7b306..69e7419757 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -95,7 +95,11 @@ const char *GUI_HoF::getMenuItemTitle(const MenuItem &menuItem) { if (!menuItem.itemId) return 0; - return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1); + // Strings 41-45 are menu labels, those must be handled uncompressed! + if (menuItem.itemId >= 41 && menuItem.itemId <= 45) + return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 0); + else + return _vm->getTableString(menuItem.itemId, _vm->_optionsBuffer, 1); } const char *GUI_HoF::getMenuItemLabel(const MenuItem &menuItem) { @@ -272,7 +276,7 @@ void KyraEngine_HoF::redrawInventory(int page) { } void KyraEngine_HoF::scrollInventoryWheel() { - WSAMovie_v2 movie(this, _screen); + WSAMovie_v2 movie(this); movie.open("INVWHEEL.WSA", 0, 0); int frames = movie.opened() ? movie.frames() : 6; memcpy(_screenBuffer, _screen->getCPagePtr(2), 64000); @@ -287,7 +291,7 @@ void KyraEngine_HoF::scrollInventoryWheel() { for (int i = 0; i <= 6 && !breakFlag; ++i) { if (movie.opened()) { _screen->hideMouse(); - movie.displayFrame(i % frames, 0, 0, 0, 0); + movie.displayFrame(i % frames, 0, 0, 0, 0, 0, 0); _screen->showMouse(); _screen->updateScreen(); } @@ -361,9 +365,9 @@ int KyraEngine_HoF::bookButton(Button *button) { _screen->showMouse(); } - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); _screen->fadeToBlack(7, &_updateFunctor); - _res->loadFileToBuf("_BOOK.COL", _screen->getPalette(0), 768); + _screen->loadPalette("_BOOK.COL", _screen->getPalette(0)); loadBookBkgd(); showBookPage(); _screen->copyRegion(0, 0, 0, 0, 0x140, 0xC8, 2, 0, Screen::CR_NO_P_CHECK); @@ -389,7 +393,7 @@ int KyraEngine_HoF::bookButton(Button *button) { } setHandItem(_itemInHand); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 768); + _screen->copyPalette(0, 2); _screen->fadePalette(_screen->getPalette(0), 7, &_updateFunctor); _screen->showMouse(); @@ -700,7 +704,6 @@ int GUI_HoF::optionsButton(Button *button) { int oldHandItem = _vm->_itemInHand; _screen->setMouseCursor(0, 0, _vm->getShapePtr(0)); _vm->displayInvWsaLastFrame(); - //XXX _displayMenu = true; for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) { @@ -763,7 +766,7 @@ int GUI_HoF::optionsButton(Button *button) { } while (_displayMenu) { - processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(*_currentMenu); getInput(); } @@ -796,16 +799,11 @@ void GUI_HoF::createScreenThumbnail(Graphics::Surface &dst) { } void GUI_HoF::setupPalette() { - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); - - uint8 *palette = _screen->getPalette(0); - for (int i = 0; i < 768; ++i) - palette[i] >>= 1; - - static const uint8 guiPal[] = { 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFc, 0xFD, 0xFE }; + _screen->copyPalette(1, 0); - for (uint i = 0; i < ARRAYSIZE(guiPal); ++i) - memcpy(_screen->getPalette(0)+guiPal[i]*3, _screen->getPalette(1)+guiPal[i]*3, 3); + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 741; ++i) + pal[i] >>= 1; if (_isDeathMenu) _screen->fadePalette(_screen->getPalette(0), 0x64); @@ -814,7 +812,7 @@ void GUI_HoF::setupPalette() { } void GUI_HoF::restorePalette() { - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -851,8 +849,7 @@ void GUI_HoF::drawSliderBar(int slider, const uint8 *shape) { position = _vm->_configTextspeed; } - position = MAX(2, position); - position = MIN(97, position); + position = CLIP(position, 2, 97); _screen->drawShape(0, shape, x+position, y, 0, 0); } @@ -908,7 +905,7 @@ int GUI_HoF::audioOptions(Button *caller) { updateAllMenuButtons(); bool speechEnabled = _vm->speechEnabled(); while (_isOptionsMenu) { - processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_audioOptions); getInput(); } @@ -956,7 +953,7 @@ int GUI_HoF::gameOptions(Button *caller) { } while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -983,7 +980,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) { _isOptionsMenu = true; while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -1094,8 +1091,7 @@ int GUI_HoF::sliderHandler(Button *caller) { else newVolume = _vm->_mouseX - caller->x - 7; - newVolume = MAX(2, newVolume); - newVolume = MIN(97, newVolume); + newVolume = CLIP(newVolume, 2, 97); if (newVolume == oldVolume) return 0; @@ -1175,7 +1171,7 @@ int GUI_HoF::loadMenu(Button *caller) { _screen->updateScreen(); while (_isLoadMenu) { - processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_loadMenu); getInput(); } diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 560bc6c2f2..9f42697ec7 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -31,6 +31,7 @@ #include "kyra/sound.h" #include "kyra/gui_lok.h" #include "kyra/timer.h" +#include "kyra/util.h" #include "common/config-manager.h" #include "common/savefile.h" @@ -86,7 +87,6 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { } } _screen->updateScreen(); - // XXX clearKyrandiaButtonIO return 0; } @@ -182,7 +182,6 @@ int KyraEngine_LoK::buttonAmuletCallback(Button *caller) { break; } _unkAmuletVar = 0; - // XXX clearKyrandiaButtonIO (!used before every return in this function!) return 1; } @@ -479,7 +478,7 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { } while (_displayMenu && !_vm->shouldQuit()) { - processHighlights(_menu[_toplevelMenu], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[_toplevelMenu]); getInput(); } @@ -538,6 +537,9 @@ void GUI_LoK::setupSavegames(Menu &menu, int num) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) { strncpy(savenames[i], header.description.c_str(), ARRAYSIZE(savenames[0])); savenames[i][34] = 0; + + Util::convertISOToDOS(savenames[i]); + menu.item[i].itemString = savenames[i]; menu.item[i].enabled = 1; menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; @@ -570,7 +572,7 @@ int GUI_LoK::saveGameMenu(Button *button) { _cancelSubMenu = false; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[2]); getInput(); } @@ -616,7 +618,7 @@ int GUI_LoK::loadGameMenu(Button *button) { _vm->_gameToLoad = -1; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[2], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[2]); getInput(); } @@ -654,9 +656,12 @@ void GUI_LoK::updateSavegameString() { if (_keyPressed.keycode) { length = strlen(_savegameName); - if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127) { + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + + if ((uint8)inputKey > 31 && (uint8)inputKey < 226) { if (length < ARRAYSIZE(_savegameName)-1) { - _savegameName[length] = _keyPressed.ascii; + _savegameName[length] = inputKey; _savegameName[length+1] = 0; redrawTextfield(); } @@ -703,7 +708,7 @@ int GUI_LoK::saveGame(Button *button) { while (_displaySubMenu && !_vm->shouldQuit()) { checkTextfieldInput(); updateSavegameString(); - processHighlights(_menu[3], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[3]); } if (_cancelSubMenu) { @@ -715,6 +720,8 @@ int GUI_LoK::saveGame(Button *button) { if (_savegameOffset == 0 && _vm->_gameToLoad == 0) _vm->_gameToLoad = getNextSavegameSlot(); if (_vm->_gameToLoad > 0) { + Util::convertDOSToISO(_savegameName); + Graphics::Surface thumb; createScreenThumbnail(thumb); _vm->saveGameState(_vm->_gameToLoad, _savegameName, &thumb); @@ -773,7 +780,7 @@ bool GUI_LoK::quitConfirm(const char *str) { _cancelSubMenu = true; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[1], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[1]); getInput(); } @@ -833,7 +840,7 @@ int GUI_LoK::gameControlsMenu(Button *button) { _cancelSubMenu = false; while (_displaySubMenu && !_vm->shouldQuit()) { - processHighlights(_menu[5], _vm->_mouseX, _vm->_mouseY); + processHighlights(_menu[5]); getInput(); } @@ -1015,25 +1022,25 @@ void GUI_LoK::fadePalette() { static const int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1}; int index = 0; - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); for (int i = 0; i < 768; i++) - _screen->_currentPalette[i] >>= 1; + _screen->getPalette(0)[i] >>= 1; while (menuPalIndexes[index] != -1) { - memcpy(&_screen->_currentPalette[menuPalIndexes[index]*3], &_screen->getPalette(2)[menuPalIndexes[index]*3], 3); - index++; + _screen->getPalette(0).copy(_screen->getPalette(2), menuPalIndexes[index], 1); + ++index; } - _screen->fadePalette(_screen->_currentPalette, 2); + _screen->fadePalette(_screen->getPalette(0), 2); } void GUI_LoK::restorePalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return; - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); - _screen->fadePalette(_screen->_currentPalette, 2); + _screen->copyPalette(0, 2); + _screen->fadePalette(_screen->getPalette(0), 2); } #pragma mark - diff --git a/engines/kyra/gui_lok.h b/engines/kyra/gui_lok.h index eec57f5546..5982ef1ce2 100644 --- a/engines/kyra/gui_lok.h +++ b/engines/kyra/gui_lok.h @@ -89,7 +89,7 @@ namespace Kyra { item.labelString = r; \ item.labelX = s; \ item.labelY = t; \ - item.unk1F = v; \ + item.keyCode = v; \ } while (0) class KyraEngine_LoK; diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 7a7de65e43..5e03f3d9bb 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -28,32 +28,40 @@ #include "kyra/lol.h" #include "kyra/screen_lol.h" #include "kyra/gui_lol.h" +#include "kyra/resource.h" +#include "kyra/util.h" + +#include "common/savefile.h" +#include "common/config-manager.h" +#include "graphics/scaler.h" + +#include "base/version.h" namespace Kyra { void LoLEngine::gui_drawPlayField() { _screen->loadBitmap("PLAYFLD.CPS", 3, 3, 0); - if (_gameFlags[15] & 0x4000) { + if (_flagsTable[31] & 0x40) { // copy compass shape static const int cx[] = { 112, 152, 224 }; _screen->copyRegion(cx[_lang], 32, 288, 0, 32, 32, 2, 2, Screen::CR_NO_P_CHECK); _compassDirection = -1; } - if (_gameFlags[15] & 0x1000) + if (_flagsTable[31] & 0x10) // draw automap book _screen->drawShape(2, _gameShapes[78], 290, 32, 0, 0); int cp = _screen->setCurPage(2); - if (_gameFlags[15] & 0x2000) { + if (_flagsTable[31] & 0x20) { gui_drawScroll(); } else { _selectedSpell = 0; } - if (_gameFlags[15] & 0x800) + if (_flagsTable[31] & 0x08) resetLampStatus(); updateDrawPage2(); @@ -548,7 +556,7 @@ void LoLEngine::gui_drawMoneyBox(int pageNum) { } void LoLEngine::gui_drawCompass() { - if (!(_gameFlags[15] & 0x4000)) + if (!(_flagsTable[31] & 0x40)) return; if (_compassDirection == -1) { @@ -577,7 +585,7 @@ void LoLEngine::gui_drawCompass() { } int LoLEngine::gui_enableControls() { - _floatingMouseArrowControl = 0; + _floatingCursorControl = 0; if (!_currentControlMode) { for (int i = 76; i < 85; i++) @@ -592,7 +600,7 @@ int LoLEngine::gui_disableControls(int controlMode) { if (_currentControlMode) return 0; - _floatingMouseArrowControl = (controlMode & 2) ? 2 : 1; + _floatingCursorControl = (controlMode & 2) ? 2 : 1; gui_toggleFightButtons(true); @@ -606,7 +614,7 @@ void LoLEngine::gui_toggleButtonDisplayMode(int shapeIndex, int mode) { static const int16 buttonX[] = { 0x0056, 0x0128, 0x000C, 0x0021, 0x0122, 0x000C, 0x0021, 0x0036, 0x000C, 0x0021, 0x0036 }; static const int16 buttonY[] = { 0x00B4, 0x00B4, 0x00B4, 0x00B4, 0x0020, 0x0084, 0x0084, 0x0084, 0x0096, 0x0096, 0x0096 }; - if (shapeIndex == 78 && !(_gameFlags[15] & 0x1000)) + if (shapeIndex == 78 && !(_flagsTable[31] & 0x10)) return; if (_currentControlMode && _needSceneRestore) @@ -836,7 +844,7 @@ void LoLEngine::gui_enableDefaultPlayfieldButtons() { gui_setFaceFramesControlButtons(29, 0); gui_setFaceFramesControlButtons(25, 33); - if (_gameFlags[15] & 0x2000) + if (_flagsTable[31] & 0x20) gui_initMagicScrollButtons(); } @@ -1364,7 +1372,7 @@ int LoLEngine::clickedInventorySlot(Button *button) { (_itemsInPlay[hItem].itemPropertyIndex == 220 || _itemsInPlay[slotItem].itemPropertyIndex == 220)) { // merge ruby of truth - WSAMovie_v2 *wsa = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *wsa = new WSAMovie_v2(this); wsa->open("truth.wsa", 0, 0); _screen->hideMouse(); @@ -1377,7 +1385,7 @@ int LoLEngine::clickedInventorySlot(Button *button) { for (int i = 0; i < 25; i++) { uint32 delayTimer = _system->getMillis() + 7 * _tickLength; _screen->copyRegion(button->x, button->y - 3, 0, 0, 25, 27, 2, 2); - wsa->displayFrame(i, 2, 0, 0, 0x4000); + wsa->displayFrame(i, 2, 0, 0, 0x4000, 0, 0); _screen->copyRegion(0, 0, button->x, button->y - 3, 25, 27, 2, 0); _screen->updateScreen(); delayUntil(delayTimer); @@ -1536,10 +1544,43 @@ int LoLEngine::clickedSceneThrowItem(Button *button) { } int LoLEngine::clickedOptions(Button *button) { + removeInputTop(); gui_toggleButtonDisplayMode(76, 1); + _updateFlags |= 4; + + Button b; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; + + if (_weaponsDisabled) + clickedExitCharInventory(&b); + + initTextFading(0, 1); + updatePortraits(); + setLampMode(true); + setMouseCursorToIcon(0); + disableSysTimer(2); + gui_toggleButtonDisplayMode(76, 0); + bool speechWasEnabled = speechEnabled(); + _gui->runMenu(_gui->_mainMenu); + + _updateFlags &= 0xfffb; + setMouseCursorToItemInHand(); + resetLampStatus(); + gui_enableDefaultPlayfieldButtons(); + enableSysTimer(2); + updateDrawPage2(); + + gui_drawPlayField(); + + if (speechWasEnabled && !textEnabled() && (!speechEnabled() || getVolume(kVolumeSpeech) == 2)) + _configVoice = 0; + + writeSettings(); + return 1; } @@ -1752,7 +1793,7 @@ int LoLEngine::clickedMoneyBox(Button *button) { } int LoLEngine::clickedCompass(Button *button) { - if (!(_gameFlags[15] & 0x4000)) + if (!(_flagsTable[31] & 0x40)) return 0; if (_compassBroken) { @@ -1766,19 +1807,19 @@ int LoLEngine::clickedCompass(Button *button) { } int LoLEngine::clickedAutomap(Button *button) { - if (!(_gameFlags[15] & 0x1000)) + if (!(_flagsTable[31] & 0x10)) return 0; removeInputTop(); displayAutomap(); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); return 1; } int LoLEngine::clickedLamp(Button *button) { - if (!(_gameFlags[15] & 0x800)) + if (!(_flagsTable[31] & 0x08)) return 0; if (_itemsInPlay[_itemInHand].itemPropertyIndex == 248) { @@ -1801,7 +1842,7 @@ int LoLEngine::clickedLamp(Button *button) { } if (_brightness) - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); return 1; } @@ -1826,9 +1867,13 @@ int LoLEngine::clickedStatusIcon(Button *button) { GUI_LoL::GUI_LoL(LoLEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { _scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollUp); _scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::scrollDown); + _redrawButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawButtonCallback); + _redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawShadedButtonCallback); + _specialProcessButton = _backUpButtonList = 0; _flagsModifier = 0; _mouseClick = 0; + _sliderSfx = 11; _buttonListChanged = false; } @@ -2164,6 +2209,624 @@ int GUI_LoL::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseW return returnValue; } +int GUI_LoL::redrawButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 225); + return 0; +} + +int GUI_LoL::redrawShadedButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 223, 227, Screen::kShadeTypeLol); + return 0; +} + +int GUI_LoL::runMenu(Menu &menu) { + _currentMenu = &menu; + _lastMenu = _currentMenu; + _newMenu = 0; + _displayMenu = true; + _menuResult = 1; + _savegameOffset = 0; + backupPage0(); + + const ScreenDim *d = _screen->getScreenDim(8); + uint32 textCursorTimer = 0; + uint8 textCursorStatus = 1; + int wW = _screen->getCharWidth('W'); + int fW = (d->w << 3) - wW; + int fC = 0; + + // LoL doesnt't have default higlighted items. No item should be + // highlighted when entering a new menu. + // Instead, the respevtive struct entry is used to determine whether + // a menu has scroll buttons or slider bars. + uint8 hasSpecialButtons = 0; + + while (_displayMenu) { + _vm->_mouseX = _vm->_mouseY = 0; + + if (_currentMenu == &_loadMenu || _currentMenu == &_saveMenu || _currentMenu == &_deleteMenu) { + updateSaveList(true); + Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Greater<int>()); + setupSavegameNames(*_currentMenu, 4); + } + + hasSpecialButtons = _currentMenu->highlightedItem; + _currentMenu->highlightedItem = 255; + + if (_currentMenu == &_gameOptions) { + char *s = (char *)_vm->_tempBuffer5120; + strncpy(s, _vm->getLangString(0x406f + _vm->_monsterDifficulty), 30); + s[29] = 0; + _currentMenu->item[0].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->_smoothScrollingEnabled ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[1].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->_floatingCursorsEnabled ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[2].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(0x42d6 + _vm->_lang), 30); + s[29] = 0; + _currentMenu->item[3].itemString = s; + s += (strlen(s) + 1); + + strncpy(s, _vm->getLangString(_vm->textEnabled() ? 0x4068 : 0x4069), 30); + s[29] = 0; + _currentMenu->item[4].itemString = s; + s += (strlen(s) + 1); + } + + if (hasSpecialButtons == 1) { + if (_savegameOffset == 0) { + _scrollUpButton.data0ShapePtr = _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = 0; + } else { + _scrollUpButton.data0ShapePtr = _vm->_gameShapes[17]; + _scrollUpButton.data1ShapePtr = _scrollUpButton.data2ShapePtr = _vm->_gameShapes[19]; + } + if ((uint)_savegameOffset == _saveSlots.size() - 4) { + _scrollDownButton.data0ShapePtr = _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = 0; + } else { + _scrollDownButton.data0ShapePtr = _vm->_gameShapes[18]; + _scrollDownButton.data1ShapePtr = _scrollDownButton.data2ShapePtr = _vm->_gameShapes[20]; + } + } + + for (uint i = 0; i < _currentMenu->numberOfItems; ++i) { + _menuButtons[i].data0Val1 = _menuButtons[i].data1Val1 = _menuButtons[i].data2Val1 = 4; + _menuButtons[i].data0Callback = _redrawShadedButtonFunctor; + _menuButtons[i].data1Callback = _menuButtons[i].data2Callback = _redrawButtonFunctor; + _menuButtons[i].flags = 0x4487; + _menuButtons[i].flags2 = 0; + } + + initMenu(*_currentMenu); + + if (hasSpecialButtons == 2) { + static const uint8 oX[] = { 0, 10, 124 }; + static const uint8 oW[] = { 10, 114, 10 }; + + for (int i = 1; i < 4; ++i) { + int tX = _currentMenu->x + _currentMenu->item[i].x; + int tY = _currentMenu->y + _currentMenu->item[i].y; + + for (int ii = 0; ii < 3; ++ii) { + Button *b = getButtonListData() + 1 + (i - 1) * 3 + ii; + b->nextButton = 0; + b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xfe; + b->data0Val3 = b->data1Val3 = b->data2Val3 = 0x01; + + b->index = ii; + b->keyCode = b->keyCode2 = 0; + + b->x = tX + oX[ii]; + b->y = tY; + b->width = oW[ii]; + b->height = _currentMenu->item[i].height; + + b->data0Val1 = b->data1Val1 = b->data2Val1 = 0; + b->flags = (ii == 1) ? 0x6606 : 0x4406; + + b->dimTableIndex = 0; + + b->buttonCallback = _currentMenu->item[i].callback; + b->arg = _currentMenu->item[i].itemId; + + _menuButtonList = addButtonToList(_menuButtonList, b); + + processButton(b); + updateButton(b); + } + + _currentMenu->item[i].labelX = _currentMenu->item[i].x - 5; + _currentMenu->item[i].labelY = _currentMenu->item[i].y + 3; + + printMenuText(getMenuItemLabel(_currentMenu->item[i]), _currentMenu->x + _currentMenu->item[i].labelX, _currentMenu->y + _currentMenu->item[i].labelY, _currentMenu->item[i].textColor, 0, 10); + + int volume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(i - 1)); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[85], tX , tY, 0, 0x10); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[87], tX + 2 + oX[1], tY, 0, 0x10); + _screen->drawShape(_screen->_curPage, _vm->_gameShapes[86], tX + oX[1] + volume, tY, 0, 0x10); + } + + _screen->updateScreen(); + } + + if (_currentMenu == &_mainMenu) { + Screen::FontId f = _screen->setFont(Screen::FID_6_FNT); + _screen->fprintString("%s", menu.x + 8, menu.y + menu.height - 12, 204, 0, 8, gScummVMVersion); + _screen->setFont(f); + _screen->updateScreen(); + } + + if (_currentMenu == &_savenameMenu) { + int mx = (d->sx << 3) - 1; + int my = d->sy - 1; + int mw = (d->w << 3) + 1; + int mh = d->h + 1; + _screen->drawShadedBox(mx, my, mx + mw, my + mh, 227, 223, Screen::kShadeTypeLol); + int pg = _screen->setCurPage(0); + _vm->_txt->clearDim(8); + textCursorTimer = 0; + textCursorStatus = 0; + + fC = _screen->getTextWidth(_saveDescription); + while (fC >= fW) { + _saveDescription[strlen(_saveDescription) - 1] = 0; + fC = _screen->getTextWidth(_saveDescription); + } + + _screen->fprintString(_saveDescription, (d->sx << 3), d->sy + 2, d->unk8, d->unkA, 0); + _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, d->unk8, 0); + _screen->setCurPage(pg); + } + + while (!_newMenu && _displayMenu) { + processHighlights(*_currentMenu); + + if (_currentMenu == &_savenameMenu) { + if (textCursorTimer <= _vm->_system->getMillis()) { + fC = _screen->getTextWidth(_saveDescription); + textCursorStatus ^= 1; + textCursorTimer = _vm->_system->getMillis() + 20 * _vm->_tickLength; + _screen->fillRect((d->sx << 3) + fC, d->sy, (d->sx << 3) + fC + wW, d->sy + d->h - 1, textCursorStatus ? d->unk8 : d->unkA, 0); + _screen->updateScreen(); + } + } + + if (getInput()) { + if (!_newMenu) + _newMenu = (_currentMenu != &_audioOptions) ? _currentMenu : 0; + else + _lastMenu = _menuResult == -1 ? _lastMenu : _currentMenu; + } + + if (!_menuResult) + _displayMenu = false; + } + + if (_newMenu != _currentMenu || !_displayMenu) + restorePage0(); + + _currentMenu->highlightedItem = hasSpecialButtons; + + if (_newMenu) + _currentMenu = _newMenu; + + _newMenu = 0; + } + + return _menuResult; +} + +void GUI_LoL::createScreenThumbnail(Graphics::Surface &dst) { + uint8 *screenPal = new uint8[768]; + _screen->getRealPalette(1, screenPal); + ::createThumbnail(&dst, _screen->getCPagePtr(7), Screen::SCREEN_W, Screen::SCREEN_H, screenPal); + delete[] screenPal; +} + +void GUI_LoL::backupPage0() { + _screen->copyPage(0, 7); +} + +void GUI_LoL::restorePage0() { + _screen->copyPage(7, 0); + _screen->updateScreen(); +} + +void GUI_LoL::setupSavegameNames(Menu &menu, int num) { + char *s = (char *)_vm->_tempBuffer5120; + + for (int i = 0; i < num; ++i) { + menu.item[i].saveSlot = -1; + menu.item[i].enabled = false; + } + + int startSlot = 0; + if (&menu == &_saveMenu && _savegameOffset == 0) + startSlot = 1; + + KyraEngine_v1::SaveHeader header; + Common::InSaveFile *in; + for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) { + if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset - startSlot]), header)) != 0) { + strncpy(s, header.description.c_str(), 80); + s[79] = 0; + + Util::convertISOToDOS(s); + + menu.item[i].itemString = s; + s += (strlen(s) + 1); + menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; + menu.item[i].enabled = true; + delete in; + } + } + + if (_savegameOffset == 0) { + if (&menu == &_saveMenu) { + strcpy(s, _vm->getLangString(0x4010)); + menu.item[0].itemString = s; + menu.item[0].saveSlot = -3; + menu.item[0].enabled = true; + } + } +} + +void GUI_LoL::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font) { + _screen->fprintString(str, x, y, c0, c1, flags); +} + +int GUI_LoL::getMenuCenterStringX(const char *str, int x1, int x2) { + if (!str) + return 0; + + int strWidth = _screen->getTextWidth(str); + int w = x2 - x1 + 1; + return x1 + (w - strWidth) / 2; +} + +int GUI_LoL::getInput() { + if (!_displayMenu) + return 0; + + Common::Point p = _vm->getMousePos(); + _vm->_mouseX = p.x; + _vm->_mouseY = p.y; + + if (_currentMenu == &_savenameMenu) { + _vm->updateInput(); + + for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); evt++) { + if (evt->event.type == Common::EVENT_KEYDOWN) + _keyPressed = evt->event.kbd; + } + } + + int inputFlag = _vm->checkInput(_menuButtonList); + + if (_currentMenu == &_savenameMenu && _keyPressed.ascii){ + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + + if ((uint8)inputKey > 31 && (uint8)inputKey < 226) { + _saveDescription[strlen(_saveDescription) + 1] = 0; + _saveDescription[strlen(_saveDescription)] = inputKey; + inputFlag |= 0x8000; + } else if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && strlen(_saveDescription)) { + _saveDescription[strlen(_saveDescription) - 1] = 0; + inputFlag |= 0x8000; + } + } + + _vm->removeInputTop(); + _keyPressed.reset(); + + if (_vm->shouldQuit()) + _displayMenu = false; + + _vm->delay(8); + return inputFlag & 0x8000 ? 1 : 0; +} + +int GUI_LoL::clickedMainMenu(Button *button) { + updateMenuButton(button); + switch (button->arg) { + case 0x4001: + _savegameOffset = 0; + _newMenu = &_loadMenu; + break; + case 0x4002: + _savegameOffset = 0; + _newMenu = &_saveMenu; + break; + case 0x4003: + _savegameOffset = 0; + _newMenu = &_deleteMenu; + break; + case 0x4004: + _newMenu = &_gameOptions; + break; + case 0x42D9: + _newMenu = &_audioOptions; + break; + case 0x4006: + _choiceMenu.menuNameId = 0x400a; + _newMenu = &_choiceMenu; + break; + case 0x4005: + _displayMenu = false; + break; + } + return 1; +} + +int GUI_LoL::clickedLoadMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + if (_currentMenu != _lastMenu) + _newMenu = _lastMenu; + else + _menuResult = 0; + return 1; + } + + int16 s = (int16)button->arg; + _vm->_gameToLoad = _loadMenu.item[-s - 2].saveSlot; + _displayMenu = false; + + return 1; +} + +int GUI_LoL::clickedSaveMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + _newMenu = &_mainMenu; + return 1; + } + + _newMenu = &_savenameMenu; + int16 s = (int16)button->arg; + _menuResult = _saveMenu.item[-s - 2].saveSlot + 1; + _saveDescription = (char*)_vm->_tempBuffer5120 + 1000; + _saveDescription[0] = 0; + if (_saveMenu.item[-s - 2].saveSlot != -3) + strcpy(_saveDescription, _saveMenu.item[-s - 2].itemString); + + return 1; +} + +int GUI_LoL::clickedDeleteMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4011) { + _newMenu = &_mainMenu; + return 1; + } + + _choiceMenu.menuNameId = 0x400b; + _newMenu = &_choiceMenu; + int16 s = (int16)button->arg; + _menuResult = _deleteMenu.item[-s - 2].saveSlot + 1; + + return 1; +} + +int GUI_LoL::clickedOptionsMenu(Button *button) { + updateMenuButton(button); + + switch (button->arg) { + case 0xfff7: + _vm->_monsterDifficulty = ++_vm->_monsterDifficulty % 3; + break; + case 0xfff6: + _vm->_smoothScrollingEnabled ^= true; + break; + case 0xfff5: + _vm->_floatingCursorsEnabled ^= true; + break; + case 0xfff4: + _vm->_lang = ++_vm->_lang % 3; + break; + case 0xfff3: + _vm->_configVoice ^= 1; + break; + case 0x4072: + char filename[13]; + snprintf(filename, sizeof(filename), "LEVEL%02d.%s", _vm->_currentLevel, _vm->_languageExt[_vm->_lang]); + if (_vm->_levelLangFile) + delete[] _vm->_levelLangFile; + _vm->_levelLangFile = _vm->resource()->fileData(filename, 0); + snprintf(filename, sizeof(filename), "LANDS.%s", _vm->_languageExt[_vm->_lang]); + if (_vm->_landsFile) + delete[] _vm->_landsFile; + _vm->_landsFile = _vm->resource()->fileData(filename, 0); + _newMenu = _lastMenu; + break; + } + + return 1; +} + +int GUI_LoL::clickedAudioMenu(Button *button) { + updateMenuButton(button); + + if (button->arg == 0x4072) { + _newMenu = _lastMenu; + return 1; + } + + int tX = button->x; + const int oldVolume = _vm->getVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3)); + int newVolume = oldVolume; + + if (button->index == 0) { + newVolume -= 10; + tX += 10; + } else if (button->index == 1) { + newVolume = _vm->_mouseX - (tX + 7); + } else if (button->index == 2) { + newVolume += 10; + tX -= 114; + } + + newVolume = CLIP(newVolume, 2, 102); + + if (newVolume == oldVolume) { + _screen->updateScreen(); + return 0; + } + + _screen->drawShape(0, _vm->_gameShapes[87], tX + oldVolume, button->y, 0, 0x10); + // Temporary HACK + const int volumeDrawX = _vm->convertVolumeFromMixer(_vm->convertVolumeToMixer(newVolume)); + _screen->drawShape(0, _vm->_gameShapes[86], tX + volumeDrawX, button->y, 0, 0x10); + _screen->updateScreen(); + + _vm->snd_stopSpeech(0); + + _vm->setVolume((KyraEngine_v1::kVolumeEntry)(button->arg - 3), newVolume); + + if (newVolume) { + if (button->arg == 4) { + _vm->snd_playSoundEffect(_sliderSfx, -1); + int16 vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]); + do { + ++_sliderSfx; + if (_sliderSfx < 47) + _sliderSfx++; + if (vocIndex == 199) + _sliderSfx = 11; + vocIndex = (int16)READ_LE_UINT16(&_vm->_ingameSoundIndex[_sliderSfx * 2]); + if (vocIndex == -1) + continue; + if (!scumm_stricmp(_vm->_ingameSoundList[vocIndex], "EMPTY")) + continue; + break; + } while (1); + } else if (button->arg == 5) { + _vm->_lastSpeechId = -1; + _vm->snd_playCharacterSpeech(0x42e0, 0, 0); + } + } + + return 1; +} + +int GUI_LoL::clickedDeathMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _deathMenu.item[0].itemId) { + _vm->quitGame(); + } else if (button->arg == _deathMenu.item[1].itemId) { + _newMenu = &_loadMenu; + } + return 1; +} + +int GUI_LoL::clickedSavenameMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _savenameMenu.item[0].itemId) { + + Util::convertDOSToISO(_saveDescription); + + int slot = _menuResult == -2 ? getNextSavegameSlot() : _menuResult; + Graphics::Surface thumb; + createScreenThumbnail(thumb); + _vm->saveGameState(slot, _saveDescription, &thumb); + thumb.free(); + + _displayMenu = false; + + } else if (button->arg == _savenameMenu.item[1].itemId) { + _newMenu = &_saveMenu; + } + + return 1; +} + +int GUI_LoL::clickedChoiceMenu(Button *button) { + updateMenuButton(button); + if (button->arg == _choiceMenu.item[0].itemId) { + if (_lastMenu == &_mainMenu) { + _vm->quitGame(); + } else if (_lastMenu == &_deleteMenu) { + _vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(_menuResult - 1)); + Common::Array<int>::iterator i = Common::find(_saveSlots.begin(), _saveSlots.end(), _menuResult); + while (i != _saveSlots.end()) { + ++i; + if (i == _saveSlots.end()) + break; + // We are only renaming all savefiles until we get some slots missing + // Also not rename quicksave slot filenames + if (*(i-1) != *i || *i >= 990) + break; + Common::String oldName = _vm->getSavegameFilename(*i); + Common::String newName = _vm->getSavegameFilename(*i-1); + _vm->_saveFileMan->renameSavefile(oldName, newName); + } + _newMenu = &_mainMenu; + } + } else if (button->arg == _choiceMenu.item[1].itemId) { + _newMenu = &_mainMenu; + } + return 1; +} + +int GUI_LoL::scrollUp(Button *button) { + updateButton(button); + if (_savegameOffset > 0) { + _savegameOffset--; + _newMenu = _currentMenu; + _menuResult = -1; + } + return 1; +} + +int GUI_LoL::scrollDown(Button *button) { + updateButton(button); + if ((uint)_savegameOffset < _saveSlots.size() - 4) { + _savegameOffset++; + _newMenu = _currentMenu; + _menuResult = -1; + } + return 1; +} + +const char *GUI_LoL::getMenuTitle(const Menu &menu) { + if (!menu.menuNameId) + return 0; + return _vm->getLangString(menu.menuNameId); +} + +const char *GUI_LoL::getMenuItemTitle(const MenuItem &menuItem) { + if (menuItem.itemId & 0x8000 && menuItem.itemString) + return menuItem.itemString; + else if (menuItem.itemId & 0x8000 || !menuItem.itemId) + return 0; + return _vm->getLangString(menuItem.itemId); +} + +const char *GUI_LoL::getMenuItemLabel(const MenuItem &menuItem) { + if (menuItem.labelId & 0x8000 && menuItem.labelString) + return menuItem.labelString; + else if (menuItem.labelId & 0x8000 || !menuItem.labelId) + return 0; + return _vm->getLangString(menuItem.labelId); +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h index 631e29bd3b..832199f23e 100644 --- a/engines/kyra/gui_lol.h +++ b/engines/kyra/gui_lol.h @@ -31,6 +31,50 @@ #include "kyra/gui.h" namespace Kyra { +#define GUI_LOL_MENU(menu, a, b, c, d, e, f, g, i) \ + do { \ + const ScreenDim *dim = _screen->getScreenDim(a); \ + menu.x = (dim->sx << 3); \ + menu.y = (dim->sy); \ + menu.width = (dim->w << 3); \ + menu.height = (dim->h); \ + menu.bkgdColor = 225; \ + menu.color1 = 223; \ + menu.color2 = 227; \ + menu.menuNameId = b; \ + menu.highlightedItem = c; \ + menu.numberOfItems = d; \ + menu.titleX = (dim->sx << 3) + (dim->w << 2); \ + menu.titleY = 6; \ + menu.textColor = 254; \ + menu.scrollUpButtonX = e; \ + menu.scrollUpButtonY = f; \ + menu.scrollDownButtonX = g; \ + menu.scrollDownButtonY = i; \ + } while (0) + + #define GUI_LOL_MENU_ITEM(item, a, b, c, d, e, f, g) \ + do { \ + item.enabled = 1; \ + item.itemId = a; \ + item.itemString = 0; \ + item.x = b; \ + item.y = c; \ + item.width = d; \ + item.height = e; \ + item.textColor = 204; \ + item.highlightColor = 254; \ + item.titleX = -1; \ + item.bkgdColor = 225; \ + item.color1 = 223; \ + item.color2 = 227; \ + item.saveSlot = 0; \ + item.labelId = f; \ + item.labelString = 0; \ + item.labelX = 0; \ + item.labelY = 0; \ + item.keyCode = g; \ + } while (0) class LoLEngine; class Screen_LoL; @@ -40,14 +84,67 @@ class GUI_LoL : public GUI { public: GUI_LoL(LoLEngine *vm); + void initStaticData(); + // button specific void processButton(Button *button); int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel); + int redrawShadedButtonCallback(Button *button); + int redrawButtonCallback(Button *button); + + int runMenu(Menu &menu); + // utilities for thumbnail creation - void createScreenThumbnail(Graphics::Surface &dst) {} + void createScreenThumbnail(Graphics::Surface &dst); private: + void backupPage0(); + void restorePage0(); + + void setupSavegameNames(Menu &menu, int num); + + void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags, Screen::FontId font=Screen::FID_9_FNT); + int getMenuCenterStringX(const char *str, int x1, int x2); + + int getInput(); + + int clickedMainMenu(Button *button); + int clickedLoadMenu(Button *button); + int clickedSaveMenu(Button *button); + int clickedDeleteMenu(Button *button); + int clickedOptionsMenu(Button *button); + int clickedAudioMenu(Button *button); + int clickedDeathMenu(Button *button); + int clickedSavenameMenu(Button *button); + int clickedChoiceMenu(Button *button); + + int scrollUp(Button *button); + int scrollDown(Button *button); + + Button *getButtonListData() { return _menuButtons; } + Button *getScrollUpButton() { return &_scrollUpButton; } + Button *getScrollDownButton() { return &_scrollDownButton; } + + + Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; } + Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; } + + uint8 defaultColor1() const { return 0xFE; } + uint8 defaultColor2() const { return 0x00; } + + const char *getMenuTitle(const Menu &menu); + const char *getMenuItemTitle(const MenuItem &menuItem); + const char *getMenuItemLabel(const MenuItem &menuItem); + + Button _menuButtons[10]; + Button _scrollUpButton; + Button _scrollDownButton; + Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _deleteMenu, _savenameMenu, _deathMenu; + Menu *_currentMenu, *_lastMenu, *_newMenu; + int _menuResult; + char *_saveDescription; + LoLEngine *_vm; Screen_LoL *_screen; @@ -59,24 +156,11 @@ private: uint16 _flagsModifier; uint8 _mouseClick; - int scrollUp(Button *button) { return 0; } - int scrollDown(Button *button) { return 0; } - - Button *getButtonListData() { return 0; } - Button *getScrollUpButton() { return 0; } - Button *getScrollDownButton() { return 0; } + int _savegameOffset; + int _sliderSfx; Button::Callback _scrollUpFunctor; Button::Callback _scrollDownFunctor; - Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; } - Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; } - - uint8 defaultColor1() const { return 0; } - uint8 defaultColor2() const { return 0; } - - const char *getMenuTitle(const Menu &menu) { return 0; } - const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; } - const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; } }; } // end of namespace Kyra diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 19c17b9504..e7001ed31f 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -352,10 +352,10 @@ void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) { frame = 13; if (page == 0) { - _invWsa->displayFrame(frame, 0, 0, 0, 0); + _invWsa->displayFrame(frame, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); } else if (page == 30) { - _invWsa->displayFrame(frame, 2, 0, -144, 0); + _invWsa->displayFrame(frame, 2, 0, -144, 0, 0, 0); } _invWsaFrame = frame; @@ -674,21 +674,21 @@ void KyraEngine_MR::showAlbum() { _screen->copyRegionToBuffer(0, 0, 0, 320, 200, _screenBuffer); _screen->copyRegionToBuffer(4, 0, 0, 320, 200, _album.backUpPage); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); _screen->fadeToBlack(9); int itemInHand = _itemInHand; removeHandItem(); - _res->loadFileToBuf("ALBUM.COL", _screen->getPalette(0), 768); + _screen->loadPalette("ALBUM.COL", _screen->getPalette(0)); loadAlbumPage(); loadAlbumPageWSA(); if (_album.leftPage.wsa->opened()) - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); if (_album.rightPage.wsa->opened()) - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); printAlbumPageText(); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -707,7 +707,7 @@ void KyraEngine_MR::showAlbum() { _screen->copyBlockToPage(0, 0, 0, 320, 200, _screenBuffer); _screen->copyBlockToPage(4, 0, 0, 320, 200, _album.backUpPage); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->fadePalette(_screen->getPalette(0), 9); delete[] _album.backUpRect; @@ -843,10 +843,10 @@ void KyraEngine_MR::processAlbum() { loadAlbumPageWSA(); if (_album.leftPage.wsa->opened()) - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); if (_album.rightPage.wsa->opened()) - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); printAlbumPageText(); @@ -899,7 +899,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.leftPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) { - _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000); + _album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, 0, 0); _screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK); ++_album.leftPage.curFrame; @@ -918,7 +918,7 @@ void KyraEngine_MR::albumUpdateAnims() { nextRun = _album.rightPage.timer + 5 * _tickLength; if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) { - _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000); + _album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, 0, 0); _screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK); ++_album.rightPage.curFrame; @@ -936,13 +936,13 @@ void KyraEngine_MR::albumUpdateAnims() { void KyraEngine_MR::albumAnim1() { for (int i = 6; i >= 3; --i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } albumRestoreRect(); - _album.wsa->displayFrame(14, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(14, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } @@ -950,7 +950,7 @@ void KyraEngine_MR::albumAnim1() { void KyraEngine_MR::albumAnim2() { for (int i = 3; i <= 6; ++i) { albumRestoreRect(); - _album.wsa->displayFrame(i, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(i, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); delayWithTicks(1); } @@ -979,25 +979,25 @@ void KyraEngine_MR::albumSwitchPages(int oldPage, int newPage, int srcPage) { _screen->copyRegion(260, 7, 260, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2); _screen->copyRegion(210, 7, 210, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->copyRegion(160, 7, 160, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0x10, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0x10, 0x07, 0x3C, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->copyRegion(10, 7, 10, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); @@ -1006,25 +1006,25 @@ void KyraEngine_MR::albumSwitchPages(int oldPage, int newPage, int srcPage) { _screen->copyRegion(10, 7, 10, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0x0A, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2); _screen->copyRegion(60, 7, 60, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->copyRegion(110, 7, 110, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2); _screen->updateScreen(); - delayWithTicks(1); + delayWithTicks(2); _screen->copyRegion(160, 7, 160, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); @@ -1269,7 +1269,7 @@ int GUI_MR::optionsButton(Button *button) { } while (_displayMenu) { - processHighlights(*_currentMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(*_currentMenu); getInput(); } @@ -1312,7 +1312,7 @@ int GUI_MR::loadMenu(Button *caller) { _screen->updateScreen(); while (_isLoadMenu) { - processHighlights(_loadMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_loadMenu); getInput(); } @@ -1362,7 +1362,7 @@ int GUI_MR::gameOptions(Button *caller) { _isOptionsMenu = true; while (_isOptionsMenu) { - processHighlights(_gameOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_gameOptions); getInput(); } @@ -1525,7 +1525,7 @@ int GUI_MR::audioOptions(Button *caller) { updateAllMenuButtons(); bool speechEnabled = _vm->speechEnabled(); while (_isOptionsMenu) { - processHighlights(_audioOptions, _vm->_mouseX, _vm->_mouseY); + processHighlights(_audioOptions); getInput(); } @@ -1554,7 +1554,7 @@ int GUI_MR::sliderHandler(Button *caller) { assert(button >= 0 && button <= 3); - int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); + const int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button)); int newVolume = oldVolume; if (caller->index >= 24 && caller->index <= 27) @@ -1564,8 +1564,7 @@ int GUI_MR::sliderHandler(Button *caller) { else newVolume = _vm->_mouseX - caller->x - 7; - newVolume = MAX(2, newVolume); - newVolume = MIN(97, newVolume); + newVolume = CLIP(newVolume, 2, 97); if (newVolume == oldVolume) return 0; @@ -1621,8 +1620,7 @@ void GUI_MR::drawSliderBar(int slider, const uint8 *shape) { int position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider)); - position = MAX(2, position); - position = MIN(97, position); + position = CLIP(position, 2, 97); _screen->drawShape(0, shape, x+position, y, 0, 0); } diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index 7e3d2b5afb..e5c8637fb5 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -27,6 +27,7 @@ #include "kyra/kyra_v2.h" #include "kyra/screen_v2.h" #include "kyra/text.h" +#include "kyra/util.h" #include "common/savefile.h" @@ -158,8 +159,9 @@ int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWh } } - int mouseX = _vm->_mouseX; - int mouseY = _vm->_mouseY; + Common::Point p = _vm->getMousePos(); + int mouseX = _vm->_mouseX = p.x; + int mouseY = _vm->_mouseY = p.y; uint16 flags = 0; @@ -454,8 +456,11 @@ void GUI_v2::setupSavegameNames(Menu &menu, int num) { Common::InSaveFile *in; for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) { if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) { - strncpy(getTableString(menu.item[i].itemId), header.description.c_str(), 80); - getTableString(menu.item[i].itemId)[79] = 0; + char *s = getTableString(menu.item[i].itemId); + strncpy(s, header.description.c_str(), 80); + s[79] = 0; + Util::convertISOToDOS(s); + menu.item[i].saveSlot = _saveSlots[i + _savegameOffset]; menu.item[i].enabled = true; delete in; @@ -601,7 +606,7 @@ int GUI_v2::saveMenu(Button *caller) { updateAllMenuButtons(); while (_isSaveMenu) { - processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_saveMenu); getInput(); } @@ -620,6 +625,7 @@ int GUI_v2::saveMenu(Button *caller) { Graphics::Surface thumb; createScreenThumbnail(thumb); + Util::convertDOSToISO(_saveDescription); _vm->saveGameState(_saveSlot, _saveDescription, &thumb); thumb.free(); @@ -697,7 +703,7 @@ int GUI_v2::deleteMenu(Button *caller) { updateAllMenuButtons(); while (_isDeleteMenu) { - processHighlights(_saveMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_saveMenu); getInput(); } @@ -749,7 +755,11 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 _cancelNameInput = _finishNameInput = false; while (running && !_vm->shouldQuit()) { checkTextfieldInput(); - processHighlights(_savenameMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_savenameMenu); + + char inputKey = _keyPressed.ascii; + Util::convertISOToDOS(inputKey); + if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER || _finishNameInput) { if (checkSavegameDescription(buffer, curPos)) { buffer[curPos] = 0; @@ -767,12 +777,12 @@ const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 drawTextfieldBlock(x2, y2, c3); _screen->updateScreen(); _lastScreenUpdate = _vm->_system->getMillis(); - } else if (_keyPressed.ascii > 31 && _keyPressed.ascii < 127 && curPos < bufferSize) { - if (x2 + getCharWidth(_keyPressed.ascii) + 7 < 0x11F) { - buffer[curPos] = _keyPressed.ascii; + } else if ((uint8)inputKey > 31 && (uint8)inputKey < 226 && curPos < bufferSize) { + if (x2 + getCharWidth(inputKey) + 7 < 0x11F) { + buffer[curPos] = inputKey; const char text[2] = { buffer[curPos], 0 }; _text->printText(text, x2, y2, c1, c2, c2); - x2 += getCharWidth(_keyPressed.ascii); + x2 += getCharWidth(inputKey); drawTextfieldBlock(x2, y2, c3); ++curPos; _screen->updateScreen(); @@ -840,7 +850,7 @@ bool GUI_v2::choiceDialog(int name, bool type) { _choice = false; while (_isChoiceMenu) { - processHighlights(_choiceMenu, _vm->_mouseX, _vm->_mouseY); + processHighlights(_choiceMenu); getInput(); } diff --git a/engines/kyra/gui_v2.h b/engines/kyra/gui_v2.h index ec30640b88..9af4572e4d 100644 --- a/engines/kyra/gui_v2.h +++ b/engines/kyra/gui_v2.h @@ -96,7 +96,7 @@ namespace Kyra { item.labelId = n; \ item.labelX = o; \ item.labelY = p; \ - item.unk1F = q; \ + item.keyCode = q; \ } while (0) class KyraEngine_v2; diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp index 9d18829252..13e269f363 100644 --- a/engines/kyra/items_hof.cpp +++ b/engines/kyra/items_hof.cpp @@ -238,9 +238,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _screen->drawShape(0, itemShape, curX, curY-16, 0, 0); _screen->updateScreen(); - // XXX: original doesn't update game state while delaying - // our implementation *could* do it, so maybe check this again - delayUntil(endDelay); + delayUntil(endDelay, false, true); } if (dstX != dstY || (dstY - startY > 16)) { @@ -275,9 +273,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _screen->drawShape(0, itemShape, x, y, 0, 0); _screen->updateScreen(); - // XXX: original doesn't update game state while delaying - // our implementation *could* do it, so maybe check this again - delayUntil(endDelay); + delayUntil(endDelay, false, true); } restoreGfxRect24x24(x, y); diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index b32988683b..c0ddd0c860 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -279,7 +279,7 @@ void LoLEngine::setHandItem(uint16 itemIndex) { int mouseOffs = 0; - if (itemIndex && !(_gameFlags[15] & 0x200)) { + if (itemIndex && !(_flagsTable[31] & 0x02)) { mouseOffs = 10; if (!_currentControlMode || textEnabled()) _txt->printMessage(0, getLangString(0x403E), getLangString(_itemProperties[_itemsInPlay[itemIndex].itemPropertyIndex].nameStringId)); @@ -451,22 +451,19 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec if (objectOnNextBlock == 1) { runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].block, t->direction >> 1), 0x8000, -1, t->item, 0, 0); - return; } else if (objectOnNextBlock == 2) { if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) { int o = _levelBlockProperties[_itemsInPlay[t->item].block].assignedObjects; - while (o & 0x8000) { ItemInPlay *i = findObject(o); o = i->nextAssignedObject; runItemScript(t->attackerId, t->item, 0x8000, o, 0); } - return; - } else { r = getNearestMonsterFromPos(x, y); + runItemScript(t->attackerId, t->item, 0x8000, r, 0); } } else if (objectOnNextBlock == 4) { @@ -476,14 +473,11 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec if (_characters[i].flags & 1) runItemScript(t->attackerId, t->item, 0x8000, i, 0); } - return; - } else { r = getNearestPartyMemberFromPos(x, y); + runItemScript(t->attackerId, t->item, 0x8000, r, 0); } } - - runItemScript(t->attackerId, t->item, 0x8000, r, 0); } void LoLEngine::updateFlyingObject(FlyingObject *t) { diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index c2c36dcc95..5c41989713 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -381,10 +381,10 @@ void KyraEngine_HoF::startup() { memset(_sceneAnims, 0, sizeof(_sceneAnims)); for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) - _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this); memset(_wsaSlots, 0, sizeof(_wsaSlots)); for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) - _wsaSlots[i] = new WSAMovie_v2(this, _screen); + _wsaSlots[i] = new WSAMovie_v2(this); _screen->_curPage = 0; @@ -415,7 +415,7 @@ void KyraEngine_HoF::startup() { setupLangButtonShapes(); loadInventoryShapes(); - _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0); _screen->copyPage(3, 0); _screen->showMouse(); @@ -451,7 +451,6 @@ void KyraEngine_HoF::startup() { (*_inventoryButtons[0].buttonCallback)(&_inventoryButtons[0]); setNextIdleAnimTimer(); - //XXX setWalkspeed(_configWalkspeed); } @@ -643,8 +642,6 @@ bool KyraEngine_HoF::handleInputUnkSub(int x, int y) { while (_emc->isValid(&_sceneScriptState)) _emc->run(&_sceneScriptState); - //XXXsys_unkKeyboad (flush? wait? whatever...) - if (queryGameFlag(0x1ED)) { _sound->beginFadeOut(); _screen->fadeToBlack(); @@ -919,9 +916,9 @@ void KyraEngine_HoF::showMessage(const char *string, int16 palIndex) { if (string) { if (palIndex != -1 || _fadeMessagePalette) { palIndex *= 3; - memcpy(_messagePal, _screen->_currentPalette + palIndex, 3); - memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3); - _screen->setScreenPalette(_screen->_currentPalette); + memcpy(_messagePal, _screen->getPalette(0).getData() + palIndex, 3); + _screen->getPalette(0).copy(_screen->getPalette(0), palIndex / 3, 1, 255); + _screen->setScreenPalette(_screen->getPalette(0)); } int x = _text->getCenterStringX(string, 0, 320); @@ -978,7 +975,7 @@ void KyraEngine_HoF::fadeMessagePalette() { } if (updatePalette) { - memcpy(_screen->getPalette(0) + 765, _messagePal, 3); + _screen->getPalette(0).copy(_messagePal, 0, 1, 255); _screen->setScreenPalette(_screen->getPalette(0)); } else { _fadeMessagePalette = false; @@ -1139,7 +1136,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) { if (palEntry != _charPalEntry && unk1) { const uint8 *src = &_scenePal[(palEntry << 4) * 3]; - uint8 *ptr = _screen->getPalette(0) + 336; + uint8 *ptr = _screen->getPalette(0).getData() + 336; for (int i = 0; i < 48; ++i) { *ptr -= (*ptr - *src) >> 1; ++ptr; @@ -1149,7 +1146,7 @@ void KyraEngine_HoF::updateCharPal(int unk1) { unkVar1 = true; _charPalEntry = palEntry; } else if (unkVar1 || !unk1) { - memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48); + _screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112); _screen->setScreenPalette(_screen->getPalette(0)); unkVar1 = false; } @@ -1550,7 +1547,7 @@ void KyraEngine_HoF::loadInvWsa(const char *filename, int run_, int delayTime, i wsaFlags |= 2; if (!_invWsa.wsa) - _invWsa.wsa = new WSAMovie_v2(this, _screen); + _invWsa.wsa = new WSAMovie_v2(this); if (!_invWsa.wsa->open(filename, wsaFlags, 0)) error("Couldn't open inventory WSA file '%s'", filename); @@ -1656,12 +1653,12 @@ void KyraEngine_HoF::displayInvWsaLastFrame() { #pragma mark - void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) { - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); Common::SeekableReadStream *file = _res->createReadStream("_POTIONS.PAL"); if (!file) error("Couldn't load cauldron palette"); file->seek(state*18, SEEK_SET); - file->read(_screen->getPalette(2)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); delete file; file = 0; @@ -1673,7 +1670,7 @@ void KyraEngine_HoF::setCauldronState(uint8 state, bool paletteFade) { _screen->updateScreen(); } - memcpy(_screen->getPalette(0)+723, _screen->getPalette(2)+723, 18); + _screen->getPalette(0).copy(_screen->getPalette(2), 241, 6); _cauldronState = state; _cauldronUseCount = 0; //if (state == 5) @@ -1833,11 +1830,11 @@ void KyraEngine_HoF::cauldronRndPaletteFade() { if (!file) error("Couldn't load cauldron palette"); file->seek(index*18, SEEK_SET); - file->read(_screen->getPalette(0)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); snd_playSoundEffect(0x6A); _screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor); file->seek(0, SEEK_SET); - file->read(_screen->getPalette(0)+723, 18); + _screen->getPalette(0).loadVGAPalette(*file, 241, 6); delete file; _screen->fadePalette(_screen->getPalette(0), 0x1E, &_updateFunctor); } diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index fcd35e7282..e5ca52abcc 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -157,7 +157,10 @@ KyraEngine_LoK::~KyraEngine_LoK() { } Common::Error KyraEngine_LoK::init() { - _screen = new Screen_LoK(this, _system); + if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay && ConfMan.getBool("16_color")) + _screen = new Screen_LoK_16(this, _system); + else + _screen = new Screen_LoK(this, _system); assert(_screen); _screen->setResolution(); @@ -358,7 +361,7 @@ void KyraEngine_LoK::startup() { loadButtonShapes(); initMainButtonList(); loadMainScreen(); - _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); // XXX _animator->initAnimStateList(); @@ -906,6 +909,9 @@ void KyraEngine_LoK::registerDefaultSettings() { // Most settings already have sensible defaults. This one, however, is // specific to the Kyra engine. ConfMan.registerDefault("walkspeed", 2); + + if (_flags.platform == Common::kPlatformPC98 && _flags.useHiResOverlay) + ConfMan.registerDefault("16_color", false); } void KyraEngine_LoK::readSettings() { diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index a0f38c3acc..a905c5521b 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -113,7 +113,6 @@ public: KyraEngine_LoK(OSystem *system, const GameFlags &flags); ~KyraEngine_LoK(); - //TODO: proper extended implementation of KyraEngine_v1::pauseEngineIntern. // _sprites and _seqplayer should be paused here too, to avoid some animation glitches, // also parts of the hardcoded Malcolm fight might need some special handling. diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index f2ea0c91df..871edd578d 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -230,7 +230,7 @@ Common::Error KyraEngine_MR::init() { _screen->setAnimBlockPtr(3500); _screen->setScreenDim(0); - _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); return Common::kNoError; @@ -269,19 +269,18 @@ Common::Error KyraEngine_MR::go() { _screen->setScreenPalette(_screen->getPalette(0)); - // XXX playMenuAudioFile(); for (int i = 0; i < 64 && !shouldQuit(); ++i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0, 0, 0, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } for (int i = 64; i > 29 && !shouldQuit(); --i) { uint32 nextRun = _system->getMillis() + 3 * _tickLength; - _menuAnim->displayFrame(i, 0, 0, 0, 0); + _menuAnim->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } @@ -327,9 +326,9 @@ Common::Error KyraEngine_MR::go() { } void KyraEngine_MR::initMainMenu() { - _menuAnim = new WSAMovie_v2(this, _screen); - _menuAnim->open("REVENGE.WSA", 1, _screen->getPalette(0)); - memset(_screen->getPalette(0), 0, 3); + _menuAnim = new WSAMovie_v2(this); + _menuAnim->open("REVENGE.WSA", 1, &_screen->getPalette(0)); + _screen->getPalette(0).fill(0, 1, 0); _menu = new MainMenu(this); MainMenu::StaticData data = { @@ -378,7 +377,7 @@ void KyraEngine_MR::playVQA(const char *name) { } _screen->hideMouse(); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); fadeOutMusic(60); _screen->fadeToBlack(60); _screen->clearPage(0); @@ -390,12 +389,11 @@ void KyraEngine_MR::playVQA(const char *name) { _soundDigital->stopAllSounds(); _screen->showMouse(); - uint8 pal[768]; // Taken from original, it used '1' here too - memset(pal, 1, sizeof(pal)); - _screen->setScreenPalette(pal); + _screen->getPalette(0).fill(0, 256, 1); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _wasPlayingVQA = true; } } @@ -541,11 +539,11 @@ void KyraEngine_MR::initMouseShapes() { } void KyraEngine_MR::startup() { - _album.wsa = new WSAMovie_v2(this, _screen); + _album.wsa = new WSAMovie_v2(this); assert(_album.wsa); - _album.leftPage.wsa = new WSAMovie_v2(this, _screen); + _album.leftPage.wsa = new WSAMovie_v2(this); assert(_album.leftPage.wsa); - _album.rightPage.wsa = new WSAMovie_v2(this, _screen); + _album.rightPage.wsa = new WSAMovie_v2(this); assert(_album.rightPage.wsa); musicUpdate(0); @@ -559,9 +557,7 @@ void KyraEngine_MR::startup() { _screen->setFont(Screen::FID_6_FNT); _stringBuffer = new char[500]; - //XXX musicUpdate(0); - //XXX allocAnimObjects(1, 16, 50); musicUpdate(0); @@ -586,19 +582,16 @@ void KyraEngine_MR::startup() { error("couldn't load _ACTOR"); musicUpdate(0); - //XXX - musicUpdate(0); openTalkFile(0); musicUpdate(0); _currentTalkFile = 0; openTalkFile(1); - //XXX loadCostPal(); musicUpdate(0); for (int i = 0; i < 16; ++i) { _sceneAnims[i].flags = 0; - _sceneAnimMovie[i] = new WSAMovie_v2(this, _screen); + _sceneAnimMovie[i] = new WSAMovie_v2(this); assert(_sceneAnimMovie[i]); } @@ -627,7 +620,7 @@ void KyraEngine_MR::startup() { loadInterfaceShapes(); musicUpdate(0); - _res->loadFileToBuf("PALETTE.COL", _screen->getPalette(0), 768); + _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); _paletteOverlay = new uint8[256]; _screen->generateOverlay(_screen->getPalette(0), _paletteOverlay, 0xF0, 0x19); @@ -655,7 +648,7 @@ void KyraEngine_MR::startup() { musicUpdate(0); runStartupScript(1, 0); _res->exists("MOODOMTR.WSA", true); - _invWsa = new WSAMovie_v2(this, _screen); + _invWsa = new WSAMovie_v2(this); assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; @@ -899,40 +892,30 @@ void KyraEngine_MR::updateCharAnimFrame(int character, int *table) { void KyraEngine_MR::updateCharPal(int unk1) { int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1) - 1; const uint8 *src = _costPalBuffer + _characterShapeFile * 72; - uint8 *dst = _screen->getPalette(0) + 432; + Palette &dst = _screen->getPalette(0); const int8 *sceneDatPal = &_sceneDatPalette[layer * 3]; if (layer != _lastCharPalLayer && unk1) { - for (int i = 0, j = 0; i < 72; ++i) { - uint8 col = *dst; - int8 addCol = *src + *sceneDatPal; - addCol = MAX<int8>(0, MIN<int8>(addCol, 63)); - addCol = (col - addCol) >> 1; - *dst -= addCol; - ++dst; - ++src; - ++sceneDatPal; - ++j; - if (j > 3) { - sceneDatPal = &_sceneDatPalette[layer * 3]; - j = 0; + for (int i = 144; i < 168; ++i) { + for (int j = 0; j < 3; ++j) { + uint8 col = dst[i * 3 + j]; + int subCol = src[(i - 144) * 3 + j] + sceneDatPal[j]; + subCol = CLIP(subCol, 0, 63); + subCol = (col - subCol) / 2; + dst[i * 3 + j] -= subCol; } } + _charPalUpdate = true; _screen->setScreenPalette(_screen->getPalette(0)); _lastCharPalLayer = layer; } else if (_charPalUpdate || !unk1) { - memcpy(dst, src, 72); - - for (int i = 0, j = 0; i < 72; ++i) { - uint8 col = *dst + *sceneDatPal; - *dst = MAX<int8>(0, MIN<int8>(col, 63)); - ++dst; - ++sceneDatPal; - ++j; - if (j >= 3) { - sceneDatPal = &_sceneDatPalette[layer * 3]; - j = 0; + dst.copy(_costPalBuffer, _characterShapeFile * 24, 24, 144); + + for (int i = 144; i < 168; ++i) { + for (int j = 0; j < 3; ++j) { + int col = dst[i * 3 + j] + sceneDatPal[j]; + dst[i * 3 + j] = CLIP(col, 0, 63); } } diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 6c06a84433..88bfb8c89b 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -50,7 +50,6 @@ public: KyraEngine_MR(OSystem *system, const GameFlags &flags); ~KyraEngine_MR(); - //TODO: proper extended implementation of KyraEngine_v2::pauseEngineIntern. // Idle animation time, item animations and album animations should be taken // care of, but since those would just produce minor glitches it's not that // important. diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index f3ba67a265..80872877d5 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -81,7 +81,7 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) Common::addDebugChannel(kDebugLevelMovie, "Movie", "Movie debug level"); Common::addDebugChannel(kDebugLevelTimer, "Timer", "Timer debug level"); - system->getEventManager()->registerRandomSource(_rnd, "kyra"); + _eventMan->registerRandomSource(_rnd, "kyra"); } ::GUI::Debugger *KyraEngine_v1::getDebugger() { @@ -94,8 +94,6 @@ void KyraEngine_v1::pauseEngineIntern(bool pause) { } Common::Error KyraEngine_v1::init() { - registerDefaultSettings(); - // Setup mixer _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); @@ -278,10 +276,10 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag) } else { switch(event.kbd.keycode) { case Common::KEYCODE_SPACE: - keys = 43; + keys = 61; break; case Common::KEYCODE_RETURN: - keys = 61; + keys = 43; break; case Common::KEYCODE_UP: case Common::KEYCODE_KP8: @@ -343,6 +341,10 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag) case Common::EVENT_LBUTTONUP: { _mouseX = event.mouse.x; _mouseY = event.mouse.y; + if (_flags.useHiResOverlay) { + _mouseX >>= 1; + _mouseY >>= 1; + } keys = (event.type == Common::EVENT_LBUTTONDOWN ? 199 : (200 | 0x800)); breakLoop = true; } break; @@ -351,6 +353,10 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag) case Common::EVENT_RBUTTONUP: { _mouseX = event.mouse.x; _mouseY = event.mouse.y; + if (_flags.useHiResOverlay) { + _mouseX >>= 1; + _mouseY >>= 1; + } keys = (event.type == Common::EVENT_RBUTTONDOWN ? 201 : (202 | 0x800)); breakLoop = true; } break; @@ -462,15 +468,18 @@ void KyraEngine_v1::resetSkipFlag(bool removeEvent) { int KyraEngine_v1::setGameFlag(int flag) { + assert((flag >> 3) >= 0 && (flag >> 3) <= ARRAYSIZE(_flagsTable)); _flagsTable[flag >> 3] |= (1 << (flag & 7)); return 1; } int KyraEngine_v1::queryGameFlag(int flag) const { + assert((flag >> 3) >= 0 && (flag >> 3) <= ARRAYSIZE(_flagsTable)); return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1); } int KyraEngine_v1::resetGameFlag(int flag) { + assert((flag >> 3) >= 0 && (flag >> 3) <= ARRAYSIZE(_flagsTable)); _flagsTable[flag >> 3] &= ~(1 << (flag & 7)); return 0; } @@ -583,27 +592,27 @@ bool KyraEngine_v1::textEnabled() { return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); } -inline int convertValueToMixer(int value) { +int KyraEngine_v1::convertVolumeToMixer(int value) { value -= 2; return (value * Audio::Mixer::kMaxMixerVolume) / 95; } -inline int convertValueFromMixer(int value) { +int KyraEngine_v1::convertVolumeFromMixer(int value) { return (value * 95) / Audio::Mixer::kMaxMixerVolume + 2; } void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) { switch (vol) { case kVolumeMusic: - ConfMan.setInt("music_volume", convertValueToMixer(value)); + ConfMan.setInt("music_volume", convertVolumeToMixer(value)); break; case kVolumeSfx: - ConfMan.setInt("sfx_volume", convertValueToMixer(value)); + ConfMan.setInt("sfx_volume", convertVolumeToMixer(value)); break; case kVolumeSpeech: - ConfMan.setInt("speech_volume", convertValueToMixer(value)); + ConfMan.setInt("speech_volume", convertVolumeToMixer(value)); break; } @@ -618,16 +627,16 @@ void KyraEngine_v1::setVolume(kVolumeEntry vol, uint8 value) { uint8 KyraEngine_v1::getVolume(kVolumeEntry vol) { switch (vol) { case kVolumeMusic: - return convertValueFromMixer(ConfMan.getInt("music_volume")); + return convertVolumeFromMixer(ConfMan.getInt("music_volume")); break; case kVolumeSfx: - return convertValueFromMixer(ConfMan.getInt("sfx_volume")); + return convertVolumeFromMixer(ConfMan.getInt("sfx_volume")); break; case kVolumeSpeech: if (speechEnabled()) - return convertValueFromMixer(ConfMan.getInt("speech_volume")); + return convertVolumeFromMixer(ConfMan.getInt("speech_volume")); else return 2; break; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index b45f21dd89..5ece70e3f1 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -153,7 +153,7 @@ public: kVolumeSpeech = 2 }; - // volume reaches from 2 to 97 + // volume reaches per default from 2 to 97 void setVolume(kVolumeEntry vol, uint8 value); uint8 getVolume(kVolumeEntry vol); @@ -181,13 +181,16 @@ protected: // Engine APIs virtual Common::Error init(); virtual Common::Error go() = 0; + virtual Common::Error run() { Common::Error err; + registerDefaultSettings(); err = init(); if (err != Common::kNoError) return err; return go(); } + virtual ::GUI::Debugger *getDebugger(); virtual bool hasFeature(EngineFeature f) const; virtual void pauseEngineIntern(bool pause); @@ -289,6 +292,9 @@ protected: const int8 *_trackMap; int _trackMapSize; + virtual int convertVolumeToMixer(int value); + virtual int convertVolumeFromMixer(int value); + // pathfinder virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 5c494b5180..020e1ea3ea 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -82,7 +82,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _curTlkFile = -1; _lastSpeaker = _lastSpeechId = _nextSpeechId = _nextSpeaker = -1; - memset(_moneyColumnHeight, 0, 5); + memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight)); _credits = 0; _itemsInPlay = 0; @@ -200,7 +200,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _partyPosX = _partyPosY = 0; _shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0; - _floatingMouseArrowControl = 0; + _floatingCursorControl = _currentFloatingCursor = 0; memset(_activeTim, 0, sizeof(_activeTim)); memset(_openDoorState, 0, sizeof(_openDoorState)); @@ -222,10 +222,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _preserveEvents = false; _buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0; - _monsterDifficulty = 1; - _smoothScrollingEnabled = true; - _floatingCursorsEnabled = false; - memset(_lvlTempData, 0, sizeof(_lvlTempData)); _mapOverlay = 0; @@ -242,7 +238,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _compassTimer = 0; _timer3Para = 0; _scriptCharacterCycle = 0; - _partyDeathFlag = -1; + _partyDamageFlags = -1; memset(&_itemScript, 0, sizeof(_itemScript)); } @@ -383,7 +379,7 @@ LoLEngine::~LoLEngine() { delete[] _ingameSoundList; } - for (int i = 0; i < 28; i++) { + for (int i = 0; i < 29; i++) { if (_lvlTempData[i]) { delete[] _lvlTempData[i]->wallsXorData; delete[] _lvlTempData[i]->flags; @@ -436,6 +432,7 @@ Common::Error LoLEngine::init() { _gui = new GUI_LoL(this); assert(_gui); + _gui->initStaticData(); _txt = new TextDisplayer_LoL(this, _screen); @@ -456,8 +453,6 @@ Common::Error LoLEngine::init() { if (!_sound->init()) error("Couldn't init sound"); - _speechFlag = speechEnabled() ? 0x48 : 0; - _wllVmpMap = new uint8[80]; memset(_wllVmpMap, 0, 80); _wllShapeMap = new int8[80]; @@ -500,7 +495,6 @@ Common::Error LoLEngine::init() { _flyingObjects = new FlyingObject[8]; memset(_flyingObjects, 0, 8 * sizeof(FlyingObject)); - memset(_gameFlags, 0, sizeof(_gameFlags)); memset(_globalScriptVars, 0, sizeof(_globalScriptVars)); _levelFileData = 0; @@ -562,7 +556,7 @@ Common::Error LoLEngine::go() { // Usually fonts etc. would be setup by the prologue code, if we skip // the prologue code we need to setup them manually here. - if (_gameToLoad != -1) { + if (_gameToLoad != -1 && action != 3) { preInit(); _screen->setFont(Screen::FID_9_FNT); } @@ -592,8 +586,6 @@ Common::Error LoLEngine::go() { if (loadGameState(_gameToLoad) != Common::kNoError) error("Couldn't load game slot %d on startup", _gameToLoad); _gameToLoad = -1; - } else if (action == 3) { - // XXX } _screen->_fadeFlag = 3; @@ -601,10 +593,6 @@ Common::Error LoLEngine::go() { enableSysTimer(1); runLoop(); - delete _tim; - _tim = 0; - - // TODO: outro return Common::kNoError; } @@ -644,10 +632,19 @@ void LoLEngine::loadItemIconShapes() { _itemIconShapes[i] = _screen->makeShapeCopy(shp, i); _screen->setMouseCursor(0, 0, _itemIconShapes[0]); + + if (!_gameShapes) { + _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0); + shp = _screen->getCPagePtr(3); + _numGameShapes = READ_LE_UINT16(shp); + _gameShapes = new uint8*[_numGameShapes]; + for (int i = 0; i < _numGameShapes; i++) + _gameShapes[i] = _screen->makeShapeCopy(shp, i); + } } void LoLEngine::setMouseCursorToIcon(int icon) { - _gameFlags[15] |= 0x200; + _flagsTable[31] |= 0x02; int i = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].shpIndex; if (i == icon) return; @@ -655,7 +652,7 @@ void LoLEngine::setMouseCursorToIcon(int icon) { } void LoLEngine::setMouseCursorToItemInHand() { - _gameFlags[15] &= 0xFDFF; + _flagsTable[31] &= 0xFD; int o = (_itemInHand == 0) ? 0 : 10; _screen->setMouseCursor(o, o, getItemIconShapePtr(_itemInHand)); } @@ -666,6 +663,53 @@ bool LoLEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, in return true; } +void LoLEngine::checkFloatingPointerRegions() { + if (!_floatingCursorsEnabled) + return; + + int t = -1; + + Common::Point p = getMousePos(); + + if (!(_updateFlags & 4) & !_floatingCursorControl) { + if (posWithinRect(p.x, p.y, 96, 0, 303, 136)) { + if (!posWithinRect(p.x, p.y, 128, 16, 271, 119)) { + if (posWithinRect(p.x, p.y, 112, 0, 287, 15)) + t = 0; + if (posWithinRect(p.x, p.y, 272, 88, 303, 319)) + t = 1; + if (posWithinRect(p.x, p.y, 112, 110, 287, 135)) + t = 2; + if (posWithinRect(p.x, p.y, 96, 88, 127, 119)) + t = 3; + if (posWithinRect(p.x, p.y, 96, 16, 127, 87)) + t = 4; + if (posWithinRect(p.x, p.y, 272, 16, 303, 87)) + t = 5; + + if (t < 4) { + int d = (_currentDirection + t) & 3; + if (!checkBlockPassability(calcNewBlockPosition(_currentBlock, d), d)) + t = 6; + } + } + } + } + + if (t == _currentFloatingCursor) + return; + + if (t == -1) { + setMouseCursorToItemInHand(); + } else { + static const uint8 floatingPtrX[] = { 7, 13, 7, 0, 0, 15, 7 }; + static const uint8 floatingPtrY[] = { 0, 7, 12, 7, 6, 6, 7 }; + _screen->setMouseCursor(floatingPtrX[t], floatingPtrY[t], _gameShapes[10 + t]); + } + + _currentFloatingCursor = t; +} + uint8 *LoLEngine::getItemIconShapePtr(int index) { int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex; if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200) @@ -719,7 +763,7 @@ int LoLEngine::mainMenu() { assert(menu); menu->init(data[dataIndex], MainMenu::Animation()); - int selection = menu->handle(_flags.isTalkie ? (hasSave ? 17 : 6) : (hasSave ? 6 : 18)); + int selection = menu->handle(_flags.isTalkie ? (hasSave ? 19 : 6) : (hasSave ? 6 : 20)); delete menu; _screen->setScreenDim(0); @@ -734,20 +778,20 @@ int LoLEngine::mainMenu() { void LoLEngine::startup() { _screen->clearPage(0); - _screen->loadBitmap("PLAYFLD.CPS", 3, 3, _screen->_currentPalette); - uint8 *tmpPal = new uint8[0x300]; - memcpy(tmpPal, _screen->_currentPalette, 0x300); - memset(_screen->_currentPalette, 0x3f, 0x180); - memcpy(_screen->_currentPalette + 3, tmpPal + 3, 3); - memset(_screen->_currentPalette + 0x240, 0x3f, 12); - _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay1, 1, 96); - _screen->generateOverlay(_screen->_currentPalette, _screen->_paletteOverlay2, 144, 65); - memcpy(_screen->_currentPalette, tmpPal, 0x300); - delete[] tmpPal; + Palette &pal = _screen->getPalette(0); + _screen->loadBitmap("PLAYFLD.CPS", 3, 3, &pal); - memset(_screen->getPalette(1), 0, 0x300); - memset(_screen->getPalette(2), 0, 0x300); + _screen->copyPalette(1, 0); + pal.fill(0, 1, 0x3F); + pal.fill(2, 126, 0x3F); + pal.fill(192, 4, 0x3F); + _screen->generateOverlay(pal, _screen->_paletteOverlay1, 1, 96); + _screen->generateOverlay(pal, _screen->_paletteOverlay2, 144, 65); + _screen->copyPalette(0, 1); + + _screen->getPalette(1).clear(); + _screen->getPalette(2).clear(); loadItemIconShapes(); _screen->setMouseCursor(0, 0, _itemIconShapes[0x85]); @@ -759,13 +803,6 @@ void LoLEngine::startup() { for (int i = 0; i < _numItemShapes; i++) _itemShapes[i] = _screen->makeShapeCopy(shp, i); - _screen->loadBitmap("GAMESHP.SHP", 3, 3, 0); - shp = _screen->getCPagePtr(3); - _numGameShapes = READ_LE_UINT16(shp); - _gameShapes = new uint8*[_numGameShapes]; - for (int i = 0; i < _numGameShapes; i++) - _gameShapes[i] = _screen->makeShapeCopy(shp, i); - _screen->loadBitmap("THROWN.SHP", 3, 3, 0); shp = _screen->getCPagePtr(3); _numThrownShapes = READ_LE_UINT16(shp); @@ -813,9 +850,6 @@ void LoLEngine::startup() { _loadSuppFilesFlag = 1; - _txt->setAnimParameters("<MORE>", 10, 31, 0); - _txt->setAnimFlag(true); - _sound->loadSfxFile("LORESFX"); setMouseCursorToItemInHand(); @@ -827,12 +861,6 @@ void LoLEngine::startupNew() { _compassDirection = _compassDirectionIndex = -1; _lastMouseRegion = -1; - - /* - _unk5 = 1; - _unk6 = 1; - _unk7 = 1 - _unk8 = 1*/ _currentLevel = 1; giveCredits(41, 0); @@ -860,9 +888,15 @@ void LoLEngine::runLoop() { enableSysTimer(2); bool _runFlag = true; - _gameFlags[36] |= 0x800; + _flagsTable[73] |= 0x08; while (!shouldQuit() && _runFlag) { + if (_gameToLoad != -1) { + if (loadGameState(_gameToLoad) != Common::kNoError) + error("Couldn't load game slot %d", _gameToLoad); + _gameToLoad = -1; + } + if (_nextScriptFunc) { runLevelScript(_nextScriptFunc, 2); _nextScriptFunc = 0; @@ -870,7 +904,7 @@ void LoLEngine::runLoop() { _timer->update(); - //checkFloatingPointerRegions(); + checkFloatingPointerRegions(); gui_updateInput(); update(); @@ -880,25 +914,74 @@ void LoLEngine::runLoop() { else updateEnvironmentalSfx(0); - if (_partyDeathFlag != -1) { + if (_partyDamageFlags != -1) { checkForPartyDeath(); - _partyDeathFlag = -1; + _partyDamageFlags = -1; } delay(_tickLength); } } +void LoLEngine::registerDefaultSettings() { + KyraEngine_v1::registerDefaultSettings(); + + // Most settings already have sensible defaults. This one, however, is + // specific to the LoL engine. + ConfMan.registerDefault("floating_cursors", false); + ConfMan.registerDefault("smooth_scrolling", true); + ConfMan.registerDefault("monster_difficulty", 1); +} + +void LoLEngine::writeSettings() { + ConfMan.setInt("monster_difficulty", _monsterDifficulty); + ConfMan.setBool("floating_cursors", _floatingCursorsEnabled); + ConfMan.setBool("smooth_scrolling", _smoothScrollingEnabled); + + switch (_lang) { + case 1: + _flags.lang = Common::FR_FRA; + break; + + case 2: + _flags.lang = Common::DE_DEU; + break; + + case 3: + _flags.lang = Common::JA_JPN; + break; + + case 0: + default: + _flags.lang = Common::EN_ANY; + } + + if (_flags.lang == _flags.replacedLang && _flags.fanLang != Common::UNK_LANG) + _flags.lang = _flags.fanLang; + + ConfMan.set("language", Common::getLanguageCode(_flags.lang)); + + KyraEngine_v1::writeSettings(); +} + +void LoLEngine::readSettings() { + _monsterDifficulty = ConfMan.getInt("monster_difficulty"); + _smoothScrollingEnabled = ConfMan.getBool("smooth_scrolling"); + _floatingCursorsEnabled = ConfMan.getBool("floating_cursors"); + + KyraEngine_v1::readSettings(); +} + void LoLEngine::update() { updateSequenceBackgroundAnimations(); if (_updateCharNum != -1 && _system->getMillis() > _updatePortraitNext) updatePortraitSpeechAnim(); - if (_gameFlags[15] & 0x800 || !(_updateFlags & 4)) + if (_flagsTable[31] & 0x08 || !(_updateFlags & 4)) updateLampStatus(); - if (_gameFlags[15] & 0x4000 && !(_updateFlags & 4) && (_compassDirection == -1 || (_currentDirection << 6) != _compassDirection || _compassStep)) + if (_flagsTable[31] & 0x40 && !(_updateFlags & 4) && (_compassDirection == -1 || (_currentDirection << 6) != _compassDirection || _compassStep)) updateCompass(); snd_updateCharacterSpeech(); @@ -1100,7 +1183,7 @@ void LoLEngine::updatePortraitSpeechAnim() { f -= 5; f += 7; - if (_speechFlag) { + if (speechEnabled()) { if (snd_updateCharacterSpeech() == 2) _updatePortraitSpeechAnimDuration = 2; else @@ -1238,7 +1321,7 @@ void LoLEngine::setCharacterMagicOrHitPoints(int charNum, int type, int points, if (charNum > 3) return; - + LoLCharacter *c = &_characters[charNum]; if (!(c->flags & 1)) return; @@ -1426,7 +1509,7 @@ void LoLEngine::gui_specialSceneSuspendControls(int controlMode) { _specialSceneFlag = 1; _currentControlMode = controlMode; calcCharPortraitXpos(); - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { @@ -1436,7 +1519,7 @@ void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { } _updateFlags &= 0xfffe; _specialSceneFlag = 0; - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { @@ -1455,7 +1538,7 @@ void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; } @@ -1589,17 +1672,18 @@ void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, in } } -void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifier) { - generateBrightnessPalette(palette, _screen->getPalette(1), brightness, modifier); +void LoLEngine::setPaletteBrightness(const Palette &srcPal, int brightness, int modifier) { + generateBrightnessPalette(srcPal, _screen->getPalette(1), brightness, modifier); _screen->fadePalette(_screen->getPalette(1), 5, 0); _screen->_fadeFlag = 0; } -void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier) { - memcpy(dst, src, 0x300); +void LoLEngine::generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier) { + dst.copy(src); _screen->loadSpecialColors(dst); + brightness = (8 - brightness) << 5; - if (modifier >= 0 && modifier < 8 && _gameFlags[15] & 0x800) { + if (modifier >= 0 && modifier < 8 && (_flagsTable[31] & 0x08)) { brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8); if (brightness < 0) brightness = 0; @@ -1611,26 +1695,21 @@ void LoLEngine::generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness } } -void LoLEngine::generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags) { - if (!src || !dst) - return; - - memcpy(dst, src, 6); - - uint8 *s = src + 6; - uint8 *d = dst + 6; +void LoLEngine::generateFlashPalette(const Palette &src, Palette &dst, int colorFlags) { + dst.copy(src, 0, 2); for (int i = 2; i < 128; i++) { for (int ii = 0; ii < 3; ii++) { - uint8 t = *s++ & 0x3f; + uint8 t = src[i * 3 + ii] & 0x3f; if (colorFlags & (1 << ii)) t += ((0x3f - t) >> 1); else t -= (t >> 1); - *d++ = t; + dst[i * 3 + ii] = t; } } - memcpy(d, s, 384); + + dst.copy(src, 128); } void LoLEngine::updateSequenceBackgroundAnimations() { @@ -1795,32 +1874,6 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) { } } -uint8 LoLEngine::getRandomNumberSpecial() { - uint8 a = _rndSpecial & 0xff; - uint8 b = (_rndSpecial >> 8) & 0xff; - uint8 c = (_rndSpecial >> 16) & 0xff; - - a >>= 1; - - uint as = a & 1; - uint bs = (b >> 7) ? 0 : 1; - uint cs = c >> 7; - - a >>= 1; - c = (c << 1) | as; - b = (b << 1) | cs; - - a -= ((_rndSpecial & 0xff) - bs); - as = a & 1; - a >>= 1; - - a = ((_rndSpecial & 0xff) >> 1) | (as << 7); - - _rndSpecial = (_rndSpecial & 0xff000000) | (c << 16) | (b << 8) | a; - - return a ^ b; -} - void LoLEngine::updateEnvironmentalSfx(int soundId) { snd_processEnvironmentalSoundEffect(soundId, _currentBlock); } @@ -1924,7 +1977,7 @@ int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) { } int LoLEngine::processMagicSpark(int charNum, int spellLevel) { - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); _screen->copyPage(0, 12); mov->open("spark1.wsa", 0, 0); @@ -2125,25 +2178,24 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { gui_drawScene(0); _screen->copyPage(0, 12); - uint8 *tpal = new uint8[768]; - uint8 *swampCol = new uint8[768]; + Palette tpal(768), swampCol(768); - if (_currentLevel == 11 && !(_gameFlags[26] & 4)) { - uint8 *sc = _screen->_currentPalette; - uint8 *dc = _screen->getPalette(2); + if (_currentLevel == 11 && !(_flagsTable[52] & 0x04)) { + uint8 *sc = _screen->getPalette(0).getData(); + uint8 *dc = _screen->getPalette(2).getData(); for (int i = 1; i < 768; i++) SWAP(sc[i], dc[i]); - _gameFlags[26] |= 4; + + _flagsTable[52] |= 0x04; static const uint8 freezeTimes[] = { 20, 28, 40, 60 }; setCharacterUpdateEvent(charNum, 8, freezeTimes[spellLevel], 1); } - uint8 *sc = _res->fileData("swampice.col", 0); - memcpy(swampCol, sc, 384); - uint8 *s = _screen->getPalette(1); - for (int i = 384; i < 768; i++) - swampCol[i] = tpal[i] = s[i] & 0x3f; + _screen->loadPalette("SWAMPICE.COL", swampCol); + tpal.copy(_screen->getPalette(1), 128); + swampCol.copy(_screen->getPalette(1), 128); + Palette &s = _screen->getPalette(1); for (int i = 1; i < 128; i++) { tpal[i * 3] = 0; uint16 v = (s[i * 3] + s[i * 3 + 1] + s[i * 3 + 2]) / 3; @@ -2153,24 +2205,25 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { if (tpal[i * 3 + 2] > 0x3f) tpal[i * 3 + 2] = 0x3f; } + generateBrightnessPalette(tpal, tpal, _brightness, _lampEffect); generateBrightnessPalette(swampCol, swampCol, _brightness, _lampEffect); swampCol[0] = swampCol[1] = swampCol[2] = tpal[0] = tpal[1] = tpal[2] = 0; - generateBrightnessPalette(_screen->_currentPalette, s, _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), s, _brightness, _lampEffect); int sX = 112; int sY = 0; - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); if (spellLevel == 0) { sX = 0; } if (spellLevel == 1 || spellLevel == 2) { - mov->open("snow.wsa", 1, 0); + mov->open("SNOW.WSA", 1, 0); if (!mov->opened()) error("Ice: Unable to load snow.wsa"); } if (spellLevel == 3) { - mov->open("ice.wsa", 1, 0); + mov->open("ICE.WSA", 1, 0); if (!mov->opened()) error("Ice: Unable to load ice.wsa"); sX = 136; @@ -2179,9 +2232,9 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { snd_playSoundEffect(71, -1); - playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, tpal, 40, false); + playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s.getData(), tpal.getData(), 40, false); - _screen->fadePaletteStep(s, tpal, _system->getMillis(), _tickLength); + _screen->fadePaletteStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); if (mov->opened()) { int r = true; if (spellLevel > 2) { @@ -2246,22 +2299,19 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { enableSysTimer(2); if (_currentLevel != 11) - generateBrightnessPalette(_screen->_currentPalette, swampCol, _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), swampCol, _brightness, _lampEffect); - playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal, swampCol, 40, 0); + playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal.getData(), swampCol.getData(), 40, 0); - _screen->fadePaletteStep(tpal, swampCol, _system->getMillis(), _tickLength); + _screen->fadePaletteStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); if (breakWall) - breakIceWall(tpal, swampCol); + breakIceWall(tpal.getData(), swampCol.getData()); static const uint8 freezeTime[] = { 20, 28, 40, 60 }; if (_currentLevel == 11) setCharacterUpdateEvent(charNum, 8, freezeTime[spellLevel], 1); - delete[] sc; - delete[] swampCol; - delete[] tpal; _screen->setCurPage(cp); return 1; } @@ -2422,7 +2472,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { int cp = _screen->setCurPage(2); _screen->copyPage(0, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("hand.wsa", 1, 0); if (!mov->opened()) error("Hand: Unable to load HAND.WSA"); @@ -2500,8 +2550,8 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { static const uint8 mistDamage[] = { 30, 70, 110, 200 }; - - _envSfxUseQueue = true; + + _envSfxUseQueue = true; inflictMagicalDamageForBlock(calcNewBlockPosition(_currentBlock, _currentDirection), charNum, mistDamage[spellLevel], 0x80); _envSfxUseQueue = false; @@ -2514,7 +2564,7 @@ int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { char wsafile[13]; snprintf(wsafile, 13, "mists%0d.wsa", spellLevel + 1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open(wsafile, 1, 0); if (!mov->opened()) error("Mist: Unable to load mists.wsa"); @@ -2546,7 +2596,7 @@ int LoLEngine::processMagicLightning(int charNum, int spellLevel) { char wsafile[13]; snprintf(wsafile, 13, "litning%d.wsa", spellLevel + 1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open(wsafile, 1, 0); if (!mov->opened()) error("Litning: Unable to load litning.wsa"); @@ -2575,7 +2625,7 @@ int LoLEngine::processMagicFog() { int cp = _screen->setCurPage(2); _screen->copyPage(0, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("fog.wsa", 0, 0); if (!mov->opened()) error("Fog: Unable to load fog.wsa"); @@ -2651,7 +2701,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { _monsters[destIds[i]].fightCurTick = destTicks[i]; } - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("swarm.wsa", 0, 0); if (!mov->opened()) @@ -2676,7 +2726,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { int LoLEngine::processMagicVaelansCube() { uint8 *tmpPal1 = new uint8[768]; uint8 *tmpPal2 = new uint8[768]; - uint8 *sp1 = _screen->getPalette(1); + uint8 *sp1 = _screen->getPalette(1).getData(); memcpy(tmpPal1, sp1, 768); memcpy(tmpPal2, sp1, 768); @@ -2713,11 +2763,11 @@ int LoLEngine::processMagicVaelansCube() { uint16 o = _levelBlockProperties[bl].assignedObjects; while (o & 0x8000) { MonsterInPlay *m = &_monsters[o & 0x7fff]; - o = m->nextAssignedObject; if (m->properties->flags & 0x1000) { inflictDamage(o, 100, 0xffff, 0, 0x80); v = 1; } + o = m->nextAssignedObject; } ctime = _system->getMillis(); @@ -2739,7 +2789,7 @@ int LoLEngine::processMagicGuardian(int charNum) { _screen->copyPage(0, 2); _screen->copyPage(2, 12); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("guardian.wsa", 0, 0); if (!mov->opened()) error("Guardian: Unable to load guardian.wsa"); @@ -2747,7 +2797,7 @@ int LoLEngine::processMagicGuardian(int charNum) { playSpellAnimation(mov, 0, 37, 2, 112, 0, 0, 0, 0, 0, false); _screen->copyPage(2, 12); - + uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection); int res = (_levelBlockProperties[bl].assignedObjects & 0x8000) ? 1 : 0; inflictMagicalDamageForBlock(bl, charNum, 200, 0x80); @@ -2759,7 +2809,7 @@ int LoLEngine::processMagicGuardian(int charNum) { _screen->copyPage(2, 12); snd_playSoundEffect(176, -1); playSpellAnimation(mov, 38, 48, 8, 112, 0, 0, 0, 0, 0, false); - + mov->close(); delete mov; @@ -2776,20 +2826,22 @@ void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) { } void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) { - uint8 *tpal = new uint8[768]; if (_lightningDiv == 2) shakeScene(1, 2, 3, 0); - uint8 *p1 = _screen->getPalette(1); + const Palette &p1 = _screen->getPalette(1); if (_lightningSfxFrame % _lightningDiv) { _screen->setScreenPalette(p1); } else { - memcpy(tpal, p1, 768); + Palette tpal(p1.getNumColors()); + tpal.copy(p1); + for (int i = 6; i < 384; i++) { uint16 v = (tpal[i] * 120) / 64; tpal[i] = (v < 64) ? v : 63; } + _screen->setScreenPalette(tpal); } @@ -2804,7 +2856,55 @@ void LoLEngine::callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y) { } _lightningSfxFrame++; - delete[] tpal; +} + +void LoLEngine::drinkBezelCup(int numUses, int charNum) { + int cp = _screen->setCurPage(2); + snd_playSoundEffect(73, -1); + + WSAMovie_v2 *mov = new WSAMovie_v2(this); + mov->open("bezel.wsa", 0, 0); + if (!mov->opened()) + error("Bezel: Unable to load bezel.wsa"); + + int x = _activeCharsXpos[charNum] - 11; + int y = 124; + int w = mov->width(); + int h = mov->height(); + + _screen->copyRegion(x, y, 0, 0, w, h, 0, 2, Screen::CR_NO_P_CHECK); + + static const uint8 bezelAnimData[] = { 0, 26, 20, 27, 61, 55, 62, 92, 86, 93, 131, 125 }; + int frm = bezelAnimData[numUses * 3]; + int hpDiff = _characters[charNum].hitPointsMax - _characters[charNum].hitPointsCur; + uint16 step = 0; + + do { + step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 2]); + increaseCharacterHitpoints(charNum, step / 256, true); + gui_drawCharPortraitWithStats(charNum); + + uint32 etime = _system->getMillis() + 4 * _tickLength; + + _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK); + mov->displayFrame(frm, 2, x, y, 0x5000, _trueLightTable1, _trueLightTable2); + _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + delayUntil(etime); + } while (++frm < bezelAnimData[numUses * 3 + 1]); + + _characters[charNum].hitPointsCur = _characters[charNum].hitPointsMax; + _screen->copyRegion(0, 0, x, y, w, h, 2, 2, Screen::CR_NO_P_CHECK); + removeCharacterEffects(&_characters[charNum], 4, 4); + gui_drawCharPortraitWithStats(charNum); + _screen->copyRegion(x, y, x, y, w, h, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + mov->close(); + delete mov; + + _screen->setCurPage(cp); } void LoLEngine::addSpellToScroll(int spell, int charNum) { @@ -2876,7 +2976,7 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); snd_playSoundEffect(95, -1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); mov->open("getspell.wsa", 0, 0); if (!mov->opened()) @@ -3079,14 +3179,14 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { sk = 100 - _monsters[target & 0x7fff].properties->skillLevel; } else { hitChanceModifier = _characters[attacker].defaultModifiers[0]; - uint8 m = _characters[attacker].skillModifiers[skill]; + int8 m = _characters[attacker].skillModifiers[skill]; if (skill == 1) m *= 3; sk = 100 - (_characters[attacker].skillLevels[skill] + m); } if (target & 0x8000) { - evadeChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[3]; + evadeChanceModifier = (_monsterModifiers[9 + _monsterDifficulty] * _monsters[target & 0x7fff].properties->fightingStats[3]) >> 8; _monsters[target & 0x7fff].flags |= 0x10; } else { evadeChanceModifier = _characters[target].defaultModifiers[3]; @@ -3096,7 +3196,7 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { if (r >= sk) return 2; - uint16 v = ((_monsterModifiers[9 + _monsterDifficulty] * evadeChanceModifier) & 0xffffff00) / hitChanceModifier; + uint16 v = (evadeChanceModifier << 8) / hitChanceModifier; if (r < v) return 0; @@ -3117,7 +3217,7 @@ int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType) return res; } -int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int deathFlag) { +int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int flags) { MonsterInPlay *m = 0; LoLCharacter *c = 0; @@ -3137,7 +3237,7 @@ int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int ski m->hitPoints = CLIP<int16>(m->hitPoints, 0, m->properties->hitPoints); if (!(attacker & 0x8000)) - applyMonsterDefenseSkill(m, attacker, deathFlag, skill, damage); + applyMonsterDefenseSkill(m, attacker, flags, skill, damage); snd_queueEnvironmentalSoundEffect(m->properties->sounds[2], m->block); checkSceneUpdateNeed(m->block); @@ -3177,13 +3277,13 @@ int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int ski setTemporaryFaceFrame(target, 6, 4, 0); // check for equipped cloud ring - if (deathFlag == 4 && itemEquipped(target, 229)) + if (flags == 4 && itemEquipped(target, 229)) damage >>= 2; setCharacterMagicOrHitPoints(target, 0, -damage, 1); if (c->hitPointsCur <= 0) { - characterHitpointsZero(target, deathFlag); + characterHitpointsZero(target, flags); } else { _characters[target].damageSuffered = damage; setCharacterUpdateEvent(target, 2, 4, 1); @@ -3200,12 +3300,12 @@ int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int ski return damage; } -void LoLEngine::characterHitpointsZero(int16 charNum, int deathFlag) { +void LoLEngine::characterHitpointsZero(int16 charNum, int flags) { LoLCharacter *c = &_characters[charNum]; c->hitPointsCur = 0; c->flags |= 8; removeCharacterEffects(c, 1, 5); - _partyDeathFlag = deathFlag; + _partyDamageFlags = flags; } void LoLEngine::removeCharacterEffects(LoLCharacter *c, int first, int last) { @@ -3287,6 +3387,52 @@ int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 } void LoLEngine::checkForPartyDeath() { + Button b; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; + + for (int i = 0; i < 4; i++) { + if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0) + continue; + return; + } + + if (_weaponsDisabled) + clickedExitCharInventory(&b); + + gui_drawAllCharPortraitsWithStats(); + + if (_partyDamageFlags & 0x40) { + _screen->fadeToBlack(40); + for (int i = 0; i < 4; i++) { + if (_characters[i].flags & 1) + increaseCharacterHitpoints(i, 1, true); + } + gui_drawAllCharPortraitsWithStats(); + _screen->fadeToPalette1(40); + + } else { + _screen->fadeClearSceneWindow(10); + restoreAfterSpecialScene(0, 1, 1, 0); + + snd_playTrack(325); + updatePortraits(); + initTextFading(0, 1); + setMouseCursorToIcon(0); + _updateFlags |= 4; + setLampMode(true); + disableSysTimer(2); + + _gui->runMenu(_gui->_deathMenu); + + setMouseCursorToItemInHand(); + _updateFlags &= 0xfffb; + resetLampStatus(); + + gui_enableDefaultPlayfieldButtons(); + enableSysTimer(2); + updateDrawPage2(); + } } void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) { @@ -3359,7 +3505,7 @@ void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, in } } -void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage) { +void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int flags, int skill, int damage) { if (_rnd.getRandomNumberRng(1, 100) > monster->properties->defenseSkillChance) return; @@ -3368,32 +3514,33 @@ void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, switch (monster->properties->defenseSkillType - 1) { case 0: case 1: - if ((deathFlag & 0x3f) == 2 || skill) + if ((flags & 0x3f) == 2 || skill) return; for (int i = 0; i < 3 ; i++) { itm = _characters[attacker].items[i]; if (!itm) continue; - if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3f) != deathFlag) + if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3f) != flags) continue; removeCharacterItem(attacker, 0x7fff); if (monster->properties->defenseSkillType == 1) { - deleteItem(itm); - if (characterSays(0x401d, _characters[attacker].id, true)) - _txt->printMessage(6, getLangString(0x401d)); - } else { giveItemToMonster(monster, itm); if (characterSays(0x401c, _characters[attacker].id, true)) _txt->printMessage(6, getLangString(0x401c)); + + } else { + deleteItem(itm); + if (characterSays(0x401d, _characters[attacker].id, true)) + _txt->printMessage(6, getLangString(0x401d)); } } break; case 2: - if (!(deathFlag & 0x80)) + if (!(flags & 0x80)) return; monster->flags |= 8; monster->direction = calcMonsterDirection(monster->x, monster->y, _partyPosX, _partyPosY) ^ 4; @@ -3402,7 +3549,7 @@ void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, break; case 3: - if (deathFlag != 3) + if (flags != 3) return; monster->hitPoints += damage; if (monster->hitPoints > monster->properties->hitPoints) @@ -3410,7 +3557,7 @@ void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, break; case 4: - if (!(deathFlag & 0x80)) + if (!(flags & 0x80)) return; monster->hitPoints += damage; if (monster->hitPoints > monster->properties->hitPoints) @@ -3418,7 +3565,7 @@ void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, break; case 5: - if ((deathFlag & 0x84) == 0x84) + if ((flags & 0x84) == 0x84) monster->numDistAttacks++; break; @@ -3499,20 +3646,20 @@ void LoLEngine::stunCharacter(int charNum) { } void LoLEngine::restoreSwampPalette() { - _gameFlags[26] &= 0xfffb; + _flagsTable[52] &= 0xFB; if (_currentLevel != 11) return; - uint8 *s = _screen->getPalette(2); - uint8 *d = _screen->_currentPalette; - uint8 *d2 = _screen->getPalette(1); + uint8 *s = _screen->getPalette(2).getData(); + uint8 *d = _screen->getPalette(0).getData(); + uint8 *d2 = _screen->getPalette(1).getData(); for (int i = 1; i < 768; i++) SWAP(s[i], d[i]); - generateBrightnessPalette(d, d2, _brightness, _lampEffect); - _screen->loadSpecialColors(s); - _screen->loadSpecialColors(d2); + generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect); + _screen->loadSpecialColors(_screen->getPalette(2)); + _screen->loadSpecialColors(_screen->getPalette(1)); playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s, d2, 40, 0); } @@ -3533,7 +3680,7 @@ void LoLEngine::launchMagicViper() { _screen->copyPage(0, 12); snd_playSoundEffect(148, -1); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("viper.wsa", 1, 0); if (!mov->opened()) error("Viper: Unable to load viper.wsa"); @@ -3583,7 +3730,7 @@ void LoLEngine::breakIceWall(uint8 *pal1, uint8 *pal2) { gui_drawScene(2); _screen->copyPage(2, 10); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); int numFrames = mov->open("shatter.wsa", 1, 0); if (!mov->opened()) error("Shatter: Unable to load shatter.wsa"); @@ -3685,7 +3832,7 @@ void LoLEngine::displayAutomap() { uint8 *tmpWll = new uint8[80]; memcpy(tmpWll, _wllBuffer4, 80); - _screen->loadBitmap("parch.cps", 2, 2, _screen->getPalette(3)); + _screen->loadBitmap("parch.cps", 2, 2, &_screen->getPalette(3)); _screen->loadBitmap("autobut.shp", 3, 5, 0); const uint8 *shp = _screen->getCPagePtr(5); @@ -3764,7 +3911,7 @@ void LoLEngine::displayAutomap() { } void LoLEngine::updateAutoMap(uint16 block) { - if (!(_gameFlags[15] & 0x1000)) + if (!(_flagsTable[31] & 0x10)) return; _levelBlockProperties[block].flags |= 7; @@ -3852,12 +3999,17 @@ void LoLEngine::loadMapLegendData(int level) { } void LoLEngine::drawMapPage(int pageNum) { + // WORKAROUND for French version. The Text does not always properly fit the screen there. + int8 textOffset = (_lang == 1) ? -2 : 0; + for (int i = 0; i < 2; i++) { - _screen->loadBitmap("parch.cps", pageNum, pageNum, _screen->getPalette(3)); + _screen->loadBitmap("parch.cps", pageNum, pageNum, &_screen->getPalette(3)); + if (_lang == 1) + _screen->copyRegion(236, 16, 236 + textOffset, 16, -textOffset, 1, pageNum, pageNum, Screen::CR_NO_P_CHECK); int cp = _screen->setCurPage(pageNum); Screen::FontId of = _screen->setFont(Screen::FID_9_FNT); - _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236, 8, 1, 0); + _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236 + textOffset, 8, 1, 0); uint16 blX = mapGetStartPosX(); uint16 bl = (mapGetStartPosY() << 5) + blX; @@ -3936,7 +4088,7 @@ void LoLEngine::drawMapPage(int pageNum) { if (l[2] == 0xffff) continue; - printMapText(l[2], 244, (tY << 3) + 22); + printMapText(l[2], 244 + textOffset, (tY << 3) + 22); if (l[5] == 0xffff) { tY++; @@ -3946,7 +4098,7 @@ void LoLEngine::drawMapPage(int pageNum) { uint16 cbl2 = l[3] + (l[4] << 5); _levelBlockProperties[cbl2].flags |= 7; _screen->drawShape(2, _automapShapes[l[5] << 2], (l[3] - sx) * 7 + _automapTopLeftX - 3, (l[4] - sy) * 6 + _automapTopLeftY - 3, 0, 0); - _screen->drawShape(2, _automapShapes[l[5] << 2], 231, (tY << 3) + 19, 0, 0); + _screen->drawShape(2, _automapShapes[l[5] << 2], 231 + textOffset, (tY << 3) + 19, 0, 0); tY++; } @@ -3955,9 +4107,9 @@ void LoLEngine::drawMapPage(int pageNum) { for (int ii = 0; ii < 11; ii++) { if (!_defaultLegendData[ii].enable) continue; - _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay); - _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0); - printMapText(_defaultLegendData[ii].stringId, 244, (tY << 3) + 22); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235 + textOffset, (tY << 3) + 21, 7, 6, 0, _mapOverlay); + _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232 + textOffset, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0); + printMapText(_defaultLegendData[ii].stringId, 244 + textOffset, (tY << 3) + 22); tY++; } diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index be734d083c..12000c31fa 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -307,6 +307,7 @@ public: Screen *screen(); GUI *gui() const; + private: Screen_LoL *_screen; GUI_LoL *_gui; @@ -326,6 +327,10 @@ private: void startup(); void startupNew(); + void registerDefaultSettings(); + void writeSettings(); + void readSettings(); + // options int _monsterDifficulty; bool _smoothScrollingEnabled; @@ -342,7 +347,9 @@ private: uint8 *getItemIconShapePtr(int index); bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2); - int _floatingMouseArrowControl; + void checkFloatingPointerRegions(); + int _floatingCursorControl; + int _currentFloatingCursor; // intro + character selection int processPrologue(); @@ -441,6 +448,9 @@ private: int _timer3Para; // sound + int convertVolumeToMixer(int value); + int convertVolumeFromMixer(int value); + void loadTalkFile(int index); void snd_playVoiceFile(int track) {} bool snd_playCharacterSpeech(int id, int8 speaker, int); @@ -473,7 +483,6 @@ private: Common::List<Audio::AudioStream*> _speechList; int _curTlkFile; - int _speechFlag; char **_ingameSoundList; int _ingameSoundListSize; @@ -627,7 +636,6 @@ private: uint16 _currentBlock; bool _sceneUpdateRequired; int16 _visibleBlockIndex[18]; - uint16 _gameFlags[40]; int16 _globalScriptVars[24]; // emc opcode @@ -714,6 +722,7 @@ private: int olol_getWallFlags(EMCState *script); int olol_changeMonsterStat(EMCState *script); int olol_getMonsterStat(EMCState *script); + int olol_releaseMonsterShapes(EMCState *script); int olol_playCharacterScriptChat(EMCState *script); int olol_playEnvironmentalSfx(EMCState *script); int olol_update(EMCState *script); @@ -724,6 +733,7 @@ private: int olol_countBlockItems(EMCState *script); int olol_characterSkillTest(EMCState *script); int olol_countAllMonsters(EMCState *script); + int olol_playEndSequence(EMCState *script); int olol_stopCharacterSpeech(EMCState *script); int olol_setPaletteBrightness(EMCState *script); int olol_calcInflictableDamage(EMCState *script); @@ -771,17 +781,19 @@ private: int olol_getNextActiveCharacter(EMCState *script); int olol_paralyzePoisonCharacter(EMCState *script); int olol_drawCharPortrait(EMCState *script); - int olol_removeInventoryItem(EMCState *script); + int olol_removeInventoryItem(EMCState *script); int olol_getAnimationLastPart(EMCState *script); int olol_assignSpecialGuiShape(EMCState *script); int olol_findInventoryItem(EMCState *script); int olol_restoreFadePalette(EMCState *script); + int olol_drinkBezelCup(EMCState *script); int olol_changeItemTypeOrFlag(EMCState *script); int olol_placeInventoryItemInHand(EMCState *script); int olol_castSpell(EMCState *script); int olol_pitDrop(EMCState *script); int olol_increaseSkill(EMCState *script); int olol_paletteFlash(EMCState *script); + int olol_restoreMagicShroud(EMCState *script); int olol_disableControls(EMCState *script); int olol_enableControls(EMCState *script); int olol_shakeScene(EMCState *script); @@ -860,9 +872,9 @@ private: void toggleSelectedCharacterFrame(bool mode); void fadeText(); void transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage); - void setPaletteBrightness(uint8 *palette, int brightness, int modifier); - void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier); - void generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags); + void setPaletteBrightness(const Palette &srcPal, int brightness, int modifier); + void generateBrightnessPalette(const Palette &src, Palette &dst, int brightness, int modifier); + void generateFlashPalette(const Palette &src, Palette &dst, int colorFlags); void updateSequenceBackgroundAnimations(); bool _dialogueField; @@ -903,7 +915,7 @@ private: void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode); void increaseExperience(int charNum, int skill, uint32 points); - void increaseCharacterHitpoints(int charNum, int points, bool unk); + void increaseCharacterHitpoints(int charNum, int points, bool ignoreDeath); LoLCharacter *_characters; uint16 _activeCharsXpos[3]; @@ -1301,7 +1313,6 @@ private: // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); - uint8 getRandomNumberSpecial(); uint8 _compassBroken; uint8 _drainMagic; @@ -1347,6 +1358,8 @@ private: void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y); void callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y); + void drinkBezelCup(int a, int charNum); + void addSpellToScroll(int spell, int charNum); void transferSpellToScollAnimation(int charNum, int spell, int slot); @@ -1393,14 +1406,14 @@ private: // fight int battleHitSkillTest(int16 attacker, int16 target, int skill); int calcInflictableDamage(int16 attacker, int16 target, int hitType); - int inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int deathFlag); + int inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int flags); void characterHitpointsZero(int16 charNum, int a); void removeCharacterEffects(LoLCharacter *c, int first, int last); int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType); void checkForPartyDeath(); void applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage); - void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage); + void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int flags, int skill, int damage); int removeCharacterItem(int charNum, int itemFlags); int paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw); void paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance); @@ -1417,7 +1430,7 @@ private: uint16 getNearestMonsterFromPos(int x, int y); uint16 getNearestPartyMemberFromPos(int x, int y); - int _partyDeathFlag; + int _partyDamageFlags; // magic atlas void displayAutomap(); @@ -1459,7 +1472,7 @@ private: Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail); void generateTempData(); - LevelTempData *_lvlTempData[28]; + LevelTempData *_lvlTempData[29]; }; } // end of namespace Kyra diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 7349cab9b5..ecd6bbe450 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -29,8 +29,9 @@ #include "graphics/thumbnail.h" #include "kyra/kyra_v1.h" +#include "kyra/util.h" -#define CURRENT_SAVE_VERSION 15 +#define CURRENT_SAVE_VERSION 16 #define GF_FLOPPY (1 << 0) #define GF_TALKIE (1 << 1) @@ -65,6 +66,8 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab in->read(descriptionBuffer, descriptionSize[i]); descriptionBuffer[descriptionSize[i]] = 0; + Util::convertDOSToISO(descriptionBuffer); + type = in->readUint32BE(); header.version = in->readUint16LE(); if (type == MKID_BE('MBL3') && header.version == 100) { diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp index 248c46c2a3..c72e2c46c0 100644 --- a/engines/kyra/saveload_lol.cpp +++ b/engines/kyra/saveload_lol.cpp @@ -119,15 +119,34 @@ Common::Error LoLEngine::loadGameState(int slot) { _inventoryCurItem = in.readSint16BE(); _itemInHand = in.readSint16BE(); _lastMouseRegion = in.readSint16BE(); - if (header.version == 14) { - for (int i = 0; i < 16; i++) - _gameFlags[i] = in.readUint16BE(); - _gameFlags[26] = in.readUint16BE(); - _gameFlags[36] = in.readUint16BE(); + + if (header.version <= 15) { + uint16 flags[40]; + memset(flags, 0, sizeof(flags)); + + if (header.version == 14) { + for (int i = 0; i < 16; i++) + flags[i] = in.readUint16BE(); + flags[26] = in.readUint16BE(); + flags[36] = in.readUint16BE(); + } else if (header.version == 15) { + for (int i = 0; i < 40; i++) + flags[i] = in.readUint16BE(); + } + + memset(_flagsTable, 0, sizeof(_flagsTable)); + for (uint i = 0; i < ARRAYSIZE(flags); ++i) { + for (uint k = 0; k < 16; ++k) { + if (flags[i] & (1 << k)) + setGameFlag(((i << 4) & 0xFFF0) | (k & 0x000F)); + } + } } else { - for (int i = 0; i < 40; i++) - _gameFlags[i] = in.readUint16BE(); + uint32 flagsSize = in.readUint32BE(); + assert(flagsSize <= sizeof(_flagsTable)); + in.read(_flagsTable, flagsSize); } + for (int i = 0; i < 24; i++) _globalScriptVars[i] = in.readUint16BE(); _brightness = in.readByte(); @@ -162,7 +181,7 @@ Common::Error LoLEngine::loadGameState(int slot) { l->direction = 5; } - for (int i = 0; i < 28; i++) { + for (int i = 0; i < 29; i++) { if (!(_hasTempDataFlags & (1 << i))) continue; @@ -245,7 +264,7 @@ Common::Error LoLEngine::loadGameState(int slot) { loadLevel(_currentLevel); gui_drawPlayField(); timerSpecialCharacterUpdate(0); - _gameFlags[36] |= 0x800; + _flagsTable[73] |= 0x08; while (!_screen->isMouseVisible()) _screen->showMouse(); @@ -323,8 +342,8 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra out->writeSint16BE(_inventoryCurItem); out->writeSint16BE(_itemInHand); out->writeSint16BE(_lastMouseRegion); - for (int i = 0; i < 40; i++) - out->writeUint16BE(_gameFlags[i]); + out->writeUint32BE(ARRAYSIZE(_flagsTable)); + out->write(_flagsTable, ARRAYSIZE(_flagsTable)); for (int i = 0; i < 24; i++) out->writeUint16BE(_globalScriptVars[i]); out->writeByte(_brightness); @@ -357,7 +376,7 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra addLevelItems(); - for (int i = 0; i < 28; i++) { + for (int i = 0; i < 29; i++) { LevelTempData *l = _lvlTempData[i]; if (!l || !(_hasTempDataFlags & (1 << i))) continue; diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index fed7877c0b..2d15af92fd 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -330,9 +330,6 @@ int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { updateCharacterAnim(0); refreshAnimObjectsIfNeed(); - if (!changedScene && !_unk4) { - //XXX - } return changedScene; } @@ -396,14 +393,14 @@ void KyraEngine_HoF::unloadScene() { void KyraEngine_HoF::loadScenePal() { uint16 sceneId = _mainCharacter.sceneId; - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); char filename[14]; strcpy(filename, _sceneList[sceneId].filename1); strcat(filename, ".COL"); _screen->loadBitmap(filename, 3, 3, 0); - memcpy(_screen->getPalette(1), _screen->getCPagePtr(3), 384); - memset(_screen->getPalette(1), 0, 3); + _screen->getPalette(1).copy(_screen->getCPagePtr(3), 0, 128); + _screen->getPalette(1).fill(0, 1, 0); memcpy(_scenePal, _screen->getCPagePtr(3)+336, 432); } @@ -669,7 +666,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) { } if (_noScriptEnter) { - memset(_screen->getPalette(0), 0, 384); + _screen->getPalette(0).fill(0, 128, 0); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -677,7 +674,7 @@ void KyraEngine_HoF::initSceneScreen(int unk1) { if (_noScriptEnter) { _screen->setScreenPalette(_screen->getPalette(1)); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 384); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); } updateCharPal(0); @@ -695,10 +692,7 @@ void KyraEngine_HoF::freeSceneShapePtrs() { } void KyraEngine_HoF::fadeScenePal(int srcIndex, int delayTime) { - uint8 *dst = _screen->getPalette(0) + 336; - const uint8 *src = _scenePal + (srcIndex << 4)*3; - memcpy(dst, src, 48); - + _screen->getPalette(0).copy(_scenePal, srcIndex << 4, 16, 112); _screen->fadePalette(_screen->getPalette(0), delayTime, &_updateFunctor); } diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp index 345998e40e..fc1ca41189 100644 --- a/engines/kyra/scene_lok.cpp +++ b/engines/kyra/scene_lok.cpp @@ -406,7 +406,7 @@ void KyraEngine_LoK::startSceneScript(int brandonAlive) { _screen->clearPage(3); _res->exists(fileNameBuffer, true); // FIXME: check this hack for amiga version - _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); + _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? &_screen->getPalette(0) : 0)); _sprites->loadSceneShapes(); _exitListPtr = 0; @@ -770,7 +770,7 @@ void KyraEngine_LoK::initSceneObjectList(int brandonAlive) { void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_flags.platform == Common::kPlatformAmiga) { if (_unkScreenVar1 && !queryGameFlag(0xF0)) { - memset(_screen->getPalette(2), 0, 32*3); + _screen->getPalette(2).clear(); if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) _screen->setScreenPalette(_screen->getPalette(2)); } @@ -782,10 +782,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_unkScreenVar1 && !queryGameFlag(0xA0)) { if (_currentCharacter->sceneId == 45 && _paletteChanged) - memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); + _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1); if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); + _screen->copyPalette(0, 10); _screen->setScreenPalette(_screen->getPalette(0)); } @@ -807,10 +807,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_unkScreenVar1 && _paletteChanged) { if (!queryGameFlag(0xA0)) { - memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); + _screen->getPalette(0).copy(_screen->getPalette(1), 228, 20); _screen->setScreenPalette(_screen->getPalette(0)); } else { - memset(_screen->getPalette(0), 0, 768); + _screen->getPalette(0).clear(); } } } diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index df4be0fa1a..945495517f 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -36,7 +36,7 @@ namespace Kyra { void LoLEngine::loadLevel(int index) { - _gameFlags[36] |= 0x800; + _flagsTable[73] |= 0x08; setMouseCursorToIcon(0x85); _nextScriptFunc = 0; @@ -86,7 +86,7 @@ void LoLEngine::loadLevel(int index) { addLevelItems(); deleteMonstersFromBlock(_currentBlock); - _screen->generateGrayOverlay(_screen->_currentPalette, _screen->_grayOverlay, 32, 16, 0, 0, 128, true); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->_grayOverlay, 32, 16, 0, 0, 128, true); _sceneDefaultUpdate = 0; if (_screen->_fadeFlag == 3) @@ -94,7 +94,7 @@ void LoLEngine::loadLevel(int index) { gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); setMouseCursorToItemInHand(); snd_playTrack(_curMusicTheme); @@ -379,28 +379,24 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight v += 128; if (_lastOverridePalFilePtr) { - uint8 *tpal = _res->fileData(_lastOverridePalFilePtr, 0); - memcpy(_screen->_currentPalette, tpal, 384); - delete[] tpal; + _res->loadFileToBuf(_lastOverridePalFilePtr, _screen->getPalette(0).getData(), 384); } else { - memcpy(_screen->_currentPalette, v, 384); + _screen->getPalette(0).copy(v, 0, 128); } v += 384; /*uint8 tmpPal = new uint8[384]; - memcpy(tmpPal, _screen->_currentPalette + 384, 384); - memset(_screen->_currentPalette + 384, 0xff, 384); - memcpy(_screen->_currentPalette + 384, tmpPal, 384);*/ + memcpy(tmpPal, _screen->getPalette(0) + 384, 384); + memset(_screen->getPalette(0) + 384, 0xff, 384); + memcpy(_screen->getPalette(0) + 384, tmpPal, 384);*/ if (_currentLevel == 11) { - uint8 *swampPal = _res->fileData("SWAMPICE.COL", 0); - memcpy(_screen->getPalette(2), swampPal, 384); - memcpy(_screen->getPalette(2) + 384, _screen->_currentPalette + 384, 384); - delete[] swampPal; - - if (_gameFlags[26] & 4) { - uint8 *pal0 = _screen->_currentPalette; - uint8 *pal2 = _screen->getPalette(2); + _screen->loadPalette("SWAMPICE.COL", _screen->getPalette(2)); + _screen->getPalette(2).copy(_screen->getPalette(0), 128); + + if (_flagsTable[52] & 0x04) { + uint8 *pal0 = _screen->getPalette(0).getData(); + uint8 *pal2 = _screen->getPalette(2).getData(); for (int i = 1; i < 768; i++) SWAP(pal0[i], pal2[i]); } @@ -427,7 +423,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight for (int i = 0; i < 7; i++) { weight = 100 - (i * _lastSpecialColorWeight); weight = (weight > 0) ? (weight * 255) / 100 : 0; - _screen->generateLevelOverlay(_screen->_currentPalette, _screen->getLevelOverlay(i), _lastSpecialColor, weight); + _screen->generateLevelOverlay(_screen->getPalette(0), _screen->getLevelOverlay(i), _lastSpecialColor, weight); for (int ii = 0; ii < 128; ii++) { if (_screen->getLevelOverlay(i)[ii] == 255) @@ -442,7 +438,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight _screen->getLevelOverlay(7)[i] = i & 0xff; _loadSuppFilesFlag = 0; - generateBrightnessPalette(_screen->_currentPalette, _screen->getPalette(1), _brightness, _lampEffect); + generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect); char tname[13]; snprintf(tname, sizeof(tname), "LEVEL%.02d.TLC", _currentLevel); @@ -524,14 +520,14 @@ bool LoLEngine::testWallInvisibility(int block, int direction) { } void LoLEngine::resetLampStatus() { - _gameFlags[15] |= 0x400; + _flagsTable[31] |= 0x04; _lampEffect = -1; updateLampStatus(); } void LoLEngine::setLampMode(bool lampOn) { - _gameFlags[15] &= 0xFBFF; - if (!(_gameFlags[15] & 0x800) || !lampOn) + _flagsTable[31] &= 0xFB; + if (!(_flagsTable[30] & 0x08) || !lampOn) return; _screen->drawShape(0, _gameShapes[43], 291, 56, 0, 0); @@ -542,20 +538,20 @@ void LoLEngine::updateLampStatus() { uint8 newLampEffect = 0; uint8 tmpOilStatus = 0; - if ((_updateFlags & 4) || !(_gameFlags[15] & 0x800)) + if ((_updateFlags & 4) || !(_flagsTable[31] & 0x08)) return; if (!_brightness || !_lampOilStatus) { newLampEffect = 8; if (newLampEffect != _lampEffect && _screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); } else { tmpOilStatus = (_lampOilStatus < 100) ? _lampOilStatus : 100; newLampEffect = (3 - ((tmpOilStatus - 1) / 25)) << 1; if (_lampEffect == -1) { if (_screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _brightness, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength; } else { if ((_lampEffect & 0xfe) == (newLampEffect & 0xfe)) { @@ -567,7 +563,7 @@ void LoLEngine::updateLampStatus() { } } else { if (_screen->_fadeFlag == 0) - setPaletteBrightness(_screen->_currentPalette, _lampEffect, newLampEffect); + setPaletteBrightness(_screen->getPalette(0), _lampEffect, newLampEffect); } } } @@ -584,7 +580,7 @@ void LoLEngine::updateLampStatus() { } void LoLEngine::updateCompass() { - if (!(_gameFlags[15] & 0x4000) || (_updateFlags & 4)) + if (!(_flagsTable[31] & 0x40) || (_updateFlags & 4)) return; if (_compassDirection == -1) { @@ -604,7 +600,7 @@ void LoLEngine::updateCompass() { if (_compassStep) _compassStep -= (((ABS(_compassStep) >> 4) + 2) * dir); - int16 d = _compassBroken ? ((int8)getRandomNumberSpecial() - _compassDirection) : (_currentDirection << 6) - _compassDirection; + int16 d = _compassBroken ? (int8(_rnd.getRandomNumber(255)) - _compassDirection) : (_currentDirection << 6) - _compassDirection; if (d <= -128) d += 256; if (d >= 128) @@ -651,12 +647,12 @@ void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int buttonShape) _sceneDefaultUpdate = 1; calcCoordinates(_partyPosX, _partyPosY, _currentBlock, 0x80, 0x80); - _gameFlags[36] &= 0xfdff; + _flagsTable[73] &= 0xFD; runLevelScript(opos, 4); runLevelScript(npos, 1); - if (!(_gameFlags[36] & 0x200)) { + if (!(_flagsTable[73] & 0x02)) { initTextFading(2, 0); if (_sceneDefaultUpdate) { @@ -1261,8 +1257,8 @@ void LoLEngine::shakeScene(int duration, int width, int height, int restore) { while (endTime > _system->getMillis()) { uint32 delayTimer = _system->getMillis() + 2 * _tickLength; - int s1 = width ? (getRandomNumberSpecial() % (width << 1)) - width : 0; - int s2 = height ? (getRandomNumberSpecial() % (height << 1)) - height : 0; + int s1 = width ? (_rnd.getRandomNumber(255) % (width << 1)) - width : 0; + int s2 = height ? (_rnd.getRandomNumber(255) % (height << 1)) - height : 0; int x1, y1, x2, y2, w, h; if (s1 >= 0) { @@ -1308,11 +1304,11 @@ void LoLEngine::processGasExplosion(int soundId) { uint16 targetBlock = 0; int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 3, targetBlock); - uint8 *p1 = _screen->getPalette(1); - uint8 *p2 = _screen->getPalette(3); + uint8 *p1 = _screen->getPalette(1).getData(); + uint8 *p2 = _screen->getPalette(3).getData(); if (dist) { - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *mov = new WSAMovie_v2(this); char file[13]; snprintf(file, 13, "gasexp%0d.wsa", dist); mov->open(file, 1, 0); @@ -1331,11 +1327,11 @@ void LoLEngine::processGasExplosion(int soundId) { p2[i * 3] = 0x3f; uint32 ctime = _system->getMillis(); - while (_screen->fadePaletteStep(_screen->_currentPalette, p2, _system->getMillis() - ctime, 10)) + while (_screen->fadePaletteStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) updateInput(); ctime = _system->getMillis(); - while (_screen->fadePaletteStep(p2, _screen->_currentPalette, _system->getMillis() - ctime, 50)) + while (_screen->fadePaletteStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) updateInput(); } @@ -1437,7 +1433,7 @@ void LoLEngine::prepareSpecialScene(int fieldType, int hasDialogue, int suspendG gui_disableControls(controlMode); if (fadeFlag) { - memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; @@ -1495,7 +1491,7 @@ int LoLEngine::restoreAfterSpecialScene(int fadeFlag, int redrawPlayField, int r if (redrawPlayField) gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); } else { _currentControlMode = 0; @@ -1517,6 +1513,7 @@ void LoLEngine::setSequenceButtons(int x, int y, int w, int h, int enableFlags) _seqWindowY2 = y + h; int offs = _itemInHand ? 10 : 0; _screen->setMouseCursor(offs, offs, getItemIconShapePtr(_itemInHand)); + _currentFloatingCursor = -1; if (w == 320) { setLampMode(0); _lampStatusSuspended = true; diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index 07a7aa0d07..a68dcfb394 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -48,10 +48,8 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 } musicUpdate(0); - if (!unk3) { - //XXX + if (!unk3) musicUpdate(0); - } if (unk1) { int x = _mainCharacter.x1; @@ -88,7 +86,7 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 newSoundFile = true; } - //XXX + _chatAltFlag = false; if (!unk3) { _emc->init(&_sceneScriptState, &_sceneScriptData); @@ -328,25 +326,23 @@ void KyraEngine_MR::freeSceneShapes() { void KyraEngine_MR::loadScenePal() { char filename[16]; - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); strcpy(filename, _sceneList[_mainCharacter.sceneId].filename1); strcat(filename, ".COL"); _screen->loadBitmap(filename, 3, 3, 0); - memcpy(_screen->getPalette(2), _screen->getCPagePtr(3), 432); - memset(_screen->getPalette(2), 0, 3); + _screen->getPalette(2).copy(_screen->getCPagePtr(3), 0, 144); + _screen->getPalette(2).fill(0, 1, 0); for (int i = 144; i <= 167; ++i) { - uint8 *palette = _screen->getPalette(2) + i * 3; + uint8 *palette = _screen->getPalette(2).getData() + i * 3; palette[0] = palette[2] = 63; palette[1] = 0; } _screen->generateOverlay(_screen->getPalette(2), _paletteOverlay, 0xF0, 0x19); - uint8 *palette = _screen->getPalette(2) + 432; - const uint8 *costPal = _costPalBuffer + _characterShapeFile * 72; - memcpy(palette, costPal, 24*3); + _screen->getPalette(2).copy(_costPalBuffer, _characterShapeFile * 24, 24, 144); } void KyraEngine_MR::loadSceneMsc() { @@ -609,7 +605,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) { } if (_noScriptEnter) { - memset(_screen->getPalette(0), 0, 432); + _screen->getPalette(0).fill(0, 144, 0); if (!_wasPlayingVQA) _screen->setScreenPalette(_screen->getPalette(0)); } @@ -619,7 +615,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) { if (_noScriptEnter) { if (!_wasPlayingVQA) _screen->setScreenPalette(_screen->getPalette(2)); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 432); + _screen->getPalette(0).copy(_screen->getPalette(2), 0, 144); if (_wasPlayingVQA) { _screen->fadeFromBlack(0x3C); _wasPlayingVQA = false; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 08b05a8da3..fa54bffa98 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -34,9 +34,15 @@ namespace Kyra { Screen::Screen(KyraEngine_v1 *vm, OSystem *system) - : _system(system), _vm(vm), _sjisInvisibleColor(0) { + : _system(system), _vm(vm), _sjisInvisibleColor(0), + _cursorColorKey((vm->gameFlags().gameID == GI_KYRA1) ? 0xFF : 0x00) { _debugEnabled = false; _maskMinY = _maskMaxY = -1; + + _drawShapeVar1 = 0; + _drawShapeVar3 = 1; + _drawShapeVar4 = 0; + _drawShapeVar5 = 0; } Screen::~Screen() { @@ -52,15 +58,13 @@ Screen::~Screen() { delete[] _sjisFontData; delete[] _sjisTempPage; - delete[] _currentPalette; - delete[] _screenPalette; + delete _screenPalette; + delete _internFadePalette; delete[] _decodeShapeBuffer; delete[] _animBlockPtr; - if (_vm->gameFlags().platform != Common::kPlatformAmiga) { - for (int i = 0; i < ARRAYSIZE(_palettes); ++i) - delete[] _palettes[i]; - } + for (uint i = 0; i < _palettes.size(); ++i) + delete _palettes[i]; CursorMan.popAllCursors(); } @@ -123,30 +127,38 @@ bool Screen::init() { memset(_shapePages, 0, sizeof(_shapePages)); - memset(_palettes, 0, sizeof(_palettes)); - _screenPalette = new uint8[768]; + const int paletteCount = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 12 : 4; + const int numColors = _use16ColorMode ? 16 : ((_vm->gameFlags().platform == Common::kPlatformAmiga) ? 32 : 256); + + _screenPalette = new Palette(numColors); assert(_screenPalette); - memset(_screenPalette, 0, 768); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) { - _currentPalette = new uint8[1248]; - assert(_currentPalette); - memset(_currentPalette, 0, 1248); + _palettes.resize(paletteCount); + for (int i = 0; i < paletteCount; ++i) { + _palettes[i] = new Palette(numColors); + assert(_palettes[i]); + } - for (int i = 0; i < 6; ++i) - _palettes[i] = _currentPalette + (i+1)*96; - } else { - _currentPalette = new uint8[768]; - assert(_currentPalette); - memset(_currentPalette, 0, 768); - for (int i = 0; i < 3; ++i) { - _palettes[i] = new uint8[768]; - assert(_palettes[i]); - memset(_palettes[i], 0, 768); + _internFadePalette = new Palette(numColors); + assert(_internFadePalette); + + setScreenPalette(getPalette(0)); + + // We setup the PC98 text mode palette at [16, 24], since that will be used + // for KANJI characters in Lands of Lore. + if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) { + uint8 palette[8 * 4]; + + for (int i = 0; i < 8; ++i) { + palette[i * 4 + 0] = ((i >> 1) & 1) * 0xFF; + palette[i * 4 + 1] = ((i >> 2) & 1) * 0xFF; + palette[i * 4 + 2] = ((i >> 0) & 1) * 0xFF; + palette[i * 4 + 3] = 0; + + _system->setPalette(palette, 16, 8); } } - setScreenPalette(_currentPalette); _curDim = 0; _charWidth = 0; _charOffset = 0; @@ -339,6 +351,148 @@ void Screen::clearCurPage() { clearOverlayPage(_curPage); } +void Screen::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { + uint8 *dstPtr = getPagePtr(_curPage); + uint8 *origDst = dstPtr; + + const ScreenDim *dim = getScreenDim(dimState); + int dimX1 = dim->sx << 3; + int dimX2 = dim->w << 3; + dimX2 += dimX1; + + int dimY1 = dim->sy; + int dimY2 = dim->h; + dimY2 += dimY1; + + int temp = y - dimY1; + if (temp < 0) { + if ((temp += h) <= 0) + return; + else { + SWAP(temp, h); + y += temp - h; + src += (temp - h) * w; + } + } + + temp = dimY2 - y; + if (temp <= 0) + return; + + if (temp < h) + h = temp; + + int srcOffset = 0; + temp = x - dimX1; + if (temp < 0) { + temp = -temp; + srcOffset = temp; + x += temp; + w -= temp; + } + + int srcAdd = 0; + + temp = dimX2 - x; + if (temp <= 0) + return; + + if (temp < w) { + SWAP(w, temp); + temp -= w; + srcAdd = temp; + } + + dstPtr += y * SCREEN_W + x; + uint8 *dst = dstPtr; + + if (_curPage == 0 || _curPage == 1) + addDirtyRect(x, y, w, h); + + clearOverlayRect(_curPage, x, y, w, h); + + temp = h; + int curY = y; + while (h--) { + src += srcOffset; + ++curY; + int cW = w; + + switch (plotFunc) { + case 0: + memcpy(dst, src, cW); + dst += cW; src += cW; + break; + + case 1: + while (cW--) { + uint8 d = *src++; + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst++ = d; + } + break; + + case 4: + while (cW--) { + uint8 d = *src++; + if (d) + *dst = d; + ++dst; + } + break; + + case 5: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst = d; + } + ++dst; + } + break; + + case 8: + case 9: + while (cW--) { + uint8 d = *src++; + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + break; + + case 12: + case 13: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } else { + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + } + break; + + default: + break; + } + + dst = (dstPtr += SCREEN_W); + src += srcAdd; + } +} + uint8 Screen::getPagePixel(int pageNum, int x, int y) { assert(pageNum < SCREEN_PAGE_NUM); assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H); @@ -354,26 +508,25 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) { } void Screen::fadeFromBlack(int delay, const UpdateFunctor *upFunc) { - fadePalette(_currentPalette, delay, upFunc); + fadePalette(getPalette(0), delay, upFunc); } void Screen::fadeToBlack(int delay, const UpdateFunctor *upFunc) { - uint8 blackPal[768]; - memset(blackPal, 0, 768); - fadePalette(blackPal, delay, upFunc); + Palette pal(getPalette(0).getNumColors()); + fadePalette(pal, delay, upFunc); } -void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc) { +void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) { updateScreen(); int diff = 0, delayInc = 0; - getFadeParams(palData, delay, delayInc, diff); + getFadeParams(pal, delay, delayInc, diff); int delayAcc = 0; while (!_vm->shouldQuit()) { delayAcc += delayInc; - int refreshed = fadePalStep(palData, diff); + int refreshed = fadePalStep(pal, diff); if (upFunc && upFunc->isValid()) (*upFunc)(); @@ -388,7 +541,7 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u } if (_vm->shouldQuit()) { - setScreenPalette(palData); + setScreenPalette(pal); if (upFunc && upFunc->isValid()) (*upFunc)(); else @@ -396,12 +549,11 @@ void Screen::fadePalette(const uint8 *palData, int delay, const UpdateFunctor *u } } -void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) { +void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { uint8 maxDiff = 0; - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3; - for (int i = 0; i < colors; ++i) { - diff = ABS(palette[i] - _screenPalette[i]); + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + diff = ABS(pal[i] - (*_screenPalette)[i]); maxDiff = MAX<uint8>(maxDiff, diff); } @@ -417,17 +569,14 @@ void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int & } } -int Screen::fadePalStep(const uint8 *palette, int diff) { - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3; - - uint8 fadePal[768]; - memcpy(fadePal, _screenPalette, colors); +int Screen::fadePalStep(const Palette &pal, int diff) { + _internFadePalette->copy(*_screenPalette); bool needRefresh = false; - for (int i = 0; i < colors; ++i) { - int c1 = palette[i]; - int c2 = fadePal[i]; + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + int c1 = pal[i]; + int c2 = (*_internFadePalette)[i]; if (c1 != c2) { needRefresh = true; if (c1 > c2) { @@ -442,26 +591,26 @@ int Screen::fadePalStep(const uint8 *palette, int diff) { c2 = c1; } - fadePal[i] = (uint8)c2; + (*_internFadePalette)[i] = (uint8)c2; } } if (needRefresh) - setScreenPalette(fadePal); + setScreenPalette(*_internFadePalette); return needRefresh ? 1 : 0; } void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { - _currentPalette[index * 3 + 0] = red; - _currentPalette[index * 3 + 1] = green; - _currentPalette[index * 3 + 2] = blue; - setScreenPalette(_currentPalette); + getPalette(0)[index * 3 + 0] = red; + getPalette(0)[index * 3 + 1] = green; + getPalette(0)[index * 3 + 2] = blue; + setScreenPalette(getPalette(0)); } void Screen::getRealPalette(int num, uint8 *dst) { const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); - const uint8 *palData = getPalette(num); + const uint8 *palData = getPalette(num).getData(); if (!palData) { memset(dst, 0, colors * 3); @@ -469,46 +618,26 @@ void Screen::getRealPalette(int num, uint8 *dst) { } for (int i = 0; i < colors; ++i) { - dst[0] = (palData[0] << 2) | (palData[0] & 3); - dst[1] = (palData[1] << 2) | (palData[1] & 3); - dst[2] = (palData[2] << 2) | (palData[2] & 3); + dst[0] = (palData[0] * 0xFF) / 0x3F; + dst[1] = (palData[1] * 0xFF) / 0x3F; + dst[2] = (palData[2] * 0xFF) / 0x3F; dst += 3; palData += 3; } } -void Screen::setScreenPalette(const uint8 *palData) { - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); - +void Screen::setScreenPalette(const Palette &pal) { uint8 screenPal[256 * 4]; - if (palData != _screenPalette) - memcpy(_screenPalette, palData, colors*3); + _screenPalette->copy(pal); - if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) { - for (int l = 0; l < 1024; l += 64) { - const uint8 *tp = palData; - for (int i = 0; i < 16; ++i) { - screenPal[l + 4 * i + 0] = palData[1]; - screenPal[l + 4 * i + 1] = palData[0]; - screenPal[l + 4 * i + 2] = palData[2]; - screenPal[l + 4 * i + 3] = 0; - palData += 3; - } - palData = tp; - } - } else { - if (palData != _screenPalette) - memcpy(_screenPalette, palData, colors*3); - for (int i = 0; i < colors; ++i) { - screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3); - screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3); - screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3); - screenPal[4 * i + 3] = 0; - palData += 3; - } + for (int i = 0; i < pal.getNumColors(); ++i) { + screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F; + screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F; + screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F; + screenPal[4 * i + 3] = 0; } - _system->setPalette(screenPal, 0, colors); + _system->setPalette(screenPal, 0, pal.getNumColors()); } void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { @@ -656,63 +785,6 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint } } -void Screen::copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src) { - if (x < 0) - x = 0; - else if (x >= 40) - return; - - if (x + w > 40) - w = 40 - x; - - if (y < 0) - y = 0; - else if (y >= 200) - return; - - if (y + h > 200) - h = 200 - y; - - uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x * 8; - - if (_curPage == 0 || _curPage == 1) - addDirtyRect(x*8, y, w*8, h); - - clearOverlayRect(_curPage, x*8, y, w*8, h); - - while (h--) { - memcpy(dst, src, w*8); - dst += SCREEN_W; - src += w*8; - } -} - -void Screen::copyCurPageBlock(int x, int y, int w, int h, uint8 *dst) { - assert(dst); - if (x < 0) - x = 0; - else if (x >= 40) - return; - - if (x + w > 40) - w = 40 - x; - - if (y < 0) - y = 0; - else if (y >= 200) - return; - - if (y + h > 200) - h = 200 - y; - - const uint8 *src = getPagePtr(_curPage) + y * SCREEN_W + x * 8; - while (h--) { - memcpy(dst, src, w*8); - dst += w*8; - src += SCREEN_W; - } -} - void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent) { assert(sx >= 0 && w <= SCREEN_W); int x; @@ -802,17 +874,26 @@ void Screen::drawBox(int x1, int y1, int x2, int y2, int color) { drawClippedLine(x1, y2, x2, y2, color); } -void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2) { +void Screen::drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType) { assert(x1 >= 0 && y1 >= 0); hideMouse(); fillRect(x1, y1, x2, y1 + 1, color1); - fillRect(x2 - 1, y1, x2, y2, color1); + if (shadeType == kShadeTypeLol) + fillRect(x1, y1, x1 + 1, y2, color1); + else + fillRect(x2 - 1, y1, x2, y2, color1); - drawClippedLine(x1, y1, x1, y2, color2); - drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2); + if (shadeType == kShadeTypeLol) { + drawClippedLine(x2, y1, x2, y2, color2); + drawClippedLine(x2 - 1, y1 + 1, x2 - 1, y2 - 1, color2); + drawClippedLine(x1 + 1, y2 - 1, x2, y2 - 1, color2); + } else { + drawClippedLine(x1, y1, x1, y2, color2); + drawClippedLine(x1 + 1, y1 + 1, x1 + 1, y2 - 1, color2); + drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2); + } drawClippedLine(x1, y2, x2, y2, color2); - drawClippedLine(x1, y2 - 1, x2 - 1, y2 - 1, color2); showMouse(); } @@ -909,11 +990,13 @@ bool Screen::loadFont(FontId fontId, const char *filename) { error("Invalid font data (file '%s', fontSig: %.04X)", filename, fontSig); fnt->charWidthTable = fontData + READ_LE_UINT16(fontData + 8); - fnt->charSizeOffset = READ_LE_UINT16(fontData + 4); + fnt->fontDescOffset = READ_LE_UINT16(fontData + 4); fnt->charBitmapOffset = READ_LE_UINT16(fontData + 6); fnt->charWidthTableOffset = READ_LE_UINT16(fontData + 8); fnt->charHeightTableOffset = READ_LE_UINT16(fontData + 0xC); + fnt->lastGlyph = *(fnt->fontData + fnt->fontDescOffset + 3); + return true; } @@ -927,23 +1010,30 @@ int Screen::getFontHeight() const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 4); + + return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 4); } int Screen::getFontWidth() const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].charSizeOffset + 5); + + return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 5); } int Screen::getCharWidth(uint16 c) const { // FIXME: add font support for amiga version if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; + if (c & 0xFF00) return SJIS_CHARSIZE >> 1; - return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth; + + if (_fonts[_currentFont].lastGlyph < c) + return 0; + else + return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth; } int Screen::getTextWidth(const char *str) const { @@ -986,8 +1076,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 cmap[1] = color1; setTextColor(cmap, 0, 1); - Font *fnt = &_fonts[_currentFont]; - const uint8 charHeightFnt = *(fnt->fontData + fnt->charSizeOffset + 4); + const uint8 charHeightFnt = getFontHeight(); uint8 charHeight = 0; if (x < 0) @@ -1037,6 +1126,10 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 void Screen::drawCharANSI(uint8 c, int x, int y) { Font *fnt = &_fonts[_currentFont]; + + if (c > fnt->lastGlyph) + return; + uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x; uint16 bitmapOffset = READ_LE_UINT16(fnt->fontData + fnt->charBitmapOffset + c * 2); @@ -1044,15 +1137,16 @@ void Screen::drawCharANSI(uint8 c, int x, int y) { return; uint8 charWidth = *(fnt->fontData + fnt->charWidthTableOffset + c); - if (charWidth + x > SCREEN_W) + if (!charWidth || charWidth + x > SCREEN_W) return; - uint8 charH0 = *(fnt->fontData + fnt->charSizeOffset + 4); - if (charH0 + y > SCREEN_H) + uint8 charH0 = getFontHeight(); + if (!charH0 || charH0 + y > SCREEN_H) return; uint8 charH1 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2); uint8 charH2 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2 + 1); + charH0 -= charH1 + charH2; const uint8 *src = fnt->fontData + bitmapOffset; @@ -1097,15 +1191,17 @@ void Screen::drawCharANSI(uint8 c, int x, int y) { } if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, charWidth, *(fnt->fontData + fnt->charSizeOffset + 4)); + addDirtyRect(x, y, charWidth, getFontHeight()); } void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { if (!shapeData) return; - int f = _vm->gameFlags().useAltShapeHeader ? 2 : 0; - if (shapeData[f] & 1) + if (_vm->gameFlags().useAltShapeHeader) + shapeData += 2; + + if (*shapeData & 1) flags |= 0x400; va_list args; @@ -1115,11 +1211,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int 1, 3, 2, 5, 4, 3, 2, 1 }; - _drawShapeVar1 = 0; - _drawShapeVar3 = 1; - _drawShapeVar4 = 0; - _drawShapeVar5 = 0; - _dsTable = 0; _dsTableLoopCount = 0; _dsTable2 = 0; @@ -1145,8 +1236,8 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } if (flags & 0x200) { - _drawShapeVar1 += 1; - _drawShapeVar1 &= 7; + ++_drawShapeVar1; + _drawShapeVar1 &= (_vm->gameFlags().gameID == GI_KYRA1) ? 0x7 : 0xF; _drawShapeVar3 = drawShapeVar2[_drawShapeVar1]; _drawShapeVar4 = 0; _drawShapeVar5 = 256; @@ -1237,12 +1328,12 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int scaleCounterV = 0; - f = flags & 0x0f; - _dsProcessMargin = dsMarginFunc[f]; - _dsScaleSkip = dsSkipFunc[f]; - _dsProcessLine = dsLineFunc[f]; + const int drawFunc = flags & 0x0f; + _dsProcessMargin = dsMarginFunc[drawFunc]; + _dsScaleSkip = dsSkipFunc[drawFunc]; + _dsProcessLine = dsLineFunc[drawFunc]; - int ppc = (flags >> 8) & 0x3F; + const int ppc = (flags >> 8) & 0x3F; _dsPlot = dsPlotFunc[ppc]; DsPlotFunc dsPlot2 = dsPlotFunc[ppc], dsPlot3 = dsPlotFunc[ppc]; if (flags & 0x800) @@ -1274,8 +1365,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int y2 = y1 + dsDim->h; - if (_vm->gameFlags().useAltShapeHeader) - src += 2; uint16 shapeFlags = READ_LE_UINT16(src); src += 2; int shapeHeight = *src++; @@ -1318,8 +1407,6 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int t = (flags & 2) ? y2 - y - shapeHeight : y - y1; - const uint8 *s = src; - if (t < 0) { shapeHeight += t; if (shapeHeight <= 0) { @@ -1328,23 +1415,29 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } t *= -1; - uint8 *tmp = dst; + const uint8 *srcBackUp = 0; do { _dsOffscreenScaleVal1 = 0; + srcBackUp = src; _dsTmpWidth = shapeWidth; + int cnt = shapeWidth; - (this->*_dsScaleSkip)(tmp, s, cnt); + (this->*_dsScaleSkip)(dst, src, cnt); + scaleCounterV += _dsScaleH; - if (!(scaleCounterV & 0xff00)) - continue; - uint8 r = scaleCounterV >> 8; - scaleCounterV &= 0xff; - t -= r; - } while (t > 0); - - if (t < 0) + + if (scaleCounterV & 0xFF00) { + uint8 r = scaleCounterV >> 8; + scaleCounterV &= 0xFF; + t -= r; + } + } while (!(scaleCounterV & 0xFF00) && (t > 0)); + + if (t < 0) { + src = srcBackUp; scaleCounterV += (-t << 8); + } if (!(flags & 2)) y = y1; @@ -1409,6 +1502,9 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int _dsOffscreenLeft /= _dsScaleW; } + if (shapeHeight <= 0 || shpWidthScaled1 <= 0) + return; + if (pageNum == 0 || pageNum == 1) addDirtyRect(x, y, shpWidthScaled1, shapeHeight); clearOverlayRect(pageNum, x, y, shpWidthScaled1, shapeHeight); @@ -1422,28 +1518,28 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int if (!(scaleCounterV & 0xFF00)) { _dsTmpWidth = shapeWidth; int cnt = shapeWidth; - (this->*_dsScaleSkip)(d, s, cnt); + (this->*_dsScaleSkip)(d, src, cnt); } } - const uint8 *b_src = s; + const uint8 *b_src = src; do { - s = b_src; + src = b_src; _dsTmpWidth = shapeWidth; int cnt = _dsOffscreenLeft; - int scaleState = (this->*_dsProcessMargin)(d, s, cnt); + int scaleState = (this->*_dsProcessMargin)(d, src, cnt); if (_dsTmpWidth) { cnt += shpWidthScaled1; if (cnt > 0) { if (flags & 0x800) normalPlot = (curY > _maskMinY && curY < _maskMaxY); _dsPlot = normalPlot ? dsPlot2 : dsPlot3; - (this->*_dsProcessLine)(d, s, cnt, scaleState); + (this->*_dsProcessLine)(d, src, cnt, scaleState); } cnt += _dsOffscreenRight; if (cnt) - (this->*_dsScaleSkip)(d, s, cnt); + (this->*_dsScaleSkip)(d, src, cnt); } dst += dsPitch; d = dst; @@ -2492,9 +2588,14 @@ void Screen::hideMouse() { } void Screen::showMouse() { - if (_mouseLockCount == 1) + if (_mouseLockCount == 1) { CursorMan.showMouse(true); + // We need to call OSystem::updateScreen here, else the mouse cursor + // will only be visible on mouse movment. + _system->updateScreen(); + } + if (_mouseLockCount > 0) _mouseLockCount--; } @@ -2531,12 +2632,11 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { y <<= 1; mouseWidth <<= 1; mouseHeight <<= 1; - fillRect(mouseWidth, 0, mouseWidth, mouseHeight, 0, 8); } uint8 *cursor = new uint8[mouseHeight * mouseWidth]; - fillRect(0, 0, mouseWidth, mouseHeight, 0, 8); + fillRect(0, 0, mouseWidth, mouseHeight, _cursorColorKey, 8); drawShape(8, shape, 0, 0, 0, 0); int xOffset = 0; @@ -2544,11 +2644,14 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { if (_vm->gameFlags().useHiResOverlay) { xOffset = mouseWidth; scale2x(getPagePtr(8) + mouseWidth, SCREEN_W, getPagePtr(8), SCREEN_W, mouseWidth, mouseHeight); + postProcessCursor(getPagePtr(8) + mouseWidth, mouseWidth, mouseHeight, SCREEN_W); + } else { + postProcessCursor(getPagePtr(8), mouseWidth, mouseHeight, SCREEN_W); } CursorMan.showMouse(false); copyRegionToBuffer(8, xOffset, 0, mouseWidth, mouseHeight, cursor); - CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, 0); + CursorMan.replaceCursor(cursor, mouseWidth, mouseHeight, x, y, _cursorColorKey); if (isMouseVisible()) CursorMan.showMouse(true); delete[] cursor; @@ -2560,37 +2663,13 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { _system->updateScreen(); } -void Screen::copyScreenFromRect(int x, int y, int w, int h, const uint8 *ptr) { - x <<= 3; w <<= 3; - const uint8 *src = ptr; - uint8 *dst = &_pagePtrs[0][y * SCREEN_W + x]; - for (int i = 0; i < h; ++i) { - memcpy(dst, src, w); - src += w; - dst += SCREEN_W; - } - - addDirtyRect(x, y, w, h); - clearOverlayRect(0, x, y, w, h); +Palette &Screen::getPalette(int num) { + assert(num >= 0 && (uint)num < _palettes.size()); + return *_palettes[num]; } -void Screen::copyScreenToRect(int x, int y, int w, int h, uint8 *ptr) { - x <<= 3; w <<= 3; - const uint8 *src = &_pagePtrs[0][y * SCREEN_W + x]; - uint8 *dst = ptr; - for (int i = 0; i < h; ++i) { - memcpy(dst, src, w); - dst += w; - src += SCREEN_W; - } -} - -uint8 *Screen::getPalette(int num) { - assert(num >= 0 && num < (_vm->gameFlags().platform == Common::kPlatformAmiga ? 6 : 4)); - if (num == 0) - return _currentPalette; - - return _palettes[num-1]; +void Screen::copyPalette(const int dst, const int src) { + getPalette(dst).copy(getPalette(src)); } byte Screen::getShapeFlag1(int x, int y) { @@ -2710,7 +2789,7 @@ void Screen::shakeScreen(int times) { } } -void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip) { +void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) { uint32 fileSize; uint8 *srcData = _vm->resource()->fileData(filename, &fileSize); @@ -2727,9 +2806,8 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 * uint32 imgSize = scumm_stricmp(ext, "CMP") ? READ_LE_UINT32(srcData + 4) : READ_LE_UINT16(srcData); uint16 palSize = READ_LE_UINT16(srcData + 8); - if (palData && palSize) { - loadPalette(srcData + 10, palData, palSize); - } + if (pal && palSize) + loadPalette(srcData + 10, *pal, palSize); uint8 *srcPtr = srcData + 10 + palSize; uint8 *dstData = getPagePtr(dstPage); @@ -2763,38 +2841,62 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 * delete[] srcData; } -bool Screen::loadPalette(const char *filename, uint8 *palData) { - uint32 fileSize = 0; - uint8 *srcData = _vm->resource()->fileData(filename, &fileSize); - if (!srcData) +bool Screen::loadPalette(const char *filename, Palette &pal) { + Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); + + if (!stream) return false; - if (palData && fileSize) { - loadPalette(srcData, palData, fileSize); - } - delete[] srcData; + debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + pal.loadAmigaPalette(*stream, 0, stream->size() / Palette::kAmigaBytesPerColor); + else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) + pal.loadPC98Palette(*stream, 0, stream->size() / Palette::kPC98BytesPerColor); + else + pal.loadVGAPalette(*stream, 0, stream->size() / Palette::kVGABytesPerColor); + + delete stream; return true; } -void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) { +bool Screen::loadPaletteTable(const char *filename, int firstPalette) { + Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); + + if (!stream) + return false; + + debugC(3, kDebugLevelScreen, "Screen::loadPaletteTable('%s', %d)", filename, firstPalette); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) { - assert(bytes % 2 == 0); - assert(bytes / 2 <= 256); - bytes >>= 1; - const uint16 *src = (const uint16 *)data; - for (int i = 0; i < bytes; ++i) { - uint16 col = READ_BE_UINT16(src); ++src; - palData[2] = (col & 0xF) << 2; col >>= 4; - palData[1] = (col & 0xF) << 2; col >>= 4; - palData[0] = (col & 0xF) << 2; col >>= 4; - palData += 3; - } - } else if (_use16ColorMode) { - for (int i = 0; i < bytes; ++i) - palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0); + const int numColors = getPalette(firstPalette).getNumColors(); + const int palSize = getPalette(firstPalette).getNumColors() * Palette::kAmigaBytesPerColor; + const int numPals = stream->size() / palSize; + + for (int i = 0; i < numPals; ++i) + getPalette(i + firstPalette).loadAmigaPalette(*stream, 0, numColors); } else { - memcpy(palData, data, bytes); + const int numColors = getPalette(firstPalette).getNumColors(); + const int palSize = getPalette(firstPalette).getNumColors() * Palette::kVGABytesPerColor; + const int numPals = stream->size() / palSize; + + for (int i = 0; i < numPals; ++i) + getPalette(i + firstPalette).loadVGAPalette(*stream, 0, numColors); } + + delete stream; + return true; +} + +void Screen::loadPalette(const byte *data, Palette &pal, int bytes) { + Common::MemoryReadStream stream(data, bytes, false); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + pal.loadAmigaPalette(stream, 0, stream.size() / Palette::kAmigaBytesPerColor); + else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) + pal.loadPC98Palette(stream, 0, stream.size() / Palette::kPC98BytesPerColor); + else + pal.loadVGAPalette(stream, 0, stream.size() / Palette::kVGABytesPerColor); } // dirty rect handling @@ -2992,8 +3094,17 @@ int SJIStoFMTChunk(int f, int s) { // copied from scumm\charset.cpp } // end of anonymous namespace void Screen::drawCharSJIS(uint16 c, int x, int y) { - int color1 = _textColorsMap[1]; - int color2 = _textColorsMap[0]; + int color1, color2; + + if (_use16ColorMode) { + // PC98 16 color games specify a color value which is for the + // PC98 text mode palette, thus we need to remap it. + color1 = ((_textColorsMap[1] >> 5) & 0x7) + 16; + color2 = ((_textColorsMap[0] >> 5) & 0x7) + 16; + } else { + color1 = _textColorsMap[1]; + color2 = _textColorsMap[0]; + } memset(_sjisTempPage2, _sjisInvisibleColor, 324); memset(_sjisSourceChar, 0, 36); @@ -3164,5 +3275,102 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { #pragma mark - +Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) { + _palData = new uint8[numColors * 3]; + assert(_palData); + + memset(_palData, 0, numColors * 3); +} + +Palette::~Palette() { + delete[] _palData; + _palData = 0; +} + +void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + stream.read(_palData + startIndex * 3, colors * 3); +} + +void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + for (int i = 0; i < colors; ++i) { + uint16 col = stream.readUint16BE(); + _palData[(i + startIndex) * 3 + 2] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + _palData[(i + startIndex) * 3 + 1] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + _palData[(i + startIndex) * 3 + 0] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + } +} + +void Palette::loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + for (int i = 0; i < colors; ++i) { + const byte g = stream.readByte(), r = stream.readByte(), b = stream.readByte(); + + _palData[(i + startIndex) * 3 + 0] = ((r & 0x0F) * 0x3F) / 0x0F; + _palData[(i + startIndex) * 3 + 1] = ((g & 0x0F) * 0x3F) / 0x0F; + _palData[(i + startIndex) * 3 + 2] = ((b & 0x0F) * 0x3F) / 0x0F; + } +} + +void Palette::clear() { + memset(_palData, 0, _numColors * 3); +} + +void Palette::fill(int firstCol, int numCols, uint8 value) { + assert(firstCol >= 0 && firstCol + numCols <= _numColors); + + memset(_palData + firstCol * 3, CLIP<int>(value, 0, 63), numCols * 3); +} + +void Palette::copy(const Palette &source, int firstCol, int numCols, int dstStart) { + if (numCols == -1) + numCols = MIN(source.getNumColors(), _numColors) - firstCol; + if (dstStart == -1) + dstStart = firstCol; + + assert(numCols >= 0 && numCols <= _numColors); + assert(firstCol >= 0 && firstCol <= source.getNumColors()); + assert(dstStart >= 0 && dstStart + numCols <= _numColors); + + memcpy(_palData + dstStart * 3, source._palData + firstCol * 3, numCols * 3); +} + +void Palette::copy(const uint8 *source, int firstCol, int numCols, int dstStart) { + if (source == _palData) + return; + + if (dstStart == -1) + dstStart = firstCol; + + assert(numCols >= 0 && numCols <= _numColors); + assert(firstCol >= 0); + assert(dstStart >= 0 && dstStart + numCols <= _numColors); + + memcpy(_palData + dstStart * 3, source + firstCol * 3, numCols * 3); +} + +uint8 *Palette::fetchRealPalette() const { + uint8 *buffer = new uint8[_numColors * 3]; + assert(buffer); + + uint8 *dst = buffer; + const uint8 *palData = _palData; + + for (int i = 0; i < _numColors; ++i) { + dst[0] = (palData[0] << 2) | (palData[0] & 3); + dst[1] = (palData[1] << 2) | (palData[1] & 3); + dst[2] = (palData[2] << 2) | (palData[2] & 3); + + dst += 3; + palData += 3; + } + + return buffer; +} + } // End of namespace Kyra diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index a6e3ef9e9a..390d058bb8 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -29,7 +29,9 @@ #include "common/util.h" #include "common/func.h" #include "common/list.h" +#include "common/array.h" #include "common/rect.h" +#include "common/stream.h" class OSystem; @@ -53,10 +55,112 @@ struct ScreenDim { struct Font { uint8 *fontData; uint8 *charWidthTable; - uint16 charSizeOffset; + uint16 fontDescOffset; uint16 charBitmapOffset; uint16 charWidthTableOffset; uint16 charHeightTableOffset; + + uint8 lastGlyph; +}; + +/** + * A class that manages KYRA palettes. + * + * This class stores the palette data as VGA RGB internally. + */ +class Palette { +public: + Palette(const int numColors); + ~Palette(); + + enum { + kVGABytesPerColor = 3, + kPC98BytesPerColor = 3, + kAmigaBytesPerColor = 2 + }; + + /** + * Load a VGA palette from the given stream. + */ + void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Load a AMIGA palette from the given stream. + */ + void loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Load a PC98 16 color palette from the given stream. + */ + void loadPC98Palette(Common::ReadStream &stream, int startIndex, int colors); + + /** + * Return the number of colors this palette manages. + */ + int getNumColors() const { return _numColors; } + + /** + * Set all palette colors to black. + */ + void clear(); + + /** + * Fill the given indexes with the given component value. + * + * @param firstCol the first color, which should be overwritten. + * @param numCols number of colors, which schould be overwritten. + * @param value color component value, which should be stored. + */ + void fill(int firstCol, int numCols, uint8 value); + + /** + * Copy data from another palette. + * + * @param source palette to copy data from. + * @param firstCol the first color of the source which should be copied. + * @param numCols number of colors, which should be copied. -1 all remaining colors. + * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start. + */ + void copy(const Palette &source, int firstCol = 0, int numCols = -1, int dstStart = -1); + + /** + * Copy data from a raw VGA palette. + * + * @param source source buffer + * @param firstCol the first color of the source which should be copied. + * @param numCols number of colors, which should be copied. + * @param dstStart the first color, which should be ovewritten. If -1 firstCol will be used as start. + */ + void copy(const uint8 *source, int firstCol, int numCols, int dstStart = -1); + + /** + * Fetch a RGB palette. + * + * @return a pointer to the RGB palette data, the client must delete[] it. + */ + uint8 *fetchRealPalette() const; + + //XXX + uint8 &operator[](const int index) { + assert(index >= 0 && index <= _numColors * 3); + return _palData[index]; + } + + const uint8 &operator[](const int index) const { + assert(index >= 0 && index <= _numColors * 3); + return _palData[index]; + } + + /** + * Gets raw access to the palette. + * + * TODO: Get rid of this. + */ + uint8 *getData() { return _palData; } + const uint8 *getData() const { return _palData; } +private: + uint8 *_palData; + const int _numColors; }; class Screen { @@ -110,12 +214,11 @@ public: // page cur. functions int setCurPage(int pageNum); - - void copyFromCurPageBlock(int x, int y, int w, int h, const uint8 *src); - void copyCurPageBlock(int x, int y, int w, int h, uint8 *dst); - void clearCurPage(); + void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); + // page 0 functions void copyToPage0(int y, int h, uint8 page, uint8 *seqBuf); void shakeScreen(int times); @@ -142,21 +245,25 @@ public: void fadeFromBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); - void fadePalette(const uint8 *palData, int delay, const UpdateFunctor *upFunc = 0); - virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff); - int fadePalStep(const uint8 *palette, int diff); + virtual void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0); + virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + virtual int fadePalStep(const Palette &pal, int diff); void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue); - void setScreenPalette(const uint8 *palData); - const uint8 *getScreenPalette() const { return _screenPalette; } + virtual void setScreenPalette(const Palette &pal); void getRealPalette(int num, uint8 *dst); - uint8 *getPalette(int num); + Palette &getPalette(int num); + void copyPalette(const int dst, const int src); // gui specific (processing on _curPage) + enum ShadeType { + kShadeTypeKyra, + kShadeTypeLol + }; void drawLine(bool vertical, int x, int y, int length, int color); void drawClippedLine(int x1, int y1, int x2, int y2, int color); - void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2); + void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2, ShadeType shadeType = kShadeTypeKyra); void drawBox(int x1, int y1, int x2, int y2, int color); // font/text handling @@ -199,10 +306,11 @@ public: void rectClip(int &x, int &y, int w, int h); // misc - void loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData, bool skip=false); + void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip=false); - bool loadPalette(const char *filename, uint8 *palData); - void loadPalette(const byte *data, uint8 *palData, int bytes); + bool loadPalette(const char *filename, Palette &pal); + bool loadPaletteTable(const char *filename, int firstPalette); + void loadPalette(const byte *data, Palette &pal, int bytes); void setAnimBlockPtr(int size); @@ -220,7 +328,6 @@ public: int _charWidth; int _charOffset; int _curPage; - uint8 *_currentPalette; uint8 *_shapePages[2]; int _maskMinY, _maskMaxY; FontId _currentFont; @@ -231,6 +338,7 @@ public: static uint decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize); static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false); static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor); + static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true); static void convertAmigaMsc(uint8 *data); @@ -240,7 +348,7 @@ protected: void updateDirtyRectsOvl(); void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); - void mergeOverlay(int x, int y, int w, int h); + virtual void mergeOverlay(int x, int y, int w, int h); // overlay specific byte *getOverlayPtr(int pageNum); @@ -258,10 +366,6 @@ protected: }; int16 encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size); - void restoreMouseRect(); - void copyMouseToScreen(); - void copyScreenFromRect(int x, int y, int w, int h, const uint8 *ptr); - void copyScreenToRect(int x, int y, int w, int h, uint8 *ptr); template<bool noXor> static void wrapped_decodeFrameDelta(uint8 *dst, const uint8 *src); template<bool noXor> static void wrapped_decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch); @@ -279,8 +383,9 @@ protected: uint8 *_sjisSourceChar; uint8 _sjisInvisibleColor; - uint8 *_screenPalette; - uint8 *_palettes[6]; + Palette *_screenPalette; + Common::Array<Palette *> _palettes; + Palette *_internFadePalette; Font _fonts[FID_NUM]; uint8 _textColorsMap[16]; @@ -291,7 +396,11 @@ protected: uint8 *_animBlockPtr; int _animBlockSize; + // mouse handling int _mouseLockCount; + const uint8 _cursorColorKey; + + virtual void postProcessCursor(uint8 *data, int w, int h, int pitch) {}; enum { kMaxDirtyRects = 50 diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp index 206f8beb87..516cb5bc41 100644 --- a/engines/kyra/screen_hof.cpp +++ b/engines/kyra/screen_hof.cpp @@ -44,8 +44,8 @@ const ScreenDim *Screen_HoF::getScreenDim(int dim) { return &_screenDimTable[dim]; } -void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) { - uint8 tmpPal[768]; +void Screen_HoF::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) { + Palette tmpPal(lastColor); for (int i = 0; i != lastColor; i++) { if (flag) { @@ -63,7 +63,7 @@ void Screen_HoF::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in } for (int i = 0; i < lastColor; i++) - grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor); + grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor); } void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index 088e8b7f55..1c17a424b3 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -41,7 +41,7 @@ public: const ScreenDim *getScreenDim(int dim); // sequence player - void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); + void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage); void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp index 6d97db2f28..9fdeae1398 100644 --- a/engines/kyra/screen_lok.cpp +++ b/engines/kyra/screen_lok.cpp @@ -26,8 +26,9 @@ #include "kyra/kyra_lok.h" #include "kyra/screen_lok.h" -namespace Kyra { +#include "graphics/cursorman.h" +namespace Kyra { Screen_LoK::Screen_LoK(KyraEngine_LoK *vm, OSystem *system) : Screen(vm, system) { @@ -80,13 +81,15 @@ const ScreenDim *Screen_LoK::getScreenDim(int dim) { void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { assert(_vm->palTable1()[palIndex]); - assert(_currentPalette); - uint8 tempPal[768]; - memcpy(tempPal, _currentPalette, 768); - memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3); + + Palette tempPal(getPalette(0).getNumColors()); + tempPal.copy(getPalette(0)); + tempPal.copy(_vm->palTable1()[palIndex], 0, size, startIndex); + fadePalette(tempPal, fadeTime*18); - memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3); - setScreenPalette(_currentPalette); + + getPalette(0).copy(tempPal, startIndex, size); + setScreenPalette(getPalette(0)); _system->updateScreen(); } @@ -237,4 +240,200 @@ int Screen_LoK::getRectSize(int x, int y) { return ((x*y) << 3); } +#pragma mark - + +Screen_LoK_16::Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system) : Screen_LoK(vm, system) { + memset(_paletteDither, 0, sizeof(_paletteDither)); +} + +void Screen_LoK_16::setScreenPalette(const Palette &pal) { + _screenPalette->copy(pal); + + for (int i = 0; i < 256; ++i) + paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2); + + set16ColorPalette(_palette16); +} + +void Screen_LoK_16::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc) { + uint8 notBlackFlag = 0; + for (int i = 0; i < 768; ++i) { + if ((*_screenPalette)[i]) + notBlackFlag |= 1; + if (pal[i]) + notBlackFlag |= 2; + } + + if (notBlackFlag == 1 || notBlackFlag == 2) { + bool upFade = false; + + for (int i = 0; i < 768; ++i) { + if ((*_screenPalette)[i] < pal[i]) { + upFade = true; + break; + } + } + + if (upFade) { + for (int i = 0; i < 256; ++i) + paletteMap(i, pal[i * 3 + 0] << 2, pal[i * 3 + 1] << 2, pal[i * 3 + 2] << 2); + _forceFullUpdate = true; + } + + uint8 color16Palette[16 * 3]; + + if (upFade) + memset(color16Palette, 0, sizeof(color16Palette)); + else + memcpy(color16Palette, _palette16, sizeof(color16Palette)); + + set16ColorPalette(color16Palette); + updateScreen(); + + for (int i = 0; i < 16; ++i) { + set16ColorPalette(color16Palette); + + for (int k = 0; k < 48; ++k) { + if (upFade) { + if (color16Palette[k] < _palette16[k]) + ++color16Palette[k]; + } else { + if (color16Palette[k] > 0) + --color16Palette[k]; + } + } + + if (upFunc && upFunc->isValid()) + (*upFunc)(); + else + _system->updateScreen(); + + _vm->delay((delay >> 5) * _vm->tickLength()); + } + } + + setScreenPalette(pal); +} + +void Screen_LoK_16::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { + error("Screen_LoK_16::getFadeParams called"); +} + +int Screen_LoK_16::fadePalStep(const Palette &pal, int diff) { + error("Screen_LoK_16::fadePalStep called"); + return 0; +} + +void Screen_LoK_16::paletteMap(uint8 idx, int r, int g, int b) { + const int red = r; + const int green = g; + const int blue = b; + + uint16 rgbDiff = 1000; + int rDiff = 0, gDiff = 0, bDiff = 0; + + int index1 = -1; + + for (int i = 0; i < 16; ++i) { + const int realR = _palette16[i * 3 + 0] << 4; + const int realG = _palette16[i * 3 + 1] << 4; + const int realB = _palette16[i * 3 + 2] << 4; + + uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB); + + if (diff < rgbDiff) { + rgbDiff = diff; + index1 = i; + + rDiff = r - realR; + gDiff = g - realG; + bDiff = b - realB; + } + } + + r = rDiff / 4 + red; + g = gDiff / 4 + green; + b = bDiff / 4 + blue; + + rgbDiff = 1000; + int index2 = -1; + + for (int i = 0; i < 16; ++i) { + const int realR = _palette16[i * 3 + 0] << 4; + const int realG = _palette16[i * 3 + 1] << 4; + const int realB = _palette16[i * 3 + 2] << 4; + + uint16 diff = ABS(r - realR) + ABS(g - realG) + ABS(b - realB); + + if (diff < rgbDiff) { + rgbDiff = diff; + index2 = i; + } + } + + _paletteDither[idx].bestMatch = index1; + _paletteDither[idx].invertMatch = index2; +} + +void Screen_LoK_16::convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor) { + const int rowAdd = pitch * 2 - w; + + uint8 *row1 = page; + uint8 *row2 = page + pitch; + + for (int i = 0; i < h; i += 2) { + for (int k = 0; k < w; k += 2) { + if (keyColor == -1 || keyColor != *row1) { + const PaletteDither &dither = _paletteDither[*row1]; + + *row1++ = dither.bestMatch; + *row1++ = dither.invertMatch; + *row2++ = dither.invertMatch; + *row2++ = dither.bestMatch; + } else { + row1 += 2; + row2 += 2; + } + } + + row1 += rowAdd; + row2 += rowAdd; + } +} + +void Screen_LoK_16::mergeOverlay(int x, int y, int w, int h) { + byte *dst = _sjisOverlayPtrs[0] + y * 640 + x; + + // We do a game screen rect to 16 color dithering here. It is + // important that we do not dither the overlay, since else the + // japanese fonts will look wrong. + convertTo16Colors(dst, w, h, 640); + + const byte *src = _sjisOverlayPtrs[1] + y * 640 + x; + + int add = 640 - w; + + while (h--) { + for (x = 0; x < w; ++x, ++dst) { + byte col = *src++; + if (col != _sjisInvisibleColor) + *dst = _paletteDither[col].bestMatch; + } + dst += add; + src += add; + } +} + +void Screen_LoK_16::set16ColorPalette(const uint8 *pal) { + uint8 palette[16 * 4]; + for (int i = 0; i < 16; ++i) { + palette[i * 4 + 0] = (pal[i * 3 + 0] * 0xFF) / 0x0F; + palette[i * 4 + 1] = (pal[i * 3 + 1] * 0xFF) / 0x0F; + palette[i * 4 + 2] = (pal[i * 3 + 2] * 0xFF) / 0x0F; + palette[i * 4 + 3] = 0; + } + + _system->setPalette(palette, 0, 16); +} + } // end of namespace Kyra diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h index d74da66df5..4eb22df374 100644 --- a/engines/kyra/screen_lok.h +++ b/engines/kyra/screen_lok.h @@ -77,6 +77,38 @@ protected: uint8 *_saveLoadPageOvl[8]; }; +class Screen_LoK_16 : public Screen_LoK { +public: + Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system); + + void setScreenPalette(const Palette &pal); + + void fadePalette(const Palette &pal, int delay, const UpdateFunctor *upFunc = 0); + void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + int fadePalStep(const Palette &pal, int diff); +private: + void updateDirtyRectsOvl(); + + void convertTo16Colors(uint8 *page, int w, int h, int pitch, int keyColor = -1); + void postProcessCursor(uint8 *data, int width, int height, int pitch) { + convertTo16Colors(data, width, height, pitch, _cursorColorKey); + } + void mergeOverlay(int x, int y, int w, int h); + + void set16ColorPalette(const uint8 *pal); + + void paletteMap(uint8 idx, int r, int g, int b); + + struct PaletteDither { + uint8 bestMatch; + uint8 invertMatch; + }; + + PaletteDither _paletteDither[256]; + + static const uint8 _palette16[48]; +}; + } // end of namespace Kyra #endif diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 5f64a1cddd..b9bf9961c5 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -105,7 +105,7 @@ void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint va_end(vaList); if (flags & 1) - x -= getTextWidth(string) >> 1; + x -= (getTextWidth(string) >> 1); if (flags & 2) x -= getTextWidth(string); @@ -144,8 +144,8 @@ void Screen_LoL::fprintStringIntro(const char *format, int x, int y, uint8 c1, u printText(buffer, x, y, c1, c2); } -void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) { - uint8 tmpPal[768]; +void Screen_LoL::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors) { + Palette tmpPal(lastColor); for (int i = 0; i != lastColor; i++) { int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR; @@ -157,11 +157,11 @@ void Screen_LoL::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, in } for (int i = 0; i < lastColor; i++) - grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor, skipSpecialColors); + grayOverlay[i] = findLeastDifferentColor(tmpPal.getData() + 3 * i, srcPal, 0, lastColor, skipSpecialColors); } -uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight) { - if (!srcPal || !ovl) +uint8 *Screen_LoL::generateLevelOverlay(const Palette &srcPal, uint8 *ovl, int opColor, int weight) { + if (!ovl) return ovl; if (weight > 255) @@ -186,7 +186,7 @@ uint8 *Screen_LoL::generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opC int m = 0x7fff; int ii = 127; int x = 1; - const uint8 *s = srcPal + 3; + const uint8 *s = srcPal.getData() + 3; do { if (i == x) { @@ -282,14 +282,13 @@ void Screen_LoL::fadeClearSceneWindow(int delay) { if (_fadeFlag == 1) return; - uint8 *tpal = new uint8[768]; + Palette tpal(getPalette(0).getNumColors()); + tpal.copy(getPalette(0), 128); - memcpy(tpal, _currentPalette, 768); - memset(tpal, 0, 384); loadSpecialColors(tpal); fadePalette(tpal, delay); + fillRect(112, 0, 288, 120, 0); - delete[] tpal; _fadeFlag = 1; } @@ -838,18 +837,18 @@ void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) { } void Screen_LoL::fadeToPalette1(int delay) { - loadSpecialColors(_palettes[0]); - fadePalette(_palettes[0], delay); + loadSpecialColors(getPalette(1)); + fadePalette(getPalette(1), delay); _fadeFlag = 0; } -void Screen_LoL::loadSpecialColors(uint8 *destPalette) { - memcpy(destPalette + 0x240, _screenPalette + 0x240, 12); +void Screen_LoL::loadSpecialColors(Palette &dst) { + dst.copy(*_screenPalette, 192, 4); } void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) { - uint8 *s = _screenPalette + srcColorIndex * 3; - uint8 *d = _screenPalette + dstColorIndex * 3; + uint8 *s = _screenPalette->getData() + srcColorIndex * 3; + uint8 *d = _screenPalette->getData() + dstColorIndex * 3; memcpy(d, s, 3); uint8 ci[4]; @@ -862,9 +861,9 @@ void Screen_LoL::copyColor(int dstColorIndex, int srcColorIndex) { } bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime) { - uint8 *dst = _screenPalette + 3 * dstColorIndex; - uint8 *src = _screenPalette + 3 * srcColorIndex; - uint8 *p = getPalette(1) + 3 * dstColorIndex; + const uint8 *dst = _screenPalette->getData() + 3 * dstColorIndex; + const uint8 *src = _screenPalette->getData() + 3 * srcColorIndex; + uint8 *p = getPalette(1).getData() + 3 * dstColorIndex; bool res = false; @@ -897,22 +896,21 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT p++; } - uint8 tpal[768]; - memcpy(tpal, _screenPalette, 768); - memcpy(tpal + dstColorIndex * 3, tmpPalEntry, 3); - setScreenPalette(tpal); + _internFadePalette->copy(*_screenPalette); + _internFadePalette->copy(tmpPalEntry, 0, 1, dstColorIndex); + setScreenPalette(*_internFadePalette); updateScreen(); return res; } bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) { - uint8 tpal[768]; - uint8 *p1 = _palettes[0]; + Palette &p1 = getPalette(1); bool res = false; for (int i = 0; i < 768; i++) { uint8 out = 0; + if (elapsedTime < targetTime) { int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f)); if (d) @@ -925,19 +923,92 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u res = false; } - tpal[i] = out; + (*_internFadePalette)[i] = out; } - setScreenPalette(tpal); + setScreenPalette(*_internFadePalette); updateScreen(); return res; } +uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs) { + if (!src1) + src1 = _screenPalette->getData(); + + uint8 *p1 = dst; + uint8 *p2 = src1; + uint8 *p3 = src2; + + for (int i = 0; i < 768; i++) { + int8 val = (int8)*p3++ - (int8)*p2++; + *dst++ = (uint8)val; + } + + int16 t = 0; + int16 d = 256 / numTabs; + + for (int i = 1; i < numTabs - 1; i++) { + p2 = src1; + p3 = p1; + t += d; + + for (int ii = 0; ii < 768; ii++) { + int16 val = (((int8)*p3++ * t) >> 8) + (int8)*p2++; + *dst++ = (uint8)val; + } + } + + memcpy(p1, src1, 768); + memcpy(dst, src2, 768); + + dst += 768; + return dst; +} + uint8 Screen_LoL::getShapePaletteSize(const uint8 *shp) { return shp[10]; } +void Screen_LoL::mergeOverlay(int x, int y, int w, int h) { + // For now we convert to 16 colors on overlay merging. If that gives + // any problems, like Screen functionallity not prepared for the + // format PC98 16 color uses, we'll need to think of a better way. + // + // We must do this before merging the overlay, else the font colors + // will be wrong. + if (_use16ColorMode) + convertPC98Gfx(_sjisOverlayPtrs[0] + y * 640 + x, w, h, 640); + + Screen_v2::mergeOverlay(x, y, w, h); +} + +void Screen_LoL::convertPC98Gfx(uint8 *data, int w, int h, int pitch) { + while (h--) { + for (int i = 0; i < w; ++i) { + *data = _paletteConvTable[*data]; + ++data; + } + + data += pitch - w; + } +} + +void Screen_LoL::postProcessCursor(uint8 *data, int w, int h, int pitch) { + if (!_use16ColorMode) + return; + + while (h--) { + for (int i = 0; i < w; ++i) { + if (*data != _cursorColorKey) + *data = _paletteConvTable[*data]; + ++data; + } + + data += pitch - w; + } +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 1ad5379d29..2545064b58 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -46,8 +46,8 @@ public: int curDimIndex() { return _curDimIndex; } void modifyScreenDim(int dim, int x, int y, int w, int h); - void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...); - void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...); + void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) GCC_PRINTF(2, 8); + void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...) GCC_PRINTF(2, 9); void drawGridBox(int x, int y, int w, int h, int col); void fadeClearSceneWindow(int delay); @@ -70,13 +70,14 @@ public: // palette stuff void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0); void fadeToPalette1(int delay); - void loadSpecialColors(uint8 *destPalette); + void loadSpecialColors(Palette &dst); void copyColor(int dstColorIndex, int srcColorIndex); bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTime, uint32 targetTime); bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime); + uint8 *generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs); - void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); - uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight); + void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); + uint8 *generateLevelOverlay(const Palette &Pal, uint8 *ovl, int opColor, int weight); uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; } void copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl); @@ -91,6 +92,9 @@ public: uint8 *_grayOverlay; int _fadeFlag; + // PC98 specific + static void convertPC98Gfx(uint8 *data, int w, int h, int pitch); + private: LoLEngine *_vm; @@ -105,6 +109,10 @@ private: uint8 *_levelOverlays[8]; + static const uint8 _paletteConvTable[256]; + void mergeOverlay(int x, int y, int w, int h); + void postProcessCursor(uint8 *data, int width, int height, int pitch); + // magic atlas void calcBoundariesIntern(int dstX, int dstY, int c, int d); diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index e72321346f..177d7d66dd 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -38,39 +38,38 @@ Screen_v2::~Screen_v2() { delete[] _wsaFrameAnimBuffer; } -uint8 *Screen_v2::generateOverlay(const uint8 *palette, uint8 *buffer, int startColor, uint16 factor) { - if (!palette || !buffer) +uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int startColor, uint16 factor) { + if (!buffer) return buffer; factor = MIN<uint16>(255, factor); factor >>= 1; factor &= 0xFF; - const byte col1 = palette[startColor * 3 + 0]; - const byte col2 = palette[startColor * 3 + 1]; - const byte col3 = palette[startColor * 3 + 2]; + const byte col1 = pal[startColor * 3 + 0]; + const byte col2 = pal[startColor * 3 + 1]; + const byte col3 = pal[startColor * 3 + 2]; uint8 *dst = buffer; *dst++ = 0; for (int i = 1; i != 255; ++i) { uint8 processedPalette[3]; - const uint8 *src = palette + i*3; byte col; - col = *src++; + col = pal[i * 3 + 0]; col -= ((((col - col1) * factor) << 1) >> 8) & 0xFF; processedPalette[0] = col; - col = *src++; + col = pal[i * 3 + 1]; col -= ((((col - col2) * factor) << 1) >> 8) & 0xFF; processedPalette[1] = col; - col = *src++; + col = pal[i * 3 + 2]; col -= ((((col - col3) * factor) << 1) >> 8) & 0xFF; processedPalette[2] = col; - *dst++ = findLeastDifferentColor(processedPalette, palette+3, 255)+1; + *dst++ = findLeastDifferentColor(processedPalette, pal, 1, 255) + 1; } return buffer; @@ -90,7 +89,7 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint } } -int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors) { +int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors) { int m = 0x7fff; int r = 0x101; @@ -98,11 +97,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p if (skipSpecialColors && i >= 0xc0 && i <= 0xc3) continue; - int v = paletteEntry[0] - *palette++; + int v = paletteEntry[0] - pal[(i + firstColor) * 3 + 0]; int c = v * v; - v = paletteEntry[1] - *palette++; + v = paletteEntry[1] - pal[(i + firstColor) * 3 + 1]; c += (v * v); - v = paletteEntry[2] - *palette++; + v = paletteEntry[2] - pal[(i + firstColor) * 3 + 2]; c += (v * v); if (c <= m) { @@ -114,12 +113,11 @@ int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *p return r; } -void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff) { +void Screen_v2::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { int maxDiff = 0; diff = 0; - int len = _use16ColorMode ? 48 : 768; - for (int i = 0; i < len; ++i) { - diff = ABS(palette[i] - _screenPalette[i]); + for (int i = 0; i < pal.getNumColors() * 3; ++i) { + diff = ABS(pal[i] - (*_screenPalette)[i]); maxDiff = MAX(maxDiff, diff); } @@ -137,148 +135,6 @@ void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, in } } -void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, - int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { - uint8 *dstPtr = getPagePtr(_curPage); - uint8 *origDst = dstPtr; - - const ScreenDim *dim = getScreenDim(dimState); - int dimX1 = dim->sx << 3; - int dimX2 = dim->w << 3; - dimX2 += dimX1; - - int dimY1 = dim->sy; - int dimY2 = dim->h; - dimY2 += dimY1; - - int temp = y - dimY1; - if (temp < 0) { - if ((temp += h) <= 0) - return; - else { - SWAP(temp, h); - y += temp - h; - src += (temp - h) * w; - } - } - - temp = dimY2 - y; - if (temp <= 0) - return; - - if (temp < h) - h = temp; - - int srcOffset = 0; - temp = x - dimX1; - if (temp < 0) { - temp = -temp; - srcOffset = temp; - x += temp; - w -= temp; - } - - int srcAdd = 0; - - temp = dimX2 - x; - if (temp <= 0) - return; - - if (temp < w) { - SWAP(w, temp); - temp -= w; - srcAdd = temp; - } - - dstPtr += y * SCREEN_W + x; - uint8 *dst = dstPtr; - - if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, w, h); - - clearOverlayRect(_curPage, x, y, w, h); - - temp = h; - int curY = y; - while (h--) { - src += srcOffset; - ++curY; - int cW = w; - - switch (plotFunc) { - case 0: - memcpy(dst, src, cW); - dst += cW; src += cW; - break; - - case 1: - while (cW--) { - uint8 d = *src++; - uint8 t = unkPtr1[d]; - if (t != 0xFF) - d = unkPtr2[*dst + (t << 8)]; - *dst++ = d; - } - break; - - case 4: - while (cW--) { - uint8 d = *src++; - if (d) - *dst = d; - ++dst; - } - break; - - case 5: - while (cW--) { - uint8 d = *src++; - if (d) { - uint8 t = unkPtr1[d]; - if (t != 0xFF) - d = unkPtr2[*dst + (t << 8)]; - *dst = d; - } - ++dst; - } - break; - - case 8: - case 9: - while (cW--) { - uint8 d = *src++; - uint8 t = _shapePages[0][dst - origDst] & 7; - if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } - break; - - case 12: - case 13: - while (cW--) { - uint8 d = *src++; - if (d) { - uint8 t = _shapePages[0][dst - origDst] & 7; - if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } else { - d = _shapePages[1][dst - origDst]; - *dst++ = d; - } - } - break; - - default: - break; - } - - dst = (dstPtr += SCREEN_W); - src += srcAdd; - } -} - const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { uint16 shapes = READ_LE_UINT16(shpFile); @@ -428,6 +284,9 @@ void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, memcpy(dst + x2 + cdm.sx, _wsaFrameAnimBuffer + na, w2); dst += 320; } while (++nb < h2); + + if (!dstPage) + addDirtyRect(x2, y2, w2, h2); } bool Screen_v2::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) { diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index 18bac764ec..3aa726334c 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -37,17 +37,14 @@ public: ~Screen_v2(); // screen page handling - void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, - int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); - void checkedPageUpdate(int srcPage, int dstPage); // palette handling - uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor); + uint8 *generateOverlay(const Palette &pal, uint8 *buffer, int color, uint16 factor); void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay); - int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors, bool skipSpecialColors = false); + int findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors = false); - virtual void getFadeParams(const uint8 *palette, int delay, int &delayInc, int &diff); + virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); // shape handling uint8 *getPtrToShape(uint8 *shpFile, int shape); diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index 9035708f5e..0473f03591 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -66,6 +66,42 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm) { #undef OPCODE } +bool EMCInterpreter::callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case MKID_BE('TEXT'): + _scriptData->text = new byte[chunk._size]; + assert(_scriptData->text); + if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size) + error("Couldn't read TEXT chunk from file '%s'", _filename); + break; + + case MKID_BE('ORDR'): + _scriptData->ordr = new uint16[chunk._size >> 1]; + assert(_scriptData->ordr); + if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size) + error("Couldn't read ORDR chunk from file '%s'", _filename); + + for (int i = (chunk._size >> 1) - 1; i >= 0; --i) + _scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]); + break; + + case MKID_BE('DATA'): + _scriptData->data = new uint16[chunk._size >> 1]; + assert(_scriptData->data); + if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size) + error("Couldn't read DATA chunk from file '%s'", _filename); + + for (int i = (chunk._size >> 1) - 1; i >= 0; --i) + _scriptData->data[i] = READ_BE_UINT16(&_scriptData->data[i]); + break; + + default: + warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename); + } + + return false; +} + bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode*> *opcodes) { Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); if (!stream) { @@ -75,47 +111,17 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo memset(scriptData, 0, sizeof(EMCData)); + _scriptData = scriptData; + _filename = filename; + IFFParser iff(*stream); - Common::IFFChunk *chunk = 0; - - while ((chunk = iff.nextChunk()) != 0) { - switch (chunk->id) { - case MKID_BE('TEXT'): - scriptData->text = new byte[chunk->size]; - assert(scriptData->text); - if (chunk->read(scriptData->text, chunk->size) != chunk->size) - error("Couldn't read TEXT chunk from file '%s'", filename); - break; - - case MKID_BE('ORDR'): - scriptData->ordr = new uint16[chunk->size >> 1]; - assert(scriptData->ordr); - if (chunk->read(scriptData->ordr, chunk->size) != chunk->size) - error("Couldn't read ORDR chunk from file '%s'", filename); - - for (int i = (chunk->size >> 1) - 1; i >= 0; --i) - scriptData->ordr[i] = READ_BE_UINT16(&scriptData->ordr[i]); - break; - - case MKID_BE('DATA'): - scriptData->data = new uint16[chunk->size >> 1]; - assert(scriptData->data); - if (chunk->read(scriptData->data, chunk->size) != chunk->size) - error("Couldn't read DATA chunk from file '%s'", filename); - - for (int i = (chunk->size >> 1) - 1; i >= 0; --i) - scriptData->data[i] = READ_BE_UINT16(&scriptData->data[i]); - break; - - default: - warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename); - } - } + Common::Functor1Mem< Common::IFFChunk &, bool, EMCInterpreter > c(this, &EMCInterpreter::callback); + iff.parse(c); - if (!scriptData->ordr) + if (!_scriptData->ordr) error("No ORDR chunk found in file: '%s'", filename); - if (!scriptData->data) + if (!_scriptData->data) error("No DATA chunk found in file: '%s'", filename); if (stream->err()) @@ -123,10 +129,10 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo delete stream; - scriptData->sysFuncs = opcodes; + _scriptData->sysFuncs = opcodes; - strncpy(scriptData->filename, filename, 13); - scriptData->filename[12] = 0; + strncpy(_scriptData->filename, filename, 13); + _scriptData->filename[12] = 0; return true; } diff --git a/engines/kyra/script.h b/engines/kyra/script.h index 88bbe86c4d..862cfb7d97 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -70,7 +70,7 @@ class KyraEngine_v1; class IFFParser : public Common::IFFParser { public: - IFFParser(Common::SeekableReadStream &input) : Common::IFFParser(input) { + IFFParser(Common::ReadStream &input) : Common::IFFParser(&input) { // It seems Westwood missunderstood the 'size' field of the FORM chunk. // // For EMC scripts (type EMC2) it's filesize instead of filesize - 8, @@ -84,9 +84,9 @@ public: // Both lead to some problems in our IFF parser, either reading after the end // of file or producing a "Chunk overread" error message. To work around this // we need to adjust the size field properly. - if (_typeId == MKID_BE('EMC2')) + if (_formType == MKID_BE('EMC2')) _formChunk.size -= 8; - else if (_typeId == MKID_BE('AVFS')) + else if (_formType == MKID_BE('AVFS')) _formChunk.size += 4; } }; @@ -108,6 +108,11 @@ protected: KyraEngine_v1 *_vm; int16 _parameter; + const char *_filename; + EMCData *_scriptData; + + bool callback(Common::IFFChunk &chunk); + typedef void (EMCInterpreter::*OpcodeProc)(EMCState *); struct OpcodeEntry { OpcodeProc proc; diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index b2a581cece..1b8c1d32b3 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -146,7 +146,7 @@ int KyraEngine_HoF::o2_meanWhileScene(EMCState *script) { const char *palfile = stackPosString(1); _screen->loadBitmap(cpsfile, 3, 3, 0); - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); _screen->loadPalette(palfile, _screen->getPalette(2)); _screen->fillRect(0, 0, 319, 199, 207); _screen->setScreenPalette(_screen->getPalette(2)); @@ -559,14 +559,14 @@ int KyraEngine_HoF::o2_enableAnimObject(EMCState *script) { int KyraEngine_HoF::o2_loadPalette384(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_loadPalette384(%p) ('%s')", (const void *)script, stackPosString(0)); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); - _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1), 384); + _screen->copyPalette(1, 0); + _res->loadFileToBuf(stackPosString(0), _screen->getPalette(1).getData(), 384); return 0; } int KyraEngine_HoF::o2_setPalette384(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setPalette384(%p) ()", (const void *)script); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 384); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); _screen->setScreenPalette(_screen->getPalette(0)); return 0; } @@ -774,13 +774,13 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { displayInvWsaLastFrame(); backUpPage0(); - memcpy(_screen->getPalette(2), _screen->getPalette(0), 768); + _screen->copyPalette(2, 0); _screen->clearPage(3); _screen->loadBitmap("_NOTE.CPS", 3, 3, 0); sprintf(filename, "_NTEPAL%.1d.COL", letter+1); - _res->loadFileToBuf(filename, _screen->getPalette(0), 768); + _screen->loadPalette(filename, _screen->getPalette(0)); _screen->fadeToBlack(0x14); @@ -819,7 +819,7 @@ int KyraEngine_HoF::o2_showLetter(EMCState *script) { _screen->hideMouse(); _screen->fadeToBlack(0x14); restorePage0(); - memcpy(_screen->getPalette(0), _screen->getPalette(2), 768); + _screen->copyPalette(0, 2); _screen->fadePalette(_screen->getPalette(0), 0x14); setHandItem(_itemInHand); _screen->showMouse(); @@ -1125,25 +1125,25 @@ int KyraEngine_HoF::o2_resetInputColorCode(EMCState *script) { int KyraEngine_HoF::o2_mushroomEffect(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_mushroomEffect(%p)", (const void *)script); - memcpy(_screen->getPalette(2), _screen->_currentPalette, 768); + _screen->copyPalette(2, 0); for (int i = 1; i < 768; i += 3) - _screen->_currentPalette[i] = 0; + _screen->getPalette(0)[i] = 0; snd_playSoundEffect(106); - _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor); - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); + _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor); + _screen->copyPalette(0, 2); for (int i = 0; i < 768; i += 3) { - _screen->_currentPalette[i] = _screen->_currentPalette[i + 1] = 0; - _screen->_currentPalette[i + 2] += (((int8)_screen->_currentPalette[i + 2]) >> 1); - if (_screen->_currentPalette[i + 2] > 63) - _screen->_currentPalette[i + 2] = 63; + _screen->getPalette(0)[i] = _screen->getPalette(0)[i + 1] = 0; + _screen->getPalette(0)[i + 2] += (((int8)_screen->getPalette(0)[i + 2]) >> 1); + if (_screen->getPalette(0)[i + 2] > 63) + _screen->getPalette(0)[i + 2] = 63; } snd_playSoundEffect(106); - _screen->fadePalette(_screen->_currentPalette, 90, &_updateFunctor); + _screen->fadePalette(_screen->getPalette(0), 90, &_updateFunctor); - memcpy(_screen->_currentPalette, _screen->getPalette(2), 768); - _screen->fadePalette(_screen->_currentPalette, 30, &_updateFunctor); + _screen->copyPalette(0, 2); + _screen->fadePalette(_screen->getPalette(0), 30, &_updateFunctor); return 0; } @@ -1262,19 +1262,23 @@ int KyraEngine_HoF::o2_stopSceneAnimation(EMCState *script) { int KyraEngine_HoF::o2_processPaletteIndex(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_processPaletteIndex(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - uint8 *palette = _screen->getPalette(0); + Palette &palette = _screen->getPalette(0); + const int index = stackPos(0); const bool updatePalette = (stackPos(4) != 0); const int delayTime = stackPos(5); + palette[index*3+0] = (stackPos(1) * 0x3F) / 100; palette[index*3+1] = (stackPos(2) * 0x3F) / 100; palette[index*3+2] = (stackPos(3) * 0x3F) / 100; + if (updatePalette) { if (delayTime > 0) _screen->fadePalette(palette, delayTime, &_updateFunctor); else _screen->setScreenPalette(palette); } + return 0; } @@ -1396,7 +1400,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) { assert(strings); _screen->clearPage(0); - _screen->loadPalette("THANKS.COL", _screen->_currentPalette); + _screen->loadPalette("THANKS.COL", _screen->getPalette(0)); _screen->loadBitmap("THANKS.CPS", 3, 3, 0); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); @@ -1406,7 +1410,7 @@ int KyraEngine_HoF::o2_demoFinale(EMCState *script) { for (int i = 0; i < 6; i++) _text->printText(strings[i], _text->getCenterStringX(strings[i], 1, 319), y + i * 10, 255, 207, 0); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->updateScreen(); _eventList.clear(); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 03a5d4efc1..849c6b776d 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -231,7 +231,8 @@ int KyraEngine_LoK::o1_fadeSpecialPalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); if (_currentCharacter->sceneId != 45) { if (stackPos(0) == 13) { - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3); + // TODO: Check this! + _screen->copyPalette(0, 12); _screen->setScreenPalette(_screen->getPalette(0)); } } else { @@ -427,7 +428,7 @@ int KyraEngine_LoK::o1_runWSAFromBeginningToEnd(EMCState *script) { int wsaFrame = 0; while (running) { - _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(wsaFrame++, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; if (wsaFrame >= _movieObjects[wsaIndex]->frames()) running = false; @@ -458,7 +459,7 @@ int KyraEngine_LoK::o1_displayWSAFrame(EMCState *script) { int waitTime = stackPos(3); int wsaIndex = stackPos(4); _screen->hideMouse(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { @@ -500,7 +501,7 @@ int KyraEngine_LoK::o1_runWSAFrames(EMCState *script) { _screen->hideMouse(); for (; startFrame <= endFrame; ++startFrame) { uint32 nextRun = _system->getMillis() + delayTime * _tickLength; - _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(startFrame, 0, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < nextRun) { _sprites->updateSceneAnims(); @@ -578,7 +579,7 @@ int KyraEngine_LoK::o1_restoreAllObjectBackgrounds(EMCState *script) { int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3); + _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1)); return 0; } @@ -682,7 +683,7 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) { _screen->hideMouse(); uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 2, xpos, ypos, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); @@ -753,7 +754,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { // what shouldn't happen. So we're not updating the screen for this special // case too. if (startFrame == 18 && endFrame == 18 && _currentRoom == 45) { - _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(18, 0, xpos, ypos, 0, 0, 0); delay(waitTime * _tickLength); return 0; } @@ -765,7 +766,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame >= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -783,7 +784,7 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int frame = startFrame; while (endFrame <= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); - _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos); + _movieObjects[wsaIndex]->displayFrame(frame, 0, xpos, ypos, 0, 0, 0); if (waitTime) _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { @@ -912,8 +913,6 @@ int KyraEngine_LoK::o1_placeCharacterInOtherScene(EMCState *script) { int KyraEngine_LoK::o1_getKey(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_getKey(%p) ()", (const void *)script); - // TODO: Check this implementation - while (true) { delay(10); @@ -1243,8 +1242,8 @@ int KyraEngine_LoK::o1_setFireberryGlowPalette(EMCState *script) { palIndex = 14; } } - const uint8 *palette = _specialPalettes[palIndex]; - memcpy(_screen->getPalette(1) + 684, palette, 44); + + _screen->getPalette(1).copy(_specialPalettes[palIndex], 0, 15, 228); return 0; } @@ -1276,7 +1275,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { if (code == 14) snd_playSoundEffect(0x73); - amulet.displayFrame(code, 0, 224, 152); + amulet.displayFrame(code, 0, 224, 152, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < nextTime) { @@ -1501,40 +1500,38 @@ int KyraEngine_LoK::o1_setNoDrawShapesFlag(EMCState *script) { int KyraEngine_LoK::o1_fadeEntirePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int cmd = stackPos(0); - uint8 *fadePal = 0; + + int fadePal = 0; if (_flags.platform == Common::kPlatformAmiga) { if (cmd == 0) { - fadePal = _screen->getPalette(2); - memset(fadePal, 0, 32*3); - memcpy(_screen->getPalette(4), _screen->getPalette(0), 32*3); + _screen->getPalette(2).clear(); + fadePal = 2; + _screen->copyPalette(4, 0); } else if (cmd == 1) { - fadePal = _screen->getPalette(0); - memcpy(_screen->getPalette(0), _screen->getPalette(4), 32*3); + fadePal = 0; + _screen->copyPalette(0, 4); } else if (cmd == 2) { - fadePal = _screen->getPalette(0); - memset(_screen->getPalette(2), 0, 32*3); + fadePal = 0; + _screen->getPalette(2).clear(); } } else { if (cmd == 0) { - fadePal = _screen->getPalette(2); - uint8 *screenPal = _screen->getPalette(0); - uint8 *backUpPal = _screen->getPalette(3); - - memcpy(backUpPal, screenPal, sizeof(uint8)*768); - memset(fadePal, 0, sizeof(uint8)*768); + fadePal = 2; + _screen->getPalette(2).clear(); + _screen->copyPalette(3, 0); } else if (cmd == 1) { - //fadePal = _screen->getPalette(3); + //fadePal = 3; warning("unimplemented o1_fadeEntirePalette function"); return 0; } else if (cmd == 2) { - memset(_screen->getPalette(2), 0, 768); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); - fadePal = _screen->getPalette(0); + _screen->getPalette(2).clear(); + _screen->copyPalette(0, 1); + fadePal = 0; } } - _screen->fadePalette(fadePal, stackPos(1)); + _screen->fadePalette(_screen->getPalette(fadePal), stackPos(1)); return 0; } diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 33edfa0e24..a606419722 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -206,12 +206,10 @@ int LoLEngine::olol_delay(EMCState *script) { int LoLEngine::olol_setGameFlag(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGameFlag(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - assert((stackPos(0) >> 4) < 40); - if (stackPos(1)) - _gameFlags[stackPos(0) >> 4] |= (1 << (stackPos(0) & 0x0f)); + setGameFlag(stackPos(0)); else - _gameFlags[stackPos(0) >> 4] &= (~(1 << (stackPos(0) & 0x0f))); + resetGameFlag(stackPos(0)); return 1; } @@ -221,12 +219,7 @@ int LoLEngine::olol_testGameFlag(EMCState *script) { if (stackPos(0) < 0) return 0; - assert((stackPos(0) >> 4) < 40); - - if (_gameFlags[stackPos(0) >> 4] & (1 << (stackPos(0) & 0x0f))) - return 1; - - return 0; + return queryGameFlag(stackPos(0)); } int LoLEngine::olol_loadLevelGraphics(EMCState *script) { @@ -616,7 +609,7 @@ int LoLEngine::olol_fadePalette(EMCState *script) { int LoLEngine::olol_loadBitmap(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_clearDialogueField(%p) (%s, %d)", (const void *)script, stackPosString(0), stackPos(1)); - _screen->loadBitmap(stackPosString(0), 3, 3, _screen->getPalette(3)); + _screen->loadBitmap(stackPosString(0), 3, 3, &_screen->getPalette(3)); if (stackPos(1) != 2) _screen->copyPage(3, stackPos(1)); return 1; @@ -670,7 +663,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) { case 12: return _drainMagic; case 13: - return _speechFlag; + return getVolume(kVolumeSpeech) - 2; default: break; } @@ -871,7 +864,7 @@ int LoLEngine::olol_fadeClearSceneWindow(EMCState *script) { int LoLEngine::olol_fadeSequencePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeSequencePalette(%p)", (const void *)script); - memcpy(_screen->getPalette(3) + 0x180, _screen->_currentPalette + 0x180, 0x180); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; @@ -883,7 +876,7 @@ int LoLEngine::olol_redrawPlayfield(EMCState *script) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; return 1; } @@ -1280,6 +1273,13 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) { return 0; } +int LoLEngine::olol_releaseMonsterShapes(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_releaseMonsterShapes(%p)", (const void *)script); + for (int i = 0; i < 3; i++) + releaseMonsterShapes(i); + return 0; +} + int LoLEngine::olol_playCharacterScriptChat(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playCharacterScriptChat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); snd_stopSpeech(1); @@ -1392,6 +1392,30 @@ int LoLEngine::olol_countAllMonsters(EMCState *script){ return res; } +int LoLEngine::olol_playEndSequence(EMCState *script){ + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playEndSequence(%p)", (const void *)script); + + int c = 0; + if (_characters[0].id == -9) + c = 1; + else if (_characters[0].id == -5) + c = 3; + else if (_characters[0].id == -1) + c = 2; + + while (snd_updateCharacterSpeech()) + delay(_tickLength); + + _eventList.clear(); + _screen->hideMouse(); + _screen->getPalette(1).clear(); + + showOutro(c, (_monsterDifficulty == 2)); + quitGame(); + + return 0; +} + int LoLEngine::olol_stopCharacterSpeech(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopCharacterSpeech(%p)", (const void *)script); snd_stopSpeech(1); @@ -1404,7 +1428,7 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) { uint16 old = _brightness; _brightness = stackPos(0); if (stackPos(1) == 1) - setPaletteBrightness(_screen->_currentPalette, stackPos(0), _lampEffect); + setPaletteBrightness(_screen->getPalette(0), stackPos(0), _lampEffect); return old; } @@ -1970,10 +1994,16 @@ int LoLEngine::olol_findInventoryItem(EMCState *script) { return -1; } +int LoLEngine::olol_drinkBezelCup(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drinkBezelCup(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + drinkBezelCup(3 - stackPos(0), stackPos(1)); + return 1; +} + int LoLEngine::olol_restoreFadePalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreFadePalette(%p)", (const void *)script); - memcpy(_screen->_currentPalette, _screen->getPalette(1), 384); - _screen->fadePalette(_screen->_currentPalette, 10); + _screen->getPalette(0).copy(_screen->getPalette(1), 0, 128); + _screen->fadePalette(_screen->getPalette(0), 10); _screen->_fadeFlag = 0; return 1; } @@ -2071,27 +2101,29 @@ int LoLEngine::olol_increaseSkill(EMCState *script) { int LoLEngine::olol_paletteFlash(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_paletteFlash(%p) (%d)", (const void *)script, stackPos(0)); - uint8 *s = _screen->getPalette(1); - uint8 *d = _screen->getPalette(3); + Palette &p1 = _screen->getPalette(1); + Palette &p2 = _screen->getPalette(3); + uint8 ovl[256]; - generateFlashPalette(s, d, stackPos(0)); - _screen->loadSpecialColors(s); - _screen->loadSpecialColors(d); + generateFlashPalette(p1, p2, stackPos(0)); + _screen->loadSpecialColors(p1); + _screen->loadSpecialColors(p2); if (_smoothScrollModeNormal) { for (int i = 0; i < 256; i++) ovl[i] = i; ovl[1] = 6; + _screen->copyRegion(112, 0, 112, 0, 176, 120, 0, 2); _screen->applyOverlay(112, 0, 176, 120, 0, ovl); } - _screen->setScreenPalette(d); + _screen->setScreenPalette(p2); _screen->updateScreen(); delay(2 * _tickLength); - _screen->setScreenPalette(s); + _screen->setScreenPalette(p1); if (_smoothScrollModeNormal) _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); @@ -2099,6 +2131,75 @@ int LoLEngine::olol_paletteFlash(EMCState *script) { return 0; } +int LoLEngine::olol_restoreMagicShroud(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreMagicShroud(%p)", (const void *)script); + + WSAMovie_v2 *mov = new WSAMovie_v2(this); + mov->open("DARKLITE.WSA", 2, 0); + if (!mov->opened()) + return 0; + + _screen->hideMouse(); + + // TODO: This function could need some major cleanup to work with our + // new palette code without needless conversions. + uint8 *fadeTab = new uint8[21504]; + uint8 *tpal1 = fadeTab; + uint8 *tpal2 = tpal1 + 768; + uint8 *tpal3 = tpal2 + 768; + uint8 *tpal4 = 0; + _res->loadFileToBuf("LITEPAL1.COL", tpal1, 768); + tpal2 = _screen->generateFadeTable(tpal3, 0, tpal1, 21); + _res->loadFileToBuf("LITEPAL2.COL", tpal2, 768); + tpal4 = tpal2; + tpal2 += 768; + _res->loadFileToBuf("LITEPAL3.COL", tpal1, 768); + _screen->generateFadeTable(tpal2, tpal4, tpal1, 4); + + Palette pal(768); + + for (int i = 0; i < 21; i++) { + uint32 etime = _system->getMillis() + 20 * _tickLength; + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); + _screen->updateScreen(); + + pal.copy(tpal3, 0, 256); + _screen->setScreenPalette(pal); + tpal3 += 768; + + if (i == 2 || i == 5 || i == 8 || i == 11 || i == 13 || i == 15 || i == 17 || i == 19) + snd_playSoundEffect(95, -1); + delayUntil(etime); + } + + pal.copy(tpal3, 0, 256); + snd_playSoundEffect(91, -1); + _screen->fadePalette(pal, 300); + tpal3 += 768; + + for (int i = 22; i < 38; i++) { + uint32 etime = _system->getMillis() + 12 * _tickLength; + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); + _screen->updateScreen(); + if (i == 22 || i == 24 || i == 28 || i == 32) { + snd_playSoundEffect(131, -1); + + pal.copy(tpal3, 0, 256); + _screen->setScreenPalette(pal); + tpal3 += 768; + } + delayUntil(etime); + } + + mov->close(); + delete mov; + delete[] fadeTab; + + _screen->showMouse(); + + return 1; +} + int LoLEngine::olol_disableControls(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_disableControls(%p) (%d)", (const void *)script, stackPos(0)); return gui_disableControls(stackPos(0)); @@ -2214,7 +2315,7 @@ int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_setupPaletteFadeEx(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - memcpy(_screen->getPalette(0), _screen->getPalette(1), 768); + _screen->copyPalette(0, 1); _screen->getFadeParams(_screen->getPalette(0), param[0], _tim->_palDelayInc, _tim->_palDiff); _tim->_palDelayAcc = 0; @@ -2292,7 +2393,6 @@ int LoLEngine::tlol_setPartyPosition(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeClearWindow(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - uint8 *tmp = 0; switch (param[0]) { case 0: @@ -2300,10 +2400,9 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { break; case 1: - tmp = _screen->getPalette(3); - memcpy(tmp + 0x180, _screen->_currentPalette + 0x180, 0x180); - _screen->loadSpecialColors(tmp); - _screen->fadePalette(tmp, 10); + _screen->getPalette(3).copy(_screen->getPalette(0), 128); + _screen->loadSpecialColors(_screen->getPalette(3)); + _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; break; @@ -2312,9 +2411,8 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { break; case 3: - tmp = _screen->getPalette(3); - _screen->loadSpecialColors(tmp); - _screen->fadePalette(tmp, 10); + _screen->loadSpecialColors(_screen->getPalette(3)); + _screen->fadePalette(_screen->getPalette(3), 10); _screen->_fadeFlag = 0; break; @@ -2322,13 +2420,12 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) { if (_screen->_fadeFlag != 2) _screen->fadeClearSceneWindow(10); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); _screen->_fadeFlag = 0; break; case 5: - tmp = _screen->getPalette(3); - _screen->loadSpecialColors(tmp); + _screen->loadSpecialColors(_screen->getPalette(3)); _screen->fadePalette(_screen->getPalette(1), 10); _screen->_fadeFlag = 0; break; @@ -2428,7 +2525,7 @@ int LoLEngine::tlol_fadeInScene(const TIM *tim, const uint16 *param) { strcpy(filename, sceneFile); strcat(filename, ".CPS"); - _screen->loadBitmap(filename, 7, 5, _screen->getPalette(0)); + _screen->loadBitmap(filename, 7, 5, &_screen->getPalette(0)); filename[0] = 0; @@ -2464,9 +2561,11 @@ int LoLEngine::tlol_unusedResourceFunc(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_fadeInPalette(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_fadeInPalette(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); const char *bitmap = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1))); - uint8 palette[768]; - _screen->loadBitmap(bitmap, 3, 3, palette); - _screen->fadePalette(palette, param[1]); + + Palette pal(_screen->getPalette(0).getNumColors()); + _screen->loadBitmap(bitmap, 3, 3, &pal); + _screen->fadePalette(pal, param[1]); + return 1; } @@ -2483,7 +2582,7 @@ int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) { if (param[1] == 0xFFFF) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK); } else { - anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0); + anim->wsa->displayFrame(param[1], 2, anim->x, anim->y, 0, 0, 0); _screen->copyRegion(anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->xAdd(), anim->wsa->yAdd(), anim->wsa->width(), anim->wsa->height(), 2, 0); } @@ -2654,7 +2753,7 @@ void LoLEngine::setupOpcodeTable() { // 0x5C Opcode(olol_getMonsterStat); - OpcodeUnImpl(); + Opcode(olol_releaseMonsterShapes); Opcode(olol_playCharacterScriptChat); Opcode(olol_update); @@ -2672,7 +2771,7 @@ void LoLEngine::setupOpcodeTable() { // 0x68 Opcode(olol_countAllMonsters); - OpcodeUnImpl(); + Opcode(olol_playEndSequence); Opcode(olol_stopCharacterSpeech); Opcode(olol_setPaletteBrightness); @@ -2769,7 +2868,7 @@ void LoLEngine::setupOpcodeTable() { // 0xA8 OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_drinkBezelCup); Opcode(olol_changeItemTypeOrFlag); // 0xAC @@ -2780,7 +2879,7 @@ void LoLEngine::setupOpcodeTable() { // 0xB0 Opcode(olol_paletteFlash); - OpcodeUnImpl(); + Opcode(olol_restoreMagicShroud); Opcode(olol_dummy1); // anim buffer select? Opcode(olol_disableControls); diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 558d703f15..1800bd1939 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -381,13 +381,10 @@ int KyraEngine_MR::o3_checkInRect(EMCState *script) { y += desc[1]; } - if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { - //XXX + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) return 1; - } else { - //XXX + else return 0; - } } int KyraEngine_MR::o3_updateConversations(EMCState *script) { diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index e9ca23a4c9..424a62aaf8 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -116,6 +116,33 @@ TIMInterpreter::~TIMInterpreter() { delete[] _animations; } +bool TIMInterpreter::callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case MKID_BE('TEXT'): + _tim->text = new byte[chunk._size]; + assert(_tim->text); + if (chunk._stream->read(_tim->text, chunk._size) != chunk._size) + error("Couldn't read TEXT chunk from file '%s'", _filename); + break; + + case MKID_BE('AVTL'): + _avtlChunkSize = chunk._size >> 1; + _tim->avtl = new uint16[_avtlChunkSize]; + assert(_tim->avtl); + if (chunk._stream->read(_tim->avtl, chunk._size) != chunk._size) + error("Couldn't read AVTL chunk from file '%s'", _filename); + + for (int i = _avtlChunkSize - 1; i >= 0; --i) + _tim->avtl[i] = READ_LE_UINT16(&_tim->avtl[i]); + break; + + default: + warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk._type), chunk._size, _filename); + } + + return false; +} + TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) { if (!_vm->resource()->exists(filename)) return 0; @@ -124,44 +151,21 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc if (!stream) error("Couldn't open TIM file '%s'", filename); - IFFParser iff(*stream); - Common::IFFChunk *chunk = 0; - - TIM *tim = new TIM; - assert(tim); - memset(tim, 0, sizeof(TIM)); + _avtlChunkSize = 0; + _filename = filename; - tim->procFunc = -1; - tim->opcodes = opcodes; + _tim = new TIM; + assert(_tim); + memset(_tim, 0, sizeof(TIM)); - int avtlChunkSize = 0; - - while ((chunk = iff.nextChunk()) != 0) { - switch (chunk->id) { - case MKID_BE('TEXT'): - tim->text = new byte[chunk->size]; - assert(tim->text); - if (chunk->read(tim->text, chunk->size) != chunk->size) - error("Couldn't read TEXT chunk from file '%s'", filename); - break; - - case MKID_BE('AVTL'): - avtlChunkSize = chunk->size >> 1; - tim->avtl = new uint16[avtlChunkSize]; - assert(tim->avtl); - if (chunk->read(tim->avtl, chunk->size) != chunk->size) - error("Couldn't read AVTL chunk from file '%s'", filename); - - for (int i = avtlChunkSize - 1; i >= 0; --i) - tim->avtl[i] = READ_LE_UINT16(&tim->avtl[i]); - break; + _tim->procFunc = -1; + _tim->opcodes = opcodes; - default: - warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename); - } - } + IFFParser iff(*stream); + Common::Functor1Mem< Common::IFFChunk &, bool, TIMInterpreter > c(this, &TIMInterpreter::callback); + iff.parse(c); - if (!tim->avtl) + if (!_tim->avtl) error("No AVTL chunk found in file: '%s'", filename); if (stream->err()) @@ -169,17 +173,17 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc delete stream; - int num = (avtlChunkSize < TIM::kCountFuncs) ? avtlChunkSize : (int)TIM::kCountFuncs; + int num = (_avtlChunkSize < TIM::kCountFuncs) ? _avtlChunkSize : (int)TIM::kCountFuncs; for (int i = 0; i < num; ++i) - tim->func[i].avtl = tim->avtl + tim->avtl[i]; + _tim->func[i].avtl = _tim->avtl + _tim->avtl[i]; - strncpy(tim->filename, filename, 13); - tim->filename[12] = 0; + strncpy(_tim->filename, filename, 13); + _tim->filename[12] = 0; - tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM"); - tim->lolCharacter = 0; + _tim->isLoLOutro = (_vm->gameFlags().gameID == GI_LOL) && !scumm_stricmp(filename, "LOLFINAL.TIM"); + _tim->lolCharacter = 0; - return tim; + return _tim; } void TIMInterpreter::unload(TIM *&tim) const { @@ -300,13 +304,15 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { memcpy(filename, text+1, end-1-text); } - if (filename[0]) + const bool isPC98 = (_vm->gameFlags().platform == Common::kPlatformPC98); + if (filename[0] && (_vm->speechEnabled() || isPC98)) _vm->sound()->voicePlay(filename); if (text[0] == '$') text = strchr(text + 1, '$') + 1; - setupTextPalette((flags < 0) ? 1 : flags, 0); + if (!isPC98) + setupTextPalette((flags < 0) ? 1 : flags, 0); if (flags < 0) { static const uint8 colorMap[] = { 0x00, 0xF0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -324,7 +330,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { char *str = text; int heightAdd = 0; - while (str[0]) { + while (str[0] && _vm->textEnabled()) { char *nextLine = strchr(str, '\r'); backupChar = 0; @@ -335,10 +341,16 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { int width = _screen->getTextWidth(str); - if (flags >= 0) - _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00); - else + if (flags >= 0) { + if (isPC98) { + static const uint8 colorMap[] = { 0xE1, 0xE1, 0xC1, 0xA1, 0x81, 0x61 }; + _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, colorMap[flags], 0x00); + } else { + _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, 0xF0, 0x00); + } + } else { _screen->printText(str, (320 - width) >> 1, 188, 0xF0, 0x00); + } heightAdd += _screen->getFontHeight(); str += strlen(str); @@ -423,7 +435,7 @@ void TIMInterpreter::setupTextPalette(uint index, int fadePalette) { }; for (int i = 0; i < 15; ++i) { - uint8 *palette = _screen->getPalette(0) + (240 + i) * 3; + uint8 *palette = _screen->getPalette(0).getData() + (240 + i) * 3; uint8 c1 = (((15 - i) << 2) * palTable[index*3+0]) / 100; uint8 c2 = (((15 - i) << 2) * palTable[index*3+1]) / 100; @@ -471,10 +483,10 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char if (isLoLDemo) anim->wsa = new WSAMovie_v1(_vm); else - anim->wsa = new WSAMovie_v2(_vm, _screen); + anim->wsa = new WSAMovie_v2(_vm); assert(anim->wsa); - anim->wsa->open(file, wsaOpenFlags, (index == 1) ? _screen->getPalette(0) : 0); + anim->wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); } if (anim->wsa && anim->wsa->opened()) { @@ -511,14 +523,14 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char snprintf(file, 32, "%s.CPS", filename); if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, _screen->getPalette(0)); + _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); _screen->updateScreen(); } - anim->wsa->displayFrame(0, 0, x, y, 0); + anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); } if (wsaFlags & 2) @@ -535,7 +547,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char snprintf(file, 32, "%s.CPS", filename); if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, _screen->getPalette(0)); + _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); @@ -941,21 +953,21 @@ TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const c snprintf(file, 32, "%s.WSA", filename); if (_vm->resource()->exists(file)) { - anim->wsa = new WSAMovie_v2(_vm, TIMInterpreter::_screen); + anim->wsa = new WSAMovie_v2(_vm); assert(anim->wsa); - anim->wsa->open(file, wsaOpenFlags, _screen->getPalette(3)); + anim->wsa->open(file, wsaOpenFlags, &_screen->getPalette(3)); } if (wsaFlags & 1) { if (_screen->_fadeFlag != 1) _screen->fadeClearSceneWindow(10); - memcpy(_screen->getPalette(3) + 384, _screen->_currentPalette + 384, 384); + _screen->getPalette(3).copy(_screen->getPalette(0), 128, 128); } else if (wsaFlags & 2) { _screen->fadeToBlack(10); } if (wsaFlags & 7) - anim->wsa->displayFrame(0, 0, x, y, 0); + anim->wsa->displayFrame(0, 0, x, y, 0, 0, 0); if (wsaFlags & 3) { _screen->loadSpecialColors(_screen->getPalette(3)); @@ -1000,7 +1012,7 @@ void TIMInterpreter_LoL::advanceToOpcode(int opcode) { void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) { _screen->setScreenDim(5); - if (numStr == 1 && _vm->_speechFlag) { + if (numStr == 1 && _vm->speechEnabled()) { _dialogueNumButtons = 0; _dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0; } else { @@ -1051,7 +1063,7 @@ void TIMInterpreter_LoL::startBackgroundAnimation(int animIndex, int part) { // WORKAROUND for some bugged scripts that will try to display frames of non-existent animations if (anim->wsa) - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); } void TIMInterpreter_LoL::stopBackgroundAnimation(int animIndex) { @@ -1110,7 +1122,7 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) { anim->nextFrame += (anim->frameDelay * _vm->_tickLength); - anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0); anim->nextFrame += _system->getMillis(); } @@ -1126,10 +1138,12 @@ void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int la _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); _screen->updateScreen(); } else { - anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0); + anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0); _screen->updateScreen(); } - _vm->delayUntil(next); + int32 del = (int32)(next - _system->getMillis()); + if (del > 0) + _vm->delay(del, true); } } @@ -1162,7 +1176,8 @@ uint16 TIMInterpreter_LoL::processDialogue() { int x = _dialogueButtonPosX; for (int i = 0; i < _dialogueNumButtons; i++) { - if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { + Common::Point p = _vm->getMousePos(); + if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { _dialogueHighlightedButton = i; break; } @@ -1222,7 +1237,8 @@ uint16 TIMInterpreter_LoL::processDialogue() { x = _dialogueButtonPosX; for (int i = 0; i < _dialogueNumButtons; i++) { - if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { + Common::Point p = _vm->getMousePos(); + if (_vm->posWithinRect(p.x, p.y, x, _dialogueButtonPosY, x + 74, _dialogueButtonPosY + 9)) { _dialogueHighlightedButton = i; res = _dialogueHighlightedButton + 1; break; diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index 10337b4b09..40049c3dec 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -121,6 +121,8 @@ public: TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes); void unload(TIM *&tim) const; + bool callback(Common::IFFChunk &chunk); + virtual Animation *initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags); virtual int freeAnimStruct(int index); @@ -169,6 +171,11 @@ protected: bool _finished; + // used when loading + int _avtlChunkSize; + const char *_filename; + TIM *_tim; + Common::String _vocFiles[120]; Animation *_animations; diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index 54d6f2cbe3..2145591c03 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -92,7 +92,7 @@ uint8 *SeqPlayer::setPanPages(int pageNum, int shape) { } void SeqPlayer::makeHandShapes() { - _screen->loadBitmap("WRITING.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("WRITING.CPS", 3, 3, &_screen->getPalette(0)); if (_vm->gameFlags().platform == Common::kPlatformMacintosh || _vm->gameFlags().platform == Common::kPlatformAmiga) { freeHandShapes(); @@ -148,7 +148,7 @@ void SeqPlayer::s1_wsaPlayFrame() { _seqMovies[wsaObj].pos.x = READ_LE_UINT16(_seqData); _seqData += 2; _seqMovies[wsaObj].pos.y = *_seqData++; assert(_seqMovies[wsaObj].movie); - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); _seqMovies[wsaObj].frame = frame; } @@ -160,7 +160,7 @@ void SeqPlayer::s1_wsaPlayNextFrame() { frame = 0; _seqMovies[wsaObj].frame = 0; } - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); } void SeqPlayer::s1_wsaPlayPrevFrame() { @@ -171,7 +171,7 @@ void SeqPlayer::s1_wsaPlayPrevFrame() { frame = _seqMovies[wsaObj].numFrames; _seqMovies[wsaObj].frame = frame; } else { - _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y); + _seqMovies[wsaObj].movie->displayFrame(frame, _seqMovies[wsaObj].page, _seqMovies[wsaObj].pos.x, _seqMovies[wsaObj].pos.y, 0, 0, 0); } } @@ -194,21 +194,18 @@ void SeqPlayer::s1_copyWaitTicks() { void SeqPlayer::s1_shuffleScreen() { _screen->shuffleScreen(0, 16, 320, 128, 2, 0, 0, false); - _screen->_curPage = 2; if (_specialBuffer) - _screen->copyCurPageBlock(0, 16, 40, 128, _specialBuffer); + _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer); _screen->_curPage = 0; } void SeqPlayer::s1_copyView() { - int y = 128; - if (!_copyViewOffs) - y -= 8; + int h = !_copyViewOffs ? 120 : 128; if (_specialBuffer && !_copyViewOffs) - _screen->copyToPage0(16, y, 3, _specialBuffer); + _screen->copyToPage0(16, h, 3, _specialBuffer); else - _screen->copyRegion(0, 16, 0, 16, 320, y, 2, 0); + _screen->copyRegion(0, 16, 0, 16, 320, h, 2, 0); } void SeqPlayer::s1_loopInit() { @@ -244,25 +241,21 @@ void SeqPlayer::s1_loadPalette() { if (_vm->gameFlags().platform == Common::kPlatformAmiga) { if (!colNum) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 576, 3*32); + _screen->copyPalette(0, 6); else if (colNum == 3) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 672, 3*32); + _screen->copyPalette(0, 7); else if (colNum == 4) - memcpy(_screen->_currentPalette, _screen->_currentPalette + 288, 3*32); + _screen->copyPalette(0, 3); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); } else { - uint32 fileSize; - uint8 *srcData; - srcData = _res->fileData(_vm->seqCOLTable()[colNum], &fileSize); - memcpy(_screen->_currentPalette, srcData, fileSize); - delete[] srcData; + _screen->loadPalette(_vm->seqCOLTable()[colNum], _screen->getPalette(0)); } } void SeqPlayer::s1_loadBitmap() { uint8 cpsNum = *_seqData++; - _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, _screen->_currentPalette); + _screen->loadBitmap(_vm->seqCPSTable()[cpsNum], 3, 3, &_screen->getPalette(0)); } void SeqPlayer::s1_fadeToBlack() { @@ -449,10 +442,7 @@ void SeqPlayer::s1_allocTempBuffer() { if (!_specialBuffer && !_copyViewOffs) { _specialBuffer = new uint8[40960]; assert(_specialBuffer); - int page = _screen->_curPage; - _screen->_curPage = 0; - _screen->copyCurPageBlock(0, 0, 320, 128, _specialBuffer); - _screen->_curPage = page; + _screen->copyRegionToBuffer(2, 0, 16, 320, 128, _specialBuffer); } } } diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 4e53399fbf..90b2fdd580 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -62,7 +62,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { int oldPage = _screen->setCurPage(2); for (int i = 0; i < 4; ++i) - memset(_screen->getPalette(i), 0, 0x300); + _screen->getPalette(i).clear(); _screen->clearPage(10); _screen->clearPage(12); @@ -77,7 +77,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { _screen->clearPage(0); _screen->clearPage(8); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); _seqFrameCounter = 0; _seqStartTime = _system->getMillis(); @@ -87,7 +87,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { SeqProc cb = _callbackS[seqNum]; if (cseq.flags & 2) { - _screen->loadBitmap(cseq.cpsFile, 2, 2, _screen->getPalette(0)); + _screen->loadBitmap(cseq.cpsFile, 2, 2, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); } else { _screen->setCurPage(2); @@ -100,9 +100,9 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (cseq.flags & 1) { _seqWsa->close(); - _seqWsa->open(cseq.wsaFile, 0, _screen->getPalette(0)); + _seqWsa->open(cseq.wsaFile, 0, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); - _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0); + _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0, 0, 0); } if (cseq.flags & 4) { @@ -174,7 +174,7 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { if (_seqWsa) { int f = _seqWsaCurrentFrame % _seqWsa->frames(); - _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0); + _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0, 0, 0); } _screen->copyPage(2, 12); @@ -361,7 +361,7 @@ int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { } int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - uint8 *tmpPal = &(_screen->getPalette(3)[0x101]); + uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101; memset(tmpPal, 0, 256); _seqSubFrameEndTimeInternal = 0; uint32 now = 0; @@ -372,9 +372,9 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm _sound->playTrack(4); _seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength; - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -384,7 +384,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm break; case 1: - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x40, 0, 0, 0, 0x100, true); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); for (int i = 0; i < 256; i++) tmpPal[_screen->getPalette(3)[i]] = 1; @@ -417,7 +417,7 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm case 201: _screen->setScreenPalette(_screen->getPalette(2)); _screen->updateScreen(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->setScreenPalette(_screen->getPalette(0)); @@ -465,10 +465,10 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) _seqSubframePlaying = true; _sound->playTrack(5); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -482,7 +482,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) seq_waitForTextsTimeout(); _screen->copyPage(12, 2); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); _screen->copyPage(2, 12); @@ -503,7 +503,7 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) case 340: seq_resetActiveWSA(0); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); @@ -539,10 +539,10 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { _seqSubframePlaying = true; _sound->playTrack(6); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -556,7 +556,7 @@ int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { case 201: seq_waitForTextsTimeout(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3)); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); @@ -631,9 +631,9 @@ int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) { _seqTextColor[1] = 0xf7; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false); + _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); break; case 1: @@ -661,7 +661,7 @@ int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) _seqTextColor[1] = 0xfd; memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; _screen->setTextColorMap(_seqTextColorMap); break; @@ -831,7 +831,7 @@ int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm case 0: _sound->playTrack(3); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -924,7 +924,7 @@ int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 255; _screen->setTextColorMap(_seqTextColorMap); @@ -1006,7 +1006,7 @@ int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1096,7 +1096,7 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1172,9 +1172,9 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) break; case 0: - _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 254) & 0xff); + _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 254) & 0xff); memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 254) & 0xff); + _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff); _screen->setTextColorMap(_seqTextColorMap); seq_playTalkText(_flags.isTalkie ? 30 : 26); break; @@ -1339,7 +1339,7 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1426,7 +1426,7 @@ int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) case 0: if (_seqFrameCounter == 1) { _sound->playTrack(4); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff; + _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; memset(_seqTextColorMap, _seqTextColor[1], 16); _seqTextColor[0] = _seqTextColorMap[1] = 0xff; _screen->setTextColorMap(_seqTextColorMap); @@ -1501,7 +1501,7 @@ void KyraEngine_HoF::seq_finaleActorScreen() { static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; - _screen->loadBitmap("finale.cps", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); _screen->setFont(Screen::FID_GOLDFONT_FNT); int talkieCreditsSize, talkieCreditsSpecialSize; @@ -1781,19 +1781,21 @@ int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { #ifdef ENABLE_LOL int KyraEngine_HoF::seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - uint8 *tmpPal = _screen->getPalette(2); + Palette &tmpPal = _screen->getPalette(2); if (!(_seqFrameCounter % 100)) { if (_seqFrameCounter == 0) { _sound->haltTrack(); _sound->playTrack(6); } - memcpy(tmpPal, _screen->getPalette(0), 0x300); + tmpPal.copy(_screen->getPalette(0)); + for (int i = 3; i < 0x300; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; if (tmpPal[i] > 0x3f) tmpPal[i] = 0x3f; } + seq_playTalkText(_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); @@ -1926,13 +1928,15 @@ int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm if (_seqFrameCounter % 175) { _screen->setScreenPalette(_screen->getPalette(0)); } else { - uint8 *tmpPal = _screen->getPalette(2); - memcpy(tmpPal, _screen->getPalette(0), 0x300); + Palette &tmpPal = _screen->getPalette(2); + tmpPal.copy(_screen->getPalette(0)); + for (int i = 3; i < 0x300; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; if (tmpPal[i] > 0x3f) tmpPal[i] = 0x3f; } + seq_playTalkText(_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); @@ -2045,37 +2049,35 @@ char *KyraEngine_HoF::seq_preprocessString(const char *srcStr, int width) { } void KyraEngine_HoF::seq_sequenceCommand(int command) { - uint8 pal[768]; - for (int i = 0; i < 8; i++) seq_resetActiveWSA(i); switch (command) { case 0: - memset(pal, 0, 0x300); - _screen->fadePalette(pal, 36); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + _screen->fadeToBlack(36); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); break; case 1: - memset(pal, 0x3F, 0x300); seq_playTalkText(_rnd.getRandomBit()); - _screen->fadePalette(pal, 16); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + + _screen->getPalette(0).fill(0, 256, 0x3F); + _screen->fadePalette(_screen->getPalette(0), 16); + + _screen->copyPalette(1, 0); break; case 3: _screen->copyPage(2, 0); _screen->fadePalette(_screen->getPalette(0), 16); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); break; case 4: _screen->copyPage(2, 0); _screen->fadePalette(_screen->getPalette(0), 36); - memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300); + _screen->copyPalette(1, 0); break; case 5: @@ -2093,17 +2095,17 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) { break; case 8: - memset(pal, 0, 0x300); - _screen->fadePalette(pal, 16); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); + _screen->fadeToBlack(16); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); delay(120 * _tickLength); break; - case 9: - for (int i = 0; i < 0x100; i++) { - int pv = (_screen->getPalette(0)[3 * i] + _screen->getPalette(0)[3 * i + 1] + _screen->getPalette(0)[3 * i + 2]) / 3; + case 9: { + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 256; i++) { + int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3; pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff; } @@ -2112,9 +2114,8 @@ void KyraEngine_HoF::seq_sequenceCommand(int command) { //pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f; _screen->fadePalette(pal, 64); - memcpy(_screen->getPalette(0), pal, 0x300); - memcpy(_screen->getPalette(1), pal, 0x300); - break; + _screen->copyPalette(1, 0); + } break; default: break; @@ -2201,7 +2202,7 @@ void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { NestedSequence s = _sequences->seqn[seqNum]; if (!_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie = new WSAMovie_v2(this, _screen); + _activeWSA[wsaNum].movie = new WSAMovie_v2(this); assert(_activeWSA[wsaNum].movie); } @@ -2246,7 +2247,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { case 0: xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2); break; @@ -2254,7 +2255,7 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { case 1: xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1); break; @@ -2263,21 +2264,21 @@ void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { seq_waitForTextsTimeout(); xa = -_activeWSA[wsaNum].movie->xAdd(); ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0); + _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0, 0, 0); seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2); break; case 3: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene2.cmp"); break; case 4: _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0); + _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 12); seq_cmpFadeFrame("scene3.cmp"); break; @@ -2364,10 +2365,10 @@ bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { if (_activeWSA[wsaNum].movie) { if (_activeWSA[wsaNum].flags & 0x20) { - _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); + _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); _activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay; } else { - _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000); + _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); } } @@ -2477,7 +2478,7 @@ void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, i _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; if (wsa) - wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0); + wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0); _screen->copyPage(2, 12); @@ -2663,9 +2664,9 @@ void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int if (palCycle) { for (int col = 133; col > 112; col--) - memcpy(_screen->_currentPalette + (col * 3), _screen->_currentPalette + ((col - 1) * 3), 3); - memcpy(_screen->_currentPalette + 336, _screen->_currentPalette + 399, 3); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); + _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); + _screen->setScreenPalette(_screen->getPalette(0)); } delayUntil(_seqSubFrameEndTimeInternal); @@ -2721,32 +2722,32 @@ void KyraEngine_HoF::seq_scrollPage(int bottom, int top) { } void KyraEngine_HoF::seq_showStarcraftLogo() { - WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(2); _res->loadPakFile("INTROGEN.PAK"); - int endframe = ci->open("ci.wsa", 0, _screen->_currentPalette); + int endframe = ci->open("ci.wsa", 0, &_screen->getPalette(0)); _res->unloadPakFile("INTROGEN.PAK"); if (!ci->opened()) { delete ci; return; } _screen->hideMouse(); - ci->displayFrame(0, 2, 0, 0, 0); + ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { _seqEndTime = _system->getMillis() + 50; if (skipFlag()) break; - ci->displayFrame(i, 2, 0, 0, 0); + ci->displayFrame(i, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); } if (!skipFlag()) { _seqEndTime = _system->getMillis() + 50; - ci->displayFrame(0, 2, 0, 0, 0); + ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(_seqEndTime - _system->getMillis()); @@ -2760,7 +2761,7 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { void KyraEngine_HoF::seq_init() { _seqProcessedString = new char[200]; - _seqWsa = new WSAMovie_v2(this, _screen); + _seqWsa = new WSAMovie_v2(this); _activeWSA = new ActiveWSA[8]; _activeText = new ActiveText[10]; diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 12ede98ad4..d483409090 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -42,7 +42,7 @@ namespace Kyra { void KyraEngine_LoK::seq_demo() { snd_playTheme(0, 2); - _screen->loadBitmap("START.CPS", 7, 7, _screen->_currentPalette); + _screen->loadBitmap("START.CPS", 7, 7, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); _screen->fadeFromBlack(); @@ -50,8 +50,8 @@ void KyraEngine_LoK::seq_demo() { _screen->fadeToBlack(); _screen->clearPage(0); - _screen->loadBitmap("TOP.CPS", 7, 7, NULL); - _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette); + _screen->loadBitmap("TOP.CPS", 7, 7, 0); + _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0)); _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0); _screen->updateScreen(); @@ -77,7 +77,7 @@ void KyraEngine_LoK::seq_demo() { _seq->playSequence(_seq_Demo4, true); _screen->clearPage(0); - _screen->loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette); + _screen->loadBitmap("FINAL.CPS", 7, 7, &_screen->getPalette(0)); _screen->_curPage = 0; _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0); _screen->updateScreen(); @@ -128,7 +128,7 @@ void KyraEngine_LoK::seq_intro() { void KyraEngine_LoK::seq_introLogos() { if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { - _screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("LOGO.CPS", 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); _screen->fadeFromBlack(); @@ -141,7 +141,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->clearPage(0); if (_flags.platform == Common::kPlatformAmiga) { - _screen->loadPalette("INTRO.PAL", _screen->_currentPalette); + _screen->loadPaletteTable("INTRO.PAL", 0); _screen->loadBitmap("BOTTOM.CPS", 3, 5, 0); _screen->loadBitmap("TOP.CPS", 3, 3, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 2, 0); @@ -149,7 +149,7 @@ void KyraEngine_LoK::seq_introLogos() { _screen->copyRegion(0, 0, 0, 0, 320, 190, 0, 2); } else { _screen->loadBitmap("TOP.CPS", 7, 7, 0); - _screen->loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette); + _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0)); _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0); _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0); } @@ -166,8 +166,8 @@ void KyraEngine_LoK::seq_introLogos() { delay(60 * _tickLength); if (_flags.platform == Common::kPlatformAmiga) { - memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*32, 3*32); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->copyPalette(0, 1); + _screen->setScreenPalette(_screen->getPalette(0)); } if ((_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) && !seq_skipSequence()) || shouldQuit()) { @@ -181,7 +181,7 @@ void KyraEngine_LoK::seq_introLogos() { return; if (_flags.platform == Common::kPlatformAmiga) { - memcpy(_screen->_currentPalette, _screen->_currentPalette + 3*64, 3*32); + _screen->copyPalette(0, 2); _screen->fadeToBlack(); _screen->copyRegion(0, 0, 0, 0, 320, 200, 4, 0); _screen->fadeFromBlack(); @@ -236,22 +236,22 @@ void KyraEngine_LoK::seq_introStory() { return; if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) - _screen->loadBitmap("TEXT.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN) - _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::DE_DEU) - _screen->loadBitmap("TEXT_GER.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_GER.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::FR_FRA) - _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::ES_ESP) - _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::IT_ITA && !_flags.isTalkie) - _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, &_screen->getPalette(0)); else if (_flags.lang == Common::IT_ITA && _flags.isTalkie) - _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0)); else warning("no story graphics file found"); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0); if (_flags.lang == Common::JA_JPN) { @@ -569,12 +569,9 @@ void KyraEngine_LoK::seq_winterScroll1() { _sprites->_anims[i].play = false; _animator->sprites()[i].active = 0; } - uint8 tmpPal[768]; - memcpy(tmpPal, _screen->_currentPalette, 768); - memcpy(&tmpPal[684], palTable2()[0], 60); - _screen->fadePalette(tmpPal, 72); - memcpy(&_screen->_currentPalette[684], palTable2()[0], 60); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228); + _screen->fadePalette(_screen->getPalette(0), 72); + _screen->setScreenPalette(_screen->getPalette(0)); setGameFlag(0xB3); } else { delayWithTicks(120); @@ -950,8 +947,8 @@ int KyraEngine_LoK::seq_playEnd() { _screen->hideMouse(); _screen->fadeSpecialPalette(32, 228, 20, 60); delay(60 * _tickLength); - _screen->loadBitmap("GEMHEAL.CPS", 3, 3, _screen->_currentPalette); - _screen->setScreenPalette(_screen->_currentPalette); + _screen->loadBitmap("GEMHEAL.CPS", 3, 3, &_screen->getPalette(0)); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0); uint32 nextTime = _system->getMillis() + 120 * _tickLength; _finalA = new WSAMovie_v1(this); @@ -966,7 +963,7 @@ int KyraEngine_LoK::seq_playEnd() { else if (i == 20) snd_playSoundEffect(0x0E); nextTime = _system->getMillis() + 8 * _tickLength; - _finalA->displayFrame(i, 0, 8, 8); + _finalA->displayFrame(i, 0, 8, 8, 0, 0, 0); _screen->updateScreen(); } delete _finalA; @@ -1004,14 +1001,14 @@ void KyraEngine_LoK::seq_playEnding() { _screen->hideMouse(); _screen->_curPage = 0; _screen->fadeToBlack(); - _screen->loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette); + _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0)); _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); _screen->_curPage = 0; // XXX assert(_homeString); drawSentenceCommand(_homeString[0], 179); - memset(_screen->getPalette(2), 0, sizeof(uint8)*768); + _screen->getPalette(2).clear(); _screen->setScreenPalette(_screen->getPalette(2)); _seqPlayerFlag = true; @@ -1045,7 +1042,7 @@ void KyraEngine_LoK::seq_playCredits() { } else _screen->setFont(Screen::FID_8_FNT); - _screen->loadBitmap("CHALET.CPS", 4, 4, _screen->_currentPalette); + _screen->loadBitmap("CHALET.CPS", 4, 4, &_screen->getPalette(0)); _screen->setCurPage(0); _screen->clearCurPage(); @@ -1123,10 +1120,10 @@ void KyraEngine_LoK::seq_playCredits() { _screen->setCurPage(2); - memset(_screen->getPalette(2), 0, sizeof(uint8)*768); + _screen->getPalette(2).clear(); _screen->setScreenPalette(_screen->getPalette(2)); _screen->copyRegion(8, 32, 8, 32, 312, 128, 4, 0, Screen::CR_NO_P_CHECK); - _screen->fadePalette(_screen->_currentPalette, 0x5A); + _screen->fadePalette(_screen->getPalette(0), 0x5A); Common::Event event; bool finished = false; @@ -1198,7 +1195,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 2: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1213,7 +1210,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { if (_system->getMillis() < timer1) { if (_system->getMillis() >= timer2) { frame = _rnd.getRandomNumberRng(14, 17); - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; } @@ -1225,7 +1222,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 4: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1239,7 +1236,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 5: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1253,7 +1250,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 6: if (_unkEndSeqVar4) { if (frame <= 33 && _system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1278,7 +1275,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { case 8: if (_system->getMillis() >= timer2) { - _finalA->displayFrame(frame, 0, 8, 46); + _finalA->displayFrame(frame, 0, 8, 46, 0, 0, 0); _screen->updateScreen(); timer2 = _system->getMillis() + 8 * _tickLength; ++frame; @@ -1295,7 +1292,7 @@ int KyraEngine_LoK::handleMalcolmFlag() { snd_playSoundEffect(12); for (int i = 0; i < 18; ++i) { timer2 = _system->getMillis() + 4 * _tickLength; - _finalC->displayFrame(i, 0, 16, 50); + _finalC->displayFrame(i, 0, 16, 50, 0, 0, 0); _screen->updateScreen(); delayUntil(timer2); } @@ -1353,7 +1350,7 @@ int KyraEngine_LoK::handleBeadState() { switch (_beadStateVar) { case 0: if (beadState1.x != -1 && _endSequenceBackUpRect) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); } @@ -1367,7 +1364,7 @@ int KyraEngine_LoK::handleBeadState() { case 1: if (beadState1.x != -1) { if (_endSequenceBackUpRect) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); } beadState1.x = -1; @@ -1402,14 +1399,14 @@ int KyraEngine_LoK::handleBeadState() { beadState1.dstY = beadState1.y; return 0; } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; } } - _screen->copyCurPageBlock(x >> 3, y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, x, y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) @@ -1422,12 +1419,12 @@ int KyraEngine_LoK::handleBeadState() { case 3: if (_system->getMillis() >= timer1) { timer1 = _system->getMillis() + 4 * _tickLength; - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = beadState1.dstX + table1[beadState1.tableIndex]; beadState1.y = beadState1.dstY + table2[beadState1.tableIndex]; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], beadState1.x, beadState1.y, 0, 0); if (_lastDisplayedPanPage >= 17) @@ -1476,11 +1473,11 @@ int KyraEngine_LoK::handleBeadState() { _beadStateVar = 0; } } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) { _lastDisplayedPanPage = 0; @@ -1496,24 +1493,24 @@ int KyraEngine_LoK::handleBeadState() { int x = 0, y = 0; if (processBead(beadState1.x, beadState1.y, x, y, &beadState2)) { if (beadState2.dstX == 290) { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); uint32 nextRun = 0; for (int i = 0; i < 8; ++i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i, 0, 224, 8); + _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } snd_playSoundEffect(0x0D); for (int i = 7; i >= 0; --i) { nextRun = _system->getMillis() + _tickLength; - _finalB->displayFrame(i, 0, 224, 8); + _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0); _screen->updateScreen(); delayUntil(nextRun); } initBeadState(beadState1.x, beadState1.y, 63, 60, 12, &beadState2); } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = -1; beadState1.tableIndex = 0; @@ -1521,11 +1518,11 @@ int KyraEngine_LoK::handleBeadState() { _malcolmFlag = 9; } } else { - _screen->copyFromCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; - _screen->copyCurPageBlock(beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyRegionToBuffer(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0); if (_lastDisplayedPanPage > 17) _lastDisplayedPanPage = 0; @@ -1679,11 +1676,11 @@ void KyraEngine_LoK::updateKyragemFading() { _kyragemFadingState.timerCount = _system->getMillis() + 4 * _tickLength; int palPos = 684; for (int i = 0; i < 20; ++i) { - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset]; - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset]; - _screen->_currentPalette[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset]; + _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset]; } - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _animator->_updateScreen = true; switch (_kyragemFadingState.nextOperation) { case 0: diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index bba384ced4..beea129f66 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -43,7 +43,7 @@ int LoLEngine::processPrologue() { if (_flags.isDemo) { _screen->fadePalette(_screen->getPalette(1), 30, 0); - _screen->loadBitmap("FINAL.CPS", 2, 2, _screen->getPalette(0)); + _screen->loadBitmap("FINAL.CPS", 2, 2, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); _screen->fadePalette(_screen->getPalette(0), 30, 0); delayWithTicks(300); @@ -57,7 +57,7 @@ int LoLEngine::processPrologue() { int processSelection = -1; while (!shouldQuit() && processSelection == -1) { - _screen->loadBitmap("TITLE.CPS", 2, 2, _screen->getPalette(0)); + _screen->loadBitmap("TITLE.CPS", 2, 2, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); _screen->setFont(Screen::FID_6_FNT); @@ -71,11 +71,14 @@ int LoLEngine::processPrologue() { _eventList.clear(); int selection = mainMenu(); - _screen->hideMouse(); - // Unlike the original, we add a nice fade to black - memset(_screen->getPalette(0), 0, 768); - _screen->fadePalette(_screen->getPalette(0), 0x54); + if (selection != 3) { + _screen->hideMouse(); + + // Unlike the original, we add a nice fade to black + _screen->getPalette(0).clear(); + _screen->fadeToBlack(0x54); + } switch (selection) { case 0: // New game @@ -90,7 +93,8 @@ int LoLEngine::processPrologue() { break; case 3: // Load game - //processSelection = 3; + if (_gui->runMenu(_gui->_loadMenu)) + processSelection = 3; break; case 4: // Quit game @@ -100,7 +104,7 @@ int LoLEngine::processPrologue() { } } - if (processSelection == 0 || processSelection == 3) { + if (processSelection == 0) { _sound->loadSoundFile(0); _sound->playTrack(6); chooseCharacter(); @@ -131,7 +135,6 @@ void LoLEngine::setupPrologueData(bool load) { const char * const *fileList = _flags.isTalkie ? fileListCD : (_flags.useInstallerPackage ? fileListFloppy : fileListFloppyExtracted); - char filename[32]; for (uint i = 0; fileList[i]; ++i) { filename[0] = '\0'; @@ -155,7 +158,7 @@ void LoLEngine::setupPrologueData(bool load) { _screen->clearPage(3); if (load) { - _chargenWSA = new WSAMovie_v2(this, _screen); + _chargenWSA = new WSAMovie_v2(this); assert(_chargenWSA); //_charSelection = -1; @@ -165,7 +168,7 @@ void LoLEngine::setupPrologueData(bool load) { _selectionAnimFrames[1] = _selectionAnimFrames[3] = 1; memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers)); - memset(_screen->getPalette(1), 0, 768); + _screen->getPalette(1).clear(); _sound->setSoundList(&_soundData[kMusicIntro]); @@ -181,9 +184,8 @@ void LoLEngine::setupPrologueData(bool load) { } else { delete _chargenWSA; _chargenWSA = 0; - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); if (shouldQuit()) return; @@ -200,9 +202,8 @@ void LoLEngine::showIntro() { if (_flags.platform == Common::kPlatformPC98) showStarcraftLogo(); - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); _screen->clearPage(4); @@ -274,8 +275,8 @@ int LoLEngine::chooseCharacter() { while (!_screen->isMouseVisible()) _screen->showMouse(); - _screen->loadBitmap("CHAR.CPS", 2, 2, _screen->getPalette(0)); - _screen->loadBitmap("BACKGRND.CPS", 4, 4, _screen->getPalette(0)); + _screen->loadBitmap("CHAR.CPS", 2, 2, &_screen->getPalette(0)); + _screen->loadBitmap("BACKGRND.CPS", 4, 4, &_screen->getPalette(0)); if (!_chargenWSA->open("CHARGEN.WSA", 1, 0)) error("Couldn't load CHARGEN.WSA"); @@ -368,7 +369,7 @@ void LoLEngine::kingSelectionIntro() { _sound->voicePlay("KING01", &_speechHandle); int index = 4; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -384,7 +385,7 @@ void LoLEngine::kingSelectionIntro() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -407,7 +408,7 @@ void LoLEngine::kingSelectionReminder() { _sound->voicePlay("KING02", &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { _chargenWSA->displayFrame(_chargenFrameTable[index+9], 0, 113, 0, 0, 0, 0); _screen->copyRegion(_selectionPosTable[_reminderChar1IdxTable[index]*2+0], _selectionPosTable[_reminderChar1IdxTable[index]*2+1], _charPreviews[0].x, _charPreviews[0].y, 32, 32, 4, 0); _screen->copyRegion(_selectionPosTable[_reminderChar2IdxTable[index]*2+0], _selectionPosTable[_reminderChar2IdxTable[index]*2+1], _charPreviews[1].x, _charPreviews[1].y, 32, 32, 4, 0); @@ -421,7 +422,7 @@ void LoLEngine::kingSelectionReminder() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -434,7 +435,7 @@ void LoLEngine::kingSelectionOutro() { _sound->voicePlay("KING03", &_speechHandle); int index = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { index = MAX(index, 4); _chargenWSA->displayFrame(_chargenFrameTable[index], 0, 113, 0, 0, 0, 0); @@ -446,7 +447,7 @@ void LoLEngine::kingSelectionOutro() { _system->delayMillis(10); } - if (_speechFlag) + if (speechEnabled()) index = (index + 1) % 22; else if (++index >= 27) break; @@ -581,13 +582,13 @@ void LoLEngine::selectionCharInfoIntro(char *file) { bool processAnim = true; while (_charSelectionInfoResult == -1 && !shouldQuit()) { - if (_speechFlag && !_sound->isVoicePresent(file)) + if (speechEnabled() && !_sound->isVoicePresent(file)) break; _sound->voicePlay(file, &_speechHandle); int i = 0; - while ((!_speechFlag || (_speechFlag && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) { + while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) { _screen->drawShape(0, _screen->getPtrToShape(_screen->getCPagePtr(9), _charInfoFrameTable[i]), 11, 130, 0, 0); _screen->updateScreen(); @@ -597,7 +598,7 @@ void LoLEngine::selectionCharInfoIntro(char *file) { _system->delayMillis(10); } - if (_speechFlag || processAnim) + if (speechEnabled() || processAnim) i = (i + 1) % 32; if (i == 0) processAnim = false; @@ -641,19 +642,19 @@ int LoLEngine::selectionCharAccept() { } void LoLEngine::showStarcraftLogo() { - WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen); + WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(0); _screen->clearPage(2); - int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette); + int endframe = ci->open("ci01.wsa", 0, &_screen->getPalette(0)); if (!ci->opened()) { delete ci; return; } _screen->hideMouse(); - ci->displayFrame(0, 2, 32, 80, 0); + ci->displayFrame(0, 2, 32, 80, 0, 0, 0); _screen->copyPage(2, 0); _screen->fadeFromBlack(); int inputFlag = 0; @@ -661,7 +662,7 @@ void LoLEngine::showStarcraftLogo() { inputFlag = checkInput(0) & 0xff; if (shouldQuit() || inputFlag) break; - ci->displayFrame(i, 2, 32, 80, 0); + ci->displayFrame(i, 2, 32, 80, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); delay(4 * _tickLength); @@ -725,9 +726,8 @@ void LoLEngine::setupEpilogueData(bool load) { if (_flags.platform == Common::kPlatformPC98) _sound->loadSoundFile("SOUND.DAT"); } else { - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); if (shouldQuit()) return; @@ -742,9 +742,8 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { TIMInterpreter *timBackUp = _tim; _tim = new TIMInterpreter(this, _screen, _system); - uint8 *pal = _screen->getPalette(0); - memset(pal, 0, 768); - _screen->setScreenPalette(pal); + _screen->getPalette(0).clear(); + _screen->setScreenPalette(_screen->getPalette(0)); _screen->clearPage(0); _screen->clearPage(4); @@ -799,27 +798,28 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { showCredits(); + _eventList.clear(); + switch (character) { case 0: - _screen->loadBitmap("KIERAN.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("KIERAN.CPS", 3, 3, &_screen->getPalette(0)); break; case 1: - _screen->loadBitmap("AK'SHEL.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("AK'SHEL.CPS", 3, 3, &_screen->getPalette(0)); break; case 2: - _screen->loadBitmap("MICHAEL.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("MICHAEL.CPS", 3, 3, &_screen->getPalette(0)); break; case 3: - _screen->loadBitmap("CONRAD.CPS", 3, 3, _screen->getPalette(0)); + _screen->loadBitmap("CONRAD.CPS", 3, 3, &_screen->getPalette(0)); break; default: _screen->clearPage(3); - memset(_screen->getPalette(0), 0, 768); - break; + _screen->getPalette(0).clear(); } _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -854,8 +854,8 @@ void LoLEngine::showCredits() { _screen->setTextColorMap(colorMap); _screen->_charWidth = 0; - _screen->loadBitmap("ROOM.CPS", 2, 2, _screen->getPalette(0)); - memset(_screen->getPalette(0) + 764, 0, 3); + _screen->loadBitmap("ROOM.CPS", 2, 2, &_screen->getPalette(0)); + _screen->getPalette(0).fill(255, 1, 0); _screen->fadeToBlack(30); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); @@ -863,7 +863,7 @@ void LoLEngine::showCredits() { _screen->_charOffset = 0; char *credits = (char *)_res->fileData("CREDITS.TXT", 0); - processCredits(credits, 19, 4, 5); + processCredits(credits, 21, 4, 5); delete[] credits; uint32 endTime = _system->getMillis() + 120 * _tickLength; @@ -893,8 +893,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { uint8 *doorShape = _screen->makeShapeCopy(_screen->getCPagePtr(5), 0); assert(doorShape); - _screen->drawShape(0, doorShape, 0, 0, 20, 0x10); - _screen->drawShape(0, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(0, doorShape, 0, 0, 22, 0x10); + _screen->drawShape(0, doorShape, 0, 0, 23, 0x11); int curShapeFile = 0; uint8 *shapes[12]; @@ -904,7 +904,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { uint8 *monsterPal = _res->fileData("MONSTERS.PAL", 0); assert(monsterPal); - memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + 0 * 3, 40 * 3); + _screen->getPalette(0).copy(monsterPal, 0, 40, 88); _screen->fadePalette(_screen->getPalette(0), 30); uint32 waitTimer = _system->getMillis(); @@ -929,6 +929,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { uint8 *animBlock = new uint8[40960]; assert(animBlock); memset(animBlock, 0, 40960); + int inputFlag = 0; do { while (_system->getMillis() < waitTimer && !shouldQuit()) @@ -1039,8 +1040,8 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { } else { if (!monsterAnimFrame && doorRedraw) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, page, Screen::CR_NO_P_CHECK); - _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); - _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(page, doorShape, 0, 0, 22, 0x10); + _screen->drawShape(page, doorShape, 0, 0, 23, 0x11); --frameCounter; doorRedraw = false; @@ -1059,32 +1060,32 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { bool isRightMonster = ((curShapeFile - 1) & 1) != 0; if (isRightMonster) { - doorSD = 21; + doorSD = 23; doorX = _outroRightDoorPos[monsterAnimFrame * 2 + 0]; doorY = _outroRightDoorPos[monsterAnimFrame * 2 + 1]; monsterX = _outroRightMonsterPos[monsterAnimFrame * 2 + 0]; monsterY = _outroRightMonsterPos[monsterAnimFrame * 2 + 1]; - _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); + _screen->drawShape(page, doorShape, 0, 0, 22, 0x10); } else { - doorSD = 20; + doorSD = 22; doorX = _outroLeftDoorPos[monsterAnimFrame * 2 + 0]; doorY = _outroLeftDoorPos[monsterAnimFrame * 2 + 1]; monsterX = _outroLeftMonsterPos[monsterAnimFrame * 2 + 0]; monsterY = _outroLeftMonsterPos[monsterAnimFrame * 2 + 1]; - _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + _screen->drawShape(page, doorShape, 0, 0, 23, 0x11); } if (monsterAnimFrame >= 8) - _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); _screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster | (monsterAnimFrame < 20)) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]); if (monsterAnimFrame < 8) - _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 6, Screen::CR_NO_P_CHECK); doorRedraw = true; @@ -1126,14 +1127,16 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { curShapeFile = curShapeFile % 28; loadOutroShapes(curShapeFile, shapes); - memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + curShapeFile * 40 * 3, 40 * 3); + _screen->getPalette(0).copy(monsterPal, curShapeFile * 40, 40, 88); _screen->setScreenPalette(_screen->getPalette(0)); needNewShape = false; } _screen->updateScreen(); - } while (countStrings && !checkInput(0) && !shouldQuit()); + inputFlag = checkInput(0); + removeInputTop(); + } while (countStrings && !(inputFlag && !(inputFlag & 0x800)) && !shouldQuit()); removeInputTop(); delete[] animBlock; diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index d0e34a0be6..63a42837aa 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -34,7 +34,7 @@ namespace Kyra { bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { - if (!_speechFlag) + if (!speechEnabled()) return false; if (speaker < 65) { @@ -160,7 +160,7 @@ void LoLEngine::snd_stopSpeech(bool setFlag) { } void LoLEngine::snd_playSoundEffect(int track, int volume) { - if (track == 1 && (_lastSfxTrack == -1 || _lastSfxTrack == 1)) + if ((track == 1 && (_lastSfxTrack == -1 || _lastSfxTrack == 1)) || shouldQuit()) return; _lastSfxTrack = track; @@ -186,12 +186,13 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { } if (hasVocFile) { - _sound->voicePlay(_ingameSoundList[vocIndex], 0, volume & 0xff, true); + if (_sound->isVoicePresent(_ingameSoundList[vocIndex])) + _sound->voicePlay(_ingameSoundList[vocIndex], 0, volume & 0xff, true); } else if (_flags.platform == Common::kPlatformPC) { if (_sound->getSfxType() == Sound::kMidiMT32) - track = track < _ingameMT32SoundIndexSize ? _ingameMT32SoundIndex[track] - 1 : -1; + track = (track < _ingameMT32SoundIndexSize) ? (_ingameMT32SoundIndex[track] - 1) : -1; else if (_sound->getSfxType() == Sound::kMidiGM) - track = track < _ingameGMSoundIndexSize ? _ingameGMSoundIndex[track] - 1: -1; + track = (track < _ingameGMSoundIndexSize) ? (_ingameGMSoundIndex[track] - 1) : -1; if (track == 168) track = 167; @@ -202,7 +203,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { } void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) { - if (!_sound->sfxEnabled()) + if (!_sound->sfxEnabled() || shouldQuit()) return; if (_environmentSfx) @@ -303,6 +304,15 @@ int LoLEngine::snd_stopMusic() { return snd_playTrack(-1); } +int LoLEngine::convertVolumeToMixer(int value) { + value -= 2; + return (value * Audio::Mixer::kMaxMixerVolume) / 100; +} + +int LoLEngine::convertVolumeFromMixer(int value) { + return (value * 100) / Audio::Mixer::kMaxMixerVolume + 2; +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp index f798251525..451b77cec2 100644 --- a/engines/kyra/sound_midi.cpp +++ b/engines/kyra/sound_midi.cpp @@ -311,10 +311,8 @@ void MidiOutput::sendSysEx(const byte p1, const byte p2, const byte p3, const by } void MidiOutput::metaEvent(byte type, byte *data, uint16 length) { - if (type == 0x2F) { // End of Track + if (type == 0x2F) // End of Track deinitSource(_curSource); - //XXX - } _output->metaEvent(type, data, length); } diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 1980f62d7c..fe0a44c052 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1504,7 +1504,7 @@ public: private: void updatesRegs(); - uint8 _updateRequestBuf[32]; + uint8 _updateRequestBuf[64]; int _updateRequest; int _rand; @@ -2657,7 +2657,7 @@ void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool fo } if (!force) { - if (_updateRequest == 31) { + if (_updateRequest >= 63) { warning("TownsPC98_OpnSquareSineSource: event buffer overflow"); _updateRequest = -1; } @@ -3420,6 +3420,8 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To } TownsPC98_OpnDriver::~TownsPC98_OpnDriver() { + reset(); + if (_channels) { for (int i = 0; i < _numChan; i++) delete _channels[i]; @@ -4120,7 +4122,7 @@ void SoundPC98::playSoundEffect(uint8 track) { // This has been disabled for now since I don't know // how to make up the correct track number. It probably // needs a map. - //_driver->loadSoundEffectData(_sfxTrackData, track); + _driver->loadSoundEffectData(_sfxTrackData, track); } diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index 147ded3cfd..3cc632a391 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -47,7 +47,7 @@ Sprites::Sprites(KyraEngine_LoK *vm, OSystem *system) { _spriteDefStart = 0; memset(_drawLayerTable, 0, sizeof(_drawLayerTable)); _sceneAnimatorBeaconFlag = 0; - system->getEventManager()->registerRandomSource(_rnd, "kyraSprites"); + _vm->getEventManager()->registerRandomSource(_rnd, "kyraSprites"); } Sprites::~Sprites() { @@ -420,16 +420,16 @@ void Sprites::loadDat(const char *filename, SceneExits &exits) { if (_vm->gameFlags().platform == Common::kPlatformAmiga) { if (_vm->queryGameFlag(0xA0)) - memcpy(_screen->getPalette(3), _screen->getPalette(4), 32*3); + _screen->copyPalette(3, 4); else - memcpy(_screen->getPalette(3), _screen->getPalette(0), 32*3); + _screen->copyPalette(3, 0); } else { if (_vm->queryGameFlag(0xA0)) - memcpy(_screen->getPalette(1), _screen->getPalette(3), 768); + _screen->copyPalette(1, 3); else - memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + _screen->copyPalette(1, 0); - _screen->loadPalette(_dat + 0x17, _screen->getPalette(1) + 684, 60); + _screen->getPalette(1).copy(_dat + 0x17, 0, 20, 228); } uint8 *data = _dat + 0x6B; diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 8d856796ff..8cee1dc5fc 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -771,12 +771,20 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) { break; case 2: - /////// - // TODO + return (m->fightCurTick >= 13) ? 13 : m->fightCurTick; break; case 3: - /////// - // TODO + switch (m->mode) { + case 5: + return m->damageReceived ? 5 : 6; + case 8: + return (m->fightCurTick + 6); + case 11: + return 5; + default: + return m->damageReceived ? 5 : m->currentSubFrame; + } + break; default: break; @@ -1084,7 +1092,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) { setMonsterMode(monster, 7); if ((monster->mode != 11) && (monster->mode != 14)) { - if (!(getRandomNumberSpecial() & 3)) { + if (!(_rnd.getRandomNumber(255) & 3)) { monster->shiftStep = (++monster->shiftStep) & 0x0f; checkSceneUpdateNeed(monster->block); } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 3f41768c3c..e8597c8326 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -1584,7 +1584,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { _screen->clearPage(page); if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) - _screen->loadBitmap("MAIN15.CPS", page, page, _screen->getPalette(0)); + _screen->loadBitmap("MAIN15.CPS", page, page, &_screen->getPalette(0)); else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA)) _screen->loadBitmap("MAIN_ENG.CPS", page, page, 0); else if (_flags.lang == Common::FR_FRA) @@ -1599,7 +1599,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { warning("no main graphics file found"); if (_flags.platform == Common::kPlatformAmiga) - memcpy(_screen->getPalette(1), _screen->getPalette(0), 32*3); + _screen->copyPalette(1, 0); _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 0); } @@ -2011,9 +2011,108 @@ void LoLEngine::initStaticResource() { #undef cb } +void GUI_LoL::initStaticData() { + GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + + for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) + GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + + GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_mainMenu.item[0], 0x4001, 16, 23, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[1], 0x4002, 16, 40, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[2], 0x4003, 16, 57, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[3], 0x4004, 16, 74, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[4], 0x42D9, 16, 91, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[5], 0x4006, 16, 108, 176, 15, 0, 0); + GUI_LOL_MENU_ITEM(_mainMenu.item[6], 0x4005, 88, 127, 104, 15, 0, 110); + Button::Callback mainMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedMainMenu); + for (int i = 0; i < 7; ++i) + _mainMenu.item[i].callback = mainMenuFunctor; + + GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu); + for (int i = 0; i < 5; ++i) + _loadMenu.item[i].callback = loadMenuFunctor; + + GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu); + for (int i = 0; i < 5; ++i) + _saveMenu.item[i].callback = saveMenuFunctor; + + GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, 110); + Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu); + for (int i = 0; i < 5; ++i) + _deleteMenu.item[i].callback = deleteMenuFunctor; + + GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, 110); + Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu); + for (int i = 0; i < 6; ++i) + _gameOptions.item[i].callback = optionsMenuFunctor; + + GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, 110); + GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0); + Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu); + for (int i = 0; i < 4; ++i) + _audioOptions.item[i].callback = audioMenuFunctor; + + GUI_LOL_MENU(_deathMenu, 11, 0x4013, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_deathMenu.item[0], 0x4006, 8, 30, 104, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deathMenu.item[1], 0x4001, 176, 30, 104, 15, 0, 0); + Button::Callback deathMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeathMenu); + for (int i = 0; i < 2; ++i) + _deathMenu.item[i].callback = deathMenuFunctor; + + GUI_LOL_MENU(_savenameMenu, 7, 0x4053, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_savenameMenu.item[0], 0x4012, 8, 38, 72, 15, 0, 43); + GUI_LOL_MENU_ITEM(_savenameMenu.item[1], 0x4011, 176, 38, 72, 15, 0, 110); + Button::Callback savenameMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSavenameMenu); + for (int i = 0; i < 2; ++i) + _savenameMenu.item[i].callback = savenameMenuFunctor; + + GUI_LOL_MENU(_choiceMenu, 11, 0, 0, 2, -1, -1, -1, -1); + GUI_LOL_MENU_ITEM(_choiceMenu.item[0], 0x4007, 8, 30, 72, 15, 0, 0); + GUI_LOL_MENU_ITEM(_choiceMenu.item[1], 0x4008, 208, 30, 72, 15, 0, 0); + Button::Callback choiceMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedChoiceMenu); + for (int i = 0; i < 2; ++i) + _choiceMenu.item[i].callback = choiceMenuFunctor; +} #endif // ENABLE_LOL +const uint8 Screen_LoK_16::_palette16[48] = { + 0x00, 0x00, 0x00, 0x02, 0x07, 0x0B, 0x0C, 0x06, 0x04, + 0x0E, 0x09, 0x07, 0x00, 0x06, 0x03, 0x00, 0x0C, 0x07, + 0x0A, 0x0A, 0x0A, 0x08, 0x03, 0x03, 0x02, 0x02, 0x02, + 0x08, 0x0B, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x05, 0x05, 0x05, 0x00, 0x0F, 0x0F, 0x0F, 0x0D, 0x00, + 0x0F, 0x0F, 0x0F +}; + const ScreenDim Screen_LoK::_screenDimTable[] = { { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 }, { 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 }, @@ -3018,6 +3117,8 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = { { 0x0D, 0xA2, 0x18, 0x0C, 0xFE, 0x01, 0x00, 0x00 }, { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 }, + { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 }, + { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only) { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only) @@ -3045,6 +3146,8 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { { 0x0D, 0xA2, 0x18, 0x0C, 0x33, 0x44, 0x00, 0x00 }, { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 }, + { 0x07, 0x21, 0x1A, 0x85, 0x00, 0x00, 0x00, 0x00 }, + { 0x03, 0x32, 0x22, 0x62, 0x00, 0x00, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here) { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries) @@ -3056,6 +3159,42 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C); +// 256 -> 16 color conversion table +const uint8 Screen_LoL::_paletteConvTable[256] = { + 0x0, 0x1, 0x0, 0x3, 0x0, 0x5, 0x0, 0x7, + 0x0, 0x9, 0x0, 0xB, 0x0, 0xD, 0x0, 0xF, + 0x1, 0x1, 0x1, 0x3, 0x1, 0x5, 0x1, 0x7, + 0x1, 0x9, 0x1, 0xB, 0x1, 0xD, 0x1, 0xF, + 0x2, 0x1, 0x2, 0x3, 0x2, 0x5, 0x2, 0x7, + 0x2, 0x9, 0x2, 0xB, 0x2, 0xD, 0x2, 0xF, + 0x3, 0x1, 0x3, 0x3, 0x3, 0x5, 0x3, 0x7, + 0x3, 0x9, 0x3, 0xB, 0x3, 0xD, 0x3, 0xF, + 0x4, 0x1, 0x4, 0x3, 0x4, 0x5, 0x4, 0x7, + 0x4, 0x9, 0x4, 0xB, 0x4, 0xD, 0x4, 0xF, + 0x5, 0x1, 0x5, 0x3, 0x5, 0x5, 0x5, 0x7, + 0x5, 0x9, 0x5, 0xB, 0x5, 0xD, 0x5, 0xF, + 0x6, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x7, + 0x6, 0x9, 0x6, 0xB, 0x6, 0xD, 0x6, 0xF, + 0x7, 0x1, 0x7, 0x3, 0x7, 0x5, 0x7, 0x7, + 0x7, 0x9, 0x7, 0xB, 0x7, 0xD, 0x7, 0xF, + 0x8, 0x1, 0x8, 0x3, 0x8, 0x5, 0x8, 0x7, + 0x8, 0x9, 0x8, 0xB, 0x8, 0xD, 0x8, 0xF, + 0x9, 0x1, 0x9, 0x3, 0x9, 0x5, 0x9, 0x7, + 0x9, 0x9, 0x9, 0xB, 0x9, 0xD, 0x9, 0xF, + 0xA, 0x1, 0xA, 0x3, 0xA, 0x5, 0xA, 0x7, + 0xA, 0x9, 0xA, 0xB, 0xA, 0xD, 0xA, 0xF, + 0xB, 0x1, 0xB, 0x3, 0xB, 0x5, 0xB, 0x7, + 0xB, 0x9, 0xB, 0xB, 0xB, 0xD, 0xB, 0xF, + 0xC, 0x1, 0xC, 0x3, 0xC, 0x5, 0xC, 0x7, + 0xC, 0x9, 0xC, 0xB, 0xC, 0xD, 0xC, 0xF, + 0xD, 0x1, 0xD, 0x3, 0xD, 0x5, 0xD, 0x7, + 0xD, 0x9, 0xD, 0xB, 0xD, 0xD, 0xD, 0xF, + 0xE, 0x1, 0xE, 0x3, 0xE, 0x5, 0xE, 0x7, + 0xE, 0x9, 0xE, 0xB, 0xE, 0xD, 0xE, 0xF, + 0xF, 0x1, 0xF, 0x3, 0xF, 0x5, 0xF, 0x7, + 0xF, 0x9, 0xF, 0xB, 0xF, 0xD, 0xF, 0xF +}; + const char * const LoLEngine::_languageExt[] = { "ENG", "FRE", @@ -3241,4 +3380,3 @@ const int LoLEngine::_outroMonsterScaleTableY[] = { #endif // ENABLE_LOL } // End of namespace Kyra - diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index 6b1cb4eca2..3f4bfb65ac 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -39,12 +39,9 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const uint8 currPage; Common::Event event; - //while (towns_isEscKeyPressed() ) - //towns_getKey(); - uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis(); - if (_configVoice == 0 && chatDuration != -1) { + if (textEnabled() && !speechEnabled() && chatDuration != -1) { switch (_configTextspeed) { case 0: chatDuration *= 2; @@ -136,7 +133,6 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const _timer->enable(15); _timer->enable(18); _timer->enable(19); - //clearKyrandiaButtonIO(); } void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) { @@ -329,11 +325,11 @@ void KyraEngine_LoK::drawSentenceCommand(const char *sentence, int color) { _screen->fillRect(8, 143, 311, 152, 12); if (_startSentencePalIndex != color || _fadeText != false) { - _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3]; - _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1]; - _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2]; + _currSentenceColor[0] = _screen->getPalette(0)[765] = _screen->getPalette(0)[color*3]; + _currSentenceColor[1] = _screen->getPalette(0)[766] = _screen->getPalette(0)[color*3+1]; + _currSentenceColor[2] = _screen->getPalette(0)[767] = _screen->getPalette(0)[color*3+2]; - _screen->setScreenPalette(_screen->_currentPalette); + _screen->setScreenPalette(_screen->getPalette(0)); _startSentencePalIndex = 0; } @@ -368,10 +364,10 @@ void KyraEngine_LoK::updateTextFade() { } } - _screen->_currentPalette[765] = _currSentenceColor[0]; - _screen->_currentPalette[766] = _currSentenceColor[1]; - _screen->_currentPalette[767] = _currSentenceColor[2]; - _screen->setScreenPalette(_screen->_currentPalette); + _screen->getPalette(0)[765] = _currSentenceColor[0]; + _screen->getPalette(0)[766] = _currSentenceColor[1]; + _screen->getPalette(0)[767] = _currSentenceColor[2]; + _screen->setScreenPalette(_screen->getPalette(0)); if (finished) { _fadeText = false; diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index 7ce12f47c7..2174bcc441 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -33,8 +33,8 @@ namespace Kyra { TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen), - _scriptParameter(0), _animWidth(0), _animColor1(0), _animColor2(0), _animFlag(true), _lineCount(0), - _printFlag(false), _lineWidth(0), _numCharsTotal(0), _numCharsLeft(0), _numCharsPrinted(0) { + _scriptParameter(0), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), + _numCharsLeft(0), _numCharsPrinted(0) { memset(_stringParameters, 0, 15 * sizeof(char *)); _buffer = new char[600]; @@ -138,7 +138,7 @@ void TextDisplayer_LoL::resetDimTextPositions(int dim) { _textDimData[dim].line = 0; } -void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) { +/*void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) { static const char defaultStr[] = "<MORE>"; if (str) { @@ -152,7 +152,7 @@ void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, ui _animColor1 = 0; _animColor2 = 0; } -} +}*/ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) { int oldDim = 0; @@ -496,7 +496,7 @@ void TextDisplayer_LoL::printLine(char *str) { int lines = (sd->h - _screen->_charOffset) / fh; while (_textDimData[sdx].line >= lines) { - if (lines <= _lineCount && _animFlag) { + if (lines <= _lineCount) { _lineCount = 0; textPageBreak(); _numCharsPrinted = 0; @@ -521,8 +521,8 @@ void TextDisplayer_LoL::printLine(char *str) { char c = 0; if ((lw + _textDimData[sdx].column) > w) { - if ((lines - 1) <= _lineCount && _animFlag) - w -= (_animWidth * (_screen->getFontWidth() + _screen->_charWidth)); + if ((lines - 1) <= _lineCount) + w -= (10 * (_screen->getFontWidth() + _screen->_charWidth)); w -= _textDimData[sdx].column; @@ -608,7 +608,7 @@ void TextDisplayer_LoL::textPageBreak() { } uint32 speechPartTime = 0; - if (_vm->_speechFlag && _vm->_activeVoiceFileTotalTime && _numCharsTotal) + if (_vm->speechEnabled() && _vm->_activeVoiceFileTotalTime && _numCharsTotal) speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numCharsTotal); const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex()); @@ -643,7 +643,7 @@ void TextDisplayer_LoL::textPageBreak() { while (!inputFlag) { _vm->update(); - if (_vm->_speechFlag) { + if (_vm->speechEnabled()) { if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) { loop = false; inputFlag = 43; diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index fc707843aa..5586be730e 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -40,9 +40,6 @@ public: TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen); ~TextDisplayer_LoL(); - void setAnimParameters(const char *str, int x, uint8 col1, uint8 col2); - void setAnimFlag(bool flag) { _animFlag = flag; } - void setupField(bool mode); void expandField(); @@ -50,7 +47,7 @@ public: void resetDimTextPositions(int dim); void printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex); - void printMessage(uint16 type, const char *str, ...); + void printMessage(uint16 type, const char *str, ...) GCC_PRINTF(3, 4); int16 _scriptParameter; @@ -80,12 +77,6 @@ private: uint32 _numCharsLeft; uint32 _numCharsPrinted; - const char *_animString; - int16 _animWidth; - uint8 _animColor1; - uint8 _animColor2; - - bool _animFlag; bool _printFlag; LoLEngine *_vm; diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index e28d97d154..40f651ab01 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -581,7 +581,7 @@ void KyraEngine_MR::albumChatWaitToFinish() { frame = 13; albumRestoreRect(); - _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000); + _album.wsa->displayFrame(frame, 2, -100, 90, 0x4000, 0, 0); albumUpdateRect(); nextFrame = _system->getMillis() + _rnd.getRandomNumberRng(4, 8) * _tickLength; diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 4a66557465..84c4f8b19d 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -247,7 +247,7 @@ void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) { } void LoLEngine::timerUpdateLampState(int timerNum) { - if ((_gameFlags[15] & 0x800) && (_gameFlags[15] & 0x400) && _lampOilStatus > 0) + if ((_flagsTable[31] & 0x08) && (_flagsTable[31] & 0x04) && _lampOilStatus > 0) _lampOilStatus--; } diff --git a/engines/kyra/util.cpp b/engines/kyra/util.cpp index 794a1c78e3..fe02ba49ba 100644 --- a/engines/kyra/util.cpp +++ b/engines/kyra/util.cpp @@ -85,5 +85,68 @@ void Util::decodeString2(const char *src, char *dst) { *dst = 0; } +void Util::convertDOSToISO(char *str) { + uint8 *s = (uint8 *)str; + + for (; *s; ++s) { + if (*s >= 128) { + uint8 c = _charMapDOSToISO[*s - 128]; + + if (!c) + c = 0x20; + + *s = c; + } + } +} + +void Util::convertISOToDOS(char *str) { + while (*str) + convertISOToDOS(*str++); +} + +void Util::convertISOToDOS(char &c) { + uint8 code = (uint8)c; + if (code >= 128) { + code = _charMapISOToDOS[code - 128]; + if (!code) + code = 0x20; + } + + c = code; +} + +// CP850 to ISO-8859-1 (borrowed from engines/saga/font_map.cpp) +const uint8 Util::_charMapDOSToISO[128] = { + 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, + 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242, + 251, 249, 255, 214, 220, 248, 163, 216, 215, 0, 225, + 237, 243, 250, 241, 209, 170, 186, 191, 174, 172, 189, + 188, 161, 171, 187, 0, 0, 0, 0, 0, 193, 194, + 192, 169, 0, 0, 0, 0, 162, 165, 0, 0, 0, + 0, 0, 0, 0, 227, 195, 0, 0, 0, 0, 0, + 0, 0, 164, 240, 208, 202, 203, 200, 0, 205, 206, + 207, 0, 0, 0, 0, 166, 204, 0, 211, 223, 212, + 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221, + 175, 180, 173, 177, 0, 190, 182, 167, 247, 184, 176, + 168, 183, 185, 179, 178, 0, 160 +}; + +// ISO-8859-1 to CP850 +const uint8 Util::_charMapISOToDOS[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 173, 189, 156, 207, 190, 221, 245, 249, 184, 166, 174, + 170, 240, 169, 238, 248, 241, 253, 252, 239, 230, 244, + 250, 247, 251, 167, 175, 172, 171, 243, 168, 183, 181, + 182, 199, 142, 143, 146, 128, 212, 144, 210, 211, 222, + 214, 215, 216, 209, 165, 227, 224, 226, 229, 153, 158, + 157, 235, 233, 234, 154, 237, 232, 225, 133, 160, 131, + 198, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161, + 140, 139, 208, 164, 149, 162, 147, 228, 148, 246, 155, + 151, 163, 150, 129, 236, 231, 152 +}; + } // end of namespace Kyra diff --git a/engines/kyra/util.h b/engines/kyra/util.h index ee869d9c04..6850a4d757 100644 --- a/engines/kyra/util.h +++ b/engines/kyra/util.h @@ -34,6 +34,16 @@ class Util { public: static int decodeString1(const char *src, char *dst); static void decodeString2(const char *src, char *dst); + + // Since our current GUI font uses ISO-8859-1, this + // conversion functionallty uses that as a base. + static void convertDOSToISO(char *str); + static void convertISOToDOS(char *str); + static void convertISOToDOS(char &c); + +private: + static const uint8 _charMapDOSToISO[128]; + static const uint8 _charMapISOToDOS[128]; }; } // end of namespace Kyra diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 0b8f9c99a2..1225bc9976 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -32,12 +32,14 @@ // The jung2.vqa movie does work, but only thanks to a grotesque hack. +#include "kyra/vqa.h" + #include "common/system.h" #include "sound/audiostream.h" #include "sound/mixer.h" + #include "kyra/sound.h" #include "kyra/screen.h" -#include "kyra/vqa.h" #include "kyra/resource.h" namespace Kyra { @@ -45,6 +47,7 @@ namespace Kyra { VQAMovie::VQAMovie(KyraEngine_v1 *vm, OSystem *system) { _system = system; _vm = vm; + _screen = _vm->screen(); _opened = false; _x = _y = _drawPage = -1; } @@ -474,13 +477,13 @@ void VQAMovie::displayFrame(uint frameNum) { case MKID_BE('CPL0'): // Palette assert(size <= 3 * 256); - _file->read(_vm->screen()->_currentPalette, size); + _file->read(_screen->getPalette(0).getData(), size); break; case MKID_BE('CPLZ'): // Palette inbuf = (byte *)allocBuffer(0, size); _file->read(inbuf, size); - Screen::decodeFrame4(inbuf, _vm->screen()->_currentPalette, 768); + Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768); break; case MKID_BE('VPT0'): // Frame data @@ -520,9 +523,8 @@ void VQAMovie::displayFrame(uint frameNum) { // The frame has been decoded - if (_frameInfo[frameNum] & 0x80000000) { - _vm->screen()->setScreenPalette(_vm->screen()->_currentPalette); - } + if (_frameInfo[frameNum] & 0x80000000) + _screen->setScreenPalette(_screen->getPalette(0)); int blockPitch = _header.width / _header.blockW; @@ -562,7 +564,7 @@ void VQAMovie::displayFrame(uint frameNum) { _partialCodeBookSize = 0; } - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame); + _screen->copyBlockToPage(_drawPage, _x, _y, _header.width, _header.height, _frame); } void VQAMovie::play() { @@ -638,6 +640,7 @@ void VQAMovie::play() { } _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sound, _stream); + Common::EventManager *eventMan = _vm->getEventManager(); for (uint i = 0; i < _header.numFrames; i++) { displayFrame(i); @@ -656,17 +659,17 @@ void VQAMovie::play() { break; Common::Event event; - - Common::EventManager *eventMan = _system->getEventManager(); while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: - if (event.kbd.ascii == 27) + if (event.kbd.keycode == Common::KEYCODE_ESCAPE) return; break; + case Common::EVENT_RTL: case Common::EVENT_QUIT: return; + default: break; } @@ -675,7 +678,7 @@ void VQAMovie::play() { _system->delayMillis(10); } - _vm->screen()->updateScreen(); + _screen->updateScreen(); } // TODO: Wait for the sound to finish? diff --git a/engines/kyra/vqa.h b/engines/kyra/vqa.h index 46d3bd48fb..98e279bd29 100644 --- a/engines/kyra/vqa.h +++ b/engines/kyra/vqa.h @@ -26,13 +26,24 @@ #ifndef KYRA_VQA_H #define KYRA_VQA_H -#include "common/stream.h" +#include "common/scummsys.h" + +#include "sound/mixer.h" class OSystem; +namespace Audio { +class AppendableAudioStream; +} // end of namespace Audio + +namespace Common { +class SeekableReadStream; +} // end of namespace Common + namespace Kyra { class KyraEngine_v1; +class Screen; class VQAMovie { public: @@ -57,6 +68,7 @@ public: protected: OSystem *_system; KyraEngine_v1 *_vm; + Screen *_screen; bool _opened; int _x, _y; diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index fc33201d65..ef3fd1a966 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -38,7 +38,7 @@ namespace Kyra { WSAMovie_v1::WSAMovie_v1(KyraEngine_v1 *vm) : Movie(vm) {} WSAMovie_v1::~WSAMovie_v1() { close(); } -int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) { +int WSAMovie_v1::open(const char *filename, int offscreenDecode, Palette *palBuf) { close(); uint32 flags = 0; @@ -64,7 +64,7 @@ int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) offsPal = 0x300; _flags |= WF_HAS_PALETTE; if (palBuf) - memcpy(palBuf, wsaData + 8 + (_numFrames << 2), 0x300); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300); } if (offscreenDecode) { @@ -100,10 +100,15 @@ int WSAMovie_v1::open(const char *filename, int offscreenDecode, uint8 *palBuf) } for (int i = 1; i < _numFrames + 2; ++i) { - _frameOffsTable[i] = READ_LE_UINT32(wsaData) - frameDataOffs; + _frameOffsTable[i] = READ_LE_UINT32(wsaData); + if (_frameOffsTable[i]) + _frameOffsTable[i] -= frameDataOffs; wsaData += 4; } + if (!_frameOffsTable[_numFrames + 1]) + _flags |= WF_NO_LAST_FRAME; + // skip palette wsaData += offsPal; @@ -132,19 +137,19 @@ void WSAMovie_v1::close() { } } -void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { - if (frameNum >= _numFrames || !_opened) +void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { + if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; _x = x; _y = y; _drawPage = pageNum; - uint8 *dst; + uint8 *dst = 0; if (_flags & WF_OFFSCREEN_DECODE) dst = _offscreenBuffer; else - dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height); + dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); if (_currentFrame == _numFrames) { if (!(_flags & WF_NO_FIRST_FRAME)) { @@ -162,13 +167,13 @@ void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { int frameCount; if (_currentFrame < frameNum) { frameCount = _numFrames - frameNum + _currentFrame; - if (diffCount > frameCount) + if (diffCount > frameCount && !(_flags & WF_NO_LAST_FRAME)) frameStep = -1; else frameCount = diffCount; } else { frameCount = _numFrames - _currentFrame + frameNum; - if (frameCount >= diffCount) { + if (frameCount >= diffCount || (_flags & WF_NO_LAST_FRAME)) { frameStep = -1; frameCount = diffCount; } @@ -195,8 +200,16 @@ void WSAMovie_v1::displayFrame(int frameNum, int pageNum, int x, int y, ...) { // display _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); + if (_flags & WF_OFFSCREEN_DECODE) { + int pageBackUp = _screen->setCurPage(_drawPage); + + int plotFunc = (flags & 0xFF00) >> 12; + int unk1 = flags & 0xFF; + + _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2); + + _screen->_curPage = pageBackUp; + } } void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) { @@ -215,7 +228,7 @@ void WSAMovie_v1::processFrame(int frameNum, uint8 *dst) { WSAMovieAmiga::WSAMovieAmiga(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _buffer(0) {} -int WSAMovieAmiga::open(const char *filename, int offscreenDecode, uint8 *palBuf) { +int WSAMovieAmiga::open(const char *filename, int offscreenDecode, Palette *palBuf) { int res = WSAMovie_v1::open(filename, offscreenDecode, palBuf); if (!res) @@ -234,7 +247,7 @@ void WSAMovieAmiga::close() { WSAMovie_v1::close(); } -void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { +void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { if (frameNum >= _numFrames || frameNum < 0 || !_opened) return; @@ -261,7 +274,7 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { dst = _buffer; } else { - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer); + _screen->copyBlockToPage(_drawPage, _x, _y, _width, _height, _buffer); } } _currentFrame = 0; @@ -273,13 +286,13 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { int frameCount; if (_currentFrame < frameNum) { frameCount = _numFrames - frameNum + _currentFrame; - if (diffCount > frameCount) + if (diffCount > frameCount && !(_flags & WF_NO_LAST_FRAME)) frameStep = -1; else frameCount = diffCount; } else { frameCount = _numFrames - _currentFrame + frameNum; - if (frameCount >= diffCount) { + if (frameCount >= diffCount || (_flags & WF_NO_LAST_FRAME)) { frameStep = -1; frameCount = diffCount; } @@ -306,8 +319,16 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, ...) { // display _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) - _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); + if (_flags & WF_OFFSCREEN_DECODE) { + int pageBackUp = _screen->setCurPage(_drawPage); + + int plotFunc = (flags & 0xFF00) >> 12; + int unk1 = flags & 0xFF; + + _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, table1, table2); + + _screen->_curPage = pageBackUp; + } } void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { @@ -329,7 +350,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { dst = _offscreenBuffer; dstPitch = _width; } else { - dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height); + dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); dstPitch = Screen::SCREEN_W; } @@ -342,9 +363,9 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { #pragma mark - -WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen) : WSAMovie_v1(vm), _screen(screen), _xAdd(0), _yAdd(0) {} +WSAMovie_v2::WSAMovie_v2(KyraEngine_v1 *vm) : WSAMovie_v1(vm), _xAdd(0), _yAdd(0) {} -int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { +int WSAMovie_v2::open(const char *filename, int unk1, Palette *palBuf) { close(); uint32 flags = 0; @@ -371,7 +392,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { offsPal = 0x300; _flags |= WF_HAS_PALETTE; if (palBuf) - _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x300); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x300); } if (flags & 2) { @@ -379,7 +400,7 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { offsPal = 0x30; _flags |= WF_HAS_PALETTE; if (palBuf) - _vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x30); + _screen->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), *palBuf, 0x30); } _flags |= WF_XOR; @@ -416,17 +437,13 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { for (int i = 1; i < _numFrames + 2; ++i) { _frameOffsTable[i] = READ_LE_UINT32(wsaData); + if (_frameOffsTable[i]) + _frameOffsTable[i] -= frameDataOffs; wsaData += 4; } - for (int i = 1; i < _numFrames; ++i) - _frameOffsTable[i] -= frameDataOffs; - - // WSA movies without last frame offset need special treatment - if (_frameOffsTable[_numFrames + 1]) - _frameOffsTable[_numFrames] -= frameDataOffs; - else - _frameOffsTable[_numFrames] = 0; + if (!_frameOffsTable[_numFrames + 1]) + _flags |= WF_NO_LAST_FRAME; // skip palette wsaData += offsPal; @@ -447,90 +464,6 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) { return _numFrames; } -void WSAMovie_v2::displayFrame(int frameNum, int pageNum, int x, int y, ...) { - if (frameNum >= _numFrames || frameNum < 0 || !_opened) - return; - - _x = x + _xAdd; - _y = y + _yAdd; - _drawPage = pageNum; - - uint8 *dst = 0; - if (_flags & WF_OFFSCREEN_DECODE) - dst = _offscreenBuffer; - else - dst = _screen->getPageRect(_drawPage, _x, _y, _width, _height); - - if (_currentFrame == _numFrames) { - if (!(_flags & WF_NO_FIRST_FRAME)) { - if (_flags & WF_OFFSCREEN_DECODE) - Screen::decodeFrameDelta(dst, _deltaBuffer); - else - Screen::decodeFrameDeltaPage(dst, _deltaBuffer, _width, (_flags & WF_XOR) == 0); - } - _currentFrame = 0; - } - - // try to reduce the number of needed frame operations - int diffCount = ABS(_currentFrame - frameNum); - int frameStep = 1; - int frameCount; - if (_currentFrame < frameNum) { - frameCount = _numFrames - frameNum + _currentFrame; - if (diffCount > frameCount) - frameStep = -1; - else - frameCount = diffCount; - } else { - frameCount = _numFrames - _currentFrame + frameNum; - if (frameCount >= diffCount) { - frameStep = -1; - frameCount = diffCount; - } - } - - // process - if (frameStep > 0) { - uint16 cf = _currentFrame; - while (frameCount--) { - cf += frameStep; - processFrame(cf, dst); - if (cf == _numFrames) - cf = 0; - } - } else { - uint16 cf = _currentFrame; - while (frameCount--) { - if (cf == 0) - cf = _numFrames; - processFrame(cf, dst); - cf += frameStep; - } - } - - // display - _currentFrame = frameNum; - if (_flags & WF_OFFSCREEN_DECODE) { - int pageBackUp = _screen->_curPage; - _screen->_curPage = _drawPage; - - va_list args; - va_start(args, y); - - int copyParam = va_arg(args, int); - int plotFunc = (copyParam & 0xFF00) >> 12; - int unk1 = copyParam & 0xFF; - - const uint8 *unkPtr1 = va_arg(args, const uint8*); - const uint8 *unkPtr2 = va_arg(args, const uint8*); - va_end(args); - - _screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, unkPtr1, unkPtr2); - - _screen->_curPage = pageBackUp; - } -} - } // end of namespace Kyra diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index ab6007f060..49ac5a28fe 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -26,6 +26,7 @@ #ifndef KYRA_WSAMOVIE_H #define KYRA_WSAMOVIE_H + namespace Audio { class AppendableAudioStream; class SoundHandle; @@ -34,10 +35,11 @@ class SoundHandle; namespace Kyra { class KyraEngine_v1; class Screen_v2; +class Palette; class Movie { public: - Movie(KyraEngine_v1 *vm) : _vm(vm), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} + Movie(KyraEngine_v1 *vm) : _vm(vm), _screen(vm->screen()), _opened(false), _x(-1), _y(-1), _drawPage(-1) {} virtual ~Movie() {} virtual bool opened() { return _opened; } @@ -48,15 +50,16 @@ public: virtual int width() const = 0; virtual int height() const = 0; - virtual int open(const char *filename, int offscreen, uint8 *palette) = 0; + virtual int open(const char *filename, int offscreen, Palette *palette) = 0; virtual void close() = 0; virtual int frames() = 0; - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...) = 0; + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) = 0; protected: KyraEngine_v1 *_vm; + Screen *_screen; bool _opened; int _x, _y; @@ -71,15 +74,16 @@ public: int width() const { return _width; } int height() const { return _height; } - virtual int open(const char *filename, int offscreen, uint8 *palette); + virtual int open(const char *filename, int offscreen, Palette *palette); virtual void close(); virtual int frames() { return _opened ? _numFrames : -1; } - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2); enum WSAFlags { WF_OFFSCREEN_DECODE = 0x10, + WF_NO_LAST_FRAME = 0x20, WF_NO_FIRST_FRAME = 0x40, WF_HAS_PALETTE = 0x100, WF_XOR = 0x200 @@ -103,10 +107,10 @@ protected: class WSAMovieAmiga : public WSAMovie_v1 { public: WSAMovieAmiga(KyraEngine_v1 *vm); - int open(const char *filename, int offscreen, uint8 *palette); + int open(const char *filename, int offscreen, Palette *palette); void close(); - void displayFrame(int frameNum, int pageNum, int x, int y, ...); + void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2); private: void processFrame(int frameNum, uint8 *dst); @@ -115,11 +119,12 @@ private: class WSAMovie_v2 : public WSAMovie_v1 { public: - WSAMovie_v2(KyraEngine_v1 *vm, Screen_v2 *screen); - - int open(const char *filename, int unk1, uint8 *palette); + WSAMovie_v2(KyraEngine_v1 *vm); - virtual void displayFrame(int frameNum, int pageNum, int x, int y, ...); + int open(const char *filename, int unk1, Palette *palette); + virtual void displayFrame(int frameNum, int pageNum, int x, int y, uint16 flags, const uint8 *table1, const uint8 *table2) { + WSAMovie_v1::displayFrame(frameNum, pageNum, x + _xAdd, y + _yAdd, flags, table1, table2); + } int xAdd() const { return _xAdd; } int yAdd() const { return _yAdd; } @@ -127,8 +132,6 @@ public: void setWidth(int w) { _width = w; } void setHeight(int h) { _height = h; } protected: - Screen_v2 *_screen; - int16 _xAdd; int16 _yAdd; }; diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index 268c212008..870ebf70f3 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -53,6 +53,8 @@ static const PlainGameDescriptor lureGames[] = { namespace Lure { +using Common::GUIO_NONE; + static const LureGameDescription gameDescriptions[] = { { { @@ -61,7 +63,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.ega", "e9c9fdd8a19f7910d68e53cb84651273"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY | GF_EGA, }, @@ -73,7 +76,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "b2a8aa6d7865813a17a3c636e063572e"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -85,7 +89,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.ega", "b80aced0321f64c58df2c7d3d74dfe79"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY | GF_EGA, }, @@ -97,7 +102,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "cf69d5ada228dd74f89046691c16aafb"), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -109,7 +115,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "7aa19e444dab1ac7194d9f7a40ffe54a"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -121,7 +128,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "894a2c2caeccbad2fc2f4a79a8ee47b0"), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -133,7 +141,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "1c94475c1bb7e0e88c1757d3b5377e94"), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -145,7 +154,8 @@ static const LureGameDescription gameDescriptions[] = { AD_ENTRY1("disk1.vga", "1751145b653959f7a64fe1618d6b97ac"), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GF_FLOPPY, }, @@ -171,7 +181,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - kADFlagUseExtraAsHint + kADFlagUseExtraAsHint, + // Additional GUI options (for every game} + Common::GUIO_NOSPEECH }; class LureMetaEngine : public AdvancedMetaEngine { diff --git a/engines/lure/lure.h b/engines/lure/lure.h index 12494870ad..e8f1a7c1e1 100644 --- a/engines/lure/lure.h +++ b/engines/lure/lure.h @@ -91,7 +91,7 @@ public: bool saveGame(uint8 slotNumber, Common::String &caption); Common::String *detectSave(int slotNumber); uint8 saveVersion() { return _saveVersion; } - void GUIError(const char *msg, ...); + void GUIError(const char *msg, ...) GCC_PRINTF(2, 3); uint32 getFeatures() const; Common::Language getLanguage() const; diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index 5ca8e6d807..9781823136 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -68,6 +68,9 @@ const char *M4Engine::getGameFile(int fileType) { return NULL; } +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + static const M4GameDescription gameDescriptions[] = { { { @@ -79,7 +82,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Burger, kFeaturesCD @@ -94,7 +98,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Burger, kFeaturesCD @@ -109,7 +114,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Burger, kFeaturesCD @@ -124,7 +130,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_Burger, kFeaturesDemo @@ -139,7 +146,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_Burger, kFeaturesDemo @@ -154,7 +162,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Riddle, kFeaturesCD @@ -169,7 +178,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Riddle, kFeaturesCD @@ -184,7 +194,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Riddle, kFeaturesCD @@ -199,7 +210,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Riddle, kFeaturesCD @@ -214,7 +226,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Riddle, kFeaturesCD @@ -229,7 +242,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_Riddle, kFeaturesDemo @@ -244,7 +258,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_RexNebular, kFeaturesNone @@ -259,7 +274,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_RexNebular, kFeaturesDemo @@ -274,7 +290,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_DragonSphere, kFeaturesNone @@ -290,7 +307,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_DragonSphere, kFeaturesCD @@ -305,7 +323,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_DragonSphere, kFeaturesDemo @@ -320,7 +339,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_Phantom, kFeaturesNone @@ -335,7 +355,8 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GType_Phantom, kFeaturesCD @@ -350,12 +371,13 @@ static const M4GameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GType_Phantom, kFeaturesDemo }, - { { NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS }, 0, 0 } + { AD_TABLE_END_MARKER, 0, 0 } }; } @@ -376,7 +398,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NOMIDI }; class M4MetaEngine : public AdvancedMetaEngine { diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index e43b00146f..1dfc0c3f83 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -72,6 +72,9 @@ static const PlainGameDescriptor madeGames[] = { namespace Made { +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + static const MadeGameDescription gameDescriptions[] = { { @@ -87,7 +90,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("rtzcd.dat", "e95c38ded389e39cfbf87a8cb250b12e"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -104,7 +108,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("rtzcd.red", "cd8b62ece4677c438688c1de3f5379b9"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -120,7 +125,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.dat", "a1db8c97a78dae10f91d356f16ad07b8", 536064), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -136,7 +142,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.red", "c4e2430e6b6c6ff1562a80fb4a9df24c", 276177), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -153,7 +160,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -169,7 +177,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 276584), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -186,7 +195,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.dat", "9d740378da2d16e83d0d0efff01bf83a", 525824), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -203,7 +213,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 355442), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -220,7 +231,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.dat", "5b86035aed0277f96e3d173542b5364a", 523776), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -237,7 +249,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354971), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -254,7 +267,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.dat", "bde8251a8e34e87c54e3f93147d56c9e", 523776), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -271,7 +285,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2", 354614), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_RTZ, 0, @@ -287,7 +302,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("rtz.prj", "764d02f52ce1c219f2c0066677fba4ce"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_RTZ, 0, @@ -303,7 +319,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("demo.dat", "2a6a1354bd5346fad4aee08e5b56caaa"), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_RTZ, 0, @@ -319,7 +336,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("manhole.dat", "cb21e31ed35c963208343bc995225b73"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_MANHOLE, 0, @@ -335,7 +353,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("manhole.dat", "2b1658292599a861c4cd3cf6cdb3c581"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_MANHOLE, 0, @@ -351,7 +370,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("lgop2.dat", "8137996db200ff67e8f172ff106f2e48"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_LGOP2, 0, @@ -368,7 +388,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("lgop2.dat", "a0ffea6a3b7e39bd861edd00c397641c", 299466), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_LGOP2, 0, @@ -385,7 +406,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("lgop2.dat", "f9e974087af7cf4b7ec2d8dc45d01e0c", 295366), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_LGOP2, 0, @@ -402,7 +424,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1s("lgop2.dat", "96eb95b4d75b9a3da0b0d67e3b4a787d", 288984), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_LGOP2, 0, @@ -418,7 +441,8 @@ static const MadeGameDescription gameDescriptions[] = { AD_ENTRY1("rodneys.dat", "a79887dbaa47689facd7c6f09258ba5a"), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_RODNEY, 0, @@ -440,7 +464,8 @@ static MadeGameDescription g_fallbackDesc = { AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor Common::UNK_LANG, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, 0, 0, @@ -466,7 +491,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class MadeMetaEngine : public AdvancedMetaEngine { diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index ec483bad84..bda88e7812 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -55,6 +55,9 @@ static const PlainGameDescriptor parallactionGames[] = { namespace Parallaction { +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + static const PARALLACTIONGameDescription gameDescriptions[] = { { { @@ -73,7 +76,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_Nippon, GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT, @@ -96,7 +100,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_Nippon, GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_MULT, @@ -113,7 +118,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_Nippon, GF_LANG_EN | GF_DEMO, @@ -135,7 +141,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_Nippon, GF_LANG_IT, @@ -152,7 +159,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_BRA, GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT, @@ -168,7 +176,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_BRA, GF_LANG_EN | GF_DEMO, @@ -184,7 +193,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformAmiga, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GType_BRA, GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT, @@ -200,7 +210,8 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { }, Common::UNK_LANG, Common::kPlatformAmiga, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GType_BRA, GF_LANG_EN | GF_DEMO, @@ -227,7 +238,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class ParallactionMetaEngine : public AdvancedMetaEngine { diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp new file mode 100644 index 0000000000..6928c1eefc --- /dev/null +++ b/engines/parallaction/disk.cpp @@ -0,0 +1,145 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "parallaction/disk.h" +#include "parallaction/graphics.h" + +namespace Parallaction { + +void ILBMLoader::setupBuffer(uint32 w, uint32 h) { + _intBuffer = 0; + switch (_bodyMode) { + case BODYMODE_SURFACE: + if (!_surf) { + _surf = new Graphics::Surface; + assert(_surf); + } + _surf->create(w, h, 1); + _mode = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES; + _intBuffer = (byte*)_surf->pixels; + break; + + case BODYMODE_MASKBUFFER: + if (!_maskBuffer) { + _maskBuffer = new MaskBuffer; + assert(_maskBuffer); + } + _maskBuffer->create(w, h); + _mode = Graphics::ILBMDecoder::ILBM_2_PACK_PLANES; + _intBuffer = _maskBuffer->data; + break; + + case BODYMODE_PATHBUFFER: + if (!_pathBuffer) { + _pathBuffer = new PathBuffer; + assert(_pathBuffer); + } + _pathBuffer->create(w, h); + _mode = Graphics::ILBMDecoder::ILBM_1_PACK_PLANES; + _intBuffer = _pathBuffer->data; + break; + + default: + error("Invalid bodyMode '%i' for ILBMLoader", _bodyMode); + break; + } +} + +bool ILBMLoader::callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case ID_BMHD: + _decoder.loadHeader(chunk._stream); + break; + + case ID_CMAP: + if (_palette) { + chunk._stream->read(_palette, chunk._size); + } + break; + + case ID_CRNG: + if (_crng) { + PaletteFxRange *ptr = &_crng[_numCRNG]; + chunk._stream->read((byte*)ptr, chunk._size); + ptr->_timer = FROM_BE_16(ptr->_timer); + ptr->_step = FROM_BE_16(ptr->_step); + ptr->_flags = FROM_BE_16(ptr->_flags); + ++_numCRNG; + } + break; + + case ID_BODY: + setupBuffer(_decoder._header.width, _decoder._header.height); + assert(_intBuffer); + _decoder.loadBitmap(_mode, _intBuffer, chunk._stream); + return true; // stop the parser + } + + return false; +} + +void ILBMLoader::load(Common::ReadStream *in, bool disposeStream) { + Common::IFFParser parser(in, disposeStream); + Common::Functor1Mem< Common::IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback); + parser.parse(c); +} + +ILBMLoader::ILBMLoader(uint32 bodyMode, byte *palette, PaletteFxRange *crng) { + _bodyMode = bodyMode; + _surf = 0; + _maskBuffer = 0; + _pathBuffer = 0; + _palette = palette; + _crng = crng; + _numCRNG = 0; +} + +ILBMLoader::ILBMLoader(Graphics::Surface *surf, byte *palette, PaletteFxRange *crng) { + _bodyMode = ILBMLoader::BODYMODE_SURFACE; + _surf = surf; + _palette = palette; + _crng = crng; + _numCRNG = 0; +} + +ILBMLoader::ILBMLoader(MaskBuffer *buffer) { + _bodyMode = ILBMLoader::BODYMODE_MASKBUFFER; + _maskBuffer = buffer; + _palette = 0; + _crng = 0; + _numCRNG = 0; +} + +ILBMLoader::ILBMLoader(PathBuffer *buffer) { + _bodyMode = ILBMLoader::BODYMODE_PATHBUFFER; + _pathBuffer = buffer; + _palette = 0; + _crng = 0; + _numCRNG = 0; +} + + + +} diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index 4cc2711e96..a9da429473 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -33,6 +33,7 @@ #include "common/file.h" #include "graphics/surface.h" +#include "graphics/iff.h" @@ -77,8 +78,37 @@ public: virtual Table* loadTable(const char* name) = 0; virtual Common::SeekableReadStream* loadMusic(const char* name) = 0; virtual Common::SeekableReadStream* loadSound(const char* name) = 0; - virtual void loadMask(const char *name, MaskBuffer &buffer) { } - virtual void loadPath(const char *name, PathBuffer &buffer) { } + virtual MaskBuffer *loadMask(const char *name, uint32 w, uint32 h) { return 0; } + virtual PathBuffer *loadPath(const char *name, uint32 w, uint32 h) { return 0; } +}; + +struct PaletteFxRange; + +struct ILBMLoader { + enum { + BODYMODE_SURFACE, + BODYMODE_MASKBUFFER, + BODYMODE_PATHBUFFER + }; + uint32 _bodyMode; + Graphics::Surface *_surf; + MaskBuffer *_maskBuffer; + PathBuffer *_pathBuffer; + byte *_palette; + PaletteFxRange *_crng; + uint32 _mode; + byte* _intBuffer; + uint32 _numCRNG; + Graphics::ILBMDecoder _decoder; + + ILBMLoader(uint32 bodyMode, byte *palette = 0, PaletteFxRange *crng = 0); + ILBMLoader(Graphics::Surface *surf, byte *palette = 0, PaletteFxRange *crng = 0); + ILBMLoader(MaskBuffer *buffer); + ILBMLoader(PathBuffer *buffer); + + bool callback(Common::IFFChunk &chunk); + void setupBuffer(uint32 w, uint32 h); + void load(Common::ReadStream *in, bool disposeStream = false); }; @@ -235,8 +265,8 @@ public: Table* loadTable(const char* name); Common::SeekableReadStream* loadMusic(const char* name); Common::SeekableReadStream* loadSound(const char* name); - void loadMask(const char *name, MaskBuffer &buffer); - void loadPath(const char *name, PathBuffer &buffer); + MaskBuffer *loadMask(const char *name, uint32 w, uint32 h); + PathBuffer *loadPath(const char *name, uint32 w, uint32 h); }; class DosDemoDisk_br : public DosDisk_br { @@ -272,7 +302,7 @@ public: GfxObj* loadObjects(const char *name, uint8 part = 0); Common::SeekableReadStream* loadMusic(const char* name); Common::SeekableReadStream* loadSound(const char* name); - void loadMask(const char *name, MaskBuffer &buffer); + MaskBuffer *loadMask(const char *name, uint32 w, uint32 h); }; } // namespace Parallaction diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index ec4fc32cc1..46c849e6f2 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -28,7 +28,6 @@ #include "common/config-manager.h" #include "parallaction/parallaction.h" #include "parallaction/parser.h" -#include "parallaction/iff.h" namespace Parallaction { @@ -331,32 +330,40 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) { } } -void DosDisk_br::loadMask(const char *name, MaskBuffer &buffer) { +MaskBuffer *DosDisk_br::loadMask(const char *name, uint32 w, uint32 h) { if (!name) { - return; + return 0; } Common::SeekableReadStream *stream = openFile("msk/" + Common::String(name), ".msk"); - // NOTE: info.width and info.height are only valid if the background graphics - // have already been loaded - buffer.bigEndian = false; - stream->read(buffer.data, buffer.size); + MaskBuffer *buffer = new MaskBuffer; + assert(buffer); + buffer->create(w, h); + buffer->bigEndian = false; + + stream->read(buffer->data, buffer->size); delete stream; + + return buffer; } -void DosDisk_br::loadPath(const char *name, PathBuffer &buffer) { +PathBuffer *DosDisk_br::loadPath(const char *name, uint32 w, uint32 h) { if (!name) { - return; + return 0; } Common::SeekableReadStream *stream = openFile("pth/" + Common::String(name), ".pth"); - // NOTE: info.width and info.height are only valid if the background graphics - // have already been loaded - buffer.bigEndian = false; - stream->read(buffer.data, buffer.size); + PathBuffer *buffer = new PathBuffer; + assert(buffer); + buffer->create(w, h); + buffer->bigEndian = false; + + stream->read(buffer->data, buffer->size); delete stream; + + return buffer; } void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) { @@ -380,18 +387,12 @@ void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char } if (mask) { - info._mask = new MaskBuffer; - info._mask->create(info.width, info.height); - loadMask(mask, *info._mask); + info._mask = loadMask(mask, info.width, info.height); } if (path) { - info._path = new PathBuffer; - info._path->create(info.width, info.height); - loadPath(path, *info._path); + info._path = loadPath(path, info.width, info.height); } - - return; } Table* DosDisk_br::loadTable(const char* name) { @@ -459,7 +460,7 @@ void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColo void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { byte r,g,b; - byte *pal, *p; + byte *p; Common::SeekableReadStream *stream; uint i; @@ -488,20 +489,14 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { } stream = openFile("backs/" + Common::String(filename), ".bkg"); - ILBMDecoder decoder(stream, true); - // TODO: encapsulate surface creation - info.bg.w = decoder.getWidth(); - info.bg.h = decoder.getHeight(); - info.bg.pitch = info.bg.w; - info.bg.bytesPerPixel = 1; - info.bg.pixels = decoder.getBitmap(); - assert(info.bg.pixels); + byte pal[768]; + ILBMLoader loader(&info.bg, pal); + loader.load(stream, true); info.width = info.bg.w; info.height = info.bg.h; - pal = decoder.getPalette(); p = pal; for (i = 16; i < 32; i++) { r = *p >> 2; @@ -516,8 +511,6 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { // Overwrite the first color (transparent key) in the palette info.palette.setEntry(0, pal[0] >> 2, pal[1] >> 2, pal[2] >> 0); - delete []pal; - // background data is drawn used the upper portion of the palette adjustForPalette(info.bg); } @@ -543,27 +536,24 @@ void finalpass(byte *buffer, uint32 size) { } } -void AmigaDisk_br::loadMask(const char *name, MaskBuffer &buffer) { +MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) { if (!name) { - return; + return 0; } debugC(1, kDebugDisk, "AmigaDisk_br::loadMask '%s'", name); Common::SeekableReadStream *stream = tryOpenFile("msk/" + Common::String(name), ".msk"); if (!stream) { - return; + return 0; } - ILBMDecoder decoder(stream, true); + ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER); + loader.load(stream, true); - // TODO: the buffer is allocated by the caller, so a copy here is - // unavoidable... a better solution would be inform the function - // of the size of the mask (the size in the mask file is not valid!) - byte *bitmap = decoder.getBitmap(2, true); - memcpy(buffer.data, bitmap, buffer.size); - finalpass(buffer.data, buffer.size); - - buffer.bigEndian = true; + MaskBuffer *buffer = loader._maskBuffer; + buffer->bigEndian = true; + finalpass(buffer->data, buffer->size); + return buffer; } void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path) { @@ -573,18 +563,12 @@ void AmigaDisk_br::loadScenery(BackgroundInfo& info, const char* name, const cha loadBackground(info, name); } if (mask) { - info._mask = new MaskBuffer; - info._mask->create(info.width, info.height); - loadMask(mask, *info._mask); + info._mask = loadMask(mask, info.width, info.height); } if (path) { - info._path = new PathBuffer; - info._path->create(info.width, info.height); - loadPath(path, *info._path); + info._path = loadPath(path, info.width, info.height); } - - return; } void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) { @@ -596,20 +580,13 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) { debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name); Common::String sName = name; - Common::SeekableReadStream *stream = openFile("ras/" + sName, ".ras"); - ILBMDecoder decoder(stream, true); - Graphics::Surface* surf = new Graphics::Surface; - assert(surf); + ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); + loader.load(stream, true); - // TODO: encapsulate surface creation - surf->w = decoder.getWidth(); - surf->h = decoder.getHeight(); - surf->pitch = surf->w; - surf->bytesPerPixel = 1; - surf->pixels = decoder.getBitmap(); - assert(surf->pixels); + Graphics::Surface* surf = loader._surf; + assert(surf); // Static pictures are drawn used the upper half of the palette: this must be // done before shadow mask is applied. This way, only really transparent pixels @@ -741,15 +718,16 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { debugC(5, kDebugDisk, "AmigaDisk_br::loadObjects"); Common::SeekableReadStream *stream = openFile(name); - ILBMDecoder decoder(stream, true); + ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); + loader.load(stream, true); uint16 max = objectsMax[part]; if (_vm->getFeatures() & GF_DEMO) max = 72; byte *data = new byte[max * 2601]; - byte *srcPtr = decoder.getBitmap(); - int w = decoder.getWidth(); + byte *srcPtr = (byte*)loader._surf->getBasePtr(0,0); + int w = loader._surf->w; // Convert to the expected display format for (int i = 0; i < max; i++) { @@ -764,7 +742,7 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { dst += 51; } } - free(srcPtr); + delete loader._surf; return new GfxObj(0, new Cnv(max, 51, 51, data, true)); } diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index 8aa2a9f543..d35b338069 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -23,18 +23,11 @@ * */ -#include "parallaction/iff.h" #include "common/config-manager.h" #include "parallaction/parser.h" #include "parallaction/parallaction.h" -namespace Audio { - class AudioStream; - - AudioStream *make8SVXStream(Common::ReadStream &input); -} - namespace Parallaction { @@ -900,56 +893,18 @@ void AmigaDisk_ns::buildMask(byte* buf) { } } -// TODO: extend the ILBMDecoder to return CRNG chunks and get rid of this BackgroundDecoder crap -class BackgroundDecoder : public ILBMDecoder { - -public: - BackgroundDecoder(Common::SeekableReadStream *input, bool disposeStream = false) : ILBMDecoder(input, disposeStream) { - } - - uint32 getCRNG(PaletteFxRange *ranges, uint32 num) { - assert(ranges); - - uint32 size = _parser.getIFFBlockSize(ID_CRNG); - if (size == (uint32)-1) { - return 0; - } - - uint32 count = MIN((uint32)(size / sizeof(PaletteFxRange)), num); - _parser.loadIFFBlock(ID_CRNG, ranges, count * sizeof(PaletteFxRange)); - - for (uint32 i = 0; i < count; ++i) { - ranges[i]._timer = FROM_BE_16(ranges[i]._timer); - ranges[i]._step = FROM_BE_16(ranges[i]._step); - ranges[i]._flags = FROM_BE_16(ranges[i]._flags); - } - - return count; - } -}; - void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { - - Common::SeekableReadStream *s = openFile(name); - BackgroundDecoder decoder(s, true); - PaletteFxRange ranges[6]; - memset(ranges, 0, 6*sizeof(PaletteFxRange)); - decoder.getCRNG(ranges, 6); + byte pal[768]; - // TODO: encapsulate surface creation - info.bg.w = decoder.getWidth(); - info.bg.h = decoder.getHeight(); - info.bg.pitch = info.bg.w; - info.bg.bytesPerPixel = 1; - info.bg.pixels = decoder.getBitmap(); + Common::SeekableReadStream *s = openFile(name); + ILBMLoader loader(&info.bg, pal, ranges); + loader.load(s, true); info.width = info.bg.w; info.height = info.bg.h; - byte *pal = decoder.getPalette(); - assert(pal); byte *p = pal; for (uint i = 0; i < 32; i++) { byte r = *p >> 2; @@ -960,7 +915,6 @@ void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { p++; info.palette.setEntry(i, r, g, b); } - delete []pal; for (uint j = 0; j < 6; j++) { info.setPaletteRange(j, ranges[j]); @@ -979,9 +933,9 @@ void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) { return; // no errors if missing mask files: not every location has one } - ILBMDecoder decoder(s, true); - byte *pal = decoder.getPalette(); - assert(pal); + byte pal[768]; + ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER, pal); + loader.load(s, true); byte r, g, b; for (uint i = 0; i < 4; i++) { @@ -990,14 +944,8 @@ void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) { b = pal[i*3+2]; info.layers[i] = (((r << 4) & 0xF00) | (g & 0xF0) | (b >> 4)) & 0xFF; } - delete []pal; - info._mask = new MaskBuffer; - info._mask->w = info.width; - info._mask->h = info.height; - info._mask->internalWidth = info.width >> 2; - info._mask->size = info._mask->internalWidth * info._mask->h; - info._mask->data = decoder.getBitmap(2, true); + info._mask = loader._maskBuffer; } void AmigaDisk_ns::loadPath(BackgroundInfo& info, const char *name) { @@ -1010,15 +958,10 @@ void AmigaDisk_ns::loadPath(BackgroundInfo& info, const char *name) { return; // no errors if missing path files: not every location has one } - ILBMDecoder decoder(s, true); - info._path = new PathBuffer; - info._path->create(info.width, info.height); + ILBMLoader loader(ILBMLoader::BODYMODE_PATHBUFFER); + loader.load(s, true); + info._path = loader._pathBuffer; info._path->bigEndian = true; - - byte *bitmap = decoder.getBitmap(1, true); - assert(bitmap); - memcpy(info._path->data, bitmap, info._path->size); - delete bitmap; } void AmigaDisk_ns::loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) { diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index ec72b14c15..fc6cb28d9e 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -162,9 +162,7 @@ void BackgroundInfo::loadGfxObjMask(const char *name, GfxObj *obj) { Common::Rect rect; obj->getRect(0, rect); - MaskBuffer *buf = new MaskBuffer; - buf->create(rect.width(), rect.height()); - _vm->_disk->loadMask(name, *buf); + MaskBuffer *buf = _vm->_disk->loadMask(name, rect.width(), rect.height()); obj->_maskId = addMaskPatch(buf); obj->_hasMask = true; @@ -174,9 +172,7 @@ void BackgroundInfo::loadGfxObjPath(const char *name, GfxObj *obj) { Common::Rect rect; obj->getRect(0, rect); - PathBuffer *buf = new PathBuffer; - buf->create(rect.width(), rect.height()); - _vm->_disk->loadPath(name, *buf); + PathBuffer *buf = _vm->_disk->loadPath(name, rect.width(), rect.height()); obj->_pathId = addPathPatch(buf); obj->_hasPath = true; diff --git a/engines/parallaction/iff.cpp b/engines/parallaction/iff.cpp deleted file mode 100644 index 43dcac3697..0000000000 --- a/engines/parallaction/iff.cpp +++ /dev/null @@ -1,276 +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. - * - * $URL$ - * $Id$ - * - */ - - -#include "common/iff_container.h" -#include "common/stream.h" -#include "common/util.h" -#include "parallaction/iff.h" - -namespace Parallaction { - - -void IFFParser::setInputStream(Common::SeekableReadStream *stream) { - destroy(); - - assert(stream); - _stream = stream; - _startOffset = 0; - _endOffset = _stream->size(); - - _formType = 0; - _formSize = (uint32)-1; - - if (_stream->size() < 12) { - // this file is too small to be a valid IFF container - return; - } - - if (_stream->readUint32BE() != ID_FORM) { - // no FORM header was found - return; - } - - _formSize = _stream->readUint32BE(); - _formType = _stream->readUint32BE(); -} - -void IFFParser::destroy() { - _stream = 0; - _startOffset = _endOffset = 0; -} - -uint32 IFFParser::getFORMSize() const { - return _formSize; -} - -Common::IFF_ID IFFParser::getFORMType() const { - return _formType; -} - -uint32 IFFParser::moveToIFFBlock(Common::IFF_ID chunkName) { - uint32 size = (uint32)-1; - - _stream->seek(_startOffset + 0x0C); - - while ((uint)_stream->pos() < _endOffset) { - uint32 chunk = _stream->readUint32BE(); - uint32 size_temp = _stream->readUint32BE(); - - if (chunk != chunkName) { - _stream->seek((size_temp + 1) & (~1), SEEK_CUR); - assert((uint)_stream->pos() <= _endOffset); - } else { - size = size_temp; - break; - } - } - - return size; -} - -uint32 IFFParser::getIFFBlockSize(Common::IFF_ID chunkName) { - uint32 size = moveToIFFBlock(chunkName); - return size; -} - -bool IFFParser::loadIFFBlock(Common::IFF_ID chunkName, void *loadTo, uint32 ptrSize) { - uint32 chunkSize = moveToIFFBlock(chunkName); - - if (chunkSize == (uint32)-1) { - return false; - } - - uint32 loadSize = 0; - loadSize = MIN(ptrSize, chunkSize); - _stream->read(loadTo, loadSize); - return true; -} - -Common::SeekableReadStream *IFFParser::getIFFBlockStream(Common::IFF_ID chunkName) { - uint32 chunkSize = moveToIFFBlock(chunkName); - - if (chunkSize == (uint32)-1) { - return 0; - } - - uint32 pos = _stream->pos(); - return new Common::SeekableSubReadStream(_stream, pos, pos + chunkSize, false); -} - - -// ILBM decoder implementation - -ILBMDecoder::ILBMDecoder(Common::SeekableReadStream *in, bool disposeStream) : _in(in), _disposeStream(disposeStream), _hasHeader(false), _bodySize((uint32)-1), _paletteSize((uint32)-1) { - assert(in); - _parser.setInputStream(in); - - if (_parser.getFORMType() != ID_ILBM) { - return; - } - - _hasHeader = _parser.loadIFFBlock(ID_BMHD, &_header, sizeof(_header)); - if (!_hasHeader) { - return; - } - - _header.width = TO_BE_16(_header.width); - _header.height = TO_BE_16(_header.height); - - _paletteSize = _parser.getIFFBlockSize(ID_CMAP); - _bodySize = _parser.getIFFBlockSize(ID_BODY); -} - - -ILBMDecoder::~ILBMDecoder() { - if (_disposeStream) { - delete _in; - } -} - -uint32 ILBMDecoder::getWidth() { - assert(_hasHeader); - return _header.width; -} - -uint32 ILBMDecoder::getHeight() { - assert(_hasHeader); - return _header.height; -} - -uint32 ILBMDecoder::getNumColors() { - assert(_hasHeader); - return (1 << _header.depth); -} - -byte *ILBMDecoder::getPalette() { - assert(_paletteSize != (uint32)-1); - byte *palette = new byte[_paletteSize]; - assert(palette); - _parser.loadIFFBlock(ID_CMAP, palette, _paletteSize); - return palette; -} - -byte *ILBMDecoder::getBitmap(uint32 numPlanes, bool packPlanes) { - assert(_bodySize != (uint32)-1); - assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); - - numPlanes = MIN(numPlanes, (uint32)_header.depth); - if (numPlanes > 4) { - packPlanes = false; - } - - uint32 bitmapSize = _header.width * _header.height; - uint32 bitmapWidth = _header.width; - if (packPlanes) { - bitmapSize /= (8 / numPlanes); - bitmapWidth /= (8 / numPlanes); - } - - Common::SeekableReadStream *bodyStream = _parser.getIFFBlockStream(ID_BODY); - assert(bodyStream); - - byte *bitmap = (byte*)calloc(bitmapSize, 1); - assert(bitmap); - - switch (_header.pack) { - case 1: { // PackBits compressed bitmap - Graphics::PackBitsReadStream stream(*bodyStream); - - byte *out = bitmap; - - // setup a buffer to hold enough data to build a line in the output - uint32 scanWidth = ((_header.width + 15)/16) << 1; - byte *scanBuffer = (byte*)malloc(scanWidth * _header.depth); - - for (uint i = 0; i < _header.height; ++i) { - byte *s = scanBuffer; - for (uint32 j = 0; j < _header.depth; ++j) { - stream.read(s, scanWidth); - s += scanWidth; - } - - planarToChunky(out, bitmapWidth, scanBuffer, scanWidth, numPlanes, packPlanes); - out += bitmapWidth; - } - - free(scanBuffer); - break; - } - default: - error("only RLE compressed ILBM files are supported"); - break; - } - - delete bodyStream; - - return bitmap; -} - - -void ILBMDecoder::planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes) { - byte pix, ofs, bit; - byte *s; - - uint32 pixels = width; - if (packPlanes) { - pixels *= (8 / nPlanes); - } - - for (uint32 x = 0; x < pixels; ++x) { - - pix = 0; - ofs = x >> 3; - bit = 0x80 >> (x & 7); - - // first build a pixel by scanning all the usable planes in the input - s = in; - for (uint32 plane = 0; plane < nPlanes; ++plane) { - if (s[ofs] & bit) { - pix |= (1 << plane); - } - s += planeWidth; - } - - - // then output the pixel according to the requested packing - if (!packPlanes) { - out[x] = pix; - } else - if (nPlanes == 1) { - out[x/8] |= (pix << (x & 7)); - } else - if (nPlanes == 2) { - out[x/4] |= (pix << ((x & 3) << 1)); - } else - if (nPlanes == 4) { - out[x/2] |= (pix << ((x & 1) << 2)); - } - } - -} - - -} // End of namespace Parallaction diff --git a/engines/parallaction/iff.h b/engines/parallaction/iff.h deleted file mode 100644 index 43f78bf001..0000000000 --- a/engines/parallaction/iff.h +++ /dev/null @@ -1,105 +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. - * - * $URL$ - * $Id$ - * - */ - -#ifndef PARALLACTION_IFF_H -#define PARALLACTION_IFF_H - -#include "common/stream.h" -#include "common/iff_container.h" // for IFF chunk names -#include "graphics/iff.h" // for BMHD - -// this IFF parser code is courtesy of the Kyra engine team ;) - -namespace Parallaction { - -class IFFParser { -public: - IFFParser() : _stream(0), _startOffset(0), _endOffset(0) {} - IFFParser(Common::SeekableReadStream *stream) : _stream(0), _startOffset(0), _endOffset(0) { - setInputStream(stream); - } - ~IFFParser() { destroy(); } - - void setInputStream(Common::SeekableReadStream *stream); - - operator bool() const { return (_startOffset != _endOffset) && _stream; } - - uint32 getFORMSize() const; - Common::IFF_ID getFORMType() const; - - uint32 getIFFBlockSize(Common::IFF_ID chunk); - bool loadIFFBlock(Common::IFF_ID chunk, void *loadTo, uint32 ptrSize); - Common::SeekableReadStream *getIFFBlockStream(Common::IFF_ID chunkName); -private: - void destroy(); - uint32 moveToIFFBlock(Common::IFF_ID chunkName); - - Common::SeekableReadStream *_stream; - uint32 _startOffset; - uint32 _endOffset; - - uint32 _formSize; - Common::IFF_ID _formType; -}; - - - - -class ILBMDecoder { - Common::SeekableReadStream *_in; - bool _disposeStream; - - void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); - -protected: - IFFParser _parser; - Graphics::BMHD _header; - bool _hasHeader; - uint32 _bodySize; - uint32 _paletteSize; - - -public: - ILBMDecoder(Common::SeekableReadStream *input, bool disposeStream = false); - - virtual ~ILBMDecoder(); - - uint32 getWidth(); - uint32 getHeight(); - uint32 getNumColors(); - byte *getPalette(); - - byte *getBitmap(uint32 numPlanes, bool packPlanes); - byte *getBitmap() { - assert(_hasHeader); - return getBitmap(_header.depth, false); - } -}; - - -} - -#endif - diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 16b79c3d5a..d65653cd92 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -7,6 +7,7 @@ MODULE_OBJS := \ debug.o \ detection.o \ dialogue.o \ + disk.o \ disk_br.o \ disk_ns.o \ exec.o \ @@ -18,7 +19,6 @@ MODULE_OBJS := \ gui.o \ gui_br.o \ gui_ns.o \ - iff.o \ input.o \ inventory.o \ objects.o \ diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h index f0ecea67bb..8fcfb94a9a 100644 --- a/engines/parallaction/sound.h +++ b/engines/parallaction/sound.h @@ -84,6 +84,14 @@ enum { SC_PAUSE }; +struct Channel { + Audio::AudioStream *stream; + Audio::SoundHandle handle; + uint32 volume; +}; + + + class SoundMan_ns : public SoundManImpl { public: enum { @@ -148,16 +156,9 @@ class AmigaSoundMan_ns : public SoundMan_ns { Audio::AudioStream *_musicStream; Audio::SoundHandle _musicHandle; - struct Channel { - Audio::Voice8Header header; - int8 *data; - uint32 dataSize; - bool dispose; - Audio::SoundHandle handle; - uint32 flags; - } _channels[NUM_SFX_CHANNELS]; + Channel _channels[NUM_SFX_CHANNELS]; - void loadChannelData(const char *filename, Channel *ch); + Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping); public: AmigaSoundMan_ns(Parallaction_ns *vm); @@ -192,21 +193,12 @@ protected: bool _musicEnabled; bool _sfxEnabled; + Channel _channels[NUM_SFX_CHANNELS]; + virtual void playMusic() = 0; virtual void stopMusic() = 0; virtual void pause(bool p) = 0; - struct Channel { - Audio::Voice8Header header; - int8 *data; - uint32 dataSize; - bool dispose; - Audio::SoundHandle handle; - uint32 flags; - } _channels[NUM_SFX_CHANNELS]; - - virtual void loadChannelData(const char *filename, Channel *ch) = 0; - public: SoundMan_br(Parallaction_br *vm); ~SoundMan_br(); @@ -228,7 +220,7 @@ class DosSoundMan_br : public SoundMan_br { MidiPlayer_MSC *_midiPlayer; - void loadChannelData(const char *filename, Channel *ch); + Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping); public: DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver); @@ -246,7 +238,7 @@ class AmigaSoundMan_br : public SoundMan_br { Audio::AudioStream *_musicStream; Audio::SoundHandle _musicHandle; - void loadChannelData(const char *filename, Channel *ch); + Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping); public: AmigaSoundMan_br(Parallaction_br *vm); diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp index 4915eb41e2..c0e3f3b24a 100644 --- a/engines/parallaction/sound_br.cpp +++ b/engines/parallaction/sound_br.cpp @@ -401,19 +401,29 @@ DosSoundMan_br::~DosSoundMan_br() { delete _midiPlayer; } -void DosSoundMan_br::loadChannelData(const char *filename, Channel *ch) { +Audio::AudioStream *DosSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) { Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); - ch->dataSize = stream->size(); - ch->data = (int8*)malloc(ch->dataSize); - if (stream->read(ch->data, ch->dataSize) != ch->dataSize) + uint32 dataSize = stream->size(); + int8 *data = (int8*)malloc(dataSize); + if (stream->read(data, dataSize) != dataSize) error("DosSoundMan_br::loadChannelData: Read failed"); - ch->dispose = true; delete stream; // TODO: Confirm sound rate - ch->header.samplesPerSec = 11025; + int rate = 11025; + + uint32 loopStart = 0, loopEnd = 0; + uint32 flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE; + + if (looping) { + loopEnd = dataSize; + flags |= Audio::Mixer::FLAG_LOOP; + } + + ch->stream = Audio::makeLinearInputStream((byte *)data, dataSize, rate, flags, loopStart, loopEnd); + return ch->stream; } void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { @@ -426,16 +436,8 @@ void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, i debugC(1, kDebugAudio, "DosSoundMan_br::playSfx(%s, %u, %i, %i)", filename, channel, looping, volume); Channel *ch = &_channels[channel]; - loadChannelData(filename, ch); - - uint32 loopStart = 0, loopEnd = 0, flags = Audio::Mixer::FLAG_UNSIGNED; - if (looping) { - loopEnd = ch->dataSize; - flags |= Audio::Mixer::FLAG_LOOP; - } - - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize, - ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd); + Audio::AudioStream *input = loadChannelData(filename, ch, looping); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume); } void DosSoundMan_br::playMusic() { @@ -468,22 +470,27 @@ AmigaSoundMan_br::~AmigaSoundMan_br() { stopMusic(); } -void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) { +Audio::AudioStream *AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) { Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); + Audio::AudioStream *input = 0; + if (_vm->getFeatures() & GF_DEMO) { - ch->dataSize = stream->size(); - ch->data = (int8*)malloc(ch->dataSize); - if (stream->read(ch->data, ch->dataSize) != ch->dataSize) + uint32 dataSize = stream->size(); + int8 *data = (int8*)malloc(dataSize); + if (stream->read(data, dataSize) != dataSize) error("DosSoundMan_br::loadChannelData: Read failed"); // TODO: Confirm sound rate - ch->header.samplesPerSec = 11025; + int rate = 11025; + input = Audio::makeLinearInputStream((byte *)data, dataSize, rate, Audio::Mixer::FLAG_AUTOFREE, 0, 0); } else { - Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); - decoder.decode(); + input = Audio::make8SVXStream(*stream, looping); } - ch->dispose = true; + delete stream; + + ch->stream = input; + return input; } void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { @@ -501,24 +508,13 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel); Channel *ch = &_channels[channel]; - loadChannelData(filename, ch); - - uint32 loopStart = 0, loopEnd = 0, flags = 0; - if (looping) { - // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and - // repeatHiSamples fields, but Nippon Safes handles loops according to flags - // set in its location scripts and always operates on the whole data. - loopStart = 0; - loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples; - flags = Audio::Mixer::FLAG_LOOP; - } + Audio::AudioStream *input = loadChannelData(filename, ch, looping); if (volume == -1) { - volume = ch->header.volume; + volume = ch->volume; } - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize, - ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume); } void AmigaSoundMan_br::playMusic() { @@ -560,15 +556,6 @@ void AmigaSoundMan_br::pause(bool p) { SoundMan_br::SoundMan_br(Parallaction_br *vm) : _vm(vm) { _mixer = _vm->_mixer; - _channels[0].data = 0; - _channels[0].dispose = false; - _channels[1].data = 0; - _channels[1].dispose = false; - _channels[2].data = 0; - _channels[2].dispose = false; - _channels[3].data = 0; - _channels[3].dispose = false; - _musicEnabled = true; _sfxEnabled = true; } @@ -595,12 +582,9 @@ void SoundMan_br::stopSfx(uint channel) { return; } - if (_channels[channel].dispose) { - debugC(1, kDebugAudio, "SoundMan_br::stopSfx(%i)", channel); - _mixer->stopHandle(_channels[channel].handle); - free(_channels[channel].data); - _channels[channel].data = 0; - } + debugC(1, kDebugAudio, "SoundMan_br::stopSfx(%i)", channel); + _mixer->stopHandle(_channels[channel].handle); + _channels[channel].stream = 0; } void SoundMan_br::execute(int command, const char *parm) { diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp index d0688c7264..65ee75ed98 100644 --- a/engines/parallaction/sound_ns.cpp +++ b/engines/parallaction/sound_ns.cpp @@ -335,14 +335,6 @@ void DosSoundMan_ns::playLocationMusic(const char *location) { AmigaSoundMan_ns::AmigaSoundMan_ns(Parallaction_ns *vm) : SoundMan_ns(vm) { _musicStream = 0; - _channels[0].data = 0; - _channels[0].dispose = false; - _channels[1].data = 0; - _channels[1].dispose = false; - _channels[2].data = 0; - _channels[2].dispose = false; - _channels[3].data = 0; - _channels[3].dispose = false; } AmigaSoundMan_ns::~AmigaSoundMan_ns() { @@ -360,30 +352,30 @@ static int8 res_amigaBeep[AMIGABEEP_SIZE] = { 0, 20, 40, 60, 80, 60, 40, 20, 0, -20, -40, -60, -80, -60, -40, -20 }; +Audio::AudioStream *AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch, bool looping) { + Audio::AudioStream *input = 0; -void AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch) { if (!scumm_stricmp("beep", filename)) { - ch->header.oneShotHiSamples = 0; - ch->header.repeatHiSamples = 0; - ch->header.samplesPerHiCycle = 0; - ch->header.samplesPerSec = 11934; - ch->header.volume = 160; - ch->data = (int8*)malloc(AMIGABEEP_SIZE * NUM_REPEATS); - int8* odata = ch->data; + // TODO: make a permanent stream out of this + uint32 dataSize = AMIGABEEP_SIZE * NUM_REPEATS; + int8 *data = (int8*)malloc(dataSize); + int8 *odata = data; for (uint i = 0; i < NUM_REPEATS; i++) { memcpy(odata, res_amigaBeep, AMIGABEEP_SIZE); odata += AMIGABEEP_SIZE; } - ch->dataSize = AMIGABEEP_SIZE * NUM_REPEATS; - ch->dispose = true; - return; + int rate = 11934; + ch->volume = 160; + input = Audio::makeLinearInputStream((byte *)data, dataSize, rate, Audio::Mixer::FLAG_AUTOFREE, 0, 0); + } else { + Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); + input = Audio::make8SVXStream(*stream, looping); + delete stream; } - Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); - Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); - decoder.decode(); - ch->dispose = true; - delete stream; + ch->stream = input; + + return input; } void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, int volume) { @@ -397,27 +389,13 @@ void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel); Channel *ch = &_channels[channel]; - loadChannelData(filename, ch); - - uint32 loopStart, loopEnd, flags; - if (looping) { - // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and - // repeatHiSamples fields, but Nippon Safes handles loops according to flags - // set in its location scripts and always operates on the whole data. - loopStart = 0; - loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples; - flags = Audio::Mixer::FLAG_LOOP; - } else { - loopStart = loopEnd = 0; - flags = 0; - } + Audio::AudioStream *input = loadChannelData(filename, ch, looping); if (volume == -1) { - volume = ch->header.volume; + volume = ch->volume; } - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize, - ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume); } void AmigaSoundMan_ns::stopSfx(uint channel) { @@ -426,12 +404,9 @@ void AmigaSoundMan_ns::stopSfx(uint channel) { return; } - if (_channels[channel].dispose) { - debugC(1, kDebugAudio, "AmigaSoundMan_ns::stopSfx(%i)", channel); - _mixer->stopHandle(_channels[channel].handle); - free(_channels[channel].data); - _channels[channel].data = 0; - } + debugC(1, kDebugAudio, "AmigaSoundMan_ns::stopSfx(%i)", channel); + _mixer->stopHandle(_channels[channel].handle); + _channels[channel].stream = 0; } void AmigaSoundMan_ns::playMusic() { diff --git a/engines/queen/command.cpp b/engines/queen/command.cpp index 2ae222479d..81f0f3ff89 100644 --- a/engines/queen/command.cpp +++ b/engines/queen/command.cpp @@ -123,7 +123,7 @@ public: virtual void displayTemp(InkColor color, const char *name, bool outlined) { char temp[MAX_COMMAND_LEN]; // don't show a space after the goto and give commands in the Greek version - if (_command[1] != -34 && !(_command[1] == -2 && strlen(_command) > 5)) + if (_command[1] != (char)-34 && !(_command[1] == (char)-2 && strlen(_command) > 5)) sprintf(temp, "%s %s", _command, name); else sprintf(temp, "%s%s", _command, name); @@ -132,7 +132,7 @@ public: virtual void addObject(const char *objName) { // don't show a space after the goto and give commands in the Greek version - if (_command[1] != -34 && !(_command[1] == -2 && strlen(_command) > 5)) + if (_command[1] != (char)-34 && !(_command[1] == (char)-2 && strlen(_command) > 5)) strcat(_command, " "); strcat(_command, objName); } diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp index 3c984c20fa..ec074190d3 100644 --- a/engines/queen/queen.cpp +++ b/engines/queen/queen.cpp @@ -120,10 +120,13 @@ GameList QueenMetaEngine::detectGames(const Common::FSList &fslist) const { GameDescriptor dg(queenGameDescriptor.gameid, queenGameDescriptor.description, version.language, version.platform); if (version.features & Queen::GF_DEMO) { dg.updateDesc("Demo"); + dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_INTERVIEW) { dg.updateDesc("Interview"); + dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_FLOPPY) { dg.updateDesc("Floppy"); + dg.setGUIOptions(Common::GUIO_NOSPEECH); } else if (version.features & Queen::GF_TALKIE) { dg.updateDesc("Talkie"); } diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index b3600b14c4..faf9cbed80 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -120,7 +120,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class SagaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h index e6991e054a..70e1022f8a 100644 --- a/engines/saga/detection_tables.h +++ b/engines/saga/detection_tables.h @@ -167,6 +167,9 @@ static const GamePatchDescription ITEMacPatch_Files[] = { { NULL, 0, 0} }; +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + static const SAGAGameDescription gameDescriptions[] = { // ITE Section //////////////////////////////////////////////////////////////////////////////////////////// @@ -192,7 +195,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GID_ITE, // Game id GF_OLD_ITE_DOS, // features @@ -216,7 +220,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GID_ITE, GF_WYRMKEEP | GF_SCENE_SUBSTITUTES | GF_MONO_MUSIC | GF_LE_VOICES, @@ -241,7 +246,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GID_ITE, GF_WYRMKEEP | GF_NON_INTERACTIVE | GF_LE_VOICES, @@ -266,7 +272,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_ITE, GF_WYRMKEEP | GF_SCENE_SUBSTITUTES, @@ -291,7 +298,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformWindows, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_ITE, GF_WYRMKEEP | GF_NON_INTERACTIVE | GF_8BIT_UNSIGNED_PCM, @@ -323,7 +331,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, GF_8BIT_UNSIGNED_PCM, @@ -346,7 +355,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, GF_WYRMKEEP, @@ -377,7 +387,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformUnknown, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, GF_WYRMKEEP, @@ -406,7 +417,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformUnknown, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, GF_WYRMKEEP, @@ -429,7 +441,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, GF_EXTRA_ITE_CREDITS, @@ -452,7 +465,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, 0, @@ -475,7 +489,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, 0, @@ -499,7 +514,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_ITE, 0, @@ -525,7 +541,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_ITE, GF_ITE_FLOPPY, @@ -548,7 +565,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_ITE, GF_ITE_FLOPPY, @@ -571,7 +589,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_ITE, GF_ITE_FLOPPY, @@ -603,7 +622,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_IHNM, GF_IHNM_DEMO, @@ -634,7 +654,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -663,7 +684,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -690,7 +712,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -718,7 +741,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -745,7 +769,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -769,7 +794,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformMacintosh, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_IHNM, 0, @@ -798,7 +824,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DINO, 0, @@ -827,7 +854,8 @@ static const SAGAGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_FTA2, 0, diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index a7c802f0c9..f43db12d1a 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -472,7 +472,7 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) { if (sceneSubstitutes[i].sceneId == sceneNumber) { Surface bbmBuffer; - byte *pal, *colors; + byte *pal, colors[768]; Common::File file; Rect rect; PalEntry cPal[PAL_ENTRIES]; @@ -480,8 +480,8 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy _vm->_interface->setMode(kPanelSceneSubstitute); if (file.open(sceneSubstitutes[i].image)) { - Graphics::decodePBM(file, bbmBuffer, pal); - colors = pal; + Graphics::decodePBM(file, bbmBuffer, colors); + pal = colors; rect.setWidth(bbmBuffer.w); rect.setHeight(bbmBuffer.h); _vm->_gfx->drawRegion(rect, (const byte*)bbmBuffer.pixels); @@ -490,7 +490,6 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy cPal[j].green = *pal++; cPal[j].blue = *pal++; } - free(colors); _vm->_gfx->setPalette(cPal); } diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f9e13304c5..bf919c3a25 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -37,7 +37,7 @@ #include "sci/gfx/gfx_gui.h" // for sciw_set_status_bar #include "sci/gfx/gfx_state_internal.h" #include "sci/gfx/gfx_widgets.h" // for getPort -#include "sci/sfx/songlib.h" // for songlib_t +#include "sci/sfx/songlib.h" // for SongLibrary #include "sci/sfx/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0 #include "sci/sfx/sci_midi.h" #include "sci/vocabulary.h" @@ -46,14 +46,11 @@ namespace Sci { -extern EngineState *g_EngineState; - int g_debug_sleeptime_factor = 1; int g_debug_simulated_key = 0; bool g_debug_track_mouse_clicks = false; bool g_debug_weak_validations = true; - Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; @@ -80,6 +77,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords)); DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); DCmd_Register("parse", WRAP_METHOD(Console, cmdParse)); + DCmd_Register("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes)); // Resources DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump)); DCmd_Register("resource_id", WRAP_METHOD(Console, cmdResourceId)); @@ -141,11 +139,28 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); + DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias + DCmd_Register("step", WRAP_METHOD(Console, cmdStep)); + DCmd_Register("s", WRAP_METHOD(Console, cmdStep)); // alias + DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent)); + DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias + DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); + DCmd_Register("sret", WRAP_METHOD(Console, cmdStepRet)); // alias + DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal)); + DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias + DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk)); + DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias + DCmd_Register("disasm", WRAP_METHOD(Console, cmdDissassemble)); + DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDissassembleAddress)); + DCmd_Register("send", WRAP_METHOD(Console, cmdSend)); + DCmd_Register("go", WRAP_METHOD(Console, cmdGo)); // Breakpoints DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); DCmd_Register("bp_exec_method", WRAP_METHOD(Console, cmdBreakpointExecMethod)); + DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointExecMethod)); // alias DCmd_Register("bp_exec_function", WRAP_METHOD(Console, cmdBreakpointExecFunction)); + DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointExecFunction)); // alias // VM DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); @@ -154,7 +169,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); + DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); + DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); @@ -171,18 +188,24 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { con_hook_int(&(gfx_options.dirty_frames), "dirty_frames", "Dirty frames management\n"); */ + + debugState.isValid = false; + debugState.seeking = kDebugSeekNothing; + debugState.seekLevel = 0; + debugState.runningStep = 0; + debugState.stopOnEvent = false; } Console::~Console() { } void Console::preEnter() { - g_EngineState->_sound.sfx_suspend(true); + _vm->_gamestate->_sound.sfx_suspend(true); _vm->_mixer->pauseAll(true); } void Console::postEnter() { - g_EngineState->_sound.sfx_suspend(false); + _vm->_gamestate->_sound.sfx_suspend(false); _vm->_mixer->pauseAll(false); } @@ -205,6 +228,12 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("weak_validations: Turns some validation errors into warnings\n"); DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); DebugPrintf("\n"); + DebugPrintf("Debug flags\n"); + DebugPrintf("-----------\n"); + DebugPrintf("debugflag_list - Lists the available debug flags and their status\n"); + DebugPrintf("debugflag_enable - Enables a debug flag\n"); + DebugPrintf("debugflag_disable - Disables a debug flag\n"); + DebugPrintf("\n"); DebugPrintf("Commands\n"); DebugPrintf("--------\n"); DebugPrintf("Kernel:\n"); @@ -220,6 +249,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" parser_words - Shows the words from the parse node tree\n"); DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n"); DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n"); + DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); DebugPrintf("\n"); DebugPrintf("Resources:\n"); DebugPrintf(" hexdump - Dumps the specified resource to standard output\n"); @@ -289,13 +319,22 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" registers - Shows the current register values\n"); DebugPrintf(" dissect_script - Examines a script\n"); DebugPrintf(" set_acc - Sets the accumulator\n"); - DebugPrintf(" backtrace - Dumps the send/self/super/call/calle/callb stack\n"); + DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); + DebugPrintf(" step / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); + DebugPrintf(" step_ret / sret - Steps forward until ret is called on the current execution stack level.\n"); + DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); + DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); + DebugPrintf(" disasm - Disassembles a method by name\n"); + DebugPrintf(" disasm_addr - Disassembles one or more commands\n"); + DebugPrintf(" send - Sends a message to an object\n"); + DebugPrintf(" go - Executes the script\n"); DebugPrintf("\n"); DebugPrintf("Breakpoints:\n"); DebugPrintf(" bp_list - Lists the current breakpoints\n"); DebugPrintf(" bp_del - Deletes a breakpoint with the specified index\n"); - DebugPrintf(" bp_exec_method - Sets a breakpoint on the execution of the specified method\n"); - DebugPrintf(" bp_exec_function - Sets a breakpoint on the execution of the specified exported function\n"); + DebugPrintf(" bp_exec_method / bpx - Sets a breakpoint on the execution of the specified method\n"); + DebugPrintf(" bp_exec_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); DebugPrintf("\n"); DebugPrintf("VM:\n"); DebugPrintf(" script_steps - Shows the number of executed SCI operations\n"); @@ -304,8 +343,8 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" stack - Lists the specified number of stack elements\n"); DebugPrintf(" value_type - Determines the type of a value\n"); DebugPrintf(" view_listnode - Examines the list node at the given address\n"); - DebugPrintf(" view_reference - Examines an arbitrary reference\n"); - DebugPrintf(" view_object - Examines the object at the given address\n"); + DebugPrintf(" view_reference / vr - Examines an arbitrary reference\n"); + DebugPrintf(" view_object / vo - Examines the object at the given address\n"); DebugPrintf(" active_object - Shows information on the currently active object or class\n"); DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); DebugPrintf("\n"); @@ -341,8 +380,8 @@ bool Console::cmdGetVersion(int argc, const char **argv) { bool Console::cmdOpcodes(int argc, const char **argv) { DebugPrintf("Opcode names in numeric order [index: type name]:\n"); - for (uint seeker = 0; seeker < g_EngineState->_kernel->getOpcodesSize(); seeker++) { - opcode op = g_EngineState->_kernel->getOpcode(seeker); + for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getOpcodesSize(); seeker++) { + opcode op = _vm->_gamestate->_kernel->getOpcode(seeker); DebugPrintf("%03x: %03x %20s | ", seeker, op.type, op.name.c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); @@ -355,8 +394,8 @@ bool Console::cmdOpcodes(int argc, const char **argv) { bool Console::cmdSelectors(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); - for (uint seeker = 0; seeker < g_EngineState->_kernel->getSelectorNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getSelectorName(seeker).c_str()); + for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getSelectorNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, _vm->_gamestate->_kernel->getSelectorName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -368,8 +407,8 @@ bool Console::cmdSelectors(int argc, const char **argv) { bool Console::cmdKernelFunctions(int argc, const char **argv) { DebugPrintf("Kernel function names in numeric order:\n"); - for (uint seeker = 0; seeker < g_EngineState->_kernel->getKernelNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, g_EngineState->_kernel->getKernelName(seeker).c_str()); + for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getKernelNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, _vm->_gamestate->_kernel->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -380,29 +419,118 @@ bool Console::cmdKernelFunctions(int argc, const char **argv) { } bool Console::cmdSuffixes(int argc, const char **argv) { - g_EngineState->_vocabulary->printSuffixes(); + _vm->_gamestate->_vocabulary->printSuffixes(); return true; } bool Console::cmdParserWords(int argc, const char **argv) { - g_EngineState->_vocabulary->printParserWords(); + _vm->_gamestate->_vocabulary->printParserWords(); + + return true; +} + +enum { + kParseEndOfInput = 0, + kParseOpeningParenthesis = 1, + kParseClosingParenthesis = 2, + kParseNil = 3, + kParseNumber = 4 +}; + +int parseNodes(EngineState *s, int *i, int *pos, int type, int nr, int argc, const char **argv) { + int nextToken = 0, nextValue = 0, newPos = 0, oldPos = 0; + + if (type == kParseNil) + return 0; + + if (type == kParseNumber) { + s->parser_nodes[*pos += 1].type = kParseTreeLeafNode; + s->parser_nodes[*pos].content.value = nr; + return *pos; + } + if (type == kParseEndOfInput) { + sciprintf("Unbalanced parentheses\n"); + return -1; + } + if (type == kParseClosingParenthesis) { + sciprintf("Syntax error at token %d\n", *i); + return -1; + } + + s->parser_nodes[oldPos = ++(*pos)].type = kParseTreeBranchNode; + + for (int j = 0; j <= 1; j++) { + if (*i == argc) { + nextToken = kParseEndOfInput; + } else { + const char *token = argv[(*i)++]; + + if (!strcmp(token, "(")) { + nextToken = kParseOpeningParenthesis; + } else if (!strcmp(token, ")")) { + nextToken = kParseClosingParenthesis; + } else if (!strcmp(token, "nil")) { + nextToken = kParseNil; + } else { + nextValue = strtol(token, NULL, 0); + nextToken = kParseNumber; + } + } + + if ((newPos = s->parser_nodes[oldPos].content.branches[j] = parseNodes(s, i, pos, nextToken, nextValue, argc, argv)) == -1) + return -1; + } + + const char *token = argv[(*i)++]; + if (strcmp(token, ")")) + sciprintf("Expected ')' at token %d\n", *i); + + return oldPos; +} + +bool Console::cmdSetParseNodes(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Sets the contents of all parse nodes.\n"); + DebugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]); + DebugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n"); + return true; + } + + int i = 0; + int pos = -1; + int nextToken = 0, nextValue = 0; + + const char *token = argv[i++]; + + if (!strcmp(token, "(")) { + nextToken = kParseOpeningParenthesis; + } else if (!strcmp(token, ")")) { + nextToken = kParseClosingParenthesis; + } else if (!strcmp(token, "nil")) { + nextToken = kParseNil; + } else { + nextValue = strtol(token, NULL, 0); + nextToken = kParseNumber; + } + + if (parseNodes(_vm->_gamestate, &i, &pos, nextToken, nextValue, argc, argv) == -1) + return 1; + + vocab_dump_parse_tree("debug-parse-tree", _vm->_gamestate->parser_nodes); return true; } bool Console::cmdRegisters(int argc, const char **argv) { DebugPrintf("Current register values:\n"); -#if 0 - // TODO: p_restadjust - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(g_EngineState->r_acc), PRINT_REG(g_EngineState->r_prev), *p_restadjust); -#endif + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), *debugState.p_restadjust); - if (!g_EngineState->_executionStack.empty()) { -#if 0 - // TODO: p_pc, p_objp, p_pp, p_sp - DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp)); -#endif + if (!_vm->_gamestate->_executionStack.empty()) { + EngineState *s = _vm->_gamestate; // for PRINT_STK + DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", + PRINT_REG(*debugState.p_pc), PRINT_REG(*debugState.p_objp), + PRINT_STK(*debugState.p_pp), PRINT_STK(*debugState.p_sp)); } else DebugPrintf("<no execution stack: pc,obj,fp omitted>\n"); @@ -428,7 +556,7 @@ bool Console::cmdHexDump(int argc, const char **argv) { if (res == kResourceTypeInvalid) DebugPrintf("Resource type '%s' is not valid\n", argv[1]); else { - Resource *resource = _vm->getResMgr()->findResource(res, resNum, 0); + Resource *resource = _vm->getResMgr()->findResource(ResourceId(res, resNum), 0); if (resource) { Common::hexdump(resource->data, resource->size, 16, 0); DebugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); @@ -460,13 +588,13 @@ bool Console::cmdDissectScript(int argc, const char **argv) { return true; } - g_EngineState->_kernel->dissectScript(atoi(argv[1]), g_EngineState->_vocabulary); + _vm->_gamestate->_kernel->dissectScript(atoi(argv[1]), _vm->_gamestate->_vocabulary); return true; } bool Console::cmdRoomNumber(int argc, const char **argv) { - DebugPrintf("Current room number is %d\n", g_EngineState->currentRoomNumber()); + DebugPrintf("Current room number is %d\n", _vm->_gamestate->currentRoomNumber()); return true; } @@ -489,7 +617,7 @@ bool Console::cmdResourceSize(int argc, const char **argv) { if (res == kResourceTypeInvalid) DebugPrintf("Resource type '%s' is not valid\n", argv[1]); else { - Resource *resource = _vm->getResMgr()->findResource(res, resNum, 0); + Resource *resource = _vm->getResMgr()->findResource(ResourceId(res, resNum), 0); if (resource) { DebugPrintf("Resource size: %d\n", resource->size); } else { @@ -559,7 +687,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) { } for (; resNumber <= resMax; resNumber++) { - if ((script = _vm->getResMgr()->findResource(restype, resNumber, 0))) { + if ((script = _vm->getResMgr()->findResource(ResourceId(restype, resNumber), 0))) { unsigned int seeker = 0, seekerold = 0; uint32 comppos = 0; int output_script_name = 0; @@ -593,7 +721,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) { } bool Console::cmdList(int argc, const char **argv) { - if (argc != 2) { + if (argc < 2) { DebugPrintf("Lists all the resources of a given type\n"); cmdResourceTypes(argc, argv); return true; @@ -604,32 +732,54 @@ bool Console::cmdList(int argc, const char **argv) { if (res == kResourceTypeInvalid) DebugPrintf("Unknown resource type: '%s'\n", argv[1]); else { - int j = 0; - for (int i = 0; i < sci_max_resource_nr[_vm->getResMgr()->_sciVersion]; i++) { - if (_vm->getResMgr()->testResource(res, i)) { - DebugPrintf("%s.%03d | ", getResourceTypeName((ResourceType)res), i); - if (j % 5 == 0) + int number = -1; + + if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) { + if (argc != 3) { + DebugPrintf("Please specify map number\n"); + return true; + } + number = atoi(argv[2]); + } + + Common::List<ResourceId> *resources = _vm->getResMgr()->listResources(res, number); + sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::List<ResourceId>::iterator itr = resources->begin(); + + int cnt = 0; + while (itr != resources->end()) { + if (number == -1) { + DebugPrintf("%8i", itr->number); + if (++cnt % 10 == 0) + DebugPrintf("\n"); + } + else if (number == (int)itr->number) { + DebugPrintf("(%3i, %3i, %3i, %3i) ", (itr->tuple >> 24) & 0xff, (itr->tuple >> 16) & 0xff, + (itr->tuple >> 8) & 0xff, itr->tuple & 0xff); + if (++cnt % 4 == 0) DebugPrintf("\n"); - j++; } + itr++; } DebugPrintf("\n"); + + delete resources; } return true; } bool Console::cmdClearScreen(int argc, const char **argv) { - gfxop_clear_box(g_EngineState->gfx_state, gfx_rect(0, 0, 320, 200)); - gfxop_update_box(g_EngineState->gfx_state, gfx_rect(0, 0, 320, 200)); + gfxop_clear_box(_vm->_gamestate->gfx_state, gfx_rect(0, 0, 320, 200)); + gfxop_update_box(_vm->_gamestate->gfx_state, gfx_rect(0, 0, 320, 200)); return false; } bool Console::cmdRedrawScreen(int argc, const char **argv) { - g_EngineState->visual->draw(Common::Point(0, 0)); - gfxop_update_box(g_EngineState->gfx_state, gfx_rect(0, 0, 320, 200)); - gfxop_update(g_EngineState->gfx_state); - gfxop_sleep(g_EngineState->gfx_state, 0); + _vm->_gamestate->visual->draw(Common::Point(0, 0)); + gfxop_update_box(_vm->_gamestate->gfx_state, gfx_rect(0, 0, 320, 200)); + gfxop_update(_vm->_gamestate->gfx_state); + gfxop_sleep(_vm->_gamestate->gfx_state, 0); return false; } @@ -641,8 +791,8 @@ bool Console::cmdSaveGame(int argc, const char **argv) { } int result = 0; - for (uint i = 0; i < g_EngineState->_fileHandles.size(); i++) - if (g_EngineState->_fileHandles[i].isOpen()) + for (uint i = 0; i < _vm->_gamestate->_fileHandles.size(); i++) + if (_vm->_gamestate->_fileHandles[i].isOpen()) result++; if (result) @@ -656,7 +806,7 @@ bool Console::cmdSaveGame(int argc, const char **argv) { } // TODO: enable custom descriptions? force filename into a specific format? - if (gamestate_save(g_EngineState, out, "debugging")) { + if (gamestate_save(_vm->_gamestate, out, "debugging")) { DebugPrintf("Saving the game state to '%s' failed\n", argv[1]); } @@ -676,17 +826,17 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { Common::SeekableReadStream *in; if (!(in = saveFileMan->openForLoading(argv[1]))) { // found a savegame file - newstate = gamestate_restore(g_EngineState, in); + newstate = gamestate_restore(_vm->_gamestate, in); delete in; } if (newstate) { - g_EngineState->successor = newstate; // Set successor + _vm->_gamestate->successor = newstate; // Set successor script_abort_flag = 2; // Abort current game with replay - g_debugstate_valid = 0; + debugState.isValid = false; - shrink_execution_stack(g_EngineState, g_EngineState->execution_stack_base + 1); + shrink_execution_stack(_vm->_gamestate, _vm->_gamestate->execution_stack_base + 1); return 0; } else { DebugPrintf("Restoring gamestate '%s' failed.\n", argv[1]); @@ -705,27 +855,27 @@ bool Console::cmdRestartGame(int argc, const char **argv) { } if (!scumm_stricmp(argv[1], "play")) { - g_EngineState->restarting_flags |= SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; + _vm->_gamestate->restarting_flags |= SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; } else if (!scumm_stricmp(argv[1], "replay")) { - g_EngineState->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; + _vm->_gamestate->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; } else { DebugPrintf("Invalid usage of %s\n", argv[0]); return true; } - g_EngineState->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; + _vm->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; script_abort_flag = 1; - g_debugstate_valid = 0; + debugState.isValid = false; return false; } bool Console::cmdClassTable(int argc, const char **argv) { DebugPrintf("Available classes:\n"); - for (uint i = 0; i < g_EngineState->_classtable.size(); i++) { - if (g_EngineState->_classtable[i].reg.segment) { + for (uint i = 0; i < _vm->_gamestate->_classtable.size(); i++) { + if (_vm->_gamestate->_classtable[i].reg.segment) { DebugPrintf(" Class 0x%x at %04x:%04x (script 0x%x)\n", i, - PRINT_REG(g_EngineState->_classtable[i].reg), g_EngineState->_classtable[i].script); + PRINT_REG(_vm->_gamestate->_classtable[i].reg), _vm->_gamestate->_classtable[i].script); } } @@ -735,10 +885,10 @@ bool Console::cmdClassTable(int argc, const char **argv) { bool Console::cmdSentenceFragments(int argc, const char **argv) { DebugPrintf("Sentence fragments (used to build Parse trees)\n"); - for (uint i = 0; i < g_EngineState->_vocabulary->getParserBranchesSize(); i++) { + for (uint i = 0; i < _vm->_gamestate->_vocabulary->getParserBranchesSize(); i++) { int j = 0; - const parse_tree_branch_t &branch = g_EngineState->_vocabulary->getParseTreeBranch(i); + const parse_tree_branch_t &branch = _vm->_gamestate->_vocabulary->getParseTreeBranch(i); DebugPrintf("R%02d: [%x] ->", i, branch.id); while ((j < 10) && branch.data[j]) { int dat = branch.data[j++]; @@ -770,7 +920,7 @@ bool Console::cmdSentenceFragments(int argc, const char **argv) { DebugPrintf("\n"); } - DebugPrintf("%d rules.\n", g_EngineState->_vocabulary->getParserBranchesSize()); + DebugPrintf("%d rules.\n", _vm->_gamestate->_vocabulary->getParserBranchesSize()); return true; } @@ -793,24 +943,24 @@ bool Console::cmdParse(int argc, const char **argv) { } DebugPrintf("Parsing '%s'\n", string); - bool res = g_EngineState->_vocabulary->tokenizeString(words, string, &error); + bool res = _vm->_gamestate->_vocabulary->tokenizeString(words, string, &error); if (res && !words.empty()) { int syntax_fail = 0; - vocab_synonymize_tokens(words, g_EngineState->_synonyms); + vocab_synonymize_tokens(words, _vm->_gamestate->_synonyms); DebugPrintf("Parsed to the following blocks:\n"); for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i) DebugPrintf(" Type[%04x] Group[%04x]\n", i->_class, i->_group); - if (g_EngineState->_vocabulary->parseGNF(g_EngineState->parser_nodes, words, true)) + if (_vm->_gamestate->_vocabulary->parseGNF(_vm->_gamestate->parser_nodes, words, true)) syntax_fail = 1; // Building a tree failed if (syntax_fail) DebugPrintf("Building a tree failed.\n"); else - vocab_dump_parse_tree("debug-parse-tree", g_EngineState->parser_nodes); + vocab_dump_parse_tree("debug-parse-tree", _vm->_gamestate->parser_nodes); } else { DebugPrintf("Unknown word: '%s'\n", error); @@ -832,11 +982,11 @@ bool Console::cmdParserNodes(int argc, const char **argv) { for (int i = 0; i < end; i++) { DebugPrintf(" Node %03x: ", i); - if (g_EngineState->parser_nodes[i].type == PARSE_TREE_NODE_LEAF) - DebugPrintf("Leaf: %04x\n", g_EngineState->parser_nodes[i].content.value); + if (_vm->_gamestate->parser_nodes[i].type == kParseTreeLeafNode) + DebugPrintf("Leaf: %04x\n", _vm->_gamestate->parser_nodes[i].content.value); else - DebugPrintf("Branch: ->%04x, ->%04x\n", g_EngineState->parser_nodes[i].content.branches[0], - g_EngineState->parser_nodes[i].content.branches[1]); + DebugPrintf("Branch: ->%04x, ->%04x\n", _vm->_gamestate->parser_nodes[i].content.branches[0], + _vm->_gamestate->parser_nodes[i].content.branches[1]); } return true; @@ -860,10 +1010,10 @@ bool Console::cmdDrawPic(int argc, const char **argv) { if (argc == 4) flags = atoi(argv[3]); - gfxop_new_pic(g_EngineState->gfx_state, atoi(argv[1]), flags, default_palette); - gfxop_clear_box(g_EngineState->gfx_state, gfx_rect(0, 0, 320, 200)); - gfxop_update(g_EngineState->gfx_state); - gfxop_sleep(g_EngineState->gfx_state, 0); + gfxop_new_pic(_vm->_gamestate->gfx_state, atoi(argv[1]), flags, default_palette); + gfxop_clear_box(_vm->_gamestate->gfx_state, gfx_rect(0, 0, 320, 200)); + gfxop_update(_vm->_gamestate->gfx_state); + gfxop_sleep(_vm->_gamestate->gfx_state, 0); return false; } @@ -878,10 +1028,10 @@ bool Console::cmdDrawRect(int argc, const char **argv) { int col = CLIP<int>(atoi(argv[5]), 0, 15); - gfxop_set_clip_zone(g_EngineState->gfx_state, gfx_rect_fullscreen); - gfxop_fill_box(g_EngineState->gfx_state, gfx_rect(atoi(argv[1]), atoi(argv[2]), - atoi(argv[3]), atoi(argv[4])), g_EngineState->ega_colors[col]); - gfxop_update(g_EngineState->gfx_state); + gfxop_set_clip_zone(_vm->_gamestate->gfx_state, gfx_rect_fullscreen); + gfxop_fill_box(_vm->_gamestate->gfx_state, gfx_rect(atoi(argv[1]), atoi(argv[2]), + atoi(argv[3]), atoi(argv[4])), _vm->_gamestate->ega_colors[col]); + gfxop_update(_vm->_gamestate->gfx_state); return false; } @@ -898,9 +1048,9 @@ bool Console::cmdDrawCel(int argc, const char **argv) { int cel = atoi(argv[3]); int palette = atoi(argv[4]); - gfxop_set_clip_zone(g_EngineState->gfx_state, gfx_rect_fullscreen); - gfxop_draw_cel(g_EngineState->gfx_state, view, loop, cel, Common::Point(160, 100), g_EngineState->ega_colors[0], palette); - gfxop_update(g_EngineState->gfx_state); + gfxop_set_clip_zone(_vm->_gamestate->gfx_state, gfx_rect_fullscreen); + gfxop_draw_cel(_vm->_gamestate->gfx_state, view, loop, cel, Common::Point(160, 100), _vm->_gamestate->ega_colors[0], palette); + gfxop_update(_vm->_gamestate->gfx_state); return false; } @@ -921,7 +1071,7 @@ bool Console::cmdViewInfo(int argc, const char **argv) { DebugPrintf("Resource view.%d ", view); - loops = gfxop_lookup_view_get_loops(g_EngineState->gfx_state, view); + loops = gfxop_lookup_view_get_loops(_vm->_gamestate->gfx_state, view); if (loops < 0) DebugPrintf("does not exist.\n"); @@ -931,17 +1081,17 @@ bool Console::cmdViewInfo(int argc, const char **argv) { for (i = 0; i < loops; i++) { int j, cels; - DebugPrintf("Loop %d: %d cels.\n", i, cels = gfxop_lookup_view_get_cels(g_EngineState->gfx_state, view, i)); + DebugPrintf("Loop %d: %d cels.\n", i, cels = gfxop_lookup_view_get_cels(_vm->_gamestate->gfx_state, view, i)); for (j = 0; j < cels; j++) { int width; int height; Common::Point mod; // Show pixmap on screen - view_pixmaps = g_EngineState->gfx_state->gfxResMan->getView(view, &i, &j, palette); - gfxop_draw_cel(g_EngineState->gfx_state, view, i, j, Common::Point(0,0), transparent, palette); + view_pixmaps = _vm->_gamestate->gfx_state->gfxResMan->getView(view, &i, &j, palette); + gfxop_draw_cel(_vm->_gamestate->gfx_state, view, i, j, Common::Point(0,0), transparent, palette); - gfxop_get_cel_parameters(g_EngineState->gfx_state, view, i, j, &width, &height, &mod); + gfxop_get_cel_parameters(_vm->_gamestate->gfx_state, view, i, j, &width, &height, &mod); DebugPrintf(" cel %d: size %dx%d, adj+(%d,%d)\n", j, width, height, mod.x, mod.y); } @@ -963,7 +1113,7 @@ bool Console::cmdUpdateZone(int argc, const char **argv) { int width = atoi(argv[3]); int height = atoi(argv[4]); - g_EngineState->gfx_state->driver->update(gfx_rect(x, y, width, height), Common::Point(x, y), GFX_BUFFER_FRONT); + _vm->_gamestate->gfx_state->driver->update(gfx_rect(x, y, width, height), Common::Point(x, y), GFX_BUFFER_FRONT); return false; } @@ -983,14 +1133,14 @@ bool Console::cmdPropagateZone(int argc, const char **argv) { int map = CLIP<int>(atoi(argv[5]), 0, 1); rect_t rect = gfx_rect(x, y, width, height); - gfxop_set_clip_zone(g_EngineState->gfx_state, gfx_rect_fullscreen); + gfxop_set_clip_zone(_vm->_gamestate->gfx_state, gfx_rect_fullscreen); if (map == 1) - gfxop_clear_box(g_EngineState->gfx_state, rect); + gfxop_clear_box(_vm->_gamestate->gfx_state, rect); else - gfxop_update_box(g_EngineState->gfx_state, rect); - gfxop_update(g_EngineState->gfx_state); - gfxop_sleep(g_EngineState->gfx_state, 0); + gfxop_update_box(_vm->_gamestate->gfx_state, rect); + gfxop_update(_vm->_gamestate->gfx_state); + gfxop_sleep(_vm->_gamestate->gfx_state, 0); return false; } @@ -1005,18 +1155,18 @@ bool Console::cmdFillScreen(int argc, const char **argv) { int col = CLIP<int>(atoi(argv[1]), 0, 15); - gfxop_set_clip_zone(g_EngineState->gfx_state, gfx_rect_fullscreen); - gfxop_fill_box(g_EngineState->gfx_state, gfx_rect_fullscreen, g_EngineState->ega_colors[col]); - gfxop_update(g_EngineState->gfx_state); + gfxop_set_clip_zone(_vm->_gamestate->gfx_state, gfx_rect_fullscreen); + gfxop_fill_box(_vm->_gamestate->gfx_state, gfx_rect_fullscreen, _vm->_gamestate->ega_colors[col]); + gfxop_update(_vm->_gamestate->gfx_state); return false; } bool Console::cmdCurrentPort(int argc, const char **argv) { - if (!g_EngineState->port) + if (!_vm->_gamestate->port) DebugPrintf("There is no port active currently.\n"); else - DebugPrintf("Current port ID: %d\n", g_EngineState->port->_ID); + DebugPrintf("Current port ID: %d\n", _vm->_gamestate->port->_ID); return true; } @@ -1032,16 +1182,16 @@ bool Console::cmdPrintPort(int argc, const char **argv) { GfxPort *port; if (!scumm_stricmp(argv[1], "current")) { - port = g_EngineState->port; + port = _vm->_gamestate->port; if (!port) DebugPrintf("There is no active port currently\n"); else port->print(0); } else { - if (!g_EngineState->visual) { + if (!_vm->_gamestate->visual) { DebugPrintf("Visual is uninitialized\n"); } else { - port = g_EngineState->visual->getPort(atoi(argv[1])); + port = _vm->_gamestate->visual->getPort(atoi(argv[1])); if (!port) DebugPrintf("No such port\n"); else @@ -1055,7 +1205,7 @@ bool Console::cmdPrintPort(int argc, const char **argv) { bool Console::cmdParseGrammar(int argc, const char **argv) { DebugPrintf("Parse grammar, in strict GNF:\n"); - g_EngineState->_vocabulary->buildGNF(true); + _vm->_gamestate->_vocabulary->buildGNF(true); return true; } @@ -1063,8 +1213,8 @@ bool Console::cmdParseGrammar(int argc, const char **argv) { bool Console::cmdVisualState(int argc, const char **argv) { DebugPrintf("State of the current visual widget:\n"); - if (g_EngineState->visual) - g_EngineState->visual->print(0); + if (_vm->_gamestate->visual) + _vm->_gamestate->visual->print(0); else DebugPrintf("The visual widget is uninitialized.\n"); @@ -1072,11 +1222,11 @@ bool Console::cmdVisualState(int argc, const char **argv) { } bool Console::cmdFlushPorts(int argc, const char **argv) { - gfxop_set_pointer_cursor(g_EngineState->gfx_state, GFXOP_NO_POINTER); + gfxop_set_pointer_cursor(_vm->_gamestate->gfx_state, GFXOP_NO_POINTER); DebugPrintf("Flushing dynamically allocated ports (for memory profiling)...\n"); - delete g_EngineState->visual; - g_EngineState->gfx_state->gfxResMan->freeAllResources(); - g_EngineState->visual = NULL; + delete _vm->_gamestate->visual; + _vm->_gamestate->gfx_state->gfxResMan->freeAllResources(); + _vm->_gamestate->visual = NULL; return true; } @@ -1084,8 +1234,8 @@ bool Console::cmdFlushPorts(int argc, const char **argv) { bool Console::cmdDynamicViews(int argc, const char **argv) { DebugPrintf("List of active dynamic views:\n"); - if (g_EngineState->dyn_views) - g_EngineState->dyn_views->print(0); + if (_vm->_gamestate->dyn_views) + _vm->_gamestate->dyn_views->print(0); else DebugPrintf("The list is empty.\n"); @@ -1095,8 +1245,8 @@ bool Console::cmdDynamicViews(int argc, const char **argv) { bool Console::cmdDroppedViews(int argc, const char **argv) { DebugPrintf("List of dropped dynamic views:\n"); - if (g_EngineState->drop_views) - g_EngineState->drop_views->print(0); + if (_vm->_gamestate->drop_views) + _vm->_gamestate->drop_views->print(0); else DebugPrintf("The list is empty.\n"); @@ -1105,13 +1255,13 @@ bool Console::cmdDroppedViews(int argc, const char **argv) { bool Console::cmdPriorityBands(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Priority bands start at y=%d. They end at y=%d\n", g_EngineState->priority_first, g_EngineState->priority_last); - DebugPrintf("Use %d <priority band> to print the start of priority for the specified priority band (0 - 15)\n", argv[0]); + DebugPrintf("Priority bands start at y=%d. They end at y=%d\n", _vm->_gamestate->priority_first, _vm->_gamestate->priority_last); + DebugPrintf("Use %s <priority band> to print the start of priority for the specified priority band (0 - 15)\n", argv[0]); return true; } int zone = CLIP<int>(atoi(argv[1]), 0, 15); - DebugPrintf("Zone %x starts at y=%d\n", zone, _find_priority_band(g_EngineState, zone)); + DebugPrintf("Zone %x starts at y=%d\n", zone, _find_priority_band(_vm->_gamestate, zone)); return true; } @@ -1123,15 +1273,15 @@ bool Console::cmdStatusBarColors(int argc, const char **argv) { return true; } - g_EngineState->titlebar_port->_color = g_EngineState->ega_colors[atoi(argv[1])]; - g_EngineState->titlebar_port->_bgcolor = g_EngineState->ega_colors[atoi(argv[2])]; + _vm->_gamestate->titlebar_port->_color = _vm->_gamestate->ega_colors[atoi(argv[1])]; + _vm->_gamestate->titlebar_port->_bgcolor = _vm->_gamestate->ega_colors[atoi(argv[2])]; - g_EngineState->status_bar_foreground = atoi(argv[1]); - g_EngineState->status_bar_background = atoi(argv[2]); + _vm->_gamestate->status_bar_foreground = atoi(argv[1]); + _vm->_gamestate->status_bar_background = atoi(argv[2]); - sciw_set_status_bar(g_EngineState, g_EngineState->titlebar_port, g_EngineState->_statusBarText, - g_EngineState->status_bar_foreground, g_EngineState->status_bar_background); - gfxop_update(g_EngineState->gfx_state); + sciw_set_status_bar(_vm->_gamestate, _vm->_gamestate->titlebar_port, _vm->_gamestate->_statusBarText, + _vm->_gamestate->status_bar_foreground, _vm->_gamestate->status_bar_background); + gfxop_update(_vm->_gamestate->gfx_state); return false; } @@ -1139,8 +1289,8 @@ bool Console::cmdStatusBarColors(int argc, const char **argv) { bool Console::cmdPrintSegmentTable(int argc, const char **argv) { DebugPrintf("Segment table:\n"); - for (uint i = 0; i < g_EngineState->seg_manager->_heap.size(); i++) { - MemObject *mobj = g_EngineState->seg_manager->_heap[i]; + for (uint i = 0; i < _vm->_gamestate->seg_manager->_heap.size(); i++) { + MemObject *mobj = _vm->_gamestate->seg_manager->_heap[i]; if (mobj && mobj->getType()) { DebugPrintf(" [%04x] ", i); @@ -1201,10 +1351,10 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { bool Console::segmentInfo(int nr) { DebugPrintf("[%04x] ", nr); - if ((nr < 0) || ((uint)nr >= g_EngineState->seg_manager->_heap.size()) || !g_EngineState->seg_manager->_heap[nr]) + if ((nr < 0) || ((uint)nr >= _vm->_gamestate->seg_manager->_heap.size()) || !_vm->_gamestate->seg_manager->_heap[nr]) return false; - MemObject *mobj = g_EngineState->seg_manager->_heap[nr]; + MemObject *mobj = _vm->_gamestate->seg_manager->_heap[nr]; switch (mobj->getType()) { @@ -1227,10 +1377,10 @@ bool Console::segmentInfo(int nr) { for (uint i = 0; i < scr->_objects.size(); i++) { DebugPrintf(" "); // Object header - Object *obj = obj_get(g_EngineState, scr->_objects[i].pos); + Object *obj = obj_get(_vm->_gamestate, scr->_objects[i].pos); if (obj) DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(scr->_objects[i].pos), - obj_get_name(g_EngineState, scr->_objects[i].pos), obj->_variables.size(), obj->methods_nr); + obj_get_name(_vm->_gamestate, scr->_objects[i].pos), obj->_variables.size(), obj->methods_nr); } } break; @@ -1271,12 +1421,12 @@ bool Console::segmentInfo(int nr) { reg_t objpos; objpos.offset = i; objpos.segment = nr; - DebugPrintf(" [%04x] %s; copy of ", i, obj_get_name(g_EngineState, objpos)); + DebugPrintf(" [%04x] %s; copy of ", i, obj_get_name(_vm->_gamestate, objpos)); // Object header - Object *obj = obj_get(g_EngineState, ct->_table[i].pos); + Object *obj = obj_get(_vm->_gamestate, ct->_table[i].pos); if (obj) DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].pos), - obj_get_name(g_EngineState, ct->_table[i].pos), obj->_variables.size(), obj->methods_nr); + obj_get_name(_vm->_gamestate, ct->_table[i].pos), obj->_variables.size(), obj->methods_nr); } } break; @@ -1342,7 +1492,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { } if (!scumm_stricmp(argv[1], "all")) { - for (uint i = 0; i < g_EngineState->seg_manager->_heap.size(); i++) + for (uint i = 0; i < _vm->_gamestate->seg_manager->_heap.size(); i++) segmentInfo(i); } else { int nr = atoi(argv[1]); @@ -1361,7 +1511,7 @@ bool Console::cmdKillSegment(int argc, const char **argv) { return true; } - g_EngineState->seg_manager->getScript(atoi(argv[1]))->setLockers(0); + _vm->_gamestate->seg_manager->getScript(atoi(argv[1]))->setLockers(0); return true; } @@ -1377,24 +1527,24 @@ bool Console::cmdShowMap(int argc, const char **argv) { return true; } - gfxop_set_clip_zone(g_EngineState->gfx_state, gfx_rect_fullscreen); + gfxop_set_clip_zone(_vm->_gamestate->gfx_state, gfx_rect_fullscreen); int map = atoi(argv[1]); switch (map) { case 0: - g_EngineState->visual->add_dirty_abs((GfxContainer *)g_EngineState->visual, gfx_rect(0, 0, 320, 200), 0); - g_EngineState->visual->draw(Common::Point(0, 0)); + _vm->_gamestate->visual->add_dirty_abs((GfxContainer *)_vm->_gamestate->visual, gfx_rect(0, 0, 320, 200), 0); + _vm->_gamestate->visual->draw(Common::Point(0, 0)); break; case 1: - gfx_xlate_pixmap(g_EngineState->gfx_state->pic->priority_map, g_EngineState->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); - gfxop_draw_pixmap(g_EngineState->gfx_state, g_EngineState->gfx_state->pic->priority_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); + gfx_xlate_pixmap(_vm->_gamestate->gfx_state->pic->priority_map, _vm->_gamestate->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); + gfxop_draw_pixmap(_vm->_gamestate->gfx_state, _vm->_gamestate->gfx_state->pic->priority_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); break; case 2: - gfx_xlate_pixmap(g_EngineState->gfx_state->control_map, g_EngineState->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); - gfxop_draw_pixmap(g_EngineState->gfx_state, g_EngineState->gfx_state->control_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); + gfx_xlate_pixmap(_vm->_gamestate->gfx_state->control_map, _vm->_gamestate->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); + gfxop_draw_pixmap(_vm->_gamestate->gfx_state, _vm->_gamestate->gfx_state->control_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); break; default: @@ -1402,7 +1552,7 @@ bool Console::cmdShowMap(int argc, const char **argv) { return true; } - gfxop_update(g_EngineState->gfx_state); + gfxop_update(_vm->_gamestate->gfx_state); return false; } @@ -1410,14 +1560,14 @@ bool Console::cmdShowMap(int argc, const char **argv) { bool Console::cmdSongLib(int argc, const char **argv) { DebugPrintf("Song library:\n"); - song_t *seeker = *(g_EngineState->_sound._songlib.lib); + Song *seeker = _vm->_gamestate->_sound._songlib._lib; do { DebugPrintf(" %p", (void *)seeker); if (seeker) { - DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->handle, seeker->priority, seeker->status); - seeker = seeker->next; + DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->_handle, seeker->_priority, seeker->_status); + seeker = seeker->_next; } DebugPrintf("\n"); } while (seeker); @@ -1428,12 +1578,12 @@ bool Console::cmdSongLib(int argc, const char **argv) { bool Console::cmdGCInvoke(int argc, const char **argv) { DebugPrintf("Performing garbage collection...\n"); - run_gc(g_EngineState); + run_gc(_vm->_gamestate); return true; } bool Console::cmdGCObjects(int argc, const char **argv) { - reg_t_hash_map *use_map = find_all_used_references(g_EngineState); + reg_t_hash_map *use_map = find_all_used_references(_vm->_gamestate); DebugPrintf("Reachable object references (normalised):\n"); for (reg_t_hash_map::iterator i = use_map->begin(); i != use_map->end(); ++i) { @@ -1447,7 +1597,7 @@ bool Console::cmdGCObjects(int argc, const char **argv) { void _print_address(void * _, reg_t addr) { if (addr.segment) - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); + ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); } bool Console::cmdGCShowReachable(int argc, const char **argv) { @@ -1460,20 +1610,20 @@ bool Console::cmdGCShowReachable(int argc, const char **argv) { reg_t addr; - if (parse_reg_t(g_EngineState, argv[1], &addr)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &addr)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment); + MemObject *mobj = GET_SEGMENT_ANY(*_vm->_gamestate->seg_manager, addr.segment); if (!mobj) { DebugPrintf("Unknown segment : %x\n", addr.segment); return 1; } DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); - mobj->listAllOutgoingReferences(g_EngineState, addr, NULL, _print_address); + mobj->listAllOutgoingReferences(_vm->_gamestate, addr, NULL, _print_address); return true; } @@ -1489,13 +1639,13 @@ bool Console::cmdGCShowFreeable(int argc, const char **argv) { reg_t addr; - if (parse_reg_t(g_EngineState, argv[1], &addr)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &addr)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment); + MemObject *mobj = GET_SEGMENT_ANY(*_vm->_gamestate->seg_manager, addr.segment); if (!mobj) { DebugPrintf("Unknown segment : %x\n", addr.segment); return true; @@ -1519,39 +1669,35 @@ bool Console::cmdGCNormalize(int argc, const char **argv) { reg_t addr; - if (parse_reg_t(g_EngineState, argv[1], &addr)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &addr)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - MemObject *mobj = GET_SEGMENT_ANY(*g_EngineState->seg_manager, addr.segment); + MemObject *mobj = GET_SEGMENT_ANY(*_vm->_gamestate->seg_manager, addr.segment); if (!mobj) { DebugPrintf("Unknown segment : %x\n", addr.segment); return true; } - addr = mobj->findCanonicAddress(g_EngineState->seg_manager, addr); + addr = mobj->findCanonicAddress(_vm->_gamestate->seg_manager, addr); DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); return true; } bool Console::cmdVMVarlist(int argc, const char **argv) { - //const char *varnames[] = {"global", "local", "temp", "param"}; + const char *varnames[] = {"global", "local", "temp", "param"}; DebugPrintf("Addresses of variables in the VM:\n"); -#if 0 - // TODO: p_var_segs, p_vars, p_var_base, p_var_max - for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(p_var_segs[i], p_vars[i] - p_var_base[i]))); - if (p_var_max) - DebugPrintf(" total %d", p_var_max[i]); + DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(debugState.p_var_segs[i], debugState.p_vars[i] - debugState.p_var_base[i]))); + if (debugState.p_var_max) + DebugPrintf(" total %d", debugState.p_var_max[i]); DebugPrintf("\n"); } -#endif return true; } @@ -1567,7 +1713,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } - //const char *varnames[] = {"global", "local", "temp", "param"}; + const char *varnames[] = {"global", "local", "temp", "param"}; const char *varabbrev = "gltp"; const char *vartype_pre = strchr(varabbrev, *argv[1]); int vartype; @@ -1585,31 +1731,21 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } -#if 0 - // TODO: p_var_max - if ((p_var_max) && (p_var_max[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", p_var_max[vartype], p_var_max[vartype]); + if ((debugState.p_var_max) && (debugState.p_var_max[vartype] <= idx)) { + DebugPrintf("Max. index is %d (0x%x)\n", debugState.p_var_max[vartype], debugState.p_var_max[vartype]); return true; } -#endif switch (argc) { case 2: -#if 0 - // TODO: p_vars - DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(p_vars[vartype][idx])); -#endif + DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(debugState.p_vars[vartype][idx])); break; case 3: -#if 0 - // TODO: p_vars - - if (parse_reg_t(g_EngineState, argv[3], &p_vars[vartype][idx])) { + if (parse_reg_t(_vm->_gamestate, argv[3], &debugState.p_vars[vartype][idx])) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } -#endif break; default: DebugPrintf("Too many arguments\n"); @@ -1625,19 +1761,19 @@ bool Console::cmdStack(int argc, const char **argv) { return true; } - if (g_EngineState->_executionStack.empty()) { + if (_vm->_gamestate->_executionStack.empty()) { DebugPrintf("No exec stack!"); return true; } - ExecStack &xs = g_EngineState->_executionStack.back(); + ExecStack &xs = _vm->_gamestate->_executionStack.back(); int nr = atoi(argv[1]); for (int i = nr; i > 0; i--) { if ((xs.sp - xs.fp - i) == 0) DebugPrintf("-- temp variables --\n"); - if (xs.sp - i >= g_EngineState->stack_base) - DebugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - g_EngineState->stack_base), PRINT_REG(xs.sp[-i])); + if (xs.sp - i >= _vm->_gamestate->stack_base) + DebugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _vm->_gamestate->stack_base), PRINT_REG(xs.sp[-i])); } return true; @@ -1655,13 +1791,13 @@ bool Console::cmdValueType(int argc, const char **argv) { reg_t val; - if (parse_reg_t(g_EngineState, argv[1], &val)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &val)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - int t = determine_reg_type(g_EngineState, val, true); + int t = determine_reg_type(_vm->_gamestate, val, true); int invalid = t & KSIG_INVALID; switch (t & ~KSIG_INVALID) { @@ -1699,7 +1835,7 @@ bool Console::cmdViewListNode(int argc, const char **argv) { reg_t addr; - if (parse_reg_t(g_EngineState, argv[1], &addr)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &addr)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; @@ -1722,21 +1858,21 @@ bool Console::cmdViewReference(int argc, const char **argv) { reg_t reg = NULL_REG; reg_t reg_end = NULL_REG; - if (parse_reg_t(g_EngineState, argv[1], ®)) { + if (parse_reg_t(_vm->_gamestate, argv[1], ®)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } if (argc > 2) { - if (parse_reg_t(g_EngineState, argv[2], ®_end)) { + if (parse_reg_t(_vm->_gamestate, argv[2], ®_end)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } } - int type_mask = determine_reg_type(g_EngineState, reg, 1); + int type_mask = determine_reg_type(_vm->_gamestate, reg, 1); int filter; int found = 0; @@ -1766,7 +1902,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { case 0: break; case KSIG_LIST: { - List *l = lookup_list(g_EngineState, reg); + List *l = lookup_list(_vm->_gamestate, reg); DebugPrintf("list\n"); @@ -1782,11 +1918,11 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; case KSIG_OBJECT: DebugPrintf("object\n"); - printObject(g_EngineState, reg); + printObject(_vm->_gamestate, reg); break; case KSIG_REF: { int size; - unsigned char *block = g_EngineState->seg_manager->dereference(reg, &size); + unsigned char *block = _vm->_gamestate->seg_manager->dereference(reg, &size); DebugPrintf("raw data\n"); @@ -1830,32 +1966,28 @@ bool Console::cmdViewObject(int argc, const char **argv) { reg_t addr; - if (parse_reg_t(g_EngineState, argv[1], &addr)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &addr)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } DebugPrintf("Information on the object at the given address:\n"); - printObject(g_EngineState, addr); + printObject(_vm->_gamestate, addr); return true; } bool Console::cmdViewActiveObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class:\n"); - -#if 0 - // TODO: p_objp - printObject(g_EngineState, *p_objp); -#endif + printObject(_vm->_gamestate, *debugState.p_objp); return true; } bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); - printObject(g_EngineState, g_EngineState->r_acc); + printObject(_vm->_gamestate, _vm->_gamestate->r_acc); return true; } @@ -1875,13 +2007,13 @@ bool Console::cmdSetAccumulator(int argc, const char **argv) { reg_t val; - if (parse_reg_t(g_EngineState, argv[1], &val)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &val)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - g_EngineState->r_acc = val; + _vm->_gamestate->r_acc = val; return true; } @@ -1889,31 +2021,31 @@ bool Console::cmdSetAccumulator(int argc, const char **argv) { bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); - DebugPrintf("Call stack (current base: 0x%x):\n", g_EngineState->execution_stack_base); + DebugPrintf("Call stack (current base: 0x%x):\n", _vm->_gamestate->execution_stack_base); Common::List<ExecStack>::iterator iter; uint i = 0; - for (iter = g_EngineState->_executionStack.begin(); - iter != g_EngineState->_executionStack.end(); ++iter, ++i) { + for (iter = _vm->_gamestate->_executionStack.begin(); + iter != _vm->_gamestate->_executionStack.end(); ++iter, ++i) { ExecStack &call = *iter; - const char *objname = obj_get_name(g_EngineState, call.sendp); + const char *objname = obj_get_name(_vm->_gamestate, call.sendp); int paramc, totalparamc; switch (call.type) { case EXEC_STACK_TYPE_CALL: {// Normal function sciprintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : - selector_name(g_EngineState, call.selector)); + selector_name(_vm->_gamestate, call.selector)); } break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - sciprintf(" %x:[%x] k%s(", i, call.origin, g_EngineState->_kernel->getKernelName(-(call.selector) - 42).c_str()); + sciprintf(" %x:[%x] k%s(", i, call.origin, _vm->_gamestate->_kernel->getKernelName(-(call.selector) - 42).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname, g_EngineState->_kernel->getSelectorName(call.selector).c_str()); + objname, _vm->_gamestate->_kernel->getSelectorName(call.selector).c_str()); break; } @@ -1938,15 +2070,15 @@ bool Console::cmdBacktrace(int argc, const char **argv) { if (call.sp == CALL_SP_CARRY) sciprintf(" sp,fp:carry"); else { - sciprintf(" sp=ST:%04x", (unsigned)(call.sp - g_EngineState->stack_base)); - sciprintf(" fp=ST:%04x", (unsigned)(call.fp - g_EngineState->stack_base)); + sciprintf(" sp=ST:%04x", (unsigned)(call.sp - _vm->_gamestate->stack_base)); + sciprintf(" fp=ST:%04x", (unsigned)(call.fp - _vm->_gamestate->stack_base)); } } else sciprintf(" pc:none"); - sciprintf(" argp:ST:%04x", (unsigned)(call.variables_argp - g_EngineState->stack_base)); + sciprintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _vm->_gamestate->stack_base)); if (call.type == EXEC_STACK_TYPE_CALL) - sciprintf(" script: %d", (*(Script *)g_EngineState->seg_manager->_heap[call.addr.pc.segment]).nr); + sciprintf(" script: %d", (*(Script *)_vm->_gamestate->seg_manager->_heap[call.addr.pc.segment]).nr); sciprintf("\n"); } @@ -1954,8 +2086,255 @@ bool Console::cmdBacktrace(int argc, const char **argv) { return true; } +bool Console::cmdStep(int argc, const char **argv) { + debugState.isValid = false; + if (argc == 2 && atoi(argv[1]) > 0) + debugState.runningStep = atoi(argv[1]) - 1; + + return true; +} + +bool Console::cmdStepEvent(int argc, const char **argv) { + debugState.stopOnEvent = true; + debugState.isValid = false; + + return true; +} + +bool Console::cmdStepRet(int argc, const char **argv) { + debugState.seeking = kDebugSeekLevelRet; + debugState.seekLevel = _vm->_gamestate->_executionStack.size() - 1; + debugState.isValid = false; + + return true; +} + +bool Console::cmdStepGlobal(int argc, const char **argv) { + if (argc != 2) { + DebugPrintf("Steps until the global variable with the specified index is modified.\n"); + DebugPrintf("Usage: %s <global variable index>\n", argv[0]); + return true; + } + + debugState.seeking = kDebugSeekGlobal; + debugState.seekSpecial = atoi(argv[1]); + debugState.isValid = false; + + return true; +} + +bool Console::cmdStepCallk(int argc, const char **argv) { + int callk_index; + char *endptr; + + if (argc == 2) { + /* Try to convert the parameter to a number. If the conversion stops + before end of string, assume that the parameter is a function name + and scan the function table to find out the index. */ + callk_index = strtoul(argv[1], &endptr, 0); + if (*endptr != '\0') { + callk_index = -1; + for (uint i = 0; i < _vm->_gamestate->_kernel->getKernelNamesSize(); i++) + if (argv[1] == _vm->_gamestate->_kernel->getKernelName(i)) { + callk_index = i; + break; + } + + if (callk_index == -1) { + DebugPrintf("Unknown kernel function '%s'\n", argv[1]); + return true; + } + } + + debugState.seeking = kDebugSeekSpecialCallk; + debugState.seekSpecial = callk_index; + debugState.isValid = false; + } else { + debugState.seeking = kDebugSeekCallk; + debugState.isValid = false; + } + + return true; +} + +bool Console::cmdDissassemble(int argc, const char **argv) { + if (argc != 3) { + DebugPrintf("Disassembles a method by name.\n"); + DebugPrintf("Usage: %s <object> <method>\n", argv[0]); + return true; + } + + reg_t objAddr = NULL_REG; + + if (parse_reg_t(_vm->_gamestate, argv[1], &objAddr)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + Object *obj = obj_get(_vm->_gamestate, objAddr); + int selector_id = _vm->_gamestate->_kernel->findSelector(argv[2]); + reg_t addr; + + if (!obj) { + DebugPrintf("Not an object."); + return true; + } + + if (selector_id < 0) { + DebugPrintf("Not a valid selector name."); + return true; + } + + if (lookup_selector(_vm->_gamestate, objAddr, selector_id, NULL, &addr) != kSelectorMethod) { + DebugPrintf("Not a method."); + return true; + } + + do { + // TODO + //addr = disassemble(_vm->_gamestate, addr, 0, 0); + } while (addr.offset > 0); + + return true; +} + +bool Console::cmdDissassembleAddress(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Disassembles one or more commands.\n"); + DebugPrintf("Usage: %s [startaddr] <options>\n", argv[0]); + DebugPrintf("Valid options are:\n"); + DebugPrintf(" bwt : Print byte/word tag\n"); + DebugPrintf(" c<x> : Disassemble <x> bytes\n"); + DebugPrintf(" bc : Print bytecode\n"); + return true; + } + + reg_t vpc = NULL_REG; + int op_count = 1; + int do_bwc = 0; + int do_bytes = 0; + int size; + + if (parse_reg_t(_vm->_gamestate, argv[1], &vpc)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + _vm->_gamestate->seg_manager->dereference(vpc, &size); + size += vpc.offset; // total segment size + + for (int i = 1; i < argc; i++) { + if (!scumm_stricmp(argv[i], "bwt")) + do_bwc = 1; + else if (!scumm_stricmp(argv[i], "bc")) + do_bytes = 1; + else if (toupper(argv[i][0]) == 'C') + op_count = atoi(argv[i] + 1); + else { + DebugPrintf("Invalid option '%s'\n", argv[i]); + return true; + } + } + + if (op_count < 0) { + DebugPrintf("Invalid op_count\n"); + return true; + } + + do { + // TODO + //vpc = disassemble(_vm->_gamestate, vpc, do_bwc, do_bytes); + + } while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--op_count)); + + return true; +} + +bool Console::cmdSend(int argc, const char **argv) { + if (argc < 3) { + DebugPrintf("Sends a message to an object.\n"); + DebugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]); + DebugPrintf("Example: send ?fooScript cue\n"); + return true; + } + + reg_t object; + + if (parse_reg_t(_vm->_gamestate, argv[1], &object)) { + DebugPrintf("Invalid address passed for parameter 1.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + const char *selector_name = argv[2]; + StackPtr stackframe = _vm->_gamestate->_executionStack.front().sp; + int selector_id; + int i; + ExecStack *xstack; + Object *o; + reg_t fptr; + + selector_id = _vm->_gamestate->_kernel->findSelector(selector_name); + + if (selector_id < 0) { + sciprintf("Unknown selector: \"%s\"\n", selector_name); + return 1; + } + + o = obj_get(_vm->_gamestate, object); + if (o == NULL) { + sciprintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); + return 1; + } + + SelectorType selector_type = lookup_selector(_vm->_gamestate, object, selector_id, 0, &fptr); + + if (selector_type == kSelectorNone) { + sciprintf("Object does not support selector: \"%s\"\n", selector_name); + return 1; + } + + stackframe[0] = make_reg(0, selector_id); + stackframe[1] = make_reg(0, argc - 3); // -object -selector name -command name + + for (i = 3; i < argc; i++) { + if (parse_reg_t(_vm->_gamestate, argv[i], &stackframe[i])) { + DebugPrintf("Invalid address passed for parameter %d.\n", i); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + } + + xstack = add_exec_stack_entry(_vm->_gamestate, fptr, + _vm->_gamestate->_executionStack.front().sp + argc, + object, argc - 3, + _vm->_gamestate->_executionStack.front().sp - 1, 0, object, + _vm->_gamestate->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); + xstack->selector = selector_id; + xstack->type = selector_type == kSelectorVariable ? EXEC_STACK_TYPE_VARSELECTOR : EXEC_STACK_TYPE_CALL; + + // Now commit the actual function: + xstack = send_selector(_vm->_gamestate, object, object, stackframe, argc - 3, stackframe); + + xstack->sp += argc; + xstack->fp += argc; + + _vm->_gamestate->_executionStackPosChanged = true; + + return true; +} + +bool Console::cmdGo(int argc, const char **argv) { + debugState.seeking = kDebugSeekNothing; + debugState.isValid = false; + + return true; +} + bool Console::cmdBreakpointList(int argc, const char **argv) { - Breakpoint *bp = g_EngineState->bp_list; + Breakpoint *bp = _vm->_gamestate->bp_list; int i = 0; int bpdata; @@ -1994,7 +2373,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { // Find breakpoint with given index bp_prev = NULL; - bp = g_EngineState->bp_list; + bp = _vm->_gamestate->bp_list; while (bp && i < idx) { bp_prev = bp; bp = bp->next; @@ -2013,11 +2392,11 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { if (bp_prev) bp_prev->next = bp_next; else - g_EngineState->bp_list = bp_next; + _vm->_gamestate->bp_list = bp_next; // Check if there are more breakpoints of the same type. If not, clear // the respective bit in s->have_bp. - for (bp = g_EngineState->bp_list; bp; bp = bp->next) { + for (bp = _vm->_gamestate->bp_list; bp; bp = bp->next) { if (bp->type == type) { found = 1; break; @@ -2025,7 +2404,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } if (!found) - g_EngineState->have_bp &= ~type; + _vm->_gamestate->have_bp &= ~type; return true; } @@ -2044,23 +2423,23 @@ bool Console::cmdBreakpointExecMethod(int argc, const char **argv) { Thus, we can't check whether the command argument is a valid method name. A breakpoint set on an invalid method name will just never trigger. */ Breakpoint *bp; - if (g_EngineState->bp_list) { + if (_vm->_gamestate->bp_list) { // List exists, append the breakpoint to the end - bp = g_EngineState->bp_list; + bp = _vm->_gamestate->bp_list; while (bp->next) bp = bp->next; bp->next = (Breakpoint *)malloc(sizeof(Breakpoint)); bp = bp->next; } else { // No list, so create the list head - g_EngineState->bp_list = (Breakpoint *)malloc(sizeof(Breakpoint)); - bp = g_EngineState->bp_list; + _vm->_gamestate->bp_list = (Breakpoint *)malloc(sizeof(Breakpoint)); + bp = _vm->_gamestate->bp_list; } bp->next = NULL; bp->type = BREAK_SELECTOR; bp->data.name = (char *)malloc(strlen(argv[1]) + 1); strcpy(bp->data.name, argv[1]); - g_EngineState->have_bp |= BREAK_SELECTOR; + _vm->_gamestate->have_bp |= BREAK_SELECTOR; return true; } @@ -2077,22 +2456,22 @@ bool Console::cmdBreakpointExecFunction(int argc, const char **argv) { Thus, we can't check whether the command argument is a valid method name. A breakpoint set on an invalid method name will just never trigger. */ Breakpoint *bp; - if (g_EngineState->bp_list) { + if (_vm->_gamestate->bp_list) { // List exists, append the breakpoint to the end - bp = g_EngineState->bp_list; + bp = _vm->_gamestate->bp_list; while (bp->next) bp = bp->next; bp->next = (Breakpoint *)malloc(sizeof(Breakpoint)); bp = bp->next; } else { // No list, so create the list head - g_EngineState->bp_list = (Breakpoint *)malloc(sizeof(Breakpoint)); - bp = g_EngineState->bp_list; + _vm->_gamestate->bp_list = (Breakpoint *)malloc(sizeof(Breakpoint)); + bp = _vm->_gamestate->bp_list; } bp->next = NULL; bp->type = BREAK_EXPORT; bp->data.address = (atoi(argv[1]) << 16 | atoi(argv[2])); - g_EngineState->have_bp |= BREAK_EXPORT; + _vm->_gamestate->have_bp |= BREAK_EXPORT; return true; } @@ -2105,7 +2484,7 @@ bool Console::cmdIsSample(int argc, const char **argv) { return true; } - Resource *song = _vm->getResMgr()->findResource(kResourceTypeSound, atoi(argv[1]), 0); + Resource *song = _vm->getResMgr()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); SongIterator *songit; Audio::AudioStream *data; @@ -2143,7 +2522,7 @@ bool Console::cmdSfx01Header(int argc, const char **argv) { return true; } - Resource *song = _vm->getResMgr()->findResource(kResourceTypeSound, atoi(argv[1]), 0); + Resource *song = _vm->getResMgr()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); if (!song) { DebugPrintf("Doesn't exist\n"); @@ -2308,7 +2687,7 @@ bool Console::cmdSfx01Track(int argc, const char **argv) { return true; } - Resource *song = _vm->getResMgr()->findResource(kResourceTypeSound, atoi(argv[1]), 0); + Resource *song = _vm->getResMgr()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); int offset = atoi(argv[2]); @@ -2333,18 +2712,18 @@ bool Console::cmdStopSfx(int argc, const char **argv) { reg_t id; - if (parse_reg_t(g_EngineState, argv[1], &id)) { + if (parse_reg_t(_vm->_gamestate, argv[1], &id)) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } int handle = id.segment << 16 | id.offset; // frobnicate handle - EngineState* s = g_EngineState; // for PUT_SEL32V + EngineState* s = _vm->_gamestate; // for PUT_SEL32V if (id.segment) { - g_EngineState->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - g_EngineState->_sound.sfx_remove_song(handle); + _vm->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); + _vm->_gamestate->_sound.sfx_remove_song(handle); PUT_SEL32V(id, signal, -1); PUT_SEL32V(id, nodePtr, 0); PUT_SEL32V(id, handle, 0); @@ -2363,9 +2742,9 @@ bool Console::cmdExit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully script_abort_flag = 1; // Terminate VM - g_debugstate_valid = 0; - g_debug_seeking = 0; - g_debug_step_running = 0; + debugState.isValid = false; + debugState.seeking = kDebugSeekNothing; + debugState.runningStep = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully @@ -2583,7 +2962,7 @@ void Console::printList(List *l) { while (!pos.isNull()) { Node *node; - NodeTable *nt = (NodeTable *)GET_SEGMENT(*g_EngineState->seg_manager, pos.segment, MEM_OBJ_NODES); + NodeTable *nt = (NodeTable *)GET_SEGMENT(*_vm->_gamestate->seg_manager, pos.segment, MEM_OBJ_NODES); if (!nt || !nt->isValidEntry(pos.offset)) { DebugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", @@ -2610,7 +2989,7 @@ void Console::printList(List *l) { } int Console::printNode(reg_t addr) { - MemObject *mobj = GET_SEGMENT(*g_EngineState->seg_manager, addr.segment, MEM_OBJ_LISTS); + MemObject *mobj = GET_SEGMENT(*_vm->_gamestate->seg_manager, addr.segment, MEM_OBJ_LISTS); if (mobj) { ListTable *lt = (ListTable *)mobj; @@ -2627,7 +3006,7 @@ int Console::printNode(reg_t addr) { } else { NodeTable *nt; Node *node; - mobj = GET_SEGMENT(*g_EngineState->seg_manager, addr.segment, MEM_OBJ_NODES); + mobj = GET_SEGMENT(*_vm->_gamestate->seg_manager, addr.segment, MEM_OBJ_NODES); if (!mobj) { DebugPrintf("Segment #%04x is not a list or node segment\n", addr.segment); @@ -2853,34 +3232,34 @@ int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { return 1; } - g_debugstate_valid = 0; + debugState.isValid = false; opcode = s->_heap[*p_pc]; opnumber = opcode >> 1; if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { - g_debug_seeking = _DEBUG_SEEK_SO; - s_debug_seek_level = s->_executionStack.size()-1; - // Store in s_debug_seek_special the offset of the next command after send + debugState.seeking = kDebugSeekSO; + debugState.seekLevel = s->_executionStack.size()-1; + // Store in debugState.seekSpecial the offset of the next command after send switch (opcode) { case 0x46: // calle W - s_debug_seek_special = *p_pc + 5; + debugState.seekSpecial = *p_pc + 5; break; case 0x44: // callb W case 0x47: // calle B case 0x56: // super W - s_debug_seek_special = *p_pc + 4; + debugState.seekSpecial = *p_pc + 4; break; case 0x45: // callb B case 0x57: // super B case 0x4A: // send W case 0x54: // self W - s_debug_seek_special = *p_pc + 3; + debugState.seekSpecial = *p_pc + 3; break; default: - s_debug_seek_special = *p_pc + 2; + debugState.seekSpecial = *p_pc + 2; } } diff --git a/engines/sci/console.h b/engines/sci/console.h index b2e66daa0f..84a8d2f942 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -59,9 +59,10 @@ private: bool cmdSuffixes(int argc, const char **argv); bool cmdParseGrammar(int argc, const char **argv); bool cmdParserNodes(int argc, const char **argv); - bool cmdParserWords(int argc, const char **argv); + bool cmdParserWords(int argc, const char **argv); bool cmdSentenceFragments(int argc, const char **argv); bool cmdParse(int argc, const char **argv); + bool cmdSetParseNodes(int argc, const char **argv); // Resources bool cmdHexDump(int argc, const char **argv); bool cmdResourceId(int argc, const char **argv); @@ -121,6 +122,15 @@ private: bool cmdDissectScript(int argc, const char **argv); bool cmdSetAccumulator(int argc, const char **argv); bool cmdBacktrace(int argc, const char **argv); + bool cmdStep(int argc, const char **argv); + bool cmdStepEvent(int argc, const char **argv); + bool cmdStepRet(int argc, const char **argv); + bool cmdStepGlobal(int argc, const char **argv); + bool cmdStepCallk(int argc, const char **argv); + bool cmdDissassemble(int argc, const char **argv); + bool cmdDissassembleAddress(int argc, const char **argv); + bool cmdSend(int argc, const char **argv); + bool cmdGo(int argc, const char **argv); // Breakpoints bool cmdBreakpointList(int argc, const char **argv); bool cmdBreakpointDelete(int argc, const char **argv); @@ -144,6 +154,7 @@ private: private: SciEngine *_vm; + bool _mouseVisible; }; } // End of namespace Sci diff --git a/engines/sci/debug.h b/engines/sci/debug.h index ec44838826..fbd98e0d6f 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -28,19 +28,41 @@ namespace Sci { -// Various global variables used for debugging are declared here - -extern int g_stop_on_event; +enum DebugSeeking { + kDebugSeekNothing = 0, + kDebugSeekCallk = 1, // Step forward until callk is found + kDebugSeekLevelRet = 2, // Step forward until returned from this level + kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found + kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth + kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified +}; -extern int g_debugstate_valid; -extern int g_debug_seeking; -extern int g_debug_step_running; +struct DebugState { + bool isValid; + bool stopOnEvent; + DebugSeeking seeking; // Stepping forward until some special condition is met + int runningStep; // Set to > 0 to allow multiple stepping + int seekLevel; // Used for seekers that want to check their exec stack depth + int seekSpecial; // Used for special seeks + int old_pc_offset; + StackPtr old_sp; + reg_t *p_pc; + StackPtr *p_sp; + StackPtr *p_pp; + reg_t *p_objp; + int *p_restadjust; + SegmentId *p_var_segs; + reg_t **p_vars; + reg_t **p_var_base; + int *p_var_max; // May be NULL even in valid state! +}; +// Various global variables used for debugging are declared here extern int g_debug_sleeptime_factor; extern int g_debug_simulated_key; extern bool g_debug_track_mouse_clicks; extern bool g_debug_weak_validations; - +extern DebugState debugState; } // End of namespace Sci diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 38095e446e..f04c390944 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -31,9 +31,7 @@ namespace Sci { -// The 4 SCI0 engine generations (pre-395, pre-502, pre-629 and post-629) -#define GF_FOR_SCI0_BEFORE_395 (GF_SCI0_OLD | GF_SCI0_OLDGFXFUNCS | GF_SCI0_OLDGETTIME) -#define GF_FOR_SCI0_BEFORE_502 (GF_SCI0_OLDGFXFUNCS | GF_SCI0_OLDGETTIME) +#define GF_FOR_SCI0_BEFORE_395 (GF_SCI0_OLD | GF_SCI0_OLDGETTIME) #define GF_FOR_SCI0_BEFORE_629 GF_SCI0_OLDGETTIME // SCI1 @@ -113,7 +111,7 @@ static const PlainGameDescriptor SciGameTitles[] = { {{"sci-fanmade", name, { \ {"resource.map", 0, resMapMd5, resMapSize}, \ {"resource.001", 0, resMd5, resSize}, \ - {NULL, 0, NULL, 0}}, lang, Common::kPlatformPC, 0}, \ + {NULL, 0, NULL, 0}}, lang, Common::kPlatformPC, 0, GUIO_NOSPEECH}, \ 0, \ SCI_VERSION_AUTODETECT, \ ver \ @@ -123,6 +121,9 @@ static const PlainGameDescriptor SciGameTitles[] = { #define FANMADE_V(name, resMapMd5, resMapSize, resMd5, resSize, ver) FANMADE_LV(name, resMapMd5, resMapSize, resMd5, resSize, Common::EN_ANY, ver) #define FANMADE(name, resMapMd5, resMapSize, resMd5, resSize) FANMADE_LV(name, resMapMd5, resMapSize, resMd5, resSize, Common::EN_ANY, SCI_VERSION_0) +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + // Game descriptions static const struct SciGameDescription SciGameDescriptions[] = { // Astro Chicken - English DOS @@ -130,8 +131,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"astrochicken", "", { {"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474}, {"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -145,7 +146,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "3fb02ce493f6eacdcc3713851024f80e", 559540}, {"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380}, {"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -160,7 +161,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "4e0836fadc324316c1a418125709ba45", 569057}, {"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309}, {"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -172,7 +173,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "467bb5e3224bb54640c3280032aebff5", 633}, {"resource.000", 0, "9780f040d58182994e22d2e34fab85b0", 67367}, {"resource.001", 0, "2af49dbd8f2e1db4ab09f9310dc91259", 570553}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -186,7 +187,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 346731}, {"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832}, {"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -198,7 +199,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5738c163e014bbe046474de009020b82", 2727}, {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694}, {"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -209,7 +210,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"christmas1988", "", { {"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426}, {"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_395, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -220,7 +221,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"christmas1990", "16 Colors", { {"resource.map", 0, "8f656714a05b94423ac6eb10ee8797d0", 600}, {"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 272629}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -231,7 +232,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"christmas1990", "256 Colors", { {"resource.map", 0, "44b8f45b841b9b5e17e939a35e443988", 600}, {"resource.001", 0, "acde93e58fca4f7a2a5a220558a94aa8", 335362}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -242,7 +243,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"christmas1992", "", { {"resource.map", 0, "f1f8c8a8443f523422af70b4ec85b71c", 318}, {"resource.000", 0, "62fb9256f8e7e6e65a6875efdb7939ac", 203396}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -259,7 +260,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 619219}, {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 713382}, {"resource.005", 0, "605b67a9ef199a9bb015745e7c004cf4", 478384}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -270,7 +271,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"iceman", "Demo", { {"resource.map", 0, "782974f29d8a824782d2d4aea39964e3", 1056}, {"resource.001", 0, "d4b75e280d1c3a97cfef1b0bebff387c", 573647}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -286,7 +287,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "36670a917550757d57df84c96cf9e6d9", 566549}, {"resource.003", 0, "d97a96f1ab91b41cf46a02cc89b0a04e", 624303}, {"resource.004", 0, "8613c45fc771d658e5a505b9a4a54f31", 670883}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -301,7 +302,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "250b859381ebf2bf8922bd99683b0cc1", 566464}, {"resource.003", 0, "dc7c5280e7acfaffe6ef2a6c963c5f94", 622118}, {"resource.004", 0, "64f342463f6f35ba71b3509ef696ae3f", 669188}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -319,7 +320,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6821dc97cf643ba521a4e840dda3c58b", 647410}, {"resource.005", 0, "c6e551bdc24f0acc193159038d4ca767", 605882}, {"resource.006", 0, "8f880a536908ab496bbc552f7f5c3738", 585255}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -330,7 +331,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"camelot", "Demo", { {"resource.map", 0, "f4cd75c15be75e04cdca3acda2c0b0ea", 468}, {"resource.001", 0, "4930708722f34bfbaa4945fb08f55f61", 232523}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -345,7 +346,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "8e1a3a8c588007404b532b8dfacc1460", 722250}, {"resource.003", 0, "8e1a3a8c588007404b532b8dfacc1460", 723712}, {"resource.004", 0, "8e1a3a8c588007404b532b8dfacc1460", 729143}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -362,7 +363,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "8e1a3a8c588007404b532b8dfacc1460", 345734}, {"resource.006", 0, "8e1a3a8c588007404b532b8dfacc1460", 332446}, {"resource.007", 0, "8e1a3a8c588007404b532b8dfacc1460", 358182}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -380,7 +381,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "d1038c75d85a6650d48e07d174a6a913", 838175}, {"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002}, {"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -397,7 +398,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1064637}, {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -414,7 +415,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "1867136d01ece57b531032d466910522", 823686}, {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -430,7 +431,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "1867136d01ece57b531032d466910522", 823610}, {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -447,7 +448,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b7bb35c027bb424ecefcd122768e5e60", 705631}, {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243}, {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -458,7 +459,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"longbow", "Demo", { {"resource.map", 0, "cbc5cb73341de1bff1b1e20a640af220", 588}, {"resource.001", 0, "f05a20cc07eee85da8e999d0ac0f596b", 869916}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -475,7 +476,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1101869}, {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -487,7 +488,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"ecoquest", "Demo", { {"resource.map", 0, "c819e171359b7c95f4c13b846d5c034e", 873}, {"resource.001", 0, "baf9393a9bfa73098adb501e5bc5487b", 657518}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -498,7 +499,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"ecoquest", "CD", { {"resource.map", 0, "a4b73d5d2b55bdb6e44345e99c8fbdd0", 4804}, {"resource.000", 0, "d908dbef56816ac6c60dd145fdeafb2b", 3536046}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -512,7 +513,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "96d4435d24c01f1c1675e46457604c5f", 1413719}, {"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816}, {"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -526,7 +527,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212161}, {"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316}, {"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -540,7 +541,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212060}, {"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -555,7 +556,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "2fed7451bca81b0c891eed1a956f2263", 1212060}, {"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -566,7 +567,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"ecoquest2", "Demo", { {"resource.map", 0, "607cfa0d8a03b7d348c06ee727e3d939", 1321}, {"resource.000", 0, "dd6f614c43c029f063e93cd243af90a4", 525992}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -577,7 +578,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"ecoquest2", "Floppy", { {"resource.map", 0, "28fb7b6abb9fc1cb8882d7c2e701b63f", 5658}, {"resource.000", 0, "cc1d17e5637528dbe4a812699e1cbfc6", 4208192}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -588,7 +589,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"freddypharkas", "Demo", { {"resource.map", 0, "97aa9fcfe84c9993a64debd28c32393a", 1909}, {"resource.000", 0, "5ea8e7a3ea10cce6efd5c106dc62fd8c", 867724}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -599,7 +600,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"freddypharkas", "CD", { {"resource.map", 0, "d46b282f228a67ba13bd4b4009e95f8f", 6058}, {"resource.000", 0, "ee3c64ffff0ba9fb08bea2624631c598", 5490246}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -612,7 +613,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816}, {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "554f65315d851184f6e38211489fdd8f", -1}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -625,7 +626,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816}, {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "304b5a5781800affd2235152a5794fa8", -1}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -641,7 +642,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "419dbd5366f702b4123dedbbb0cffaae", 1456640}, {"resource.003", 0, "05acdc256c742e79c50b9fe7ec2cc898", 863310}, {"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -654,7 +655,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816}, {"resource.000", 0, "96b07e9b914dba1c8dc6c78a176326df", 5233230}, {"resource.msg", 0, "45b5bf74933ac3727e4cc844446dc052", 796156}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -665,7 +666,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"freddypharkas", "CD Demo", { {"resource.map", 0, "a62a7eae85dd1e6b07f39662b278437e", 1918}, {"resource.000", 0, "4962a3c4dd44e36e78ea4a7a374c2220", 957382}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -676,7 +677,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"funseeker", "", { {"resource.map", 0, "7ee6859ef74314f6d91938c3595348a9", 282}, {"resource.001", 0, "f1e680095424e31f7fae1255d36bacba", 40692}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -687,7 +688,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "CD Demo", { {"resource.map", 0, "39645952ae0ed8072c7e838f31b75464", 2490}, {"resource.000", 0, "eb3ed7477ca4110813fe1fcf35928561", 1718450}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -699,7 +700,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "", { {"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10783}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -710,7 +711,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "", { {"resource.map", 0, "65e8c14092e4c9b3b3538b7602c8c5ec", 10783}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 13022630}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -721,7 +722,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "", { {"resource.map", 0, "ad6508b0296b25c07b1f58828dc33696", 10789}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13077029}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -732,7 +733,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "CD", { {"resource.map", 0, "372d059f75856afa6d73dd84cbb8913d", 10996}, {"resource.000", 0, "69b7516962510f780d38519cc15fcc7c", 12581736}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -743,7 +744,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "CD", { {"resource.map", 0, "a7d3e55114c65647310373cb390815ba", 11392}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13400497}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -754,7 +755,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk1", "CD", { {"resource.map", 0, "7cb6e9bba15b544ec7a635c45bde9953", 11404}, {"resource.000", 0, "091cf08910780feabc56f8551b09cb36", 13381599}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -765,7 +766,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"gk2", "Demo", { {"resource.map", 0, "e0effce11c4908f4b91838741716c83d", 1351}, {"resource.000", 0, "d04cfc7f04b6f74d13025378be49ec2b", 4640330}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -785,7 +786,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.005", 0, "14b62d4a3bddee57a03cb1495a798a0f", 38075705}, {"resmap.006", 0, "ce9359037277b7d7976da185c2fa0aad", 2977}, {"ressci.006", 0, "8e44e03890205a7be12f45aaba9644b4", 60659424}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -796,7 +797,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"hoyle1", "Demo", { {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -809,7 +810,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 162783}, {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 342309}, {"resource.003", 0, "e0dd44069a62a463fd124974b915f10d", 328912}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -820,7 +821,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"hoyle1", "", { {"resource.map", 0, "1034a218943d12f1f36e753fa10c95b8", 4386}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518308}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -833,7 +834,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "2a72b1aba65fa6e339370eb86d8601d1", 5166}, {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 218755}, {"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 439502}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -846,7 +847,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "4f894d203f64aa23d9ff64d30ae36926", 2100}, {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 98138}, {"resource.002", 0, "8f2dd70abe01112eca464cda818b5eb6", 196631}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -858,7 +859,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"hoyle2", "", { {"resource.map", 0, "62ed48d20c580e5a98f102f7cd93706a", 1356}, {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 222704}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -872,7 +873,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f1f158e428398cb87fc41fb4aa8c2119", 2088}, {"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791}, {"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -885,7 +886,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"hoyle3", "Demo", { {"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735}, {"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -898,7 +899,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "7216a2972f9c595c45ab314941628e43", 2247}, {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -909,7 +910,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"hoyle4", "Demo", { {"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938}, {"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -922,7 +923,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "65cbe19b36fffc71c8e7b2686bd49ad7", 1800}, {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 313476}, {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 719747}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01_VGA_ODD, SCI_VERSION_1 @@ -938,7 +939,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "9ae2a13708d691cd42f9129173c4b39d", 795123}, {"resource.003", 0, "9ae2a13708d691cd42f9129173c4b39d", 763224}, {"resource.004", 0, "9ae2a13708d691cd42f9129173c4b39d", 820443}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -949,10 +950,10 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq1sci", "SCI Remake Demo", { {"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954}, {"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, - SCI_VERSION_01 + SCI_VERSION_0 }, // King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection) @@ -963,10 +964,10 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "fed9e0072ffd511d248674e60dee2099", 555439}, {"resource.002", 0, "fed9e0072ffd511d248674e60dee2099", 714062}, {"resource.003", 0, "fed9e0072ffd511d248674e60dee2099", 717478}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, - SCI_VERSION_01 + SCI_VERSION_0 }, // King's Quest 4 - English Amiga (from www.back2roots.org) @@ -979,7 +980,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "fb351106ec865fad9af5d78bd6b8e3cb", 663629}, {"resource.003", 0, "fd16c9c223f7dc5b65f06447615224ff", 683016}, {"resource.004", 0, "3fac034c7d130e055d05bc43a1f8d5f8", 549993}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -990,7 +991,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq4sci", "Demo", { {"resource.map", 0, "992ac7cc31d3717fe53818a9bb6d1dae", 594}, {"resource.001", 0, "143e1c14f15ad0fbfc714f648a65f661", 205330}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1005,7 +1006,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77615c595388acf3d1df8e107bfb6b52", 536573}, {"resource.003", 0, "77615c595388acf3d1df8e107bfb6b52", 707591}, {"resource.004", 0, "77615c595388acf3d1df8e107bfb6b52", 479562}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1022,7 +1023,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "851a62d00972dc4002f472cc0d84e71d", 321593}, {"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777}, {"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_395, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1039,7 +1040,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "0c8566848a76eea19a6d6220914030a7", 325102}, {"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288}, {"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_395, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1058,7 +1059,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "31a5487f4d942e6354d5be49d59707c9", 834146}, {"resource.006", 0, "26c0c25399b6715fec03fc3e12544fe3", 823048}, {"resource.007", 0, "b914b5901e786327213e779725d30dd1", 778772}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1077,7 +1078,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "5aa3d59968b569cd509dde00d4eb8751", 754201}, {"resource.006", 0, "56546b20db11a4836f900efa6d3a3e74", 672099}, {"resource.007", 0, "56546b20db11a4836f900efa6d3a3e74", 794194}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1096,7 +1097,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "de3c5c09e350fded36ca354998c2194d", 754784}, {"resource.006", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 672527}, {"resource.007", 0, "11cb750f5f816445ad0f4b9f50a4f59a", 794259}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1109,7 +1110,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f68ba690e5920725dcf9328001b90e33", 13122}, {"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368}, {"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1127,7 +1128,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "b6c43441cb78a9b484efc8e614aac092", 1287999}, {"resource.006", 0, "672ede1136e9e401658538e51bd5dc22", 1172619}, {"resource.007", 0, "2f48faf27666b58c276dda20f91f4a93", 1240456}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, 0, SCI_VERSION_1 @@ -1145,7 +1146,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "9c429782d102739f6bbb81e8b953b0cb", 1267525}, {"resource.006", 0, "d1a75fdc01840664d00366cff6919366", 1208972}, {"resource.007", 0, "c07494f0cce7c05210893938786a955b", 1337361}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1163,7 +1164,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "f4e441f284560eaa8022102315656a7d", 1267757}, {"resource.006", 0, "8eeabd92af71e766e323db2100879102", 1209325}, {"resource.007", 0, "dc10c107e0923b902326a040b9c166b9", 1337859}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1181,7 +1182,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "6556ff8e7c4d1acf6a78aea154daa76c", 1287869}, {"resource.006", 0, "da82e4beb744731d0a151f1d4922fafa", 1170456}, {"resource.007", 0, "431def14ca29cdb5e6a5e84d3f38f679", 1240176}, - {NULL, 0, NULL, 0}}, Common::PL_POL, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::PL_POL, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1194,7 +1195,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f75727c00a6d884234fa2a43c951943a", 706}, {"resource.000", 0, "535b1b920441ec73f42eaa4ccfd47b89", 264116}, {"resource.msg", 0, "54d1fdc936f98c81f9e4c19e04fb1510", 8260}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1206,7 +1207,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703}, {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, {"resource.msg", 0, "3cf5de44de36191f109d425b8450efc8", 258590}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1218,7 +1219,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703}, {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324}, {"resource.msg", 0, "756297b2155db9e43f621c6f6fb763c3", 282822}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1230,7 +1231,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq6", "CD", { {"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215}, {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, 7, SCI_VERSION_1_1 @@ -1243,7 +1244,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a73a5ab04b8f60c4b75b946a4dccea5a", 8953}, {"resource.000", 0, "4da3ad5868a775549a7cc4f72770a58e", 8537260}, {"resource.msg", 0, "41eed2d3893e1ca6c3695deba4e9d2e8", 267102}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1255,7 +1256,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq7", "", { {"resource.map", 0, "2be9ab94429c721af8e05c507e048a15", 18697}, {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 203882535}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1266,7 +1267,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq7", "", { {"resource.map", 0, "8676b0fbbd7362989a029fe72fea14c6", 18709}, {"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1277,7 +1278,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq7", "", { {"resource.map", 0, "838b9ff132bd6962026fee832e8a7ddb", 18697}, {"resource.000", 0, "eb63ea3a2c2469dc2d777d351c626404", 206626576}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1288,7 +1289,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq7", "", { {"resource.map", 0, "0b62693cbe87e3aaca3e8655a437f27f", 18709}, {"resource.000", 0, "51c1ead1163e19a2de8f121c39df7a76", 200764100}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1299,7 +1300,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"kq7", "Demo", { {"resource.map", 0, "b44f774108d63faa1d021101221c5a54", 1690}, {"resource.000", 0, "d9659d2cf0c269c6a9dc776707f5bea0", 2433827}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1317,7 +1318,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "2ab23f64306b18c28302c8ec2964c5d6", 605134}, {"resource.004", 0, "aa553977f7e5804081de293800d3bcce", 695067}, {"resource.005", 0, "bfd870d51dc97729f0914095f58e6957", 676881}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1332,7 +1333,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 721149}, {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667365}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683737}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAtariST, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1343,7 +1344,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"laurabow", "Demo", { {"resource.map", 0, "e625726268ff4e123ada11f31f0249f3", 768}, {"resource.001", 0, "0c8912290af0890f8d95faeb4ddb2d68", 333031}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1357,7 +1358,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 721381}, {"resource.003", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 667468}, {"resource.004", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 683807}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1374,7 +1375,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 327465}, {"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390}, {"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1391,7 +1392,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 327465}, {"resource.006", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 328390}, {"resource.007", 0, "e45c888d9c7c04aec0a20e9f820b79ff", 317687}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1403,7 +1404,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"laurabow2", "Demo", { {"resource.map", 0, "24dffc5db1d88c7999f13e8767ed7346", 855}, {"resource.000", 0, "2b2b1b4f7584f9b38fd13f6ab95634d1", 781912}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1415,7 +1416,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"laurabow2", "", { {"resource.map", 0, "610bfd9a852004222f0faaf5fc9e630a", 6489}, {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5035964}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1427,25 +1428,23 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"laurabow2", "CD", { {"resource.map", 0, "a70945e61ba7ac7bfea6b7bd72c6aec5", 7274}, {"resource.000", 0, "82578b8d5a7e09c4c58891ca49fae35b", 5598672}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 }, -#if 0 - // FIXME: add resource.msg, since the other files are the same as in the spanish version - // Laura Bow 2 v1.1 - German DOS Floppy (from Tobis87, updated info from markcoolio in bug report #2723787)) - // SCI interpreter version 1.001.069 (just a guess) + // Laura Bow 2 v1.1 - German DOS Floppy (from Tobis87, updated info from markcoolio in bug report #2723787, updated info from #2797962)) + // Executable scanning reports "2.000.274" {{"laurabow2", "", { {"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483}, {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {"resource.msg", 0, "795c928cd00dfec9fbc62ebcd12e1f65", 303185}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 }, -#endif // Laura Bow 2 - Spanish DOS CD (from jvprat) // Executable scanning reports "2.000.274", VERSION file reports "1.000.000, May 10, 1994" @@ -1453,7 +1452,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "3b6dfbcda210bbc3f23fd1927113bf98", 6483}, {"resource.000", 0, "57084910bc923bff5d6d9bc1b56e9604", 5028766}, {"resource.msg", 0, "71f1f0cd9f082da2e750c793a8ed9d84", 286141}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1467,7 +1466,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "38936d3c68b6f79d3ffb13955713fed7", 591352}, {"resource.002", 0, "24c958bc922b07f91e25e8c93aa01fcf", 491230}, {"resource.003", 0, "685cd6c1e05a695ab1e0db826337ee2a", 553279}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1482,7 +1481,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "24ed6dc01b1e7fbc66c3d63a5994549a", 750465}, {"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041}, {"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1495,7 +1494,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "d3bceaebef3f7be941c2038b3565161e", 922406}, {"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226}, {"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1508,7 +1507,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "d3bceaebef3f7be941c2038b3565161e", 918242}, {"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688}, {"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1519,7 +1518,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl1sci", "VGA Remake Demo", { {"resource.map", 0, "434e1f6c39d71647b34f0ee57b2bbd68", 444}, {"resource.001", 0, "0c0768215c562d9dace4a5ca53696cf3", 359913}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1535,7 +1534,21 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "112648995dbc194037f1e4ed2e195910", 1063341}, {"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908}, {"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI1_510_OR_LATER, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + + // Larry 1 VGA Remake - Russian DOS + // Executable scanning reports "1.000.510", VERSION file reports "2.0" + // SCI interpreter version 1.000.510 + {{"lsl1sci", "VGA Remake", { + {"resource.map", 0, "b54413d35e206d21ae2b2bdb092bd13a", 3198}, + {"resource.000", 0, "0d7b2afa666bd36d9535a15d3a837a66", 928566}, + {"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759}, + {"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160}, + {NULL, 0, NULL, 0}}, Common::RU_RUS, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1550,7 +1563,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "a0d4a625311d307257da7fc43d00459d", 630106}, {"resource.003", 0, "a0d4a625311d307257da7fc43d00459d", 570356}, {"resource.004", 0, "a0d4a625311d307257da7fc43d00459d", 717844}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1562,8 +1575,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl2", "Demo", { {"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528}, {"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1578,8 +1591,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "4a24443a25e2b1492462a52809605dc2", 204861}, {"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732}, {"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1594,7 +1607,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "96033f57accfca903750413fd09193c8", 204867}, {"resource.005", 0, "96033f57accfca903750413fd09193c8", 274953}, {"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_395, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1611,7 +1624,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "5c10e462c8cf589610773e4fe8bfd996", 527238}, {"resource.004", 0, "f408e59cbee1457f042e5773b8c53951", 651634}, {"resource.005", 0, "433911eb764089d493aed1f958a5615a", 524259}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1625,7 +1638,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "f18441027154292836b973c655fa3175", 578024}, {"resource.003", 0, "f18441027154292836b973c655fa3175", 506807}, {"resource.004", 0, "f18441027154292836b973c655fa3175", 513651}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1642,7 +1655,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "f18441027154292836b973c655fa3175", 302946}, {"resource.006", 0, "f18441027154292836b973c655fa3175", 282465}, {"resource.007", 0, "f18441027154292836b973c655fa3175", 257174}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1654,7 +1667,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "33a2384f395470af3d2180e37ad0322a", 1140}, {"resource.001", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 76525}, {"resource.002", 0, "f773d79b93dfd4052ec8c1cc64c1e6ab", 268299}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1669,7 +1682,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "3827a9b17b926e12dcc336860f50612a", 672403}, {"resource.003", 0, "3827a9b17b926e12dcc336860f50612a", 587036}, {"resource.004", 0, "3827a9b17b926e12dcc336860f50612a", 691932}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1684,7 +1697,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "65f1bdaa20f6d0470e9d969f22473873", 671614}, {"resource.003", 0, "65f1bdaa20f6d0470e9d969f22473873", 586921}, {"resource.004", 0, "65f1bdaa20f6d0470e9d969f22473873", 690826}, - {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -1702,7 +1715,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "3ce5901f1bc171ac0274d99a4eeb9e57", 623022}, {"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621}, {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1721,7 +1734,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "59eba83ad465b08d763b44f86afa86f6", 664717}, {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966}, {"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1732,7 +1745,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl5", "Demo", { {"resource.map", 0, "efe8d3f45ce4f6bd9a6643e0ac8d2a97", 504}, {"resource.001", 0, "8bd8d9c0b5f455ee1269d63ce86c50dd", 531380}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1750,7 +1763,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 1011944}, {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1768,7 +1781,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 959342}, {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1787,7 +1800,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 920524}, {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842}, - {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1806,7 +1819,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "0cc8d35a744031c772ca7cd21ae95273", 958079}, {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1817,7 +1830,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl5", "", { {"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919}, {"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -1828,7 +1841,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "bb8a39d9e2a77ba449a1e591109ad9a8", 6973}, {"resource.000", 0, "4462fe48c7452d98fddcec327a3e738d", 5789138}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_1_1, SCI_VERSION_1_1 @@ -1839,7 +1852,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "0b91234b7112782962cb480b7791b6e2", 7263}, {"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_1_1, SCI_VERSION_1_1 @@ -1850,7 +1863,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "bafe85f32738854135991d4324ad147e", 7268}, {"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5773160}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1861,7 +1874,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "97797ea775baaf18a1907d357d3c0ea6", 7268}, {"resource.000", 0, "f6cbc6da7b90ea135883e0759848ca2c", 5776092}, - {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1872,7 +1885,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "633bf8f42170b6271019917c8009989b", 6943}, {"resource.000", 0, "7884a8db9253e29e6b37a2651fd90ba3", 5733116}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1883,7 +1896,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lslcasino", "", { {"resource.map", 0, "194f1578f2624db813c9072359ad1639", 783}, {"resource.001", 0, "3733433b517ec3d14a3331d9ab3842ae", 344830}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -1895,7 +1908,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872}, {"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1906,7 +1919,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1917,7 +1930,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl6", "", { {"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987}, - {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1928,7 +1941,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "", { {"resmap.000", 0, "eae93e1b1d1ccc58b4691c371281c95d", 8188}, {"ressci.000", 0, "89353723488219e25589165d73ed663e", 66965678}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1939,7 +1952,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "", { {"resmap.000", 0, "c11e6bfcfc2f2d05da47e5a7df3e9b1a", 8188}, {"ressci.000", 0, "a8c6817bb94f332ff498a71c8b47f893", 66971724}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1950,7 +1963,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "", { {"resmap.000", 0, "4407849fd52fe3efb0c30fba60cd5cd4", 8206}, {"ressci.000", 0, "dc37c3055fffbefb494ff22b145d377b", 66964472}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1961,7 +1974,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "", { {"resmap.000", 0, "9852a97141f789413f29bf956052acdb", 8212}, {"ressci.000", 0, "440b9fed89590abb4e4386ed6f948ee2", 67140181}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1972,7 +1985,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "", { {"resmap.000", 0, "8f3d603e1acc834a5d598b30cdfc93f3", 8188}, {"ressci.000", 0, "32792f9bc1bf3633a88b382bb3f6e40d", 67071418}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1983,7 +1996,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lsl7", "Demo", { {"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878}, {"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -1994,7 +2007,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lighthouse", "Demo", { {"resource.map", 0, "543124606352bfa5e07696ddf2a669be", 64}, {"resource.000", 0, "5d7714416b612463d750fb9c5690c859", 28952}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2005,7 +2018,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"lighthouse", "Demo", { {"resmap.000", 0, "3bdee7a16926975a4729f75cf6b80a92", 1525}, {"ressci.000", 0, "3c585827fa4a82f4c04a56a0bc52ccee", 11494351}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2018,7 +2031,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.001", 0, "14e922c47b92156377cb49e241691792", 99591924}, {"resmap.002", 0, "c68db5333f152fea6ca2dfc75cad8b34", 7573}, {"ressci.002", 0, "175468431a979b9f317c294ce3bc1430", 94628315}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2031,7 +2044,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.001", 0, "18553177dbf83fb2cb6c8edcbb174183", 99543093}, {"resmap.002", 0, "e7dc85884a2417e2eff9de0c63dd65fa", 7630}, {"ressci.002", 0, "3c8d627c555b0e3e4f1d9955bc0f0df4", 94631127}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2043,7 +2056,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "c2cf672c3f4251e7472d4542af3bf764", 933}, {"resource.000", 0, "8be56a3a88c065ee00c02c0e29199f3a", 14643}, {"resource.001", 0, "9e33566515b18bee7915db448063bba2", 871853}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -2058,7 +2071,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "6767f8c8585f617aaa91d442f41ae714", 1032989}, {"resource.003", 0, "b1288e0821ee358d1ffe877e5900c8ec", 1047565}, {"resource.004", 0, "f79daa70390d73746742ffcfc3dc4471", 937580}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -2072,7 +2085,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "49c8f7dcd9989e4491a93554bec325b0", 238019}, {"resource.002", 0, "564f516d991032e781492592a4eaa275", 1414142}, {"resource.003", 0, "dd6cef0c592eadb7e6be9a25307c57a2", 1344719}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -2085,7 +2098,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "4aa28ac93fae03cf854594da13d9229c", 2700}, {"resource.001", 0, "fb552ae550ca1dac19ed8f6a3767612d", 262885}, {"resource.002", 0, "fb552ae550ca1dac19ed8f6a3767612d", 817191}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -2096,7 +2109,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"mothergoose", "", { {"resource.map", 0, "52aae15e493cafd1da7e1c9b657a5bb9", 7026}, {"resource.000", 0, "b7ecd8ae9e254e80310b5a668b276e6e", 2948975}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_01, SCI_VERSION_01 @@ -2108,7 +2121,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"mothergoose", "CD", { {"resource.map", 0, "1c7f311b0a2c927b2fbe81ae341fb2f6", 5790}, {"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 4369438}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2119,7 +2132,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"mothergoose", "Demo", { {"resource.map", 0, "87f9dc1cafc4d4fa835fb2f00cf3a6ef", 4560}, {"resource.001", 0, "5a0ed1d745855148364de1b3be099bac", 2070072}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2131,7 +2144,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"mothergoose", "", { {"resource.map", 0, "5159a1578c4306bfe070a3e4d8c2e1d3", 4741}, {"resource.000", 0, "1926925c95d82f0999590e93b02887c5", 15150768}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2143,7 +2156,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"msastrochicken", "", { {"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158}, {"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2167,7 +2180,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.006", 0, "3aae6559aa1df273bc542d5ac6330d75", 77901360}, {"resmap.007", 0, "afbd16ea77869a720afa1c5371de107d", 7972}, //{"ressci.007", 0, "3aae6559aa1df273bc542d5ac6330d75", 25859038}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2186,7 +2199,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.004", 0, "53f457cddb0dffc056593905c4cbb989", 42447131}, {"resmap.005", 0, "8bd5ceeedcbe16dfe55d1b90dcd4be84", 1942}, {"ressci.005", 0, "05f9fe2bee749659acb3cd2c90252fc5", 67905112}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2198,7 +2211,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pepper", "Demo", { {"resource.map", 0, "379bb4fb896630b14f2d91ed21e36ba1", 984}, {"resource.000", 0, "118f6c31a93ec7fd9a231c61125229e3", 645494}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2209,7 +2222,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pepper", "Demo", { {"resource.map", 0, "975e8df76106a5c13d12ab674f906a02", 2514}, {"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1698164}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2220,7 +2233,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pepper", "Demo", { {"resource.map", 0, "9c9b7b900651a370dd3fb38d478b1798", 2524}, {"resource.000", 0, "e6a918a2dd7a4bcecd8fb389f43287c2", 1713544}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2231,7 +2244,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq1sci", "VGA Remake", { {"resource.map", 0, "35efa814fb994b1cbdac9611e401da67", 5013}, {"resource.000", 0, "e0d5ddf34eda903a38f0837e2aa7145b", 6401433}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2245,7 +2258,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "523db0c07f1da2a822c2c39ee0482544", 179334}, {"resource.002", 0, "499737c21a28ac026e11ab817100d610", 511099}, {"resource.003", 0, "e008f5d6e2a7c4d4a0da0173e4fa8f8b", 553970}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2256,8 +2269,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq2", "Demo", { {"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576}, {"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2272,8 +2285,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "77f02def3094af804fd2371db25b7100", 342149}, {"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899}, {"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2285,8 +2298,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509525}, {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2298,8 +2311,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509760}, {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2314,7 +2327,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "f7044bb08a1fcbe5077791ed8d4996f0", 691207}, {"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891}, {"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2331,7 +2344,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "87361c17fd863b58f98828de68770279", 682288}, {"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738}, {"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2347,7 +2360,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "c18e0d408e4f4f40365d42aa15931f67", 1153561}, {"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791}, {"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2360,7 +2373,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ec8e58e7663ae5173853abf6c76b52bb", 867}, {"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150}, {"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2376,7 +2389,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "cce99b96a578b62ff6cebdae8d122feb", 1179358}, {"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956}, {"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2387,7 +2400,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq4", "Demo", { {"resource.map", 0, "be56f87a1c4a13062a30a362df860c2f", 1472}, {"resource.000", 0, "527d5684016e6816157cd15d9071b11b", 1121310}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2399,7 +2412,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq4", "", { {"resource.map", 0, "379dfe80ed6bd16c47e4b950c4722eac", 11374}, {"resource.000", 0, "fd316a09b628b7032248139003369022", 18841068}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2410,7 +2423,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq4", "", { {"resource.map", 0, "aed9643158ccf01b71f359db33137f82", 9895}, {"resource.000", 0, "da383857b3be1e4514daeba2524359e0", 15141432}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2421,7 +2434,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pq4", "", { {"resource.map", 0, "2393ee728ab930b2762cb5889f9b5aff", 9256}, {"resource.000", 0, "6ba98bd2e436739d87ecd2a9b99cabb4", 14730155}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2432,7 +2445,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"pqswat", "Demo", { {"resource.map", 0, "8c96733ef94c21526792f7ca4e3f2120", 1648}, {"resource.000", 0, "d8892f1b8c56c8f7704325460f49b300", 3676175}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2449,7 +2462,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.003", 0, "00a755e917c442ca8cf1a1bea689e6fb", 45073980}, {"resmap.004", 0, "4228038906f041623e65789500b22285", 6835}, {"ressci.004", 0, "b7e619e6ecf62fe65d5116a3a422e5f0", 46223872}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2465,7 +2478,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "439ba9b6dde216e6eb97ef3a9830fbe4", 646869}, {"resource.003", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 642203}, {"resource.004", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 641688}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2483,12 +2496,38 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "7288ed6d5da89b7a80b4af3897a7963a", 271185}, {"resource.006", 0, "69366c2a2f99917199fe1b60a4fee19d", 267852}, {"resource.007", 0, "7ab2bf8e224b57f75e0cd6e4ba790761", 272747}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, + // Quest for Glory 1 - Japanese PC-98 5.25" Floppy + // Executable scanning reports "S.old.201" + {{"qfg1", "8 Colors", { + {"resource.map", 0, "5cbeb95dd2a4b7cb242b415cc6ec1c47", 6444}, + {"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 859959}, + {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1136968}, + {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 769897}, + {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_01 + }, + + // Quest for Glory 1 - Japanese PC-98 5.25" Floppy + // Executable scanning reports "S.old.201" + {{"qfg1", "16 Colors", { + {"resource.map", 0, "3ecaba33bf77cb434067a0b8aee15097", 6444}, + {"resource.001", 0, "a21451ef6fa8179bd4b22c4950004c44", 864754}, + {"resource.002", 0, "a21451ef6fa8179bd4b22c4950004c44", 1147121}, + {"resource.003", 0, "a21451ef6fa8179bd4b22c4950004c44", 777575}, + {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_01 + }, + // Quest for Glory 1 - English Amiga // Executable scanning reports "1.002.020" // SCI interpreter version 0.000.685 @@ -2500,7 +2539,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 654096}, {"resource.004", 0, "16cd4414c37ae3bb6d6da33dce8e25e8", 689124}, {"resource.005", 0, "5f3386ef2f2b1254e4a066f5d9027324", 609529}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2515,7 +2554,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "05ddce5f437a516b89ede2438fac09d8", 635734}, {"resource.003", 0, "951299a82a8134ed12c5c18118d45c2f", 640483}, {"resource.004", 0, "951299a82a8134ed12c5c18118d45c2f", 644443}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2526,7 +2565,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg1", "VGA Remake", { {"resource.map", 0, "a731fb6c9c0b282443f7027bc8694d4c", 8469}, {"resource.000", 0, "ecace1a2771846b1a8aa1afdd44111a0", 6570147}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2537,7 +2576,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg1", "VGA Remake Demo", { {"resource.map", 0, "ac0257051c95a59c0cdc0be24d9b11fa", 729}, {"resource.000", 0, "ec6f5cf369054dd3e5392995e9975b9e", 768218}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2556,7 +2595,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "a77d2576c842b2b06da57d4ac8fc51c0", 579975}, {"resource.006", 0, "ccf5dba33e5cab6d5872838c0f8db44c", 500039}, {"resource.007", 0, "4c9fc1587545879295cb9627f56a2cb8", 575056}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_01 @@ -2571,7 +2610,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "df137dc7869cab07e1149ba2333c815c", 790750}, {"resource.003", 0, "b192607c42f6960ecdf2ad2e4f90e9bc", 972804}, {"resource.004", 0, "cd2de58e27665d5853530de93fae7cd6", 983617}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_01 @@ -2589,7 +2628,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "df137dc7869cab07e1149ba2333c815c", 478688}, {"resource.006", 0, "b1944bd664ddbd2859cdaa0c4a0d6281", 507489}, {"resource.007", 0, "cd2de58e27665d5853530de93fae7cd6", 490794}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_01 @@ -2600,7 +2639,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg3", "Demo", { {"resource.map", 0, "fd71de9b588a45f085317caacf050e91", 687}, {"resource.000", 0, "b6c69bf6c18bf177492249fe81fc6a6d", 648702}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2611,7 +2650,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg3", "", { {"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958}, {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2622,7 +2661,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg3", "", { {"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958}, {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868042}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2634,7 +2673,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "10809197c33a5e62819311d8a2f73f85", 5978}, {"resource.000", 0, "ba7ac86155e4c531e46cd73c86daa80a", 5884098}, {"resource.msg", 0, "a63974730d294dec0bea10057c36e506", 256014}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2645,7 +2684,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "Demo", { {"resource.map", 0, "1ba7c7ae1efb315326d45cb931569b1b", 922}, {"resource.000", 0, "41ba03f0b188b029132daa3ece0d3e14", 623154}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2657,7 +2696,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "", { {"resource.map", 0, "685bdb1ed47bbbb0e5e25db392da83ce", 9301}, {"resource.000", 0, "f64fd6aa3977939a86ff30783dd677e1", 11004993}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2668,7 +2707,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "", { {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2679,7 +2718,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "", { {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2693,7 +2732,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "", { {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2705,7 +2744,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"qfg4", "", { {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2716,7 +2755,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"rama", "Demo", { {"resmap.001", 0, "775304e9b2a545156be4d94209550094", 1393}, {"ressci.001", 0, "259437fd75fdf51e8207fda8c01fa4fd", 2334384}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2731,7 +2770,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"ressci.002", 0, "2a68edd064e5e4937b5e9c74b38f2082", 128562138}, {"resmap.003", 0, "31ef4c0621711585d031f0ae81707251", 1636}, {"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6860492}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2742,7 +2781,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"rama", "", { {"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70611091}, {"resmap.001", 0, "70ba2ff04a2b7fb2c52420ba7fbd47c2", 8338}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2753,7 +2792,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"shivers", "", { {"resmap.000", 0, "f2ead37749ed8f6535a2445a7d05a0cc", 46525}, {"ressci.000", 0, "4294c6d7510935f2e0a52e302073c951", 262654836}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2763,7 +2802,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"shivers", "", { {"resmap.000", 0, "f483d0a1f78334c18052e92785c3086e", 46537}, {"ressci.000", 0, "6751b144671e2deed919eb9d284b07eb", 262390692}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2774,7 +2813,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"shivers", "Demo", { {"resmap.000", 0, "d9e0bc5eddefcbe47f528760085d8927", 1186}, {"ressci.000", 0, "3a93c6340b54e07e65d0e5583354d186", 10505469}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2785,7 +2824,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"shivers2", "Demo", { {"resmap.000", 0, "d8659188b84beaef076bd869837cd530", 634}, {"ressci.000", 0, "7fbac0807a044c9543e8ac376d200e59", 4925003}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -2798,7 +2837,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "61b4f74039399e5aa1e737b16d0fc023", 1409}, {"resource.msg", 0, "1aeafe2b495de288d002109650b66614", 1364}, {"resource.000", 0, "8e10d4f05c1fd9f883384fa38a898489", 377394}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -2814,7 +2853,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "2588c1c2ca8b9bed0e3411948c0856a9", 839302}, {"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515}, {"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2830,7 +2869,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "a9e847c687529481f3a22b9bf01f45f7", 1169831}, {"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262}, {"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2841,7 +2880,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq1sci", "VGA Remake Demo", { {"resource.map", 0, "5af709ac5e0e923e0b8174f49978c30e", 636}, {"resource.001", 0, "fd99ea43f57576ded7c86036996346cf", 507642}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2858,7 +2897,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8c22700a02991b763f512f837636b3ca", 1211307}, {"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325}, {"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2872,8 +2911,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 754432}, {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496}, {"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_0, SCI_VERSION_0 }, @@ -2888,7 +2927,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 712374}, {"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053}, {"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_510_OR_LATER, SCI_VERSION_0, SCI_VERSION_0 @@ -2899,8 +2938,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq3", "Demo", { {"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612}, {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2912,8 +2951,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 485158}, {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244}, {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2925,7 +2964,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 490247}, {"resource.002", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 715777}, {"resource.003", 0, "8b55c4875298f45ea5696a5ee8f6a7fe", 703370}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2942,8 +2981,8 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "9107c2aa5398e28b5c5406df13491f85", 322107}, {"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643}, {"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, - GF_FOR_SCI0_BEFORE_502, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2955,7 +2994,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "9107c2aa5398e28b5c5406df13491f85", 567245}, {"resource.002", 0, "9107c2aa5398e28b5c5406df13491f85", 596768}, {"resource.003", 0, "9107c2aa5398e28b5c5406df13491f85", 693573}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 @@ -2973,7 +3012,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "1887ed88bb34ae7238650e8f77f26315", 798226}, {"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296}, {"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -2990,7 +3029,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "99c6a017da5e769a3b427ca52c8a564f", 824601}, {"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745}, {"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3002,7 +3041,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq4", "", { {"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3014,7 +3053,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq4", "", { {"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3031,7 +3070,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "96fa33d89d838bc3f671c5b953e7a896", 1240130}, {"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631}, {"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3048,7 +3087,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b8d6efbd3235329bfe844c794097b2c9", 1064761}, {"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765}, {"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3064,18 +3103,44 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "5289000399d503b59da9e23129256f1a", 1325546}, {"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000}, {"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, + // Space Quest 4 - Japanese PC-98 5.25" Floppy + // SCI interpreter version 1.000.1068 + {{"sq4", "", { + {"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283}, + {"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909}, + {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, + {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, + {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, + GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + + // Space Quest 4 - Japanese PC-98 5.25" Floppy + // SCI interpreter version 1.000.1068 + {{"sq4", "", { + {"resource.map", 0, "ca7bba01019222b6f3e54e9051067a99", 5283}, + {"resource.000", 0, "161d719f38ed98d33f058a8cf3dc09c3", 952909}, + {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, + {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, + GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + // Space Quest 4 - English DOS CD (from the Space Quest Collection) // Executable scanning reports "1.001.064", VERSION file reports "1.0" {{"sq4", "CD", { {"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054}, {"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3092,7 +3157,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1319306}, {"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752}, {"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3107,7 +3172,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "567608beb69d9dffdb42a8f39cb11a5e", 994323}, {"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801}, {"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408}, - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3124,7 +3189,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "47ee647b5b12232d27e63cc627c25899", 1321146}, {"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368}, {"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, GF_FOR_SCI1_200_OR_LATER, SCI_VERSION_AUTODETECT, SCI_VERSION_1 @@ -3136,7 +3201,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "66317c12ac6e818d1f7c17e83c1d9819", 6143}, {"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486}, {"resource.msg", 0, "bb8ad78793c26bdb3f77498b1d6515a9", 125988}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3147,7 +3212,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq5", "", { {"resource.map", 0, "8bde0a9adb9a3e9aaa861826874c9834", 6473}, {"resource.000", 0, "f4a48705764544d7cc64a7bb22a610df", 6025184}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3159,7 +3224,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "66317c12ac6e818d1f7c17e83c1d9819", 6143}, {"resource.000", 0, "4147edc5045e6d62998018b5614c58ec", 5496486}, {"resource.msg", 0, "7c71cfc36153cfe07b450423a51f7e68", 146282}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3170,7 +3235,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq5", "", { {"resource.000", 0, "5040026519f37199f3616fb1d4704dff", 6047170}, {"resource.map", 0, "5b09168baa2f6e2e22787429b2d72f54", 6492}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3182,7 +3247,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq6", "", { {"resource.map", 0, "6dddfa3a8f3a3a513ec9dfdfae955005", 10528}, {"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3193,7 +3258,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq6", "", { {"resource.map", 0, "e0615d6e4e10e37ae42e6a2a95aaf145", 10528}, {"resource.000", 0, "c4259ab7355aead07773397b1052827d", 41150806}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3204,7 +3269,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq6", "Demo", { {"resource.map", 0, "368f07b07433db3f819fa3fa0e5efee5", 2572}, {"resource.000", 0, "ab12724e078dea34b624e0d2a38dcd7c", 2272050}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3215,7 +3280,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"sq6", "", { {"resource.map", 0, "664d797415484f85c90b1b45aedc7686", 10534}, {"resource.000", 0, "ba87ba91e5bdabb4169dd0df75777722", 40933685}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3227,7 +3292,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"islandbrain", "", { {"resource.map", 0, "2388efef8430b041b0f3b00b9050e4a2", 3281}, {"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 2103560}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3238,7 +3303,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"islandbrain", "", { {"resource.map", 0, "3c07da06bdd1689f9d07af78fb94d0ec", 3101}, {"resource.000", 0, "ecc686e0034fb4d41de077ac7167b3cf", 1947866}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3249,7 +3314,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"islandbrain", "Demo", { {"resource.map", 0, "a8e5ca8ed1996974afa59f4c45e06195", 986}, {"resource.000", 0, "b3acd9b9dd7fe53c4ee133ac9a1acfab", 586560}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 @@ -3261,7 +3326,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"torin", "Demo", { {"resmap.000", 0, "9a3e172cde9963d0a969f26469318cec", 3403}, {"ressci.000", 0, "db3e290481c35c3224e9602e71e4a1f1", 5073868}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3272,7 +3337,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3284,7 +3349,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, // TODO: depend on one of the patches? - {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3295,7 +3360,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, - {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3306,7 +3371,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, - {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformWindows, 0, GUIO_NOSPEECH}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3317,7 +3382,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {{"torin", "", { {"resmap.000", 0, "bb3b0b22ff08df54fbe2d06263409be6", 9799}, {"ressci.000", 0, "693a259d346c9360f4a0c11fdaae430a", 55973887}, - {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformWindows, 0}, + {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformWindows, 0, GUIO_NONE}, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_32 @@ -3364,7 +3429,8 @@ static SciGameDescription s_fallbackDesc = { AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor Common::UNK_LANG, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, 0, SCI_VERSION_AUTODETECT, @@ -3388,7 +3454,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class SciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index bfd38f2c1b..a1e2c24955 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -64,13 +64,13 @@ int _reset_graphics_input(EngineState *s) { s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal1_amiga(file)); file.close(); } else { - resource = s->resmgr->findResource(kResourceTypePalette, 999, 1); + resource = s->resmgr->findResource(ResourceId(kResourceTypePalette, 999), 1); if (resource) { if (s->_version < SCI_VERSION_1_1) s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal1(999, resource->data, resource->size)); else s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal11(999, resource->data, resource->size)); - s->resmgr->unlockResource(resource, 999, kResourceTypePalette); + s->resmgr->unlockResource(resource); } else { debug(2, "Couldn't find the default palette!"); } @@ -89,14 +89,14 @@ int _reset_graphics_input(EngineState *s) { s->priority_first = 42; // Priority zone 0 ends here - if (s->_flags & GF_SCI0_OLDGFXFUNCS) + if (s->_kernel->usesOldGfxFunctions()) s->priority_last = 200; else s->priority_last = 190; font_nr = -1; do { - resource = s->resmgr->testResource(kResourceTypeFont, ++font_nr); + resource = s->resmgr->testResource(ResourceId(kResourceTypeFont, ++font_nr)); } while ((!resource) && (font_nr < sci_max_resource_nr[s->resmgr->_sciVersion])); if (!resource) { @@ -196,7 +196,7 @@ int create_class_table_sci11(EngineState *s) { char *seeker_ptr; int classnr; - Resource *vocab996 = s->resmgr->findResource(kResourceTypeVocab, 996, 1); + Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1); if (!vocab996) s->_classtable.resize(20); @@ -204,7 +204,7 @@ int create_class_table_sci11(EngineState *s) { s->_classtable.resize(vocab996->size >> 2); for (scriptnr = 0; scriptnr < 1000; scriptnr++) { - Resource *heap = s->resmgr->findResource(kResourceTypeHeap, scriptnr, 0); + Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0); if (heap) { int global_vars = READ_LE_UINT16(heap->data + 2); @@ -236,7 +236,7 @@ int create_class_table_sci11(EngineState *s) { } } - s->resmgr->unlockResource(vocab996, 996, kResourceTypeVocab); + s->resmgr->unlockResource(vocab996); vocab996 = NULL; return 0; } @@ -247,7 +247,7 @@ static int create_class_table_sci0(EngineState *s) { int classnr; int magic_offset; // For strange scripts in older SCI versions - Resource *vocab996 = s->resmgr->findResource(kResourceTypeVocab, 996, 1); + Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1); if (!vocab996) s->_classtable.resize(20); @@ -256,7 +256,7 @@ static int create_class_table_sci0(EngineState *s) { for (scriptnr = 0; scriptnr < 1000; scriptnr++) { int objtype = 0; - Resource *script = s->resmgr->findResource(kResourceTypeScript, scriptnr, 0); + Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0); if (script) { if (s->_flags & GF_SCI0_OLD) @@ -318,7 +318,7 @@ static int create_class_table_sci0(EngineState *s) { } } - s->resmgr->unlockResource(vocab996, 996, kResourceTypeVocab); + s->resmgr->unlockResource(vocab996); vocab996 = NULL; return 0; } @@ -499,7 +499,7 @@ int game_init(EngineState *s) { s->game_obj = game_obj; // Mark parse tree as unused - s->parser_nodes[0].type = PARSE_TREE_NODE_LEAF; + s->parser_nodes[0].type = kParseTreeLeafNode; s->parser_nodes[0].content.value = 0; s->_menubar = new Menubar(); // Create menu bar diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 24a7fbd1a9..1bfb66987e 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -106,7 +106,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm.push(es.objp); wm.push(es.sendp); if (es.type == EXEC_STACK_TYPE_VARSELECTOR) - wm.push(*(es.addr.varp)); + wm.push(*(es.getVarPointer(s))); } } #ifdef DEBUG_GC_VERBOSE diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index e6fa737aaf..9f9347ca18 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -45,19 +45,23 @@ struct reg_t_Hash { } }; -// The reg_t_hash_map is actually really a hashset +/* + * The reg_t_hash_map is actually really a hashset + */ typedef Common::HashMap<reg_t, bool, reg_t_Hash, reg_t_EqualTo> reg_t_hash_map; +/** + * Finds all used references and normalises them to their memory addresses + * @param s The state to gather all information from + * @return A hash map containing entries for all used references + */ reg_t_hash_map *find_all_used_references(EngineState *s); -/* Finds all used references and normalises them to their memory addresses -** Parameters: (EngineState *) s: The state to gather all information from -** Returns : (reg_t_hash_map *) A hash map containing entries for all used references -*/ +/** + * Runs garbage collection on the current system state + * @param s The state in which we should gc + */ void run_gc(EngineState *s); -/* Runs garbage collection on the current system state -** Parameters: (EngineState *) s: The state in which we should gc -*/ } // End of namespace Sci diff --git a/engines/sci/engine/grammar.cpp b/engines/sci/engine/grammar.cpp index 2c035fcb53..e75441432d 100644 --- a/engines/sci/engine/grammar.cpp +++ b/engines/sci/engine/grammar.cpp @@ -351,7 +351,7 @@ parse_rule_list_t *Vocabulary::buildGNF(bool verbose) { int ntrules_nr; parse_rule_list_t *ntlist = NULL; parse_rule_list_t *tlist, *new_tlist; - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); for (uint i = 1; i < _parserBranches.size(); i++) { // branch rule 0 is treated specially parse_rule_t *rule = _vbuild_rule(&_parserBranches[i]); @@ -414,7 +414,7 @@ parse_rule_list_t *Vocabulary::buildGNF(bool verbose) { static int _vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base) { // Opens parentheses nodes[base].content.branches[0] = (*pos) + 1; - nodes[++(*pos)].type = PARSE_TREE_NODE_BRANCH; + nodes[++(*pos)].type = kParseTreeBranchNode; nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[1] = 0; return *pos; @@ -423,7 +423,7 @@ static int _vbpt_pareno(parse_tree_node_t *nodes, int *pos, int base) { static int _vbpt_parenc(parse_tree_node_t *nodes, int *pos, int paren) { // Closes parentheses for appending nodes[paren].content.branches[1] = ++(*pos); - nodes[*pos].type = PARSE_TREE_NODE_BRANCH; + nodes[*pos].type = kParseTreeBranchNode; nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[1] = 0; return *pos; @@ -432,10 +432,10 @@ static int _vbpt_parenc(parse_tree_node_t *nodes, int *pos, int paren) { static int _vbpt_append(parse_tree_node_t *nodes, int *pos, int base, int value) { // writes one value to an existing base node and creates a successor node for writing nodes[base].content.branches[0] = ++(*pos); - nodes[*pos].type = PARSE_TREE_NODE_LEAF; + nodes[*pos].type = kParseTreeLeafNode; nodes[*pos].content.value = value; nodes[base].content.branches[1] = ++(*pos); - nodes[*pos].type = PARSE_TREE_NODE_BRANCH; + nodes[*pos].type = kParseTreeBranchNode; nodes[*pos].content.branches[0] = 0; nodes[*pos].content.branches[1] = 0; return *pos; @@ -443,7 +443,7 @@ static int _vbpt_append(parse_tree_node_t *nodes, int *pos, int base, int value) static int _vbpt_terminate(parse_tree_node_t *nodes, int *pos, int base, int value) { // Terminates, overwriting a nextwrite forknode - nodes[base].type = PARSE_TREE_NODE_LEAF; + nodes[base].type = kParseTreeLeafNode; nodes[base].content.value = value; return *pos; } @@ -477,7 +477,7 @@ static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, parse_r } int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose) { - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); // Get the start rules: parse_rule_list_t *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]); parse_rule_list_t *results = NULL; @@ -554,14 +554,14 @@ int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, { int temp, pos; - nodes[0].type = PARSE_TREE_NODE_BRANCH; + nodes[0].type = kParseTreeBranchNode; nodes[0].content.branches[0] = 1; nodes[0].content.branches[1] = 2; - nodes[1].type = PARSE_TREE_NODE_LEAF; + nodes[1].type = kParseTreeLeafNode; nodes[1].content.value = 0x141; - nodes[2].type = PARSE_TREE_NODE_BRANCH; + nodes[2].type = kParseTreeBranchNode; nodes[2].content.branches[0] = 0; nodes[2].content.branches[1] = 0; diff --git a/engines/sci/engine/intmap.h b/engines/sci/engine/intmap.h index 2cb4f69f1f..1c028975a9 100644 --- a/engines/sci/engine/intmap.h +++ b/engines/sci/engine/intmap.h @@ -83,7 +83,7 @@ public: /** * Checks whether a key is in the map, adds it if neccessary. - * @param value The key to check for/add + * @param key The key to check for/add * @param add Whether to add the key if it's not in there * @param was_added Set to non-zero if and only if the key is new, ignored if NULL. * @return The new (or old) index, or -1 if add was zero and @@ -91,6 +91,11 @@ public: */ int checkKey(int key, bool add, bool *wasAdded = 0); + /** + * Looks up a key in the map + * @parmam key The key to look for + * @return The value or -1 if not found + */ int lookupKey(int key) const; diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 3b998c7092..b03a073d8f 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -38,127 +38,9 @@ namespace Sci { // Default kernel name table #define SCI0_KNAMES_WELL_DEFINED 0x6e -#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72 -#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89 +#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 -static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = { - /*0x00*/ "Load", - /*0x01*/ "UnLoad", - /*0x02*/ "ScriptID", - /*0x03*/ "DisposeScript", - /*0x04*/ "Clone", - /*0x05*/ "DisposeClone", - /*0x06*/ "IsObject", - /*0x07*/ "RespondsTo", - /*0x08*/ "DrawPic", - /*0x09*/ "Show", - /*0x0a*/ "PicNotValid", - /*0x0b*/ "Animate", - /*0x0c*/ "SetNowSeen", - /*0x0d*/ "NumLoops", - /*0x0e*/ "NumCels", - /*0x0f*/ "CelWide", - /*0x10*/ "CelHigh", - /*0x11*/ "DrawCel", - /*0x12*/ "AddToPic", - /*0x13*/ "NewWindow", - /*0x14*/ "GetPort", - /*0x15*/ "SetPort", - /*0x16*/ "DisposeWindow", - /*0x17*/ "DrawControl", - /*0x18*/ "HiliteControl", - /*0x19*/ "EditControl", - /*0x1a*/ "TextSize", - /*0x1b*/ "Display", - /*0x1c*/ "GetEvent", - /*0x1d*/ "GlobalToLocal", - /*0x1e*/ "LocalToGlobal", - /*0x1f*/ "MapKeyToDir", - /*0x20*/ "DrawMenuBar", - /*0x21*/ "MenuSelect", - /*0x22*/ "AddMenu", - /*0x23*/ "DrawStatus", - /*0x24*/ "Parse", - /*0x25*/ "Said", - /*0x26*/ "SetSynonyms", - /*0x27*/ "HaveMouse", - /*0x28*/ "SetCursor", - /*0x29*/ "FOpen", - /*0x2a*/ "FPuts", - /*0x2b*/ "FGets", - /*0x2c*/ "FClose", - /*0x2d*/ "SaveGame", - /*0x2e*/ "RestoreGame", - /*0x2f*/ "RestartGame", - /*0x30*/ "GameIsRestarting", - /*0x31*/ "DoSound", - /*0x32*/ "NewList", - /*0x33*/ "DisposeList", - /*0x34*/ "NewNode", - /*0x35*/ "FirstNode", - /*0x36*/ "LastNode", - /*0x37*/ "EmptyList", - /*0x38*/ "NextNode", - /*0x39*/ "PrevNode", - /*0x3a*/ "NodeValue", - /*0x3b*/ "AddAfter", - /*0x3c*/ "AddToFront", - /*0x3d*/ "AddToEnd", - /*0x3e*/ "FindKey", - /*0x3f*/ "DeleteKey", - /*0x40*/ "Random", - /*0x41*/ "Abs", - /*0x42*/ "Sqrt", - /*0x43*/ "GetAngle", - /*0x44*/ "GetDistance", - /*0x45*/ "Wait", - /*0x46*/ "GetTime", - /*0x47*/ "StrEnd", - /*0x48*/ "StrCat", - /*0x49*/ "StrCmp", - /*0x4a*/ "StrLen", - /*0x4b*/ "StrCpy", - /*0x4c*/ "Format", - /*0x4d*/ "GetFarText", - /*0x4e*/ "ReadNumber", - /*0x4f*/ "BaseSetter", - /*0x50*/ "DirLoop", - /*0x51*/ "CanBeHere", - /*0x52*/ "OnControl", - /*0x53*/ "InitBresen", - /*0x54*/ "DoBresen", - /*0x55*/ "DoAvoider", - /*0x56*/ "SetJump", - /*0x57*/ "SetDebug", - /*0x58*/ "InspectObj", - /*0x59*/ "ShowSends", - /*0x5a*/ "ShowObjs", - /*0x5b*/ "ShowFree", - /*0x5c*/ "MemoryInfo", - /*0x5d*/ "StackUsage", - /*0x5e*/ "Profiler", - /*0x5f*/ "GetMenu", - /*0x60*/ "SetMenu", - /*0x61*/ "GetSaveFiles", - /*0x62*/ "GetCWD", - /*0x63*/ "CheckFreeSpace", - /*0x64*/ "ValidPath", - /*0x65*/ "CoordPri", - /*0x66*/ "StrAt", - /*0x67*/ "DeviceInfo", - /*0x68*/ "GetSaveDir", - /*0x69*/ "CheckSaveGame", - /*0x6a*/ "ShakeScreen", - /*0x6b*/ "FlushResources", - /*0x6c*/ "SinMult", - /*0x6d*/ "CosMult", - /*0x6e*/ "SinDiv", - /*0x6f*/ "CosDiv", - /*0x70*/ "Graph", - /*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING -}; - -static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = { +static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -487,6 +369,10 @@ Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { // Map a few special selectors for later use mapSelectors(); + + // SCI0 games using old graphics functions (before version 0.000.502) have the TimesSin + // kernel function, whereas newer games have the SinMult kernel function in its place + _oldGfxFunctions = !hasKernelFunction("SinMult"); } Kernel::~Kernel() { @@ -495,7 +381,7 @@ Kernel::~Kernel() { bool Kernel::loadSelectorNames(bool isOldSci0) { int count; - Resource *r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES, 0); + Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); if (!r) // No such resource? return false; @@ -520,7 +406,7 @@ bool Kernel::loadSelectorNames(bool isOldSci0) { bool Kernel::loadOpcodes() { int count, i = 0; - Resource* r = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0); + Resource* r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES), 0); _opcodes.clear(); @@ -846,35 +732,26 @@ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t)); } -// Alternative kernel func names retriever. Required for KQ1/SCI (at least). -static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) { - uint idx = 0; - - while (idx < r->size) { - Common::String tmp((const char *)r->data + idx); - names.push_back(tmp); - idx += tmp.size() + 1; - } - - // The mystery kernel function- one in each SCI0 package - names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING); +void setDefaultKernelNames(Common::StringList &names) { + names.resize(SCI_KNAMES_DEFAULT_ENTRIES_NR); + for (int i = 0; i < SCI_KNAMES_DEFAULT_ENTRIES_NR; i++) + names[i] = sci_default_knames[i]; } static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) { int count, i, index = 2, empty_to_add = 1; - Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0); + Resource *r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES), 0); if (!r) { // No kernel name table found? Fall back to default table - names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR); - for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci0_default_knames[i]; + setDefaultKernelNames(names); return; } count = READ_LE_UINT16(r->data); if (count > 1023) { - _vocab_get_knames0alt(r, names); + // Newer kernel name table, found in KQ1. We can use the default table here + setDefaultKernelNames(names); return; } @@ -898,20 +775,6 @@ static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names } } -static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) { - // vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used - // We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special" - // 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but - // if any SCI1 game has different kernel vocabulary names, it might not work. It seems - // that all SCI1 games use the same kernel vocabulary names though, so this seems to be - // a safe change. If there's any SCI1 game with different kernel vocabulary names, we can - // add special flags to it to our detector - - names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR); - for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci1_default_knames[i]; -} - #ifdef ENABLE_SCI32 static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) { /* @@ -925,7 +788,7 @@ static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &name */ //unsigned int size = 64, pos = 3; int len; - Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0); + Resource *r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES), 0); if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos) return; // FIXME: should return a default table for this engine const byte nCnt = *r->data; @@ -945,23 +808,18 @@ bool Kernel::loadKernelNames() { switch (_resmgr->_sciVersion) { case SCI_VERSION_0: case SCI_VERSION_01: - vocab_get_knames0(_resmgr, _kernelNames); - break; case SCI_VERSION_01_VGA: case SCI_VERSION_01_VGA_ODD: - // HACK: KQ5 needs the SCI1 default vocabulary names to work correctly. - // Having more vocabulary names (like in SCI1) doesn't seem to have any - // ill effects, other than resulting in unmapped functions towards the - // end, which are never used by the game interpreter anyway - // return vocab_get_knames0(resmgr, count); + vocab_get_knames0(_resmgr, _kernelNames); + break; case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: - vocab_get_knames1(_resmgr, _kernelNames); - break; case SCI_VERSION_1_1: - vocab_get_knames1(_resmgr, _kernelNames); - // KQ6CD calls unimplemented function 0x26 - _kernelNames[0x26] = "Dummy"; + setDefaultKernelNames(_kernelNames); + if (_resmgr->_sciVersion == SCI_VERSION_1_1) { + // KQ6CD calls unimplemented function 0x26 + _kernelNames[0x26] = "Dummy"; + } break; #ifdef ENABLE_SCI32 case SCI_VERSION_32: diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index ddc3f93cb7..e3ecddca26 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -69,19 +69,28 @@ public: uint getKernelNamesSize() const { return _kernelNames.size(); } const Common::String &getKernelName(uint number) const { return _kernelNames[number]; } - /* Determines the selector ID of a selector by its name - ** (const char *) selectorName: Name of the selector to look up - ** Returns : (int) The appropriate selector ID, or -1 on error - */ + /** + * Determines the selector ID of a selector by its name + * @param selectorName Name of the selector to look up + * @return The appropriate selector ID, or -1 on error + */ int findSelector(const char *selectorName) const; - /* Detects whether a particular kernel function is required in the game - ** (const char *) functionName: The name of the desired kernel function - ** Returns : (bool) true if the kernel function is listed in the kernel table, - ** false otherwise + /** + * Detects whether a particular kernel function is required in the game + * @param functionName The name of the desired kernel function + * @return True if the kernel function is listed in the kernel table, false otherwise */ bool hasKernelFunction(const char *functionName) const; + /* Applies to all versions before 0.000.502 + ** Old SCI versions used to interpret the third DrawPic() parameter inversely, + ** with the opposite default value (obviously). + ** Also, they used 15 priority zones from 42 to 200 instead of 14 priority + ** zones from 42 to 190. + */ + bool usesOldGfxFunctions() const { return _oldGfxFunctions; } + // Script dissection/dumping functions void dissectScript(int scriptNumber, Vocabulary *vocab); void dumpScriptObject(char *data, int seeker, int objsize); @@ -104,18 +113,18 @@ private: /** * Loads the kernel selector names. - * Returns true upon success, false otherwise. + * @return True upon success, false otherwise. */ bool loadSelectorNames(bool isOldSci0); - /* Maps special selectors - ** Returns : (void) - */ + /** + * Maps special selectors + */ void mapSelectors(); - /* Maps kernel functions - ** Returns : (void) - */ + /** + * Maps kernel functions + */ void mapFunctions(); /** @@ -125,10 +134,13 @@ private: bool loadOpcodes(); ResourceManager *_resmgr; + bool _oldGfxFunctions; // Kernel-related lists - // List of opcodes, loaded from vocab.998. This list is only used for debugging - // purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h) + /** + * List of opcodes, loaded from vocab.998. This list is only used for debugging + * purposes, as we hardcode the list of opcodes in the sci_opcodes enum (script.h) + */ Common::Array<opcode> _opcodes; Common::StringList _selectorNames; Common::StringList _kernelNames; @@ -178,72 +190,62 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc /******************** Text functionality ********************/ +/** + * Looks up text referenced by scripts + * SCI uses two values to reference to text: An address, and an index. The address + * determines whether the text should be read from a resource file, or from the heap, + * while the index either refers to the number of the string in the specified source, + * or to a relative position inside the text. + * + * @param s The current state + * @param address The address to look up + * @param index The relative index + * @return The referenced text, or NULL on error. + */ char *kernel_lookup_text(EngineState *s, reg_t address, int index); -/* Looks up text referenced by scripts -** Parameters: (EngineState *s): The current state -** (reg_t) address: The address to look up -** (int) index: The relative index -** Returns : (char *): The referenced text, or NULL on error. -** SCI uses two values to reference to text: An address, and an index. The address -** determines whether the text should be read from a resource file, or from the heap, -** while the index either refers to the number of the string in the specified source, -** or to a relative position inside the text. -*/ /******************** Debug functionality ********************/ - +/** + * Checks whether a heap address contains an object + * @param s The current state + * @parm obj The address to check + * @return True if it is an object, false otherwise + */ bool is_object(EngineState *s, reg_t obj); -/* Checks whether a heap address contains an object -** Parameters: (EngineState *) s: The current state -** (reg_t) obj: The address to check -** Returns : (bool) true if it is an object, false otherwise -*/ /******************** Kernel function parameter macros ********************/ /* Returns the parameter value or (alt) if not enough parameters were supplied */ - - -#define KP_ALT(x, alt) ((x < argc)? argv[x] : (alt)) -#define KP_UINT(x) ((uint16) x.offset) -#define KP_SINT(x) ((int16) x.offset) - - -#define SKPV(x) KP_SINT(argv[x]) -#define UKPV(x) KP_UINT(argv[x]) -#define SKPV_OR_ALT(x,a) KP_SINT(KP_ALT(x, make_reg(0, a))) -#define UKPV_OR_ALT(x,a) KP_UINT(KP_ALT(x, make_reg(0, a))) - +/** + * Dereferences a heap pointer + * @param s The state to operate on + * @param pointer The pointer to dereference + * @parm entries The number of values expected (for checking; use 0 for strings) + * @return A physical reference to the address pointed to, or NULL on error or + * if not enugh entries were available. + * reg_t dereferenciation also assures alignedness of data. + */ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries); byte *kernel_dereference_bulk_pointer(EngineState *s, reg_t pointer, int entries); #define kernel_dereference_char_pointer(state, pointer, entries) (char*)kernel_dereference_bulk_pointer(state, pointer, entries) -/* Dereferences a heap pointer -** Parameters: (EngineState *) s: The state to operate on -** (reg_t ) pointer: The pointer to dereference -** (int) entries: The number of values expected (for checking) -** (use 0 for strings) -** Returns : (reg_t/char *): A physical reference to the address pointed -** to, or NULL on error or if not enugh entries -** were available -** reg_t dereferenciation also assures alignedness of data. -*/ /******************** Priority macros/functions ********************/ - +/** + * Finds the position of the priority band specified + * Parameters: (EngineState *) s: State to search in + * (int) band: Band to look for + * Returns : (int) Offset at which the band starts + */ int _find_priority_band(EngineState *s, int band); -/* Finds the position of the priority band specified -** Parameters: (EngineState *) s: State to search in -** (int) band: Band to look for -** Returns : (int) Offset at which the band starts -*/ +/** + * Does the opposite of _find_priority_band + * @param s Engine state + * @param y Coordinate to check + * @return The priority band y belongs to + */ int _find_view_priority(EngineState *s, int y); -/* Does the opposite of _find_priority_band -** Parameters: (EngineState *) s: State -** (int) y: Coordinate to check -** Returns : (int) The priority band y belongs to -*/ #define SCI0_VIEW_PRIORITY_14_ZONES(y) (((y) < s->priority_first)? 0 : (((y) >= s->priority_last)? 14 : 1\ + ((((y) - s->priority_first) * 14) / (s->priority_last - s->priority_first)))) @@ -257,58 +259,62 @@ int _find_view_priority(EngineState *s, int y); #define SCI0_PRIORITY_BAND_FIRST(nr) ((((nr) == 0)? 0 : \ ((s->priority_first) + (((nr)-1) * (s->priority_last - s->priority_first)) / 15))) -#define VIEW_PRIORITY(y) _find_view_priority(s, y) -#define PRIORITY_BAND_FIRST(nr) _find_priority_band(s, nr) - - - /******************** Dynamic view list functions ********************/ - +/** + * Determines the base rectangle of the specified view object + * @param s The state to use + * @param object The object to set + * @return The absolute base rectangle + */ Common::Rect set_base(EngineState *s, reg_t object); -/* Determines the base rectangle of the specified view object -** Parameters: (EngineState *) s: The state to use -** (reg_t) object: The object to set -** Returns : (abs_rect) The absolute base rectangle -*/ +/** + * Determines the now-seen rectangle of a view object + * @param s The state to use + * @param object The object to check + * @param clip Flag to determine wheter priority band clipping + * should be performed + * @return The absolute rectangle describing the now-seen area. + */ extern Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip); -/* Determines the now-seen rectangle of a view object -** Parameters: (EngineState *) s: The state to use -** (reg_t) object: The object to check -** (byte) clip: Flag to determine wheter priority band -** clipping should be performed -** Returns : (abs_rect) The absolute rectangle describing the -** now-seen area. -*/ +/** + * Removes all views in anticipation of a new window or text + */ void _k_dyn_view_list_prepare_change(EngineState *s); -/* Removes all views in anticipation of a new window or text */ + +/** + * Redraws all views after a new window or text was added + */ void _k_dyn_view_list_accept_change(EngineState *s); -/* Redraws all views after a new window or text was added */ /******************** Misc functions ********************/ -void process_sound_events(EngineState *s); /* Get all sound events, apply their changes to the heap */ +/** + * Get all sound events, apply their changes to the heap + */ +void process_sound_events(EngineState *s); +/** + * Resolves an address into a list node + * @param s The state to operate on + * @param addr The address to resolve + * @return The list node referenced, or NULL on error + */ Node *lookup_node(EngineState *s, reg_t addr); -/* Resolves an address into a list node -** Parameters: (EngineState *) s: The state to operate on -** (reg_t) addr: The address to resolve -** Returns : (Node *) The list node referenced, or NULL on error -*/ - +/** + * Resolves a list pointer to a list + * @param s The state to operate on + * @param addr The address to resolve + * @return The list referenced, or NULL on error + */ List *lookup_list(EngineState *s, reg_t addr); -/* Resolves a list pointer to a list -** Parameters: (EngineState *) s: The state to operate on -** (reg_t) addr: The address to resolve -** Returns : (List *) The list referenced, or NULL on error -*/ /******************** Constants ********************/ diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 66395035c8..e40368a5c0 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -33,12 +33,10 @@ namespace Sci { -int g_stop_on_event = 0; - #define SCI_VARIABLE_GAME_SPEED 3 reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int mask = UKPV(0); + int mask = argv[0].toUint16(); reg_t obj = argv[1]; sci_event_t e; int oldx, oldy; @@ -90,10 +88,12 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { case SCI_EVT_KEYBOARD: if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { sciprintf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + debugState.seeking = kDebugSeekNothing; + debugState.runningStep = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { sciprintf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + debugState.seeking = kDebugSeekNothing; + debugState.runningStep = 0; } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event s->r_acc = make_reg(0, 1); @@ -110,7 +110,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { // track left buttton clicks, if requested if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) { - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", + ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y); } @@ -137,8 +137,29 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (g_stop_on_event)) { - g_stop_on_event = 0; + if ((s->r_acc.offset) && (debugState.stopOnEvent)) { + debugState.stopOnEvent = false; + + // A SCI event occured, and we have been asked to stop, so open the debug console + Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); + con->DebugPrintf("SCI event occured: "); + switch (e.type) { + case SCI_EVT_QUIT: + con->DebugPrintf("quit event\n"); + break; + case SCI_EVT_KEYBOARD: + con->DebugPrintf("keyboard event\n"); + break; + case SCI_EVT_MOUSE_RELEASE: + case SCI_EVT_MOUSE_PRESS: + con->DebugPrintf("mouse click event\n"); + break; + default: + con->DebugPrintf("unknown or no event (event type %d)\n", e.type); + } + + con->attach(); + con->onFrame(); } return s->r_acc; diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 87ddb46e50..ed18c7fcd6 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -197,7 +197,7 @@ void file_open(EngineState *s, const char *filename, int mode) { reg_t kFOpen(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *name = kernel_dereference_char_pointer(s, argv[0], 0); - int mode = UKPV(1); + int mode = argv[1].toUint16(); debug(3, "kFOpen(%s,0x%x)", name, mode); file_open(s, name, mode); @@ -227,8 +227,8 @@ void file_close(EngineState *s, int handle) { } reg_t kFClose(EngineState *s, int funct_nr, int argc, reg_t *argv) { - debug(3, "kFClose(%d)", UKPV(0)); - file_close(s, UKPV(0)); + debug(3, "kFClose(%d)", argv[0].toUint16()); + file_close(s, argv[0].toUint16()); return s->r_acc; } @@ -248,7 +248,7 @@ void fwrite_wrapper(EngineState *s, int handle, char *data, int length) { } reg_t kFPuts(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int handle = UKPV(0); + int handle = argv[0].toUint16(); char *data = kernel_dereference_char_pointer(s, argv[1], 0); fwrite_wrapper(s, handle, data, strlen(data)); @@ -267,6 +267,12 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { return; } f->_in->readLine_NEW(dest, maxsize); + // The returned string must not have an ending LF + int strSize = strlen(dest); + if (strSize > 0) { + if (dest[strSize - 1] == 0x0A) + dest[strSize - 1] = 0; + } debugC(2, kDebugLevelFile, "FGets'ed \"%s\"\n", dest); } @@ -301,8 +307,8 @@ static void fseek_wrapper(EngineState *s, int handle, int offset, int whence) { reg_t kFGets(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *dest = kernel_dereference_char_pointer(s, argv[0], 0); - int maxsize = UKPV(1); - int handle = UKPV(2); + int maxsize = argv[1].toUint16(); + int handle = argv[2].toUint16(); debug(3, "kFGets(%d,%d)", handle, maxsize); fgets_wrapper(s, dest, maxsize, handle); @@ -344,7 +350,7 @@ enum { }; reg_t kDeviceInfo(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int mode = UKPV(0); + int mode = argv[0].toUint16(); char *game_prefix, *input_s, *output_s; switch (mode) { @@ -394,7 +400,7 @@ reg_t kDeviceInfo(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_DEVICE_INFO_GET_SAVEFILE_NAME: { output_s = kernel_dereference_char_pointer(s, argv[1], 0); game_prefix = kernel_dereference_char_pointer(s, argv[2], 0); - int savegame_id = UKPV(3); + int savegame_id = argv[3].toUint16(); sprintf(output_s, "__throwaway"); debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix, savegame_id, output_s); delete_savegame(s, savegame_id); @@ -474,7 +480,7 @@ void listSavegames(Common::Array<SavegameDesc> &saves) { reg_t kCheckSaveGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *game_id = kernel_dereference_char_pointer(s, argv[0], 0); - int savedir_nr = UKPV(1); + int savedir_nr = argv[1].toUint16(); debug(3, "kCheckSaveGame(%s, %d)", game_id, savedir_nr); @@ -560,7 +566,7 @@ reg_t kGetSaveFiles(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kSaveGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *game_id = kernel_dereference_char_pointer(s, argv[0], 0); - int savedir_nr = UKPV(1); + int savedir_nr = argv[1].toUint16(); int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list char *game_description = kernel_dereference_char_pointer(s, argv[2], 0); char *version = argc > 3 ? strdup(kernel_dereference_char_pointer(s, argv[3], 0)) : NULL; @@ -633,7 +639,7 @@ reg_t kSaveGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *game_id = kernel_dereference_char_pointer(s, argv[0], 0); - int savedir_nr = UKPV(1); + int savedir_nr = argv[1].toUint16(); debug(3, "kRestoreGame(%s,%d)", game_id, savedir_nr); @@ -739,37 +745,37 @@ void DirSeeker::nextFile() { reg_t kFileIO(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int func_nr = UKPV(0); + int func_nr = argv[0].toUint16(); switch (func_nr) { case K_FILEIO_OPEN : { char *name = kernel_dereference_char_pointer(s, argv[1], 0); - int mode = UKPV(2); + int mode = argv[2].toUint16(); file_open(s, name, mode); debug(3, "K_FILEIO_OPEN(%s,0x%x)", name, mode); break; } case K_FILEIO_CLOSE : { - int handle = UKPV(1); + int handle = argv[1].toUint16(); debug(3, "K_FILEIO_CLOSE(%d)", handle); file_close(s, handle); break; } case K_FILEIO_READ_RAW : { - int handle = UKPV(1); + int handle = argv[1].toUint16(); char *dest = kernel_dereference_char_pointer(s, argv[2], 0); - int size = UKPV(3); + int size = argv[3].toUint16(); debug(3, "K_FILEIO_READ_RAW(%d,%d)", handle, size); fread_wrapper(s, dest, size, handle); break; } case K_FILEIO_WRITE_RAW : { - int handle = UKPV(1); + int handle = argv[1].toUint16(); char *buf = kernel_dereference_char_pointer(s, argv[2], 0); - int size = UKPV(3); + int size = argv[3].toUint16(); debug(3, "K_FILEIO_WRITE_RAW(%d,%d)", handle, size); fwrite_wrapper(s, handle, buf, size); @@ -788,16 +794,16 @@ reg_t kFileIO(EngineState *s, int funct_nr, int argc, reg_t *argv) { } case K_FILEIO_READ_STRING : { char *dest = kernel_dereference_char_pointer(s, argv[1], 0); - int size = UKPV(2); - int handle = UKPV(3); + int size = argv[2].toUint16(); + int handle = argv[3].toUint16(); debug(3, "K_FILEIO_READ_STRING(%d,%d)", handle, size); fgets_wrapper(s, dest, size, handle); return argv[1]; } case K_FILEIO_WRITE_STRING : { - int handle = UKPV(1); - int size = UKPV(3); + int handle = argv[1].toUint16(); + int size = argv[3].toUint16(); char *buf = kernel_dereference_char_pointer(s, argv[2], size); debug(3, "K_FILEIO_WRITE_STRING(%d,%d)", handle, size); @@ -810,9 +816,9 @@ reg_t kFileIO(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case K_FILEIO_SEEK : { - int handle = UKPV(1); - int offset = UKPV(2); - int whence = UKPV(3); + int handle = argv[1].toUint16(); + int offset = argv[2].toUint16(); + int whence = argv[3].toUint16(); debug(3, "K_FILEIO_SEEK(%d,%d,%d)", handle, offset, whence); fseek_wrapper(s, handle, offset, whence); @@ -821,7 +827,7 @@ reg_t kFileIO(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_FILEIO_FIND_FIRST : { char *mask = kernel_dereference_char_pointer(s, argv[1], 0); reg_t buf = argv[2]; - int attr = UKPV(3); // We won't use this, Win32 might, though... + int attr = argv[3].toUint16(); // We won't use this, Win32 might, though... debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask, attr); #ifndef WIN32 diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index e58fc79244..6e737597d6 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -25,6 +25,7 @@ #include "common/system.h" #include "common/events.h" +#include "graphics/cursorman.h" #include "sci/sci.h" #include "sci/debug.h" // for g_debug_sleeptime_factor @@ -163,7 +164,7 @@ int _find_view_priority(EngineState *s, int y) { return j; return 14; // Maximum } else { - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) + if (!s->_kernel->usesOldGfxFunctions()) return SCI0_VIEW_PRIORITY_14_ZONES(y); else return SCI0_VIEW_PRIORITY(y) == 15 ? 14 : SCI0_VIEW_PRIORITY(y); @@ -171,7 +172,7 @@ int _find_view_priority(EngineState *s, int y) { } int _find_priority_band(EngineState *s, int nr) { - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) { + if (!s->_kernel->usesOldGfxFunctions() && (nr < 0 || nr > 14)) { if (nr == 15) return 0xffff; else { @@ -180,7 +181,7 @@ int _find_priority_band(EngineState *s, int nr) { return 0; } - if ((s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) { + if (s->_kernel->usesOldGfxFunctions() && (nr < 0 || nr > 15)) { warning("Attempt to get priority band %d", nr); return 0; } @@ -190,7 +191,7 @@ int _find_priority_band(EngineState *s, int nr) { else { int retval; - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) + if (!s->_kernel->usesOldGfxFunctions()) retval = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr); else retval = SCI0_PRIORITY_BAND_FIRST(nr); @@ -304,16 +305,16 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : if (s->_version < SCI_VERSION_1_1) { - if (SKPV(0) <= 1) { + if (argv[0].toSint16() <= 1) { // Newer (SCI1.1) semantics: show/hide cursor - g_system->showMouse(SKPV(0) != 0); + CursorMan.showMouse(argv[0].toSint16() != 0); } else { // Pre-SCI1.1: set cursor according to the first parameter - GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, SKPV(0))); + GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16())); } } else { // SCI1.1: Show/hide cursor - g_system->showMouse(SKPV(0) != 0); + CursorMan.showMouse(argv[0].toSint16() != 0); } break; case 2 : @@ -329,37 +330,37 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { // this would open the menu on top. LSL5 is an exception, as the game can open // the menu when the player presses a button during the intro, but the cursor is // not placed on (x, 0) or (x, 1) - if (SKPV(1) <= 1) { + if (argv[1].toSint16() <= 1) { GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, - SKPV(1) == 0 ? GFXOP_NO_POINTER : SKPV(0))); + argv[1].toSint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16())); } else { // newer (SCI1.1) semantics: set pointer position GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, - Common::Point(UKPV(0), UKPV(1)))); + Common::Point(argv[0].toUint16(), argv[1].toUint16()))); } } else { // SCI1.1 and newer: set pointer position GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, - Common::Point(UKPV(0), UKPV(1)))); + Common::Point(argv[0].toUint16(), argv[1].toUint16()))); } break; case 4 : GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, - UKPV(0) == 0 ? GFXOP_NO_POINTER : SKPV(0))); + argv[0].toUint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16())); // Set pointer position, if requested if (argc > 2) { - Common::Point newpos = Common::Point(SKPV(2) + s->port->_bounds.x, SKPV(3) + s->port->_bounds.y); - GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newpos)); + Common::Point newPos = Common::Point(argv[2].toSint16() + s->port->_bounds.x, argv[3].toSint16() + s->port->_bounds.y); + GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newPos)); } break; case 3 : case 5 : case 9 : if (argc > 3) { - Common::Point hotspot = Common::Point(SKPV(3), SKPV(4)); - GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, UKPV(0), UKPV(1), UKPV(2), &hotspot)); + Common::Point hotspot = Common::Point(argv[3].toSint16(), argv[4].toSint16()); + GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), &hotspot)); } else { - GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, UKPV(0), UKPV(1), UKPV(2), NULL)); + GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), NULL)); } break; default : @@ -370,26 +371,26 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kMoveCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { - Common::Point newpos; + Common::Point newPos; - newpos = s->gfx_state->pointer_pos; + newPos = s->gfx_state->pointer_pos; if (argc == 1) { // Case ignored on IBM PC } else { - newpos.x = SKPV(0) + s->port->zone.x; - newpos.y = SKPV(1) + s->port->zone.y; + newPos.x = argv[0].toSint16() + s->port->zone.x; + newPos.y = argv[1].toSint16() + s->port->zone.y; - if (newpos.x > s->port->zone.x + s->port->zone.width) - newpos.x = s->port->zone.x + s->port->zone.width; - if (newpos.y > s->port->zone.y + s->port->zone.height) - newpos.y = s->port->zone.y + s->port->zone.height; + if (newPos.x > s->port->zone.x + s->port->zone.width) + newPos.x = s->port->zone.x + s->port->zone.width; + if (newPos.y > s->port->zone.y + s->port->zone.height) + newPos.y = s->port->zone.y + s->port->zone.height; - if (newpos.x < 0) newpos.x = 0; - if (newpos.y < 0) newpos.y = 0; + if (newPos.x < 0) newPos.x = 0; + if (newPos.y < 0) newPos.y = 0; } - GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newpos)); + GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newPos)); return s->r_acc; } @@ -397,7 +398,7 @@ reg_t kMoveCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kShow(EngineState *s, int funct_nr, int argc, reg_t *argv) { int old_map = s->pic_visible_map; - s->pic_visible_map = (gfx_map_mask_t) UKPV_OR_ALT(0, 1); + s->pic_visible_map = (argc > 0) ? (gfx_map_mask_t) argv[0].toUint16() : GFX_MASK_VISUAL; switch (s->pic_visible_map) { @@ -427,7 +428,7 @@ reg_t kShow(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kPicNotValid(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = make_reg(0, s->pic_not_valid); if (argc) - s->pic_not_valid = (byte)UKPV(0); + s->pic_not_valid = (byte)argv[0].toUint16(); return s->r_acc; } @@ -488,12 +489,12 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { GfxPort *port = s->port; int redraw_port = 0; - area = gfx_rect(SKPV(2), SKPV(1) , SKPV(4), SKPV(3)); + area = gfx_rect(argv[2].toSint16(), argv[1].toSint16() , argv[4].toSint16(), argv[3].toSint16()); area.width = area.width - area.x; // Since the actual coordinates are absolute area.height = area.height - area.y; - switch (SKPV(0)) { + switch (argv[0].toSint16()) { case K_GRAPH_GET_COLORS_NR: @@ -501,11 +502,12 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; case K_GRAPH_DRAW_LINE: { - - gfx_color_t gfxcolor = graph_map_color(s, SKPV(5), SKPV_OR_ALT(6, -1), SKPV_OR_ALT(7, -1)); + int16 priority = (argc > 6) ? argv[6].toSint16() : -1; + int16 control = (argc > 7) ? argv[7].toSint16() : -1; + gfx_color_t gfxcolor = graph_map_color(s, argv[5].toSint16(), priority, control); debugC(2, kDebugLevelGraphics, "draw_line((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n", - SKPV(2), SKPV(1), SKPV(4), SKPV(3), SKPV(5), SKPV_OR_ALT(6, -1), SKPV_OR_ALT(7, -1), gfxcolor.mask); + argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[5].toSint16(), priority, control, gfxcolor.mask); redraw_port = 1; @@ -513,7 +515,7 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { // have negative width/height). The actual dirty rectangle is constructed in gfxdr_add_dirty(). // FIXME/TODO: We need to change the semantics of this call, so that no fake rectangles are used. As it is, it's // not possible change rect_t to Common::Rect, as we assume that Common::Rect forms a *valid* rectangle. - ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_line(Common::Point(SKPV(2), SKPV(1)), Common::Point(SKPV(4), SKPV(3)), + ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_line(Common::Point(argv[2].toSint16(), argv[1].toSint16()), Common::Point(argv[4].toSint16(), argv[3].toSint16()), gfxcolor, GFX_LINE_MODE_CORRECT, GFX_LINE_STYLE_NORMAL)); } @@ -551,13 +553,14 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; case K_GRAPH_FILL_BOX_ANY: { + int16 priority = (argc > 7) ? argv[7].toSint16() : -1; + int16 control = (argc > 8) ? argv[8].toSint16() : -1; + gfx_color_t color = graph_map_color(s, argv[6].toSint16(), priority, control); - gfx_color_t color = graph_map_color(s, SKPV(6), SKPV_OR_ALT(7, -1), SKPV_OR_ALT(8, -1)); - - color.mask = (byte)UKPV(5); + color.mask = (byte)argv[5].toUint16(); debugC(2, kDebugLevelGraphics, "fill_box_any((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n", - SKPV(2), SKPV(1), SKPV(4), SKPV(3), SKPV(6), SKPV_OR_ALT(7, -1), SKPV_OR_ALT(8, -1), UKPV(5)); + argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[6].toSint16(), priority, control, argv[5].toUint16()); // FIXME/TODO: this is not right, as some of the dialogs are drawn *behind* some widgets. But at least it works for now //ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT)); // old code @@ -568,7 +571,7 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_GRAPH_UPDATE_BOX: { - debugC(2, kDebugLevelGraphics, "update_box(%d, %d, %d, %d)\n", SKPV(1), SKPV(2), SKPV(3), SKPV(4)); + debugC(2, kDebugLevelGraphics, "update_box(%d, %d, %d, %d)\n", argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16(), argv[4].toSint16()); area.x += s->port->zone.x; area.y += s->port->zone.y; @@ -581,7 +584,7 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_GRAPH_REDRAW_BOX: { - debugC(2, kDebugLevelGraphics, "redraw_box(%d, %d, %d, %d)\n", SKPV(1), SKPV(2), SKPV(3), SKPV(4)); + debugC(2, kDebugLevelGraphics, "redraw_box(%d, %d, %d, %d)\n", argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16(), argv[4].toSint16()); area.x += s->port->zone.x; area.y += s->port->zone.y; @@ -597,14 +600,14 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_GRAPH_ADJUST_PRIORITY: - debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)\n", SKPV(1), SKPV(2)); - s->priority_first = SKPV(1) - 10; - s->priority_last = SKPV(2) - 10; + debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)\n", argv[1].toSint16(), argv[2].toSint16()); + s->priority_first = argv[1].toSint16() - 10; + s->priority_last = argv[2].toSint16() - 10; break; default: - warning("Unhandled Graph() operation %04x", SKPV(0)); + warning("Unhandled Graph() operation %04x", argv[0].toSint16()); } @@ -619,9 +622,13 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) { int width, height; char *text = argv[1].segment ? (char *) kernel_dereference_bulk_pointer(s, argv[1], 0) : NULL; + const char *sep = NULL; reg_t *dest = kernel_dereference_reg_pointer(s, argv[0], 4); - int maxwidth = KP_UINT(KP_ALT(3, NULL_REG)); - int font_nr = KP_UINT(argv[2]); + int maxwidth = (argc > 3) ? argv[3].toUint16() : 0; + int font_nr = argv[2].toUint16(); + + if ((argc > 4) && (argv[4].segment)) + sep = (const char *)kernel_dereference_bulk_pointer(s, argv[4], 0); if (maxwidth < 0) maxwidth = 0; @@ -634,7 +641,7 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } - GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, text, maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE, + GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text, sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE, &width, &height, 0, NULL, NULL, NULL)); debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text, width, height); @@ -647,7 +654,7 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) { uint32 time; - int sleep_time = UKPV(0); + int sleep_time = argv[0].toUint16(); time = g_system->getMillis(); s->r_acc = make_reg(0, ((long)time - (long)s->last_wait_time) * 60 / 1000); @@ -663,15 +670,15 @@ reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kCoordPri(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int y = SKPV(0); + int y = argv[0].toSint16(); - return make_reg(0, VIEW_PRIORITY(y)); + return make_reg(0, _find_view_priority(s, y)); } reg_t kPriCoord(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int priority = SKPV(0); + int priority = argv[0].toSint16(); - return make_reg(0, PRIORITY_BAND_FIRST(priority)); + return make_reg(0, _find_priority_band(s, priority)); } void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc, reg_t *argv) { @@ -720,7 +727,7 @@ void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc, } reg_t kDirLoop(EngineState *s, int funct_nr, int argc, reg_t *argv) { - _k_dirloop(argv[0], UKPV(1), s, funct_nr, argc, argv); + _k_dirloop(argv[0], argv[1].toUint16(), s, funct_nr, argc, argv); return s->r_acc; } @@ -771,7 +778,7 @@ static int collides_with(EngineState *s, Common::Rect area, reg_t other_obj, int reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argv[0]; - reg_t cliplist_ref = KP_ALT(1, NULL_REG); + reg_t cliplist_ref = (argc > 1) ? argv[1] : NULL_REG; List *cliplist = NULL; GfxPort *port = s->picture_port; uint16 signal; @@ -863,18 +870,18 @@ reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t *argv) { } // CanBeHere reg_t kIsItSkip(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int view = SKPV(0); - int loop = SKPV(1); - int cel = SKPV(2); - int y = UKPV(3); - int x = UKPV(4); + int view = argv[0].toSint16(); + int loop = argv[1].toSint16(); + int cel = argv[2].toSint16(); + int y = argv[3].toUint16(); + int x = argv[4].toUint16(); gfxr_view_t *res = NULL; gfx_pixmap_t *pxm = NULL; res = s->gfx_state->gfxResMan->getView(view, &loop, &cel, 0); if (!res) { - GFXWARN("Attempt to get cel parameters for invalid view %d\n", view); + warning("[GFX] Attempt to get cel parameters for invalid view %d", view); return make_reg(0, -1); } @@ -888,9 +895,9 @@ reg_t kIsItSkip(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kCelHigh(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int view = SKPV(0); - int loop = SKPV(1); - int cel = SKPV(2); + int view = argv[0].toSint16(); + int loop = argv[1].toSint16(); + int cel = argv[2].toSint16(); int height, width; Common::Point offset; @@ -906,9 +913,9 @@ reg_t kCelHigh(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kCelWide(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int view = SKPV(0); - int loop = SKPV(1); - int cel = SKPV(2); + int view = argv[0].toSint16(); + int loop = argv[1].toSint16(); + int cel = argv[2].toSint16(); int height, width; Common::Point offset; @@ -967,15 +974,15 @@ reg_t kOnControl(EngineState *s, int funct_nr, int argc, reg_t *argv) { map = GFX_MASK_CONTROL; else { arg = 1; - map = (gfx_map_mask_t) SKPV(0); + map = (gfx_map_mask_t) argv[0].toSint16(); } - ystart = SKPV(arg + 1); - xstart = SKPV(arg); + ystart = argv[arg + 1].toSint16(); + xstart = argv[arg].toSint16(); if (argc > 3) { - ylen = SKPV(arg + 3) - ystart; - xlen = SKPV(arg + 2) - xstart; + ylen = argv[arg + 3].toSint16() - ystart; + xlen = argv[arg + 2].toSint16() - xstart; } return make_reg(0, gfxop_scan_bitmask(s->gfx_state, gfx_rect(xstart, ystart + 10, xlen, ylen), map)); @@ -987,23 +994,18 @@ void _k_view_list_free_backgrounds(EngineState *s, ViewObject *list, int list_nr reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { drawn_pic_t dp; - int add_to_pic = 1; + bool add_to_pic = (argc > 2) ? !argv[2].toSint16() : false; gfx_color_t transparent = s->wm_port->_bgcolor; int picFlags = DRAWPIC01_FLAG_FILL_NORMALLY; - dp.nr = SKPV(0); - dp.palette = SKPV_OR_ALT(3, 0); + if (s->_kernel->usesOldGfxFunctions()) + add_to_pic = (argc > 2) ? argv[2].toSint16() : false; - if ((argc > 1) && (UKPV(1) & K_DRAWPIC_FLAG_MIRRORED)) - picFlags |= DRAWPIC1_FLAG_MIRRORED; + dp.nr = argv[0].toSint16(); + dp.palette = (argc > 3) ? argv[3].toSint16() : 0; - if (s->_flags & GF_SCI0_OLDGFXFUNCS) { - if (!SKPV_OR_ALT(2, 0)) - add_to_pic = 0; - } else { - if (SKPV_OR_ALT(2, 1)) - add_to_pic = 0; - } + if ((argc > 1) && (argv[1].toUint16() & K_DRAWPIC_FLAG_MIRRORED)) + picFlags |= DRAWPIC1_FLAG_MIRRORED; gfxop_disable_dirty_frames(s->gfx_state); @@ -1013,7 +1015,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->old_screen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190)); - debugC(2, kDebugLevelGraphics, "Drawing pic.%03d\n", SKPV(0)); + debugC(2, kDebugLevelGraphics, "Drawing pic.%03d\n", argv[0].toSint16()); if (add_to_pic) { s->_pics.push_back(dp); @@ -1043,14 +1045,14 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->pic_priority_table = gfxop_get_pic_metainfo(s->gfx_state); if (argc > 1) - s->pic_animate = SKPV(1) & 0xff; // The animation used during kAnimate() later on + s->pic_animate = argv[1].toSint16() & 0xff; // The animation used during kAnimate() later on s->dyn_views = NULL; s->drop_views = NULL; s->priority_first = 42; - if (s->_flags & GF_SCI0_OLDGFXFUNCS) + if (s->_kernel->usesOldGfxFunctions()) s->priority_last = 200; else s->priority_last = 190; @@ -1157,9 +1159,9 @@ static Common::Rect nsrect_clip(EngineState *s, int y, Common::Rect retval, int int pri_top; if (priority == -1) - priority = VIEW_PRIORITY(y); + priority = _find_view_priority(s, y); - pri_top = PRIORITY_BAND_FIRST(priority) + 1; + pri_top = _find_priority_band(s, priority) + 1; // +1: Don't know why, but this seems to be happening if (retval.top < pri_top) @@ -1251,7 +1253,7 @@ reg_t kSetNowSeen(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kPalette(EngineState *s, int funct_nr, int argc, reg_t *argv) { - switch (UKPV(0)) { + switch (argv[0].toUint16()) { case 1: debug(5, "STUB: kPalette() effect 1, direct palette set"); break; @@ -1264,11 +1266,11 @@ reg_t kPalette(EngineState *s, int funct_nr, int argc, reg_t *argv) { case 4: { // Set palette intensity #if 0 // Colors 0 (black) and 255 (white) cannot be changed - int16 from = CLIP<int16>(1, 255, UKPV(2)); - int16 to = CLIP<int16>(1, 255, UKPV(3)); - int16 intensity = UKPV(4); + int16 from = CLIP<int16>(1, 255, argv[2].toUint16()); + int16 to = CLIP<int16>(1, 255, argv[3].toUint16()); + int16 intensity = argv[4].toUint16(); - if (argc < 5 || UKPV(5) == 0) { + if (argc < 5 || argv[5].toUint16() == 0) { s->gfx_state->gfxResMan->setPaletteIntensity(from, to, intensity); } else { warning("kPalette: argv[5] != 0"); @@ -1280,9 +1282,9 @@ reg_t kPalette(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case 5: { // Find closest color - int r = UKPV(1); - int g = UKPV(2); - int b = UKPV(3); + int r = argv[1].toUint16(); + int g = argv[2].toUint16(); + int b = argv[3].toUint16(); int i, delta, bestindex = -1, bestdelta = 200000; @@ -1312,7 +1314,7 @@ reg_t kPalette(EngineState *s, int funct_nr, int argc, reg_t *argv) { debug(5, "STUB: kPalette() effect 8, set stored palette"); break; default: - warning("kPalette(): Unimplemented subfunction: %d", UKPV(0)); + warning("kPalette(): Unimplemented subfunction: %d", argv[0].toUint16()); } return s->r_acc; @@ -1573,7 +1575,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { int font_nr = GET_SEL32V(obj, font); reg_t text_pos = GET_SEL32(obj, text); - char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL); + const char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL); int view = GET_SEL32V(obj, view); int cel = sign_extend_byte(GET_SEL32V(obj, cel)); int loop = sign_extend_byte(GET_SEL32V(obj, loop)); @@ -1587,7 +1589,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { switch (type) { case K_CONTROL_BUTTON: debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y); - ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, text, font_nr, + ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text, NULL).c_str(), font_nr, (int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled))); break; @@ -1596,7 +1598,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode); - ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, text, font_nr, mode, + ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text).c_str(), font_nr, mode, (int8)(!!(state & kControlStateDitherFramed)), (int8)inverse)); break; @@ -1623,8 +1625,8 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { case K_CONTROL_CONTROL: case K_CONTROL_CONTROL_ALIAS: { - char **entries_list = NULL; - char *seeker; + const char **entries_list = NULL; + const char *seeker; int entries_nr; int lsTop = GET_SEL32V(obj, lsTop) - text_pos.offset; int list_top = 0; @@ -1644,7 +1646,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) { if (entries_nr) { // determine list_top, selection, and the entries_list seeker = text; - entries_list = (char**)malloc(sizeof(char *) * entries_nr); + entries_list = (const char**)malloc(sizeof(char *) * entries_nr); for (i = 0; i < entries_nr; i++) { entries_list[i] = seeker; seeker += entry_size ; @@ -1698,7 +1700,8 @@ static void draw_obj_to_control_map(EngineState *s, GfxDynView *view) { if (!is_object(s, obj)) warning("View %d does not contain valid object reference %04x:%04x", view->_ID, PRINT_REG(obj)); - if (!(view->signalp && (((reg_t *)view->signalp)->offset & _K_VIEW_SIG_FLAG_IGNORE_ACTOR))) { + reg_t* sp = view->signalp.getPointer(s); + if (!(sp && (sp->offset & _K_VIEW_SIG_FLAG_IGNORE_ACTOR))) { Common::Rect abs_zone = get_nsrect(s, make_reg(view->_ID, view->_subID), 1); draw_rect_to_control_map(s, abs_zone); } @@ -1749,8 +1752,9 @@ static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { fprintf(stderr, "obj %04x:%04x has pflags %x\n", PRINT_REG(obj), (widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE))); #endif - if (widget->signalp) { - *((reg_t *)(widget->signalp)) = make_reg(0, widget->signal & 0xffff); /* Write back signal */ + reg_t* sp = widget->signalp.getPointer(s); + if (sp) { + *sp = make_reg(0, widget->signal & 0xffff); /* Write back signal */ } widget = (GfxDynView *)widget->_next; @@ -1765,7 +1769,7 @@ void _k_view_list_mark_free(EngineState *s, reg_t off) { while (w) { if (w->_ID == off.segment && w->_subID == off.offset) { - w->under_bitsp = NULL; + w->under_bitsp.obj = NULL_REG; } w = (GfxDynView *)w->_next; @@ -1792,7 +1796,7 @@ int _k_view_list_dispose_loop(EngineState *s, List *list, GfxDynView *widget, in return -1; if (GFXW_IS_DYN_VIEW(widget) && (widget->_ID != GFXW_NO_ID)) { - signal = ((reg_t *)widget->signalp)->offset; + signal = widget->signalp.getPointer(s)->offset; if (signal & _K_VIEW_SIG_FLAG_DISPOSE_ME) { reg_t obj = make_reg(widget->_ID, widget->_subID); reg_t under_bits = NULL_REG; @@ -1800,20 +1804,21 @@ int _k_view_list_dispose_loop(EngineState *s, List *list, GfxDynView *widget, in if (!is_object(s, obj)) { error("Non-object %04x:%04x present in view list during delete time", PRINT_REG(obj)); obj = NULL_REG; - } else - if (widget->under_bitsp) { // Is there a bg picture left to clean? - reg_t mem_handle = *((reg_t*)(widget->under_bitsp)); + } else { + reg_t *ubp = widget->under_bitsp.getPointer(s); + if (ubp) { // Is there a bg picture left to clean? + reg_t mem_handle = *ubp; if (mem_handle.segment) { if (!kfree(s, mem_handle)) { - *((reg_t*)(widget->under_bitsp)) = make_reg(0, widget->under_bits = 0); + *ubp = make_reg(0, widget->under_bits = 0); } else { warning("Treating viewobj %04x:%04x as no longer present", PRINT_REG(obj)); obj = NULL_REG; } } } - + } if (is_object(s, obj)) { if (invoke_selector(INV_SEL(obj, delete_, kContinueOnInvalidSelector), 0)) warning("Object at %04x:%04x requested deletion, but does not have a delete funcselector", PRINT_REG(obj)); @@ -1822,11 +1827,12 @@ int _k_view_list_dispose_loop(EngineState *s, List *list, GfxDynView *widget, in return dropped; } - if (widget->under_bitsp) - under_bits = *((reg_t*)(widget->under_bitsp)); + reg_t *ubp = widget->under_bitsp.getPointer(s); + if (ubp) + under_bits = *ubp; if (under_bits.segment) { - *((reg_t*)(widget->under_bitsp)) = make_reg(0, 0); + *ubp = make_reg(0, 0); graph_restore_box(s, under_bits); } @@ -1871,7 +1877,6 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i int palette; int signal; reg_t under_bits; - reg_t *under_bitsp, *signalp; Common::Point pos; int z; GfxDynView *widget; @@ -1913,19 +1918,21 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i PUT_SEL32V(obj, cel, cel); } + ObjVarRef under_bitsp; if (lookup_selector(s, obj, s->_kernel->_selectorMap.underBits, &(under_bitsp), NULL) != kSelectorVariable) { - under_bitsp = NULL; + under_bitsp.obj = NULL_REG; under_bits = NULL_REG; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no underBits\n", PRINT_REG(obj)); } else - under_bits = *((reg_t *)under_bitsp); + under_bits = *under_bitsp.getPointer(s); + ObjVarRef signalp; if (lookup_selector(s, obj, s->_kernel->_selectorMap.signal, &(signalp), NULL) != kSelectorVariable) { - signalp = NULL; + signalp.obj = NULL_REG; signal = 0; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no signal selector\n", PRINT_REG(obj)); } else { - signal = signalp->offset; + signal = signalp.getPointer(s)->offset; debugC(2, kDebugLevelGraphics, " with signal = %04x\n", signal); } @@ -2000,8 +2007,9 @@ static void _k_make_view_list(EngineState *s, GfxList **widget_list, List *list, widget = (GfxDynView *)(*widget_list)->_contents; while (widget) { // Read back widget values - if (widget->signalp) - widget->signal = ((reg_t *)(widget->signalp))->offset; + reg_t *sp = widget->signalp.getPointer(s); + if (sp) + widget->signal = sp->offset; widget = (GfxDynView *)widget->_next; } @@ -2227,7 +2235,7 @@ void _k_draw_view_list(EngineState *s, GfxList *list, int flags) { widget = gfxw_picviewize_dynview(widget); if (GFXW_IS_DYN_VIEW(widget) && widget->_ID) { - uint16 signal = (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) ? ((reg_t *)(widget->signalp))->offset : 0; + uint16 signal = (flags & _K_DRAW_VIEW_LIST_USE_SIGNAL) ? widget->signalp.getPointer(s)->offset : 0; if (signal & _K_VIEW_SIG_FLAG_HIDDEN) gfxw_hide_widget(widget); @@ -2247,7 +2255,7 @@ void _k_draw_view_list(EngineState *s, GfxList *list, int flags) { else gfxw_show_widget(widget); - *((reg_t *)(widget->signalp)) = make_reg(0, signal); // Write the changes back + *widget->signalp.getPointer(s) = make_reg(0, signal); // Write the changes back }; } // ...if we're drawing disposeables and this one is disposeable, or if we're drawing non- @@ -2269,13 +2277,13 @@ reg_t kAddToPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { int view, cel, loop, x, y, priority, control; GfxWidget *widget; - view = KP_UINT(argv[0]); - loop = KP_UINT(argv[1]); - cel = KP_UINT(argv[2]); - x = KP_SINT(argv[3]); - y = KP_SINT(argv[4]) + 1 /* magic + 1 */; - priority = KP_SINT(argv[5]); - control = KP_SINT(argv[6]); + view = argv[0].toUint16(); + loop = argv[1].toUint16(); + cel = argv[2].toUint16(); + x = argv[3].toSint16(); + y = argv[4].toSint16() + 1 /* magic + 1 */; + priority = argv[5].toSint16(); + control = argv[6].toSint16(); widget = gfxw_new_dyn_view(s->gfx_state, Common::Point(x, y), 0, view, loop, cel, 0, priority, -1 /* No priority */ , ALIGN_CENTER, ALIGN_BOTTOM, 0); @@ -2331,7 +2339,7 @@ reg_t kSetPort(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : { - unsigned int port_nr = SKPV(0); + unsigned int port_nr = argv[0].toSint16(); GfxPort *new_port; /* We depart from official semantics here, sorry! @@ -2354,10 +2362,10 @@ reg_t kSetPort(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } case 6 : { - port_origin_y = SKPV(0); - port_origin_x = SKPV(1); + port_origin_y = argv[0].toSint16(); + port_origin_x = argv[1].toSint16(); - if (SKPV(0) == -10) { + if (argv[0].toSint16() == -10) { s->port->draw(gfxw_point_zero); // Update the port we're leaving s->port = s->iconbar_port; activated_icon_bar = true; @@ -2365,20 +2373,20 @@ reg_t kSetPort(EngineState *s, int funct_nr, int argc, reg_t *argv) { } // Notify the graphics resource manager that the pic port bounds changed - s->gfx_state->gfxResMan->changePortBounds(UKPV(5), UKPV(4), UKPV(3) + UKPV(5), UKPV(2) + UKPV(4)); + s->gfx_state->gfxResMan->changePortBounds(argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16() + argv[5].toUint16(), argv[2].toUint16() + argv[4].toUint16()); // LSL6 calls kSetPort to extend the screen to draw the GUI. If we free all resources // here, the background picture is freed too, and this makes everything a big mess. // FIXME/TODO: This code really needs to be rewritten to conform to the original behavior if (s->_gameName != "LSL6") { - s->gfx_state->pic_port_bounds = gfx_rect(UKPV(5), UKPV(4), UKPV(3), UKPV(2)); + s->gfx_state->pic_port_bounds = gfx_rect(argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16(), argv[2].toUint16()); // FIXME: Should really only invalidate all loaded pic resources here; // this is overkill s->gfx_state->gfxResMan->freeAllResources(); } else { // WORKAROUND for LSL6 - printf("SetPort case 6 called in LSL6. Origin: %d, %d - Clip rect: %d, %d, %d, %d\n", SKPV(1), SKPV(0), UKPV(5), UKPV(4), UKPV(3), UKPV(2)); + printf("SetPort case 6 called in LSL6. Origin: %d, %d - Clip rect: %d, %d, %d, %d\n", argv[1].toSint16(), argv[0].toSint16(), argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16(), argv[2].toUint16()); } break; @@ -2392,12 +2400,12 @@ reg_t kSetPort(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kDrawCel(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int view = SKPV(0); - int loop = SKPV(1); - int cel = SKPV(2); - int x = SKPV(3); - int y = SKPV(4); - int priority = SKPV_OR_ALT(5, -1); + int view = argv[0].toSint16(); + int loop = argv[1].toSint16(); + int cel = argv[2].toSint16(); + int x = argv[3].toSint16(); + int y = argv[4].toSint16(); + int priority = (argc > 5) ? argv[5].toSint16() : -1; GfxView *new_view; /* @@ -2424,7 +2432,7 @@ reg_t kDrawCel(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kDisposeWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { - unsigned int goner_nr = SKPV(0); + unsigned int goner_nr = argv[0].toSint16(); GfxPort *goner; GfxPort *pred; @@ -2472,26 +2480,28 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { int priority; int argextra = argc == 13 ? 4 : 0; // Triggers in PQ3 and SCI1.1 games - y = SKPV(0); - x = SKPV(1); - yl = SKPV(2) - y; - xl = SKPV(3) - x; + y = argv[0].toSint16(); + x = argv[1].toSint16(); + yl = argv[2].toSint16() - y; + xl = argv[3].toSint16() - x; y += s->wm_port->_bounds.y; if (x + xl > 319) x -= ((x + xl) - 319); - flags = SKPV(5 + argextra); + flags = argv[5 + argextra].toSint16(); - priority = SKPV_OR_ALT(6 + argextra, -1); + priority = (argc > 6 + argextra) ? argv[6 + argextra].toSint16() : -1; bgcolor.mask = 0; - if (SKPV_OR_ALT(8 + argextra, 255) >= 0) { + int16 bgColor = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255; + + if (bgColor >= 0) { if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA) - bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 15)); + bgcolor.visual = get_pic_color(s, MIN<int>(bgColor, 15)); else - bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 255)); + bgcolor.visual = get_pic_color(s, bgColor); bgcolor.mask = GFX_MASK_VISUAL; } else { bgcolor.visual = PaletteEntry(0,0,0); @@ -2501,9 +2511,10 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { bgcolor.mask |= priority >= 0 ? GFX_MASK_PRIORITY : 0; bgcolor.alpha = 0; bgcolor.control = -1; - debugC(2, kDebugLevelGraphics, "New window with params %d, %d, %d, %d\n", SKPV(0), SKPV(1), SKPV(2), SKPV(3)); + debugC(2, kDebugLevelGraphics, "New window with params %d, %d, %d, %d\n", argv[0].toSint16(), argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16()); - fgcolor.visual = get_pic_color(s, SKPV_OR_ALT(7 + argextra, 0)); + int16 visualColor = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0; + fgcolor.visual = get_pic_color(s, visualColor); fgcolor.mask = GFX_MASK_VISUAL; fgcolor.control = -1; fgcolor.priority = -1; @@ -2518,14 +2529,14 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { lWhite.alpha = 0; lWhite.priority = -1; lWhite.control = -1; + const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL; window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor, - s->titlebar_port->_font, lWhite, black, argv[4 + argextra].segment ? - kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL, flags); + s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, flags); // PQ3 and SCI1.1 games have the interpreter store underBits implicitly if (argextra) - gfxw_port_auto_restore_background(s->visual, window, gfx_rect(SKPV(5), SKPV(4), SKPV(7) - SKPV(5), SKPV(6) - SKPV(4))); + gfxw_port_auto_restore_background(s->visual, window, gfx_rect(argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16() - argv[5].toSint16(), argv[6].toSint16() - argv[4].toSint16())); ADD_TO_WINDOW_PORT(window); FULL_REDRAW(); @@ -2956,8 +2967,8 @@ static void animate_do_animation(EngineState *s, int funct_nr, int argc, reg_t * reg_t kAnimate(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Animations are supposed to take a maximum of animation_delay milliseconds. - reg_t cast_list_ref = KP_ALT(0, NULL_REG); - int cycle = (KP_ALT(1, NULL_REG)).offset; + reg_t cast_list_ref = (argc > 0) ? argv[0] : NULL_REG; + int cycle = (argc > 1) ? argv[1].toUint16() : 0; List *cast_list = NULL; int open_animation = 0; @@ -3065,8 +3076,8 @@ reg_t kAnimate(EngineState *s, int funct_nr, int argc, reg_t *argv) { #define SHAKE_RIGHT 2 reg_t kShakeScreen(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int shakes = SKPV_OR_ALT(0, 1); - int directions = SKPV_OR_ALT(1, 1); + int shakes = (argc > 0) ? argv[0].toSint16() : 1; + int directions = (argc > 1) ? argv[1].toSint16() : 1; gfx_pixmap_t *screen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 0, 320, 200)); int i; @@ -3115,7 +3126,7 @@ reg_t kShakeScreen(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { int argpt; reg_t textp = argv[0]; - int index = UKPV_OR_ALT(1, 0); + int index = (argc > 1) ? argv[1].toUint16() : 0; int temp; bool save_under = false; gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 }; @@ -3157,24 +3168,24 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { } while (argpt < argc) { - switch (UKPV(argpt++)) { + switch (argv[argpt++].toUint16()) { case K_DISPLAY_SET_COORDS: - area.x = UKPV(argpt++); - area.y = UKPV(argpt++); + area.x = argv[argpt++].toUint16(); + area.y = argv[argpt++].toUint16(); debugC(2, kDebugLevelGraphics, "Display: set_coords(%d, %d)\n", area.x, area.y); break; case K_DISPLAY_SET_ALIGNMENT: - halign = (gfx_alignment_t)KP_SINT(argv[argpt++]); + halign = (gfx_alignment_t)argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_align(%d)\n", halign); break; case K_DISPLAY_SET_COLOR: - temp = KP_SINT(argv[argpt++]); + temp = argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_color(%d)\n", temp); if ((s->resmgr->_sciVersion < SCI_VERSION_01_VGA) && temp >= 0 && temp <= 15) color0 = (s->ega_colors[temp]); @@ -3191,7 +3202,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_DISPLAY_SET_BGCOLOR: - temp = KP_SINT(argv[argpt++]); + temp = argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_bg_color(%d)\n", temp); if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA && temp >= 0 && temp <= 15) bg_color = s->ega_colors[temp]; @@ -3208,20 +3219,20 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_DISPLAY_SET_GRAYTEXT: - gray = KP_SINT(argv[argpt++]); + gray = argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_graytext(%d)\n", gray); break; case K_DISPLAY_SET_FONT: - font_nr = KP_UINT(argv[argpt++]); + font_nr = argv[argpt++].toUint16(); debugC(2, kDebugLevelGraphics, "Display: set_font(\"font.%03d\")\n", font_nr); break; case K_DISPLAY_WIDTH: - area.width = UKPV(argpt++); + area.width = argv[argpt++].toUint16(); if (area.width == 0) area.width = MAX_TEXT_WIDTH_MAGIC_VALUE; @@ -3236,7 +3247,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_DISPLAY_RESTORE_UNDER: - debugC(2, kDebugLevelGraphics, "Display: restore_under(%04x)\n", UKPV(argpt)); + debugC(2, kDebugLevelGraphics, "Display: restore_under(%04x)\n", argv[argpt].toUint16()); graph_restore_box(s, argv[argpt++]); update_immediately = true; argpt++; @@ -3250,7 +3261,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; default: - debugC(2, kDebugLevelGraphics, "Unknown Display() command %x\n", UKPV(argpt - 1)); + debugC(2, kDebugLevelGraphics, "Unknown Display() command %x\n", argv[argpt - 1].toUint16()); return NULL_REG; } } @@ -3281,7 +3292,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { assert_primary_widget_lists(s); - text_handle = gfxw_new_text(s->gfx_state, area, font_nr, text, halign, ALIGN_TOP, color0, *color1, bg_color, 0); + text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0); if (!text_handle) { error("Display: Failed to create text widget"); @@ -3314,7 +3325,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv) { const char *filename = kernel_dereference_char_pointer(s, argv[0], 0); - int framerate = UKPV(1); // FIXME: verify + int framerate = argv[1].toUint16(); // FIXME: verify int frameNr = 0; SeqDecoder seq; @@ -3367,7 +3378,7 @@ reg_t kSetVideoMode(EngineState *s, int funct_nr, int argc, reg_t *argv) { // (320x240 resolution, although the intro in KQ6 is 320x200). // Refer to http://en.wikipedia.org/wiki/Mode_X - warning("STUB: SetVideoMode %d", UKPV(0)); + warning("STUB: SetVideoMode %d", argv[0].toUint16()); return s->r_acc; } diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 21fde8aeb2..e4c314c605 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -29,18 +29,18 @@ namespace Sci { reg_t kRandom(EngineState *s, int funct_nr, int argc, reg_t *argv) { - return make_reg(0, SKPV(0) + (int)((SKPV(1) + 1.0 - SKPV(0)) * (rand() / (RAND_MAX + 1.0)))); + return make_reg(0, argv[0].toSint16() + (int)((argv[1].toSint16() + 1.0 - argv[0].toSint16()) * (rand() / (RAND_MAX + 1.0)))); } reg_t kAbs(EngineState *s, int funct_nr, int argc, reg_t *argv) { // This is a hack, but so is the code in Hoyle1 that needs it. if (argv[0].segment) return make_reg(0, 0x3e8); // Yes people, this is an object - return make_reg(0, abs(SKPV(0))); + return make_reg(0, abs(argv[0].toSint16())); } reg_t kSqrt(EngineState *s, int funct_nr, int argc, reg_t *argv) { - return make_reg(0, (int16) sqrt((float) abs(SKPV(0)))); + return make_reg(0, (int16) sqrt((float) abs(argv[0].toSint16()))); } int get_angle(int xrel, int yrel) { @@ -66,10 +66,10 @@ int get_angle(int xrel, int yrel) { reg_t kGetAngle(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Based on behavior observed with a test program created with // SCI Studio. - int x1 = SKPV(0); - int y1 = SKPV(1); - int x2 = SKPV(2); - int y2 = SKPV(3); + int x1 = argv[0].toSint16(); + int y1 = argv[1].toSint16(); + int x2 = argv[2].toSint16(); + int y2 = argv[3].toSint16(); int xrel = x2 - x1; int yrel = y1 - y2; // y-axis is mirrored. int angle; @@ -101,29 +101,31 @@ reg_t kGetAngle(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kGetDistance(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int xrel = (int)(((float) SKPV(1) - SKPV_OR_ALT(3, 0)) / cos(SKPV_OR_ALT(5, 0) * PI / 180.0)); // This works because cos(0)==1 - int yrel = SKPV(0) - SKPV_OR_ALT(2, 0); - + int xdiff = (argc > 3) ? argv[3].toSint16() : 0; + int ydiff = (argc > 2) ? argv[2].toSint16() : 0; + int angle = (argc > 5) ? argv[5].toSint16() : 0; + int xrel = (int)(((float) argv[1].toSint16() - xdiff) / cos(angle * PI / 180.0)); // This works because cos(0)==1 + int yrel = argv[0].toSint16() - ydiff; return make_reg(0, (int16)sqrt((float) xrel*xrel + yrel*yrel)); } reg_t kTimesSin(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int angle = SKPV(0); - int factor = SKPV(1); + int angle = argv[0].toSint16(); + int factor = argv[1].toSint16(); return make_reg(0, (int)(factor * 1.0 * sin(angle * PI / 180.0))); } reg_t kTimesCos(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int angle = SKPV(0); - int factor = SKPV(1); + int angle = argv[0].toSint16(); + int factor = argv[1].toSint16(); return make_reg(0, (int)(factor * 1.0 * cos(angle * PI / 180.0))); } reg_t kCosDiv(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int angle = SKPV(0); - int value = SKPV(1); + int angle = argv[0].toSint16(); + int value = argv[1].toSint16(); double cosval = cos(angle * PI / 180.0); if ((cosval < 0.0001) && (cosval > 0.0001)) { @@ -134,8 +136,8 @@ reg_t kCosDiv(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kSinDiv(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int angle = SKPV(0); - int value = SKPV(1); + int angle = argv[0].toSint16(); + int value = argv[1].toSint16(); double sinval = sin(angle * PI / 180.0); if ((sinval < 0.0001) && (sinval > 0.0001)) { @@ -146,8 +148,8 @@ reg_t kSinDiv(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kTimesTan(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int param = SKPV(0); - int scale = SKPV_OR_ALT(1, 1); + int param = argv[0].toSint16(); + int scale = (argc > 1) ? argv[1].toSint16() : 1; param -= 90; if ((param % 90) == 0) { @@ -158,8 +160,8 @@ reg_t kTimesTan(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kTimesCot(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int param = SKPV(0); - int scale = SKPV_OR_ALT(1, 1); + int param = argv[0].toSint16(); + int scale = (argc > 1) ? argv[1].toSint16() : 1; if ((param % 90) == 0) { warning("Attempted tan(pi/2)"); diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 121333a6e3..c65d201b90 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -46,11 +46,11 @@ reg_t kAddMenu(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kSetMenu(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int index = UKPV(0); + int index = argv[0].toUint16(); int i = 2; while (i < argc) { - s->_menubar->setAttribute(s, (index >> 8) - 1, (index & 0xff) - 1, UKPV(i - 1), argv[i]); + s->_menubar->setAttribute(s, (index >> 8) - 1, (index & 0xff) - 1, argv[i - 1].toUint16(), argv[i]); i += 2; } @@ -58,16 +58,16 @@ reg_t kSetMenu(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kGetMenu(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int index = UKPV(0); + int index = argv[0].toUint16(); - return s->_menubar->getAttribute((index >> 8) - 1, (index & 0xff) - 1, UKPV(1)); + return s->_menubar->getAttribute((index >> 8) - 1, (index & 0xff) - 1, argv[1].toUint16()); } reg_t kDrawStatus(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t text = argv[0]; - int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground); - int bgcolor = SKPV_OR_ALT(2, s->status_bar_background); + int fgcolor = (argc > 1) ? argv[1].toSint16() : s->status_bar_foreground; + int bgcolor = (argc > 2) ? argv[2].toSint16() : s->status_bar_background; s->titlebar_port->_color.visual = get_pic_color(s, fgcolor); s->titlebar_port->_color.mask = GFX_MASK_VISUAL; @@ -92,7 +92,7 @@ reg_t kDrawStatus(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kDrawMenuBar(EngineState *s, int funct_nr, int argc, reg_t *argv) { - if (SKPV(0)) + if (argv[0].toSint16()) sciw_set_menubar(s, s->titlebar_port, s->_menubar, -1); else sciw_set_status_bar(s, s->titlebar_port, "", 0, 0); @@ -125,7 +125,7 @@ static int _menu_go_down(Menubar *menubar, int menu_nr, int item_nr) { reg_t kMenuSelect(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t event = argv[0]; - /*int pause_sound = UKPV_OR_ALT(1, 1);*/ /* FIXME: Do this eventually */ + /*int pause_sound = (argc > 1) ? argv[1].toUint16() : 1;*/ /* FIXME: Do this eventually */ bool claimed = false; int type = GET_SEL32V(event, type); int message = GET_SEL32V(event, message); diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 2e86362404..98fba97f0e 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -52,7 +52,7 @@ reg_t kGameIsRestarting(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED)); if (argc) { // Only happens during replay - if (!UKPV(0)) // Set restarting flag + if (!argv[0].toUint16()) // Set restarting flag s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED; } @@ -89,14 +89,15 @@ reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) { run_gc(s); - debugC(2, kDebugLevelRoom, "Entering room number %d", UKPV(0)); + debugC(2, kDebugLevelRoom, "Entering room number %d", argv[0].toUint16()); return s->r_acc; } reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) { sciprintf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + debugState.seeking = kDebugSeekNothing; + debugState.runningStep = 0; return s->r_acc; } @@ -127,7 +128,7 @@ reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) { return make_reg(0, retval); } - int mode = argc > 0 ? UKPV_OR_ALT(0, 0) : 0; + int mode = (argc > 0) ? argv[0].toUint16() : 0; switch (mode) { case _K_NEW_GETTIME_TICKS : @@ -164,15 +165,15 @@ enum { }; reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { - switch (UKPV(0)) { + switch (argv[0].toUint16()) { case K_MEMORY_ALLOCATE_CRITICAL : - if (!s->seg_manager->allocDynmem(UKPV(1), "kMemory() critical", &s->r_acc)) { + if (!s->seg_manager->allocDynmem(argv[1].toUint16(), "kMemory() critical", &s->r_acc)) { error("Critical heap allocation failed"); } return s->r_acc; break; case K_MEMORY_ALLOCATE_NONCRITICAL : - s->seg_manager->allocDynmem(UKPV(1), "kMemory() non-critical", &s->r_acc); + s->seg_manager->allocDynmem(argv[1].toUint16(), "kMemory() non-critical", &s->r_acc); break; case K_MEMORY_FREE : if (s->seg_manager->freeDynmem(argv[1])) { @@ -180,7 +181,7 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { } break; case K_MEMORY_MEMCPY : { - int size = UKPV(3); + int size = argv[3].toUint16(); byte *dest = kernel_dereference_bulk_pointer(s, argv[1], size); byte *src = kernel_dereference_bulk_pointer(s, argv[2], size); diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index b116fa4093..20a7be3aea 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -70,9 +70,9 @@ used in an iterative stepping algorithm reg_t kSetJump(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Input data reg_t object = argv[0]; - int dx = SKPV(1); - int dy = SKPV(2); - int gy = SKPV(3); + int dx = argv[1].toSint16(); + int dy = argv[2].toSint16(); + int gy = argv[3].toSint16(); // Derived data int c; @@ -223,8 +223,9 @@ reg_t kInitBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { int deltax = GET_SEL32SV(mover, x) - GET_SEL32SV(client, x); int deltay = GET_SEL32SV(mover, y) - GET_SEL32SV(client, y); + int step_factor = (argc < 1) ? argv[1].toUint16() : 1; - initialize_bresen(s, argc, argv, mover, KP_UINT(KP_ALT(1, make_reg(0, 1))), deltax, deltay); + initialize_bresen(s, argc, argv, mover, step_factor, deltax, deltay); return s->r_acc; } diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 3f0af0b538..c254875230 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -48,8 +48,8 @@ static void POLY_SET_POINT(byte *p, int i, const Common::Point &pt) { } static void POLY_GET_POINT_REG_T(const reg_t *p, int i, Common::Point &pt) { - pt.x = KP_SINT((p)[(i) * 2]); - pt.y = KP_SINT((p)[(i) * 2 + 1]); + pt.x = (p)[(i) * 2].toUint16(); + pt.y = (p)[(i) * 2 + 1].toUint16(); } // SCI-defined polygon types @@ -286,13 +286,13 @@ static Common::Point read_point(const byte *list, int is_reg_t, int offset) { */ static bool polygons_equal(EngineState *s, reg_t p1, reg_t p2) { // Check for same type - if (KP_UINT(GET_SEL32(p1, type)) != KP_UINT(GET_SEL32(p2, type))) + if (GET_SEL32(p1, type).toUint16() != GET_SEL32(p2, type).toUint16()) return false; - int size = KP_UINT(GET_SEL32(p1, size)); + int size = GET_SEL32(p1, size).toUint16(); // Check for same number of points - if (size != KP_UINT(GET_SEL32(p2, size))) + if (size != GET_SEL32(p2, size).toUint16()) return false; const byte *p1_points = kernel_dereference_bulk_pointer(s, GET_SEL32(p1, points), size * POLY_POINT_SIZE); @@ -356,8 +356,8 @@ static void draw_point(EngineState *s, Common::Point p, int start) { static void draw_polygon(EngineState *s, reg_t polygon) { reg_t points = GET_SEL32(polygon, points); - int size = KP_UINT(GET_SEL32(polygon, size)); - int type = KP_UINT(GET_SEL32(polygon, type)); + int size = GET_SEL32(polygon, size).toUint16(); + int type = GET_SEL32(polygon, type).toUint16(); Common::Point first, prev; const byte *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE); int is_reg_t = polygon_is_reg_t(list, size); @@ -403,8 +403,8 @@ static void draw_input(EngineState *s, reg_t poly_list, Common::Point start, Com static void print_polygon(EngineState *s, reg_t polygon) { reg_t points = GET_SEL32(polygon, points); - int size = KP_UINT(GET_SEL32(polygon, size)); - int type = KP_UINT(GET_SEL32(polygon, type)); + int size = GET_SEL32(polygon, size).toUint16(); + int type = GET_SEL32(polygon, type).toUint16(); int i; const byte *point_array = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE); int is_reg_t = polygon_is_reg_t(point_array, size); @@ -1228,9 +1228,9 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { // Returns : (Polygon *) The converted polygon int i; reg_t points = GET_SEL32(polygon, points); - int size = KP_UINT(GET_SEL32(polygon, size)); + int size = GET_SEL32(polygon, size).toUint16(); const byte *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE); - Polygon *poly = new Polygon(KP_UINT(GET_SEL32(polygon, type))); + Polygon *poly = new Polygon(GET_SEL32(polygon, type).toUint16()); int is_reg_t = polygon_is_reg_t(list, size); // WORKAROUND: broken polygon in LSL1VGA, room 350, after opening elevator @@ -1388,7 +1388,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co // Polygon is not a duplicate, so convert it polygon = convert_polygon(s, node->value); pf_s->polygons.push_back(polygon); - count += KP_UINT(GET_SEL32(node->value, size)); + count += GET_SEL32(node->value, size).toUint16(); } node = lookup_node(s, node->succ); @@ -1642,7 +1642,7 @@ static reg_t output_path(PathfindingState *p, EngineState *s) { } reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { - Common::Point start = Common::Point(SKPV(0), SKPV(1)); + Common::Point start = Common::Point(argv[0].toSint16(), argv[1].toSint16()); #ifdef DEBUG_AVOIDPATH GfxPort *port = s->picture_port; @@ -1669,10 +1669,10 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { } case 6 : case 7 : { - Common::Point end = Common::Point(SKPV(2), SKPV(3)); + Common::Point end = Common::Point(argv[2].toSint16(), argv[3].toSint16()); reg_t poly_list = argv[4]; - //int poly_list_size = UKPV(5); - int opt = UKPV_OR_ALT(6, 1); + //int poly_list_size = argv[5].toUint16(); + int opt = (argc > 6) ? argv[6].toUint16() : 1; reg_t output; PathfindingState *p; diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index e400cb0827..d82f8ff132 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -32,16 +32,16 @@ namespace Sci { reg_t read_selector(EngineState *s, reg_t object, Selector selector_id, const char *file, int line) { - reg_t *address; + ObjVarRef address; if (lookup_selector(s, object, selector_id, &address, NULL) != kSelectorVariable) return NULL_REG; else - return *address; + return *address.getPointer(s); } void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) { - reg_t *address; + ObjVarRef address; if ((selector_id < 0) || (selector_id > (int)s->_kernel->getSelectorNamesSize())) { warning("Attempt to write to invalid selector %d of" @@ -53,7 +53,7 @@ void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t va warning("Selector '%s' of object at %04x:%04x could not be" " written to (%s L%d)", s->_kernel->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); else - *address = value; + *address.getPointer(s) = value; } int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid, int kfunct, @@ -114,8 +114,8 @@ bool is_object(EngineState *s, reg_t object) { // Loads arbitrary resources of type 'restype' with resource numbers 'resnrs' // This implementation ignores all resource numbers except the first one. reg_t kLoad(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int restype = KP_UINT(argv[0]); - int resnr = KP_UINT(argv[1]); + int restype = argv[0].toUint16(); + int resnr = argv[1].toUint16(); // Request to dynamically allocate hunk memory for later use if (restype == kResourceTypeMemory) @@ -125,19 +125,27 @@ reg_t kLoad(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kLock(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int restype = UKPV(0) & 0x7f; - int resnr = UKPV(1); - int state = argc > 2 ? UKPV(2) : 1; + int state = argc > 2 ? argv[2].toUint16() : 1; + ResourceType type = (ResourceType)(argv[0].toUint16() & 0x7f); + ResourceId id = ResourceId(type, argv[1].toUint16()); Resource *which; switch (state) { case 1 : - s->resmgr->findResource((ResourceType)restype, resnr, 1); + s->resmgr->findResource(id, 1); break; case 0 : - which = s->resmgr->findResource((ResourceType)restype, resnr, 0); - s->resmgr->unlockResource(which, resnr, (ResourceType)restype); + which = s->resmgr->findResource(id, 0); + + if (which) + s->resmgr->unlockResource(which); + else { + if (id.type == kResourceTypeInvalid) + warning("[Resmgr] Attempt to unlock resource %i of invalid type %i", id.number, type); + else + warning("[Resmgr] Attempt to unlock non-existant resource %s", id.toString().c_str()); + } break; } return s->r_acc; @@ -145,7 +153,7 @@ reg_t kLock(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' reg_t kUnLoad(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int restype = KP_UINT(argv[0]); + int restype = argv[0].toUint16(); reg_t resnr = argv[1]; if (restype == kResourceTypeMemory) @@ -155,26 +163,23 @@ reg_t kUnLoad(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv) { - ResourceType restype = (ResourceType)(UKPV(0) & 0x7f); - - switch (restype) { - case kResourceTypeAudio36: - case kResourceTypeSync36: { - assert(argc >= 6); - - uint module = UKPV(1); - uint noun = UKPV(2); - uint verb = UKPV(3); - uint cond = UKPV(4); - uint seq = UKPV(5); - warning("ResCheck: checking for currently unsupported %s resource: module %i; tuple (%i, %i, %i, %i)", - getResourceTypeName(restype), module, noun, verb, cond, seq); - return make_reg(0, 1); - } - default: - Resource *res = s->resmgr->testResource(restype, UKPV(1)); - return make_reg(0, res != NULL); + Resource *res = NULL; + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); + + if ((restype == kResourceTypeAudio36) || (restype == kResourceTypeSync36)) { + if (argc >= 6) { + uint noun = argv[2].toUint16() & 0xff; + uint verb = argv[3].toUint16() & 0xff; + uint cond = argv[4].toUint16() & 0xff; + uint seq = argv[5].toUint16() & 0xff; + + res = s->resmgr->testResource(ResourceId(restype, argv[1].toUint16(), noun, verb, cond, seq)); + } + } else { + res = s->resmgr->testResource(ResourceId(restype, argv[1].toUint16())); } + + return make_reg(0, res != NULL); } reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { @@ -252,8 +257,8 @@ reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Returns script dispatch address index in the supplied script reg_t kScriptID(EngineState *s, int funct_nr, int argc, reg_t *argv) { - int script = KP_UINT(argv[0]); - int index = KP_UINT(KP_ALT(1, NULL_REG)); + int script = argv[0].toUint16(); + int index = (argc > 1) ? argv[1].toUint16() : 0; SegmentId scriptid = script_get_segment(s, script, SCRIPT_GET_LOAD); Script *scr; @@ -313,7 +318,7 @@ reg_t kIsObject(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kRespondsTo(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t obj = argv[0]; - int selector = KP_UINT(argv[1]); + int selector = argv[1].toUint16(); return make_reg(0, is_heap_object(s, obj) && lookup_selector(s, obj, selector, NULL, NULL) != kSelectorNone); } diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index b0fbda36f9..bb27589d84 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -123,7 +123,7 @@ enum AudioSyncCommands { static void script_set_priority(EngineState *s, reg_t obj, int priority) { int song_nr = GET_SEL32V(obj, number); - Resource *song = s->resmgr->findResource(kResourceTypeSound, song_nr, 0); + Resource *song = s->resmgr->findResource(ResourceId(kResourceTypeSound, song_nr), 0); int flags = GET_SEL32V(obj, flags); if (priority == -1) { @@ -140,7 +140,7 @@ static void script_set_priority(EngineState *s, reg_t obj, int priority) { } SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, songit_id_t id) { - Resource *song = s->resmgr->findResource(kResourceTypeSound, song_nr, 0); + Resource *song = s->resmgr->findResource(ResourceId(kResourceTypeSound, song_nr), 0); if (!song) return NULL; @@ -151,7 +151,7 @@ SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ int result; - song_handle_t handle; + SongHandle handle; int cue; if (s->_version >= SCI_VERSION_01) @@ -202,9 +202,9 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { - reg_t obj = KP_ALT(1, NULL_REG); - uint16 command = UKPV(0); - song_handle_t handle = FROBNICATE_HANDLE(obj); + reg_t obj = (argc > 1) ? argv[1] : NULL_REG; + uint16 command = argv[0].toUint16(); + SongHandle handle = FROBNICATE_HANDLE(obj); int number = obj.segment ? GET_SEL32V(obj, number) : -1; /* We were not going to use it anyway */ @@ -335,7 +335,7 @@ reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { case _K_SCI0_SOUND_VOLUME: { /* range from 0x0 to 0xf */ /* parameter optional. If present, set.*/ - int vol = SKPV_OR_ALT(1, -1); + int vol = (argc > 1) ? argv[1].toSint16() : -1; if (vol != -1) s->_sound.sfx_set_volume(vol << 0xf); @@ -381,9 +381,9 @@ reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { - uint16 command = UKPV(0); - reg_t obj = KP_ALT(1, NULL_REG); - song_handle_t handle = FROBNICATE_HANDLE(obj); + uint16 command = argv[0].toUint16(); + reg_t obj = (argc > 1) ? argv[1] : NULL_REG; + SongHandle handle = FROBNICATE_HANDLE(obj); int number = obj.segment ? GET_SEL32V(obj, number) : -1; /* We were not going to use it anyway */ @@ -456,7 +456,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (command) { case _K_SCI01_SOUND_MASTER_VOLME : { - int vol = SKPV_OR_ALT(1, -1); + int vol = (argc > 1) ? argv[1].toSint16() : -1; if (vol != -1) s->_sound.sfx_set_volume(vol << 0xf); @@ -487,13 +487,13 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { int looping = GET_SEL32V(obj, loop); //int vol = GET_SEL32V(obj, vol); int pri = GET_SEL32V(obj, pri); - RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) UKPV(2); /* Too lazy to look up a default value for this */ + RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) argv[2].toUint16(); /* Too lazy to look up a default value for this */ if (obj.segment) { s->_sound.sfx_song_set_status(handle, SOUND_STATUS_PLAYING); s->_sound.sfx_song_set_loops(handle, looping); s->_sound.sfx_song_renice(handle, pri); - song_lib_set_restore_behavior(s->_sound._songlib, handle, rb); + s->_sound._songlib.setSongRestoreBehavior(handle, rb); } break; @@ -503,7 +503,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { //int vol = GET_SEL32V(obj, vol); //int pri = GET_SEL32V(obj, pri); - if (obj.segment && (s->resmgr->testResource(kResourceTypeSound, number))) { + if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) { sciprintf("Initializing song number %d\n", number); s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, handle), 0, handle, number); @@ -551,7 +551,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case _K_SCI01_SOUND_SUSPEND_HANDLE : { - int state = UKPV(2); + int state = argv[2].toUint16(); int setstate = (state) ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING; @@ -647,12 +647,12 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case _K_SCI01_SOUND_MIDI_SEND : { - int channel = SKPV(2); - int midiCmd = UKPV(3) == 0xff ? + int channel = argv[2].toSint16(); + int midiCmd = argv[3].toUint16() == 0xff ? 0xe0 : /* Pitch wheel */ - 0xb0; /* UKPV(3) is actually a controller number */ - int controller = UKPV(3); - int param = UKPV(4); + 0xb0; /* argv[3].toUint16() is actually a controller number */ + int controller = argv[3].toUint16(); + int param = argv[4].toUint16(); s->_sound.sfx_send_midi(handle, channel, midiCmd, controller, param); @@ -662,7 +662,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case _K_SCI01_SOUND_HOLD : { - //int flag = SKPV(2); + //int flag = argv[2].toSint16(); break; } } @@ -671,9 +671,9 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { - uint16 command = UKPV(0); - reg_t obj = KP_ALT(1, NULL_REG); - song_handle_t handle = FROBNICATE_HANDLE(obj); + uint16 command = argv[0].toUint16(); + reg_t obj = (argc > 1) ? argv[1] : NULL_REG; + SongHandle handle = FROBNICATE_HANDLE(obj); int number = obj.segment ? GET_SEL32V(obj, number) : -1; /* We were not going to use it anyway */ @@ -798,16 +798,16 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { int looping = GET_SEL32V(obj, loop); //int vol = GET_SEL32V(obj, vol); int pri = GET_SEL32V(obj, pri); - song_t *song = song_lib_find(s->_sound._songlib, handle); + Song *song = s->_sound._songlib.findSong(handle); - if (GET_SEL32V(obj, nodePtr) && (song && number != song->resource_num)) { + if (GET_SEL32V(obj, nodePtr) && (song && number != song->_resourceNum)) { s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); s->_sound.sfx_remove_song(handle); PUT_SEL32(obj, nodePtr, NULL_REG); } if (!GET_SEL32V(obj, nodePtr) && obj.segment) { - if (!s->resmgr->testResource(kResourceTypeSound, number)) { + if (!s->resmgr->testResource(ResourceId(kResourceTypeSound, number))) { sciprintf("Could not open song number %d\n", number); return NULL_REG; } @@ -837,7 +837,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->_sound.sfx_remove_song(handle); } - if (obj.segment && (s->resmgr->testResource(kResourceTypeSound, number))) { + if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) { sciprintf("Initializing song number %d\n", number); s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, handle), 0, handle, number); @@ -866,10 +866,10 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { case _K_SCI1_SOUND_FADE_HANDLE : { fade_params_t fade; if (obj.segment) { - fade.final_volume = UKPV(2); - fade.ticks_per_step = UKPV(3); - fade.step_size = UKPV(4); - fade.action = UKPV(5) ? + fade.final_volume = argv[2].toUint16(); + fade.ticks_per_step = argv[3].toUint16(); + fade.step_size = argv[4].toUint16(); + fade.action = argv[5].toUint16() ? FADE_ACTION_FADE_AND_STOP : FADE_ACTION_FADE_AND_CONT; @@ -877,7 +877,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { /* FIXME: The next couple of lines actually STOP the handle, rather ** than fading it! */ - if (UKPV(5)) { + if (argv[5].toUint16()) { PUT_SEL32V(obj, signal, -1); PUT_SEL32V(obj, nodePtr, 0); PUT_SEL32V(obj, handle, 0); @@ -890,7 +890,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case _K_SCI1_SOUND_HOLD_HANDLE : { - int value = SKPV(2); + int value = argv[2].toSint16(); s->_sound.sfx_song_set_hold(handle, value); break; @@ -902,7 +902,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { break; } case _K_SCI1_SOUND_SET_HANDLE_PRIORITY : { - int value = SKPV(2); + int value = argv[2].toSint16(); script_set_priority(s, obj, value); break; @@ -950,7 +950,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { } case _K_SCI1_SOUND_MIDI_SEND : { s->_sound.sfx_send_midi(handle, - UKPV(2), UKPV(3), UKPV(4), UKPV(5)); + argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16(), argv[5].toUint16()); break; } case _K_SCI1_SOUND_REVERB : { @@ -975,109 +975,120 @@ reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Used for speech playback in CD games reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) { Audio::Mixer *mixer = g_system->getMixer(); - int sampleLen = 0; - if (!s->_sound._audioResource) - s->_sound._audioResource = new AudioResource(s->resmgr, s->_version); - - switch (UKPV(0)) { + switch (argv[0].toUint16()) { case kSciAudioWPlay: - case kSciAudioPlay: - s->_sound._audioResource->stop(); - - if (argc == 2) { // KQ5CD, KQ6 floppy - Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(UKPV(1), 65535, &sampleLen); - - if (audioStream) - mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->_sound._audioResource->getAudioHandle(), audioStream); - } else if (argc == 6) { // SQ4CD or newer - //uint32 volume = UKPV(1); - // Make a BE number - uint32 audioNumber = (((UKPV(2) & 0xFF) << 24) & 0xFF000000) | - (((UKPV(3) & 0xFF) << 16) & 0x00FF0000) | - (((UKPV(4) & 0xFF) << 8) & 0x0000FF00) | - ( (UKPV(5) & 0xFF) & 0x000000FF); - - printf("%d %d %d %d -> %d\n", UKPV(2), UKPV(3), UKPV(4), UKPV(5), audioNumber); // debugging - - Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(audioNumber, UKPV(1), &sampleLen); - - if (audioStream) - mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->_sound._audioResource->getAudioHandle(), audioStream); - } else { // Hopefully, this should never happen + case kSciAudioPlay: { + uint16 module; + uint32 number; + + s->_sound.stopAudio(); + + if (argc == 2) { + module = 65535; + number = argv[1].toUint16(); + } else if (argc == 6) { + module = argv[1].toUint16(); + number = ((argv[2].toUint16() & 0xff) << 24) | ((argv[3].toUint16() & 0xff) << 16) | + ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff); + } else { warning("kDoAudio: Play called with an unknown number of parameters (%d)", argc); + return NULL_REG; } - return make_reg(0, sampleLen); // return sample length in ticks + + return make_reg(0, s->_sound.startAudio(module, number)); // return sample length in ticks + } case kSciAudioStop: - s->_sound._audioResource->stop(); + s->_sound.stopAudio(); break; case kSciAudioPause: - s->_sound._audioResource->pause(); + s->_sound.pauseAudio(); break; case kSciAudioResume: - s->_sound._audioResource->resume(); + s->_sound.resumeAudio(); break; case kSciAudioPosition: - return make_reg(0, s->_sound._audioResource->getAudioPosition()); + return make_reg(0, s->_sound.getAudioPosition()); case kSciAudioRate: - s->_sound._audioResource->setAudioRate(UKPV(1)); + s->_sound.setAudioRate(argv[1].toUint16()); break; case kSciAudioVolume: - mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, UKPV(1)); + mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[1].toUint16()); break; case kSciAudioLanguage: if (argc == 1) { // In SCI1.1: tests for digital audio support return make_reg(0, 1); } else { - s->_sound._audioResource->setAudioLang(SKPV(1)); + s->resmgr->setAudioLanguage(argv[1].toSint16()); } break; default: - warning("kDoAudio: Unhandled case %d", UKPV(0)); + warning("kDoAudio: Unhandled case %d", argv[0].toUint16()); } return s->r_acc; } reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) { - switch (UKPV(0)) { - case kSciAudioSyncStart: - if (argc == 3) { // KQ5CD, KQ6 floppy - if (s->_sound._soundSync) { - s->resmgr->unlockResource(s->_sound._soundSync, s->_sound._soundSync->number, kResourceTypeSync); - } + switch (argv[0].toUint16()) { + case kSciAudioSyncStart: { + ResourceId id; - // Load sound sync resource and lock it - s->_sound._soundSync = (ResourceSync *)s->resmgr->findResource(kResourceTypeSync, UKPV(2), 1); + if (s->_sound._syncResource) { + s->resmgr->unlockResource(s->_sound._syncResource); + s->_sound._syncResource = NULL; + } - if (s->_sound._soundSync) { - s->_sound._soundSync->startSync(s, argv[1]); - } else { - // Notify the scripts to stop sound sync - PUT_SEL32V(argv[1], syncCue, -1); - } - } else if (argc == 7) { // SQ4CD or newer - // TODO - warning("kDoSync: Start called with new semantics - 6 parameters: %d %d %d %d %d %d", UKPV(1), UKPV(2), UKPV(3), UKPV(4), UKPV(5), UKPV(6)); - } else { // Hopefully, this should never happen + // Load sound sync resource and lock it + if (argc == 3) { + id = ResourceId(kResourceTypeSync, argv[2].toUint16()); + } else if (argc == 7) { + id = ResourceId(kResourceTypeSync36, argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16(), + argv[5].toUint16(), argv[6].toUint16()); + } else { warning("kDoSync: Start called with an unknown number of parameters (%d)", argc); + return s->r_acc; + } + + s->_sound._syncResource = s->resmgr->findResource(id, 1); + + if (s->_sound._syncResource) { + PUT_SEL32V(argv[1], syncCue, 0); + s->_sound._syncOffset = 0; + } else { + warning("DoSync: failed to find resource %s", id.toString().c_str()); + // Notify the scripts to stop sound sync + PUT_SEL32V(argv[1], syncCue, -1); } break; - case kSciAudioSyncNext: - if (s->_sound._soundSync) { - s->_sound._soundSync->nextSync(s, argv[1]); + } + case kSciAudioSyncNext: { + Resource *res = s->_sound._syncResource; + if (res && (s->_sound._syncOffset < res->size - 1)) { + int16 syncCue = -1; + int16 syncTime = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset); + + s->_sound._syncOffset += 2; + + if ((syncTime != -1) && (s->_sound._syncOffset < res->size - 1)) { + syncCue = (int16)READ_LE_UINT16(res->data + s->_sound._syncOffset); + s->_sound._syncOffset += 2; + } + + PUT_SEL32V(argv[1], syncTime, syncTime); + PUT_SEL32V(argv[1], syncCue, syncCue); } break; + } case kSciAudioSyncStop: - if (s->_sound._soundSync) { - s->_sound._soundSync->stopSync(); - s->resmgr->unlockResource(s->_sound._soundSync, s->_sound._soundSync->number, kResourceTypeSync); - s->_sound._soundSync = NULL; + if (s->_sound._syncResource) { + s->resmgr->unlockResource(s->_sound._syncResource); + s->_sound._syncResource = NULL; } break; default: - warning("kDoSync: Unhandled case %d", UKPV(0)); + warning("DoSync: Unhandled subfunction %d", argv[0].toUint16()); } return s->r_acc; diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 3898664921..2a30a103b6 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -48,7 +48,7 @@ char *kernel_lookup_text(EngineState *s, reg_t address, int index) { else { int textlen; int _index = index; - textres = s->resmgr->findResource(kResourceTypeText, address.offset, 0); + textres = s->resmgr->findResource(ResourceId(kResourceTypeText, address.offset), 0); if (!textres) { error("text.%03d not found", address.offset); @@ -281,7 +281,7 @@ reg_t kStrCmp(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *s2 = kernel_dereference_char_pointer(s, argv[1], 0); if (argc > 2) - return make_reg(0, strncmp(s1, s2, UKPV(2))); + return make_reg(0, strncmp(s1, s2, argv[2].toUint16())); else return make_reg(0, strcmp(s1, s2)); } @@ -304,7 +304,7 @@ reg_t kStrCpy(EngineState *s, int funct_nr, int argc, reg_t *argv) { } if (argc > 2) { - int length = SKPV(2); + int length = argv[2].toSint16(); if (length >= 0) strncpy(dest, src, length); @@ -376,19 +376,19 @@ reg_t kStrAt(EngineState *s, int funct_nr, int argc, reg_t *argv) { ((strlen(dst) < 2) || (!lsl5PasswordWorkaround && !is_print_str(dst)))) { // SQ4 array handling detected #ifndef SCUMM_BIG_ENDIAN - int odd = KP_UINT(argv[1]) & 1; + int odd = argv[1].toUint16() & 1; #else - int odd = !(KP_UINT(argv[1]) & 1); + int odd = !(argv[1].toUint16() & 1); #endif - dest2 = ((reg_t *) dest) + (KP_UINT(argv[1]) / 2); + dest2 = ((reg_t *) dest) + (argv[1].toUint16() / 2); dest = ((byte *)(&dest2->offset)) + odd; } else - dest += KP_UINT(argv[1]); + dest += argv[1].toUint16(); s->r_acc = make_reg(0, *dest); if (argc > 2) - *dest = KP_SINT(argv[2]); /* Request to modify this char */ + *dest = argv[2].toSint16(); /* Request to modify this char */ return s->r_acc; } @@ -423,7 +423,7 @@ reg_t kFormat(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t dest = argv[0]; char *target = (char *) kernel_dereference_bulk_pointer(s, dest, 0); reg_t position = argv[1]; /* source */ - int index = UKPV(2); + int index = argv[2].toUint16(); char *source; char *str_base = target; int mode = 0; @@ -452,7 +452,7 @@ reg_t kFormat(EngineState *s, int funct_nr, int argc, reg_t *argv) { #endif for (i = startarg; i < argc; i++) - arguments[i-startarg] = UKPV(i); /* Parameters are copied to prevent overwriting */ + arguments[i-startarg] = argv[i].toUint16(); /* Parameters are copied to prevent overwriting */ while ((xfer = *source++)) { if (xfer == '%') { @@ -646,13 +646,13 @@ reg_t kStrLen(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t kGetFarText(EngineState *s, int funct_nr, int argc, reg_t *argv) { - Resource *textres = s->resmgr->findResource(kResourceTypeText, UKPV(0), 0); + Resource *textres = s->resmgr->findResource(ResourceId(kResourceTypeText, argv[0].toUint16()), 0); char *seeker; - int counter = UKPV(1); + int counter = argv[1].toUint16(); if (!textres) { - error("text.%d does not exist", UKPV(0)); + error("text.%d does not exist", argv[0].toUint16()); return NULL_REG; } @@ -693,18 +693,18 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (isGetMessage) { func = K_MESSAGE_GET; - tuple.noun = UKPV(0); - tuple.verb = UKPV(2); + tuple.noun = argv[0].toUint16(); + tuple.verb = argv[2].toUint16(); tuple.cond = 0; tuple.seq = 1; } else { - func = UKPV(0); + func = argv[0].toUint16(); if (argc >= 6) { - tuple.noun = UKPV(2); - tuple.verb = UKPV(3); - tuple.cond = UKPV(4); - tuple.seq = UKPV(5); + tuple.noun = argv[2].toUint16(); + tuple.verb = argv[3].toUint16(); + tuple.cond = argv[4].toUint16(); + tuple.seq = argv[5].toUint16(); } } @@ -717,7 +717,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { reg_t retval; if (func == K_MESSAGE_GET) { - s->_msgState.loadRes(s->resmgr, UKPV(1), true); + s->_msgState.loadRes(s->resmgr, argv[1].toUint16(), true); s->_msgState.findTuple(tuple); if (isGetMessage) @@ -762,7 +762,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_MESSAGE_SIZE: { MessageState tempState; - if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple) && tempState.getMessage()) + if (tempState.loadRes(s->resmgr, argv[1].toUint16(), false) && tempState.findTuple(tuple) && tempState.getMessage()) return make_reg(0, tempState.getText().size() + 1); else return NULL_REG; @@ -772,7 +772,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_MESSAGE_REFNOUN: { MessageState tempState; - if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple)) { + if (tempState.loadRes(s->resmgr, argv[1].toUint16(), false) && tempState.findTuple(tuple)) { MessageTuple t = tempState.getRefTuple(); switch (func) { case K_MESSAGE_REFCOND: diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp index c0775ae51e..4d37d2aece 100644 --- a/engines/sci/engine/memobj.cpp +++ b/engines/sci/engine/memobj.cpp @@ -269,13 +269,6 @@ void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, //-------------------- clones -------------------- -template<typename T> -void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { - for (uint i = 0; i < _table.size(); i++) - if (isValidEntry(i)) - (*note)(param, make_reg(segId, i)); -} - void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { CloneTable *clone_table = this; Clone *clone; diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h index c006caaddc..50c43a0e88 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -166,9 +166,11 @@ public: /** This struct is used to buffer the list of send calls in send_selector() */ struct CallsStruct { + reg_t addr_func; + reg_t varp_objp; union { reg_t func; - reg_t *var; + ObjVarRef var; } address; StackPtr argp; int argc; @@ -500,7 +502,11 @@ public: entries_used--; } - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note); + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) { + for (uint i = 0; i < _table.size(); i++) + if (isValidEntry(i)) + (*note)(param, make_reg(segId, i)); + } }; diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 4f5efa106c..c019f7a3bc 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -229,11 +229,11 @@ int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) { } // Otherwise, free the old resource - resmgr->unlockResource(_currentResource, _module, kResourceTypeMessage); + resmgr->unlockResource(_currentResource); _locked = false; } - _currentResource = resmgr->findResource(kResourceTypeMessage, module, lock); + _currentResource = resmgr->findResource(ResourceId(kResourceTypeMessage, module), lock); if (_currentResource == NULL || _currentResource->data == NULL) { warning("Message: failed to load %d.msg", module); diff --git a/engines/sci/engine/said.cpp b/engines/sci/engine/said.cpp index 7d0467efa6..327231857e 100644 --- a/engines/sci/engine/said.cpp +++ b/engines/sci/engine/said.cpp @@ -1918,7 +1918,7 @@ static int said_next_node() { #define SAID_NEXT_NODE said_next_node() static int said_leaf_node(tree_t pos, int value) { - said_tree[pos].type = PARSE_TREE_NODE_LEAF; + said_tree[pos].type = kParseTreeLeafNode; if (value != VALUE_IGNORE) said_tree[pos].content.value = value; @@ -1927,7 +1927,7 @@ static int said_leaf_node(tree_t pos, int value) { } static int said_branch_node(tree_t pos, int left, int right) { - said_tree[pos].type = PARSE_TREE_NODE_BRANCH; + said_tree[pos].type = kParseTreeBranchNode; if (left != VALUE_IGNORE) said_tree[pos].content.branches[0] = left; @@ -2057,12 +2057,12 @@ static int said_parse_spec(EngineState *s, byte *spec) { // primitive functions #define AUG_READ_BRANCH(a, br, p) \ - if (tree[p].type != PARSE_TREE_NODE_BRANCH) \ + if (tree[p].type != kParseTreeBranchNode) \ return 0; \ a = tree[p].content.branches[br]; #define AUG_READ_VALUE(a, p) \ - if (tree[p].type != PARSE_TREE_NODE_LEAF) \ + if (tree[p].type != kParseTreeLeafNode) \ return 0; \ a = tree[p].content.value; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index a69e96eb3d..146d65b56d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -52,7 +52,7 @@ SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, // of the classes they are syncing. static void sync_MemObjPtr(Common::Serializer &s, MemObject *&obj); -static void sync_songlib_t(Common::Serializer &s, songlib_t &obj); +static void sync_songlib_t(Common::Serializer &s, SongLibrary &obj); static void sync_reg_t(Common::Serializer &s, reg_t &obj) { s.syncAsUint16LE(obj.segment); @@ -73,22 +73,22 @@ static void syncCStr(Common::Serializer &s, char **str) { } -static void sync_song_t(Common::Serializer &s, song_t &obj) { - s.syncAsSint32LE(obj.handle); - s.syncAsSint32LE(obj.resource_num); - s.syncAsSint32LE(obj.priority); - s.syncAsSint32LE(obj.status); - s.syncAsSint32LE(obj.restore_behavior); - s.syncAsSint32LE(obj.restore_time); - s.syncAsSint32LE(obj.loops); - s.syncAsSint32LE(obj.hold); +static void sync_song_t(Common::Serializer &s, Song &obj) { + s.syncAsSint32LE(obj._handle); + s.syncAsSint32LE(obj._resourceNum); + s.syncAsSint32LE(obj._priority); + s.syncAsSint32LE(obj._status); + s.syncAsSint32LE(obj._restoreBehavior); + s.syncAsSint32LE(obj._restoreTime); + s.syncAsSint32LE(obj._loops); + s.syncAsSint32LE(obj._hold); if (s.isLoading()) { + obj._it = 0; obj._delay = 0; - obj.it = 0; - obj.next_playing = 0; - obj.next_stopping = 0; - obj.next = 0; + obj._next = 0; + obj._nextPlaying = 0; + obj._nextStopping = 0; } } @@ -401,25 +401,25 @@ void StringFrag::saveLoadWithSerializer(Common::Serializer &s) { #pragma mark - -static void sync_songlib_t(Common::Serializer &s, songlib_t &obj) { +static void sync_songlib_t(Common::Serializer &s, SongLibrary &obj) { int songcount = 0; if (s.isSaving()) - songcount = song_lib_count(obj); + songcount = obj.countSongs(); s.syncAsUint32LE(songcount); if (s.isLoading()) { - song_lib_init(&obj); + obj._lib = 0; while (songcount--) { - song_t *newsong = (song_t *)calloc(1, sizeof(song_t)); + Song *newsong = (Song *)calloc(1, sizeof(Song)); sync_song_t(s, *newsong); - song_lib_add(obj, newsong); + obj.addSong(newsong); } } else { - song_t *seeker = *(obj.lib); + Song *seeker = obj._lib; while (seeker) { - seeker->restore_time = seeker->it->getTimepos(); + seeker->_restoreTime = seeker->_it->getTimepos(); sync_song_t(s, *seeker); - seeker = seeker->next; + seeker = seeker->_next; } } } @@ -544,9 +544,9 @@ static void load_script(EngineState *s, SegmentId seg) { scr->buf = (byte *)malloc(scr->buf_size); assert(scr->buf); - script = s->resmgr->findResource(kResourceTypeScript, scr->nr, 0); + script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scr->nr), 0); if (s->_version >= SCI_VERSION_1_1) - heap = s->resmgr->findResource(kResourceTypeHeap, scr->nr, 0); + heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scr->nr), 0); memcpy(scr->buf, script->data, script->size); if (s->seg_manager->isSci1_1) @@ -692,36 +692,31 @@ static void reconstruct_clones(EngineState *s, SegManager *self) { int _reset_graphics_input(EngineState *s); static void reconstruct_sounds(EngineState *s) { - song_t *seeker; + Song *seeker; SongIteratorType it_type = s->resmgr->_sciVersion >= SCI_VERSION_01 ? SCI_SONG_ITERATOR_TYPE_SCI1 : SCI_SONG_ITERATOR_TYPE_SCI0; - if (s->_sound._songlib.lib) - seeker = *(s->_sound._songlib.lib); - else { - song_lib_init(&s->_sound._songlib); - seeker = NULL; - } + seeker = s->_sound._songlib._lib; while (seeker) { SongIterator *base, *ff; int oldstatus; SongIterator::Message msg; - base = ff = build_iterator(s, seeker->resource_num, it_type, seeker->handle); - if (seeker->restore_behavior == RESTORE_BEHAVIOR_CONTINUE) - ff = new_fast_forward_iterator(base, seeker->restore_time); + base = ff = build_iterator(s, seeker->_resourceNum, it_type, seeker->_handle); + if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE) + ff = new_fast_forward_iterator(base, seeker->_restoreTime); ff->init(); - msg = SongIterator::Message(seeker->handle, SIMSG_SET_LOOPS(seeker->loops)); + msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops)); songit_handle_message(&ff, msg); - msg = SongIterator::Message(seeker->handle, SIMSG_SET_HOLD(seeker->hold)); + msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold)); songit_handle_message(&ff, msg); - oldstatus = seeker->status; - seeker->status = SOUND_STATUS_STOPPED; - seeker->it = ff; - s->_sound.sfx_song_set_status(seeker->handle, oldstatus); - seeker = seeker->next; + oldstatus = seeker->_status; + seeker->_status = SOUND_STATUS_STOPPED; + seeker->_it = ff; + s->_sound.sfx_song_set_status(seeker->_handle, oldstatus); + seeker = seeker->_next; } } @@ -729,7 +724,7 @@ void internal_stringfrag_strncpy(EngineState *s, reg_t *dest, reg_t *src, int le EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { EngineState *retval; - songlib_t temp; + SongLibrary temp; /* if (s->sound_server) { @@ -782,7 +777,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { temp = retval->_sound._songlib; retval->_sound.sfx_init(retval->resmgr, s->sfx_init_flags); retval->sfx_init_flags = s->sfx_init_flags; - song_lib_free(retval->_sound._songlib); + retval->_sound._songlib.freeSounds(); retval->_sound._songlib = temp; _reset_graphics_input(retval); @@ -803,8 +798,8 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { str = &retval->sys_strings->strings[i]; char *data = (char *)str->value; if (data) { - str->value = (reg_t *)calloc(str->max_size+1, sizeof(char)); // FIXME -- sizeof(char) or sizeof(reg_t) ?? - strncpy((char *)str->value, data, str->max_size+1); // FIXME -- strncpy or internal_stringfrag_strncpy ? + str->value = (reg_t *)calloc(str->max_size + 1, sizeof(reg_t)); + strncpy((char *)str->value, data, str->max_size + 1); // FIXME -- strncpy or internal_stringfrag_strncpy ? free(data); } } diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 74bbaa8854..fb094e00f6 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -200,6 +200,9 @@ void Kernel::mapSelectors() { FIND_SELECTOR(points); FIND_SELECTOR(syncCue); FIND_SELECTOR(syncTime); + FIND_SELECTOR(printLang); + FIND_SELECTOR(subtitleLang); + FIND_SELECTOR(parseLang); } void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { @@ -295,7 +298,7 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned int _seeker = 0; - Resource *script = _resmgr->findResource(kResourceTypeScript, scriptNumber, 0); + Resource *script = _resmgr->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0); if (!script) { sciprintf("Script not found!\n"); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 26ba01b440..a79fec2489 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -26,177 +26,23 @@ // Script debugger functionality. Absolutely not threadsafe. #include "sci/sci.h" +#include "sci/console.h" #include "sci/debug.h" #include "sci/engine/state.h" -#include "sci/engine/gc.h" -#include "sci/engine/kernel_types.h" -#include "sci/engine/kernel.h" -#include "sci/engine/savegame.h" -#include "sci/gfx/gfx_widgets.h" -#include "sci/gfx/gfx_gui.h" -#include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual -#include "sci/resource.h" -#include "sci/vocabulary.h" -#include "sci/sfx/iterator.h" -#include "sci/sfx/sci_midi.h" - -#include "common/util.h" -#include "common/savefile.h" - -#include "sound/audiostream.h" namespace Sci { -int g_debugstate_valid = 0; // Set to 1 while script_debug is running -int g_debug_step_running = 0; // Set to >0 to allow multiple stepping -static bool s_debug_commands_hooked = false; // Commands hooked to the console yet? -int g_debug_seeking = 0; // Stepping forward until some special condition is met -static int s_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth -static int s_debug_seek_special = 0; // Used for special seeks(1) - -#define _DEBUG_SEEK_NOTHING 0 -#define _DEBUG_SEEK_CALLK 1 // Step forward until callk is found -#define _DEBUG_SEEK_LEVEL_RET 2 // Step forward until returned from this level -#define _DEBUG_SEEK_SPECIAL_CALLK 3 // Step forward until a /special/ callk is found -#define _DEBUG_SEEK_SO 5 // Step forward until specified PC (after the send command) and stack depth -#define _DEBUG_SEEK_GLOBAL 6 // Step forward until one specified global variable is modified - -static reg_t *p_pc; -static StackPtr *p_sp; -static StackPtr *p_pp; -static reg_t *p_objp; -static int *p_restadjust; -static SegmentId *p_var_segs; -static reg_t **p_vars; -static reg_t **p_var_base; -static int *p_var_max; // May be NULL even in valid state! - -char inputbuf[256] = ""; - -union cmd_param_t { - int32 val; - const char *str; - reg_t reg; -}; - -typedef int (*ConCommand)(EngineState *s, const Common::Array<cmd_param_t> &cmdParams); - -struct cmd_mm_entry_t { - const char *name; - const char *description; -}; // All later structures must "extend" this - -struct cmd_command_t : public cmd_mm_entry_t { - ConCommand command; - const char *param; -}; - -// Dummy function, so that it compiles -int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) { - - return 0; -} - -int c_step(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - g_debugstate_valid = 0; - if (cmdParams.size() && (cmdParams[0].val > 0)) - g_debug_step_running = cmdParams[0].val - 1; - - return 0; -} - -enum { - _parse_eoi, - _parse_token_pareno, - _parse_token_parenc, - _parse_token_nil, - _parse_token_number -}; - -int _parse_getinp(int *i, int *nr, const Common::Array<cmd_param_t> &cmdParams) { - const char *token; - - if ((unsigned)*i == cmdParams.size()) - return _parse_eoi; - - token = cmdParams[(*i)++].str; - - if (!strcmp(token, "(")) - return _parse_token_pareno; - - if (!strcmp(token, ")")) - return _parse_token_parenc; - - if (!strcmp(token, "nil")) - return _parse_token_nil; - - *nr = strtol(token, NULL, 0); - - return _parse_token_number; -} - -int _parse_nodes(EngineState *s, int *i, int *pos, int type, int nr, const Common::Array<cmd_param_t> &cmdParams) { - int nexttk, nextval, newpos, oldpos; - - if (type == _parse_token_nil) - return 0; - - if (type == _parse_token_number) { - s->parser_nodes[*pos += 1].type = PARSE_TREE_NODE_LEAF; - s->parser_nodes[*pos].content.value = nr; - return *pos; - } - if (type == _parse_eoi) { - sciprintf("Unbalanced parentheses\n"); - return -1; - } - if (type == _parse_token_parenc) { - sciprintf("Syntax error at token %d\n", *i); - return -1; - } - s->parser_nodes[oldpos = ++(*pos)].type = PARSE_TREE_NODE_BRANCH; - - nexttk = _parse_getinp(i, &nextval, cmdParams); - if ((newpos = s->parser_nodes[oldpos].content.branches[0] = _parse_nodes(s, i, pos, nexttk, nextval, cmdParams)) == -1) - return -1; - - nexttk = _parse_getinp(i, &nextval, cmdParams); - if ((newpos = s->parser_nodes[oldpos].content.branches[1] = _parse_nodes(s, i, pos, nexttk, nextval, cmdParams)) == -1) - return -1; - - if (_parse_getinp(i, &nextval, cmdParams) != _parse_token_parenc) - sciprintf("Expected ')' at token %d\n", *i); - - return oldpos; -} - -int c_set_parse_nodes(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - int i = 0; - int foo, bar; - int pos = -1; - - if (!s) { - sciprintf("Not in debug state\n"); - return 1; - } - - bar = _parse_getinp(&i, &foo, cmdParams); - if (_parse_nodes(s, &i, &pos, bar, foo, cmdParams) == -1) - return 1; - - vocab_dump_parse_tree("debug-parse-tree", s->parser_nodes); - return 0; -} - extern const char *selector_name(EngineState *s, int selector); -int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) { +DebugState debugState; + +int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { Object *obj = obj_get(s, objp); byte *selectoroffset; int selectors; if (!obj) { - sciprintf("Applied prop_ofs_to_id on non-object at %04x:%04x\n", PRINT_REG(objp)); + sciprintf("Applied propertyOffsetToId on non-object at %04x:%04x\n", PRINT_REG(objp)); return -1; } @@ -213,7 +59,7 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) { } if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) { - sciprintf("Applied prop_ofs_to_id to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n", + sciprintf("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n", prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp)); return -1; } @@ -251,7 +97,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod opsize = scr[pos.offset]; opcode = opsize >> 1; - if (!g_debugstate_valid) { + if (!debugState.isValid) { sciprintf("Not in debug state\n"); return retval; } @@ -380,11 +226,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } } - if (pos == *p_pc) { // Extra information if debugging the current opcode + if (pos == *debugState.p_pc) { // Extra information if debugging the current opcode if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) || (opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) { int prop_ofs = scr[pos.offset + 1]; - int prop_id = prop_ofs_to_id(s, prop_ofs, *p_objp); + int prop_id = propertyOffsetToId(s, prop_ofs, *debugState.p_objp); sciprintf(" (%s)", selector_name(s, prop_id)); } @@ -392,39 +238,38 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod sciprintf("\n"); - if (pos == *p_pc) { // Extra information if debugging the current opcode + if (pos == *debugState.p_pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (*p_restadjust); - int argc = ((*p_sp)[- stackframe - 1]).offset; + int stackframe = (scr[pos.offset + 2] >> 1) + (*debugState.p_restadjust); + int argc = ((*debugState.p_sp)[- stackframe - 1]).offset; if (!(s->_flags & GF_SCI0_OLD)) - argc += (*p_restadjust); + argc += (*debugState.p_restadjust); sciprintf(" Kernel params: ("); for (int j = 0; j < argc; j++) { - sciprintf("%04x:%04x", PRINT_REG((*p_sp)[j - stackframe])); + sciprintf("%04x:%04x", PRINT_REG((*debugState.p_sp)[j - stackframe])); if (j + 1 < argc) sciprintf(", "); } sciprintf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = *p_restadjust; + int restmod = *debugState.p_restadjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; - reg_t *sb = *p_sp; + reg_t *sb = *debugState.p_sp; uint16 selector; - reg_t *val_ref; reg_t fun_ref; while (stackframe > 0) { int argc = sb[- stackframe + 1].offset; const char *name = NULL; - reg_t called_obj_addr = *p_objp; + reg_t called_obj_addr = *debugState.p_objp; if (opcode == op_send) called_obj_addr = s->r_acc; else if (opcode == op_self) - called_obj_addr = *p_objp; + called_obj_addr = *debugState.p_objp; selector = sb[- stackframe].offset; @@ -435,7 +280,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod sciprintf(" %s::%s[", name, (selector > s->_kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); - switch (lookup_selector(s, called_obj_addr, selector, &val_ref, &fun_ref)) { + switch (lookup_selector(s, called_obj_addr, selector, 0, &fun_ref)) { case kSelectorMethod: sciprintf("FUNCT"); argc += restmod; @@ -467,218 +312,32 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod return retval; } -static int c_disasm_addr(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - reg_t vpc = cmdParams[0].reg; - int op_count = 1; - int do_bwc = 0; - int do_bytes = 0; - unsigned int i; - int invalid = 0; - int size; - - s->seg_manager->dereference(vpc, &size); - size += vpc.offset; // total segment size - - for (i = 1; i < cmdParams.size(); i++) { - if (!scumm_stricmp(cmdParams[i].str, "bwt")) - do_bwc = 1; - else if (!scumm_stricmp(cmdParams[i].str, "bc")) - do_bytes = 1; - else if (toupper(cmdParams[i].str[0]) == 'C') - op_count = atoi(cmdParams[i].str + 1); - else { - invalid = 1; - sciprintf("Invalid option '%s'\n", cmdParams[i].str); - } - } - - if (invalid || op_count < 0) - return invalid; - - do { - vpc = disassemble(s, vpc, do_bwc, do_bytes); - - } while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--op_count)); - return 0; -} - -static int c_disasm(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - Object *obj = obj_get(s, cmdParams[0].reg); - int selector_id = s->_kernel->findSelector(cmdParams[1].str); - reg_t addr; - - if (!obj) { - sciprintf("Not an object."); - return 1; - } - - if (selector_id < 0) { - sciprintf("Not a valid selector name."); - return 1; - } - - if (lookup_selector(s, cmdParams[0].reg, selector_id, NULL, &addr) != kSelectorMethod) { - sciprintf("Not a method."); - return 1; - } - - do { - addr = disassemble(s, addr, 0, 0); - } while (addr.offset > 0); - - return 0; -} - -static int c_sg(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - g_debug_seeking = _DEBUG_SEEK_GLOBAL; - s_debug_seek_special = cmdParams[0].val; - g_debugstate_valid = 0; - - return 0; -} - -static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - int callk_index; - char *endptr; - - if (!g_debugstate_valid) { - sciprintf("Not in debug state\n"); - return 1; - } - - if (cmdParams.size() > 0) { - /* Try to convert the parameter to a number. If the conversion stops - before end of string, assume that the parameter is a function name - and scan the function table to find out the index. */ - callk_index = strtoul(cmdParams [0].str, &endptr, 0); - if (*endptr != '\0') { - callk_index = -1; - for (uint i = 0; i < s->_kernel->getKernelNamesSize(); i++) - if (cmdParams [0].str == s->_kernel->getKernelName(i)) { - callk_index = i; - break; - } - - if (callk_index == -1) { - sciprintf("Unknown kernel function '%s'\n", cmdParams[0].str); - return 1; - } - } - - g_debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK; - s_debug_seek_special = callk_index; - g_debugstate_valid = 0; - } else { - g_debug_seeking = _DEBUG_SEEK_CALLK; - g_debugstate_valid = 0; - } - - return 0; -} - -static int c_sret(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - g_debug_seeking = _DEBUG_SEEK_LEVEL_RET; - s_debug_seek_level = s->_executionStack.size()-1; - g_debugstate_valid = 0; - return 0; -} - -static int c_go(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - g_debug_seeking = 0; - g_debugstate_valid = 0; - return 0; -} - -static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - reg_t object = cmdParams[0].reg; - const char *selector_name = cmdParams[1].str; - StackPtr stackframe = s->_executionStack.front().sp; - int selector_id; - unsigned int i; - ExecStack *xstack; - Object *o; - reg_t *vptr; - reg_t fptr; - - selector_id = s->_kernel->findSelector(selector_name); - - if (selector_id < 0) { - sciprintf("Unknown selector: \"%s\"\n", selector_name); - return 1; - } - - o = obj_get(s, object); - if (o == NULL) { - sciprintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); - return 1; - } - - SelectorType selector_type = lookup_selector(s, object, selector_id, &vptr, &fptr); - - if (selector_type == kSelectorNone) { - sciprintf("Object does not support selector: \"%s\"\n", selector_name); - return 1; - } - - stackframe[0] = make_reg(0, selector_id); - stackframe[1] = make_reg(0, cmdParams.size() - 2); - - for (i = 2; i < cmdParams.size(); i++) - stackframe[i] = cmdParams[i].reg; - - xstack = add_exec_stack_entry(s, fptr, - s->_executionStack.front().sp + cmdParams.size(), - object, cmdParams.size() - 2, - s->_executionStack.front().sp - 1, 0, object, - s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->selector = selector_id; - xstack->type = selector_type == kSelectorVariable ? EXEC_STACK_TYPE_VARSELECTOR : EXEC_STACK_TYPE_CALL; - - // Now commit the actual function: - xstack = send_selector(s, object, object, stackframe, cmdParams.size() - 2, stackframe); - - xstack->sp += cmdParams.size(); - xstack->fp += cmdParams.size(); - - s->_executionStackPosChanged = true; - - return 0; -} - -// Breakpoint commands - -int c_se(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { - g_stop_on_event = 1; - g_debugstate_valid = 0; - - return 0; -} void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, int *restadjust, SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) { // Do we support a separate console? - int old_debugstate = g_debugstate_valid; - - p_var_segs = segids; - p_vars = variables; - p_var_max = variables_nr; - p_var_base = variables_base; - p_pc = pc; - p_sp = sp; - p_pp = pp; - p_objp = objp; - p_restadjust = restadjust; + bool old_debugstate = debugState.isValid; + + debugState.p_var_segs = segids; + debugState.p_vars = variables; + debugState.p_var_max = variables_nr; + debugState.p_var_base = variables_base; + debugState.p_pc = pc; + debugState.p_sp = sp; + debugState.p_pp = pp; + debugState.p_objp = objp; + debugState.p_restadjust = restadjust; sciprintf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); - g_debugstate_valid = 1; + debugState.isValid = true; disassemble(s, *pc, 0, 1); - if (g_debug_seeking == _DEBUG_SEEK_GLOBAL) - sciprintf("Global %d (0x%x) = %04x:%04x\n", s_debug_seek_special, - s_debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[s_debug_seek_special])); + if (debugState.seeking == kDebugSeekGlobal) + sciprintf("Global %d (0x%x) = %04x:%04x\n", debugState.seekSpecial, + debugState.seekSpecial, PRINT_REG(s->script_000->locals_block->_locals[debugState.seekSpecial])); - g_debugstate_valid = old_debugstate; + debugState.isValid = old_debugstate; - if (g_debug_seeking && !bp) { // Are we looking for something special? + if (debugState.seeking && !bp) { // Are we looking for something special? MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); if (mobj) { @@ -690,86 +349,65 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1]; int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1)); - switch (g_debug_seeking) { - case _DEBUG_SEEK_SPECIAL_CALLK: - if (paramb1 != s_debug_seek_special) + switch (debugState.seeking) { + case kDebugSeekSpecialCallk: + if (paramb1 != debugState.seekSpecial) return; - case _DEBUG_SEEK_CALLK: { + case kDebugSeekCallk: { if (op != op_callk) return; break; } - case _DEBUG_SEEK_LEVEL_RET: { - if ((op != op_ret) || (s_debug_seek_level < (int)s->_executionStack.size()-1)) + case kDebugSeekLevelRet: { + if ((op != op_ret) || (debugState.seekLevel < (int)s->_executionStack.size()-1)) return; break; } - case _DEBUG_SEEK_GLOBAL: + case kDebugSeekGlobal: if (op < op_sag) return; if ((op & 0x3) > 1) return; // param or temp if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 - if (paramf1 != s_debug_seek_special) + if (paramf1 != debugState.seekSpecial) return; // CORRECT global? break; + case kDebugSeekSO: + // FIXME: Unhandled? + break; + + case kDebugSeekNothing: + // FIXME: Unhandled? + break; } - g_debug_seeking = _DEBUG_SEEK_NOTHING; + debugState.seeking = kDebugSeekNothing; // OK, found whatever we were looking for } } - g_debugstate_valid = (g_debug_step_running == 0); - - if (g_debugstate_valid) { - p_pc = pc; - p_sp = sp; - p_pp = pp; - p_objp = objp; - p_restadjust = restadjust; - p_var_segs = segids; - p_vars = variables; - p_var_max = variables_nr; - p_var_base = variables_base; + debugState.isValid = (debugState.runningStep == 0); + + if (debugState.isValid) { + debugState.p_pc = pc; + debugState.p_sp = sp; + debugState.p_pp = pp; + debugState.p_objp = objp; + debugState.p_restadjust = restadjust; + debugState.p_var_segs = segids; + debugState.p_vars = variables; + debugState.p_var_max = variables_nr; + debugState.p_var_base = variables_base; sciprintf("Step #%d\n", script_step_counter); disassemble(s, *pc, 0, 1); - - if (!s_debug_commands_hooked) { - s_debug_commands_hooked = true; - - con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n" - " s 4\n\n Execute 4 commands\n\n s\n\n Execute next command"); - con_hook_command(c_disasm_addr, "disasm-addr", "!as*", "Disassembles one or more commands\n\n" - "USAGE\n\n disasm-addr [startaddr] <options>\n\n" - " Valid options are:\n" - " bwt : Print byte/word tag\n" - " c<x> : Disassemble <x> bytes\n" - " bc : Print bytecode\n\n"); - con_hook_command(c_disasm, "disasm", "!as", "Disassembles a method by name\n\nUSAGE\n\n disasm <obj> <method>\n\n"); - con_hook_command(c_snk, "snk", "s*", "Steps forward until it hits the next\n callk operation.\n" - " If invoked with a parameter, it will\n look for that specific callk.\n"); - con_hook_command(c_se, "se", "", "Steps forward until an SCI event is received.\n"); - con_hook_command(c_send, "send", "!asa*", "Sends a message to an object\nExample: send ?fooScript cue"); - con_hook_command(c_sret, "sret", "", "Steps forward until ret is called\n on the current execution stack\n level."); - con_hook_command(c_go, "go", "", "Executes the script.\n"); - con_hook_command(c_set_parse_nodes, "set_parse_nodes", "s*", "Sets the contents of all parse nodes.\n" - " Input token must be separated by\n blanks."); - con_hook_command(c_sg, "sg", "!i", - "Steps until the global variable with the\n" - "specified index is modified.\n\nSEE ALSO\n\n" - " s.1, snk.1, so.1, bpx.1"); - } // If commands were not hooked up } - if (g_debug_step_running) - g_debug_step_running--; } } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index dcf7180501..2227167673 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -129,8 +129,8 @@ Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg } void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { - Resource *script = s->resmgr->findResource(kResourceTypeScript, script_nr, 0); - Resource *heap = s->resmgr->findResource(kResourceTypeHeap, script_nr, 0); + Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); + Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); scr.script_size = script->size; scr.heap_size = 0; // Set later @@ -430,7 +430,7 @@ void SegManager::heapRelocate(reg_t block) { #define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, NULL_REG)) -reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller); +reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller); Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) { Object *obj; diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index dc91d60e69..a41d820014 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -45,29 +45,38 @@ namespace Sci { class SegManager : public Common::Serializable { public: - // Initialize the segment manager + /** + * Initialize the segment manager + */ SegManager(bool sci1_1); - // Deallocate all memory associated with the segment manager + /** + * Deallocate all memory associated with the segment manager + */ ~SegManager(); virtual void saveLoadWithSerializer(Common::Serializer &ser); // 1. Scripts - // Allocate a script into the segment manager - // Parameters: (int) script_nr: number of the script to load - // (state_t *) s: The state containing resource manager handlers to load the - // script data - // Returns : (int) 0 on failure, 1 on success - // (int) *seg_id: The segment ID of the newly allocated segment, on success + /** + * Allocate a script into the segment manager + * @param s The state containing resource manager + * handlers to load the script data + * @param script_nr The number of the script to load + * @param seg_id The segment ID of the newly allocated segment, + * on success + * @return 0 on failure, 1 on success + */ Script *allocateScript(EngineState *s, int script_nr, SegmentId *seg_id); // The script must then be initialised; see section (1b.), below. - // Forcefully deallocate a previously allocated script - // Parameters: (int) script_nr: number of the script to deallocate - // Returns : (int) 1 on success, 0 on failure + /** + * Forcefully deallocate a previously allocated script + * @param script_nr number of the script to deallocate + * @return 1 on success, 0 on failure + */ int deallocateScript(int script_nr); /** @@ -76,30 +85,40 @@ public: */ bool scriptIsLoaded(SegmentId seg); - // Validate whether the specified public function is exported by the script in the specified segment - // Parameters: (int) pubfunct: Index of the function to validate - // (int) seg: Segment ID of the script the check is to be performed for - // Returns : (uint16) 0 if the public function is invalid, its offset into the script's segment - // otherwise + /** + * Validate whether the specified public function is exported by + * the script in the specified segment + * @param pubfunct Index of the function to validate + * @param seg Segment ID of the script the check is to + * be performed for + * @return NULL if the public function is invalid, its + * offset into the script's segment otherwise + */ uint16 validateExportFunc(int pubfunct, SegmentId seg); - // Get the segment ID associated with a script number - // Parameters: (int) script_nr: Number of the script to look up - // Returns : (int) The associated segment ID, or -1 if no matching segment exists + /** + * Get the segment ID associated with a script number + * @param script_nr Number of the script to look up + * @return The associated segment ID, or -1 if no + * matching segment exists + */ SegmentId segGet(int script_nr) const; /** - * Return a pointer to the specified script. If the id is invalid, does not refer - * to a script or the script is not loaded, this will invoke error(). + * Return a pointer to the specified script. + * If the id is invalid, does not refer to a script or the script is + * not loaded, this will invoke error(). * @param seg ID of the script segment to check for - * @return pointer to the Script object + * @return A pointer to the Script object */ Script *getScript(SegmentId seg); /** - * Return a pointer to the specified script. If the id is invalid, does not refer + * Return a pointer to the specified script. + * If the id is invalid, does not refer to a script, or + * the script is not loaded, this will return NULL * @param seg ID of the script segment to check for - * @return pointer to the Script object, or NULL + * @return A pointer to the Script object, or NULL */ Script *getScriptIfLoaded(SegmentId seg); @@ -112,51 +131,70 @@ public: // to be used during script instantiation, // i.e. loading and linking. - // Initializes a script's local variable block - // Parameters: (SegmentId) seg: Segment containing the script to initialize - // (int) nr: Number of local variables to allocate - // All variables are initialized to zero. + /** + * Initializes a script's local variable block + * All variables are initialized to zero. + * @param seg Segment containing the script to initialize + * @param nr Number of local variables to allocate + */ void scriptInitialiseLocalsZero(SegmentId seg, int nr); - // Initializes a script's local variable block according to a prototype - // Parameters: (reg_t) location: Location to initialize from + /** + * Initializes a script's local variable block according to a prototype + * @param location Location to initialize from + */ void scriptInitialiseLocals(reg_t location); - // Initializes an object within the segment manager - // Parameters: (reg_t) obj_pos: Location (segment, offset) of the object - // Returns : (Object *) A newly created Object describing the object - // obj_pos must point to the beginning of the script/class block (as opposed - // to what the VM considers to be the object location) - // The corresponding Object is stored within the relevant script. + /** + * Initializes an object within the segment manager + * @param obj_pos Location (segment, offset) of the object. It must + * point to the beginning of the script/class block + * (as opposed to what the VM considers to be the + * object location) + * @returns A newly created Object describing the object, + * stored within the relevant script + */ Object *scriptObjInit(EngineState *s, reg_t obj_pos); - // Informs the segment manager that a code block must be relocated - // Parameters: (reg_t) location: Start of block to relocate + /** + * Informs the segment manager that a code block must be relocated + * @param location Start of block to relocate + */ void scriptAddCodeBlock(reg_t location); - // Tells the segment manager whether exports are wide (32-bit) or not. - // Parameters: (int) flag: 1 if exports are wide, 0 otherwise + /** + * Tells the segment manager whether exports are wide (32-bit) or not. + * @param flag 1 if exports are wide, 0 otherwise + */ void setExportWidth(int flag); - // Processes a relocation block witin a script - // Parameters: (reg_t) obj_pos: Location (segment, offset) of the block - // Returns : (Object *) Location of the relocation block - // This function is idempotent, but it must only be called after all - // objects have been instantiated, or a run-time error will occur. + /** + * Processes a relocation block witin a script + * This function is idempotent, but it must only be called after all + * objects have been instantiated, or a run-time error will occur. + * @param obj_pos Location (segment, offset) of the block + * @return Location of the relocation block + */ void scriptRelocate(reg_t block); - // Determines whether the script referenced by the indicated segment is marked as being deleted. - // Parameters: (SegmentId) Segment ID of the script to investigate - // Returns : (int) 1 iff seg points to a script and the segment is deleted, 0 otherwise - // Will return 0 when applied to an invalid or non-script seg. + /** + * Determines whether the script referenced by the indicated segment + * is marked as being deleted. + * Will return 0 when applied to an invalid or non-script seg. + * @param seg Segment ID of the script to investigate + * @return 1 iff seg points to a script and the segment is + * deleted, 0 otherwise + */ bool scriptIsMarkedAsDeleted(SegmentId seg); // 2. Clones - // Allocate a fresh clone - // Returns : (Clone*): Reference to the memory allocated for the clone - // (reg_t) *addr: The offset of the freshly allocated clone + /** + * Allocate a fresh clone + * @param addr The offset of the freshly allocated clone + * @return Reference to the memory allocated for the clone + */ Clone *alloc_Clone(reg_t *addr); @@ -166,76 +204,96 @@ public: // 4. Stack - // Allocates a data stack - // Parameters: (int) size: Number of stack entries to reserve - // Returns : (DataStack *): The physical stack - // (SegmentId) segid: Segment ID of the stack + /** + * Allocates a data stack + * @param size Number of stack entries to reserve + * @param segid Segment ID of the stack + * @return The physical stack + */ DataStack *allocateStack(int size, SegmentId *segid); // 5. System Strings - // Allocates a system string table - // Returns : (DataStack *): The physical stack - // (SegmentId) segid: Segment ID of the stack - // See also sys_string_acquire(); + /** + * Allocates a system string table + * See also sys_string_acquire(); + * @param[in] segid Segment ID of the stack + * @returns The physical stack + */ SystemStrings *allocateSysStrings(SegmentId *segid); // 5. System Strings - // Allocates a string fragments segment - // Returns : (SegmentId): Segment ID to use for string fragments - // See also stringfrag.h + /** + * Allocates a string fragments segment + * See also stringfrag.h + * @return Segment ID to use for string fragments + */ SegmentId allocateStringFrags(); // 6, 7. Lists and Nodes - // Allocate a fresh list - // Returns : (listY_t*): Reference to the memory allocated for the list - // (reg_t) *addr: The offset of the freshly allocated list + /** + * Allocate a fresh list + * @param[in] addr The offset of the freshly allocated list + * @return Reference to the memory allocated for the list + */ List *alloc_List(reg_t *addr); - // Allocate a fresh node - // Returns : (node_t*): Reference to the memory allocated for the node - // (reg_t) *addr: The offset of the freshly allocated node + /** + * Allocate a fresh node + * @param[in] addr The offset of the freshly allocated node + * @return Reference to the memory allocated for the node + */ Node *alloc_Node(reg_t *addr); // 8. Hunk Memory - // Allocate a fresh chunk of the hunk - // Parameters: (int) size: Number of bytes to allocate for the hunk entry - // (const char *) hunk_type: A descriptive string for the hunk entry, - // for debugging purposes - // Returns : (Hunk *): Reference to the memory allocated for the hunk piece - // (reg_t) *addr: The offset of the freshly allocated hunk entry + /** + * Allocate a fresh chunk of the hunk + * @param[in] size Number of bytes to allocate for the hunk entry + * @param[in] hunk_type A descriptive string for the hunk entry, for + * debugging purposes + * @param[out] addr The offset of the freshly allocated hunk entry + * @return Reference to the memory allocated for the hunk + * piece + */ Hunk *alloc_hunk_entry(const char *hunk_type, int size, reg_t *addr); - // Deallocates a hunk entry - // Parameters: (reg_t) addr: Offset of the hunk entry to delete + /** + * Deallocates a hunk entry + * @param[in] addr Offset of the hunk entry to delete + */ void free_hunk_entry(reg_t addr); // 9. Dynamic Memory - // Allocate some dynamic memory - // Parameters: (int) size: Number of bytes to allocate - // (const char_ *) description: A descriptive string, - // for debugging purposes - // Returns : (unsigned char*): Raw pointer into the allocated dynamic memory - // (reg_t) *addr: The offset of the freshly allocated X + /** + * Allocate some dynamic memory + * @param[in] size Number of bytes to allocate + * @param[in] description A descriptive string for debugging purposes + * @param[out] addr The offset of the freshly allocated X + * @return Raw pointer into the allocated dynamic + * memory + */ unsigned char *allocDynmem(int size, const char *description, reg_t *addr); - // Deallocates a piece of dynamic memory - // Parameters: (reg_t) addr: Offset of the dynmem chunk to free + /** + * Deallocates a piece of dynamic memory + * @param[in] addr Offset of the dynmem chunk to free + */ int freeDynmem(reg_t addr); - // Gets the description of a dynmem segment - // Parameters: (reg_t) addr: Segment to describe - // Returns : (const char *): Pointer to the descriptive string set in - // allocDynmem + /** + * Gets the description of a dynmem segment + * @param[in] addr Segment to describe + * @return Pointer to the descriptive string set in allocDynmem + */ const char *getDescription(reg_t addr); @@ -251,10 +309,12 @@ public: // Generic Operations on Segments and Addresses - // Dereferences a raw memory pointer - // Parameters: (reg_t) reg: The reference to dereference - // Returns : (byte *) The data block referenced - // (int) size: (optionally) the theoretical maximum size of it + /** + * Dereferences a raw memory pointer + * @param[in] reg The reference to dereference + * @param[out] size (optional) The theoretical maximum size + * @return The data block referenced + */ byte *dereference(reg_t reg, int *size); @@ -266,17 +326,17 @@ public: int initialiseScript(Script &scr, EngineState *s, int script_nr); private: - IntMapper *id_seg_map; // id - script id; seg - index of heap + IntMapper *id_seg_map; ///< id - script id; seg - index of heap public: // TODO: make private Common::Array<MemObject *> _heap; int reserved_id; int exports_wide; bool isSci1_1; - SegmentId Clones_seg_id; // ID of the (a) clones segment - SegmentId Lists_seg_id; // ID of the (a) list segment - SegmentId Nodes_seg_id; // ID of the (a) node segment - SegmentId Hunks_seg_id; // ID of the (a) hunk segment + SegmentId Clones_seg_id; ///< ID of the (a) clones segment + SegmentId Lists_seg_id; ///< ID of the (a) list segment + SegmentId Nodes_seg_id; ///< ID of the (a) node segment + SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment private: MemObject *allocNonscriptSegment(MemObjectType type, SegmentId *segid); @@ -295,11 +355,12 @@ private: Object *scriptObjInit0(EngineState *s, reg_t obj_pos); Object *scriptObjInit11(EngineState *s, reg_t obj_pos); - /* Check segment validity - ** Parameters: (int) seg: The segment to validate - ** Returns : (bool) false if 'seg' is an invalid segment - ** true if 'seg' is a valid segment - */ + /** + * Check segment validity + * @param[in] seg The segment to validate + * @return false if 'seg' is an invalid segment, true if + * 'seg' is a valid segment + */ bool check(SegmentId seg); void dbgPrint(const char* msg, void *i); // for debug only diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 0e4b63acee..e618077d54 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -123,7 +123,76 @@ EngineState::~EngineState() { } uint16 EngineState::currentRoomNumber() const { - return KP_UINT(script_000->locals_block->_locals[13]); + return script_000->locals_block->_locals[13].toUint16(); +} + +kLanguage EngineState::charToLanguage(const char c) const { + switch (c) { + case 'F': + return K_LANG_FRENCH; + case 'S': + return K_LANG_SPANISH; + case 'I': + return K_LANG_ITALIAN; + case 'G': + return K_LANG_GERMAN; + case 'J': + case 'j': + return K_LANG_JAPANESE; + case 'P': + return K_LANG_PORTUGUESE; + default: + return K_LANG_NONE; + } +} + +Common::String EngineState::getLanguageString(const char *str, kLanguage lang) const { + kLanguage secondLang = K_LANG_NONE; + + const char *seeker = str; + while (*seeker) { + if ((*seeker == '%') || (*seeker == '#')) { + secondLang = charToLanguage(*(seeker + 1)); + + if (secondLang != K_LANG_NONE) + break; + } + + seeker++; + } + + if ((secondLang == K_LANG_JAPANESE) && (*(seeker + 1) == 'J')) { + // FIXME: Add Kanji support + lang = K_LANG_ENGLISH; + } + + if (secondLang == lang) + return Common::String(seeker + 2); + + if (seeker) + return Common::String(str, seeker - str); + else + return Common::String(str); +} + +Common::String EngineState::strSplit(const char *str, const char *sep) { + EngineState *s = this; + + kLanguage lang = (kLanguage)GET_SEL32V(s->game_obj, printLang); + kLanguage subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang); + + // Use English when no language settings are present in the game + if (lang == K_LANG_NONE) + lang = K_LANG_ENGLISH; + + Common::String retval = getLanguageString(str, lang); + + if ((subLang != K_LANG_NONE) && (sep != NULL)) { + retval += sep; + retval += getLanguageString(str, subLang); + } + + return retval; } } // End of namespace Sci diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 15c1c2e63e..ecfb9fe6f7 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -88,6 +88,18 @@ enum { SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE = 4 }; +/** Supported languages */ +enum kLanguage { + K_LANG_NONE = 0, + K_LANG_ENGLISH = 1, + K_LANG_FRENCH = 33, + K_LANG_SPANISH = 34, + K_LANG_ITALIAN = 39, + K_LANG_GERMAN = 49, + K_LANG_JAPANESE = 81, + K_LANG_PORTUGUESE = 351 +}; + struct drawn_pic_t { int nr; int palette; @@ -209,6 +221,16 @@ public: uint16 currentRoomNumber() const; + /** + * Processes a multilanguage string based on the current language settings and + * returns a string that is ready to be displayed. + * @param str the multilanguage string + * @param sep optional seperator between main language and subtitle language, + * if NULL is passed no subtitle will be added to the returned string + * @return processed string + */ + Common::String strSplit(const char *str, const char *sep = "\r----------\r"); + /* Debugger data: */ Breakpoint *bp_list; /**< List of breakpoints */ int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */ @@ -239,6 +261,10 @@ public: Kernel *_kernel; EngineState *successor; /**< Successor of this state: Used for restoring */ + +private: + kLanguage charToLanguage(const char c) const; + Common::String getLanguageString(const char *str, kLanguage lang) const; }; /** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fd8ce33f51..92f890512a 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -50,7 +50,6 @@ int script_abort_flag = 0; // Set to 1 to abort execution. Set to 2 to force a r int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars - static bool breakpointFlag = false; // FIXME: Avoid non-const global vars static reg_t _dummy_register; // FIXME: Avoid non-const global vars @@ -187,13 +186,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define OBJ_PROPERTY(o, p) (validate_property(o, p)) -int script_error(EngineState *s, const char *file, int line, const char *reason) { - error("Script error in file %s, line %d: %s\n", file, line, reason); - return 0; -} -#define CORE_ERROR(area, msg) script_error(s, "[" area "] " __FILE__, __LINE__, msg) - -reg_t get_class_address(EngineState *s, int classnr, int lock, reg_t caller) { +reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller) { if (NULL == s) { warning("vm.c: get_class_address(): NULL passed for \"s\""); @@ -280,10 +273,10 @@ static void _exec_varselectors(EngineState *s) { ExecStack &xs = s->_executionStack.back(); // varselector access? if (xs.argc) { // write? - *(xs.addr.varp) = xs.variables_argp[1]; + *(xs.getVarPointer(s)) = xs.variables_argp[1]; } else // No, read - s->r_acc = *(xs.addr.varp); + s->r_acc = *(xs.getVarPointer(s)); s->_executionStack.pop_back(); } @@ -294,7 +287,6 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt // Returns a pointer to the TOS exec_stack element assert(s); - reg_t *varp; reg_t funcp; int selector; int argc; @@ -310,8 +302,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt argc = validate_arithmetic(*argp); if (argc > 0x800) { // More arguments than the stack could possibly accomodate for - CORE_ERROR("SEND", "More than 0x800 arguments to function call\n"); - return NULL; + error("send_selector(): More than 0x800 arguments to function call"); } // Check if a breakpoint is set on this method @@ -341,6 +332,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt sciprintf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, s->_selectorNames[selector].c_str()); #endif // VM_DEBUG_SEND + ObjVarRef varp; switch (lookup_selector(s, send_obj, selector, &varp, &funcp)) { case kSelectorNone: // WORKAROUND: LSL6 tries to access the invalid 'keep' selector of the game object. @@ -377,7 +369,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt #endif { // Argument is supplied -> Selector should be set if (print_send_action) { - reg_t oldReg = *varp; + reg_t oldReg = *varp.getPointer(s); reg_t newReg = argp[1]; sciprintf("[write to selector: change %04x:%04x to %04x:%04x]\n", PRINT_REG(oldReg), PRINT_REG(newReg)); @@ -396,7 +388,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt default: sciprintf("Send error: Variable selector %04x in %04x:%04x called with %04x params\n", selector, PRINT_REG(send_obj), argc); script_debug_flag = 1; // Enter debug mode - g_debug_seeking = g_debug_step_running = 0; + debugState.seeking = debugState.runningStep = 0; #endif } break; @@ -454,8 +446,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt return &(s->_executionStack.back()); } -ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, reg_t *address, int origin) { - ExecStack *xstack = add_exec_stack_entry(s, NULL_REG, address, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS); +ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) { + ExecStack *xstack = add_exec_stack_entry(s, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS); // Store selector address in sp xstack->addr.varp = address; @@ -575,8 +567,7 @@ void run_vm(EngineState *s, int restoring) { const byte *code_buf = NULL; // (Avoid spurious warning) if (!local_script) { - script_error(s, __FILE__, __LINE__, "Program Counter gone astray"); - return; + error("run_vm(): program counter gone astray (local_script pointer is null)"); } if (!restoring) @@ -606,14 +597,12 @@ void run_vm(EngineState *s, int restoring) { while (1) { byte opcode; - int old_pc_offset; - StackPtr old_sp; byte opnumber; int var_type; // See description below int var_number; - old_pc_offset = xs->addr.pc.offset; - old_sp = xs->sp; + debugState.old_pc_offset = xs->addr.pc.offset; + debugState.old_sp = xs->sp; if (s->_executionStackPosChanged) { Script *scr; @@ -688,12 +677,12 @@ void run_vm(EngineState *s, int restoring) { #ifndef DISABLE_VALIDATIONS if (xs->sp < xs->fp) - script_error(s, "[VM] "__FILE__, __LINE__, "Stack underflow"); + error("run_vm(): stack underflow"); variables_max[VAR_TEMP] = xs->sp - xs->fp; if (xs->addr.pc.offset >= code_buf_size) - script_error(s, "[VM] "__FILE__, __LINE__, "Program Counter gone astray"); + error("run_vm(): program counter gone astray"); #endif opcode = GET_OP_BYTE(); // Get opcode @@ -1048,9 +1037,9 @@ void run_vm(EngineState *s, int restoring) { if (old_xs->type == EXEC_STACK_TYPE_VARSELECTOR) { // varselector access? if (old_xs->argc) // write? - *(old_xs->addr.varp) = old_xs->variables_argp[1]; + *(old_xs->getVarPointer(s)) = old_xs->variables_argp[1]; else // No, read - s->r_acc = *(old_xs->addr.varp); + s->r_acc = *(old_xs->getVarPointer(s)); } // Not reached the base, so let's do a soft return @@ -1106,7 +1095,7 @@ void run_vm(EngineState *s, int restoring) { r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, xs->addr.pc); if (!r_temp.segment) - CORE_ERROR("VM", "Invalid superclass in object"); + error("[VM]: Invalid superclass in object"); else { s_temp = xs->sp; xs->sp -= ((opparams[1] >> 1) + restadjust); // Adjust stack @@ -1410,7 +1399,7 @@ void run_vm(EngineState *s, int restoring) { break; default: - script_error(s, __FILE__, __LINE__, "Illegal opcode"); + error("run_vm(): illegal opcode %x", opnumber); } // switch(opcode >> 1) @@ -1424,16 +1413,7 @@ void run_vm(EngineState *s, int restoring) { opnumber); } //#endif - -#if 0 - if (script_error_flag) { - g_debug_step_running = 0; // Stop multiple execution - g_debug_seeking = 0; // Stop special seeks - xs->addr.pc.offset = old_pc_offset; - xs->sp = old_sp; - } else -#endif - ++script_step_counter; + ++script_step_counter; } } @@ -1507,7 +1487,7 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object return kSelectorNone; } -SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, reg_t **vptr, reg_t *fptr) { +SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) { Object *obj = obj_get(s, obj_location); Object *species; int index; @@ -1518,9 +1498,8 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select selector_id &= ~1; if (!obj) { - CORE_ERROR("SLC-LU", "Attempt to send to non-object or invalid script"); - sciprintf("Address was %04x:%04x\n", PRINT_REG(obj_location)); - return kSelectorNone; + error("lookup_selector(): Attempt to send to non-object or invalid script. Address was %04x:%04x", + PRINT_REG(obj_location)); } if (IS_CLASS(obj)) @@ -1530,9 +1509,8 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select if (!obj) { - CORE_ERROR("SLC-LU", "Error while looking up Species class"); - sciprintf("Original address was %04x:%04x\n", PRINT_REG(obj_location)); - sciprintf("Species address was %04x:%04x\n", PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR])); + error("lookup_selector(): Error while looking up Species class.\nOriginal address was %04x:%04x. Species address was %04x:%04x\n", + PRINT_REG(obj_location), PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR])); return kSelectorNone; } @@ -1540,15 +1518,17 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select if (index >= 0) { // Found it as a variable - if (vptr) - *vptr = &obj->_variables[index]; + if (varp) { + varp->obj = obj_location; + varp->varindex = index; + } return kSelectorVariable; } return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr); } -SegmentId script_get_segment(EngineState *s, int script_nr, int load) { +SegmentId script_get_segment(EngineState *s, int script_nr, SCRIPT_GET load) { SegmentId segment; if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) @@ -1570,31 +1550,24 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) { Script *script = NULL; #ifndef DISABLE_VALIDATIONS - if (!seg) { - CORE_ERROR("EXPORTS", "Script invalid or not loaded"); - sciprintf("Script was script.%03d (0x%x)\n", - script_nr, script_nr); - return NULL_REG; - } + if (!seg) + error("script_lookup_export(): script.%03d (0x%x) is invalid or not loaded", + script_nr, script_nr); #endif script = script_locate_by_segment(s, seg); #ifndef DISABLE_VALIDATIONS - if (script - && export_index < script->exports_nr - && export_index >= 0) + if (script && export_index < script->exports_nr && export_index >= 0) #endif return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index))); #ifndef DISABLE_VALIDATIONS else { - CORE_ERROR("EXPORTS", "Export invalid or script missing "); if (!script) - sciprintf("(script.%03d missing)\n", script_nr); + error("script_lookup_export(): script.%03d missing", script_nr); else - sciprintf("(script.%03d: Sought export %d/%d)\n", - script_nr, export_index, script->exports_nr); - return NULL_REG; + error("script_lookup_export(): script.%03d: Sought invalid export %d/%d", + script_nr, export_index, script->exports_nr); } #endif } @@ -1607,9 +1580,9 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, *was_new = 1; - *script = s->resmgr->findResource(kResourceTypeScript, script_nr, 0); + *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); if (s->_version >= SCI_VERSION_1_1) - *heap = s->resmgr->findResource(kResourceTypeHeap, script_nr, 0); + *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) { sciprintf("Script 0x%x requested but not found\n", script_nr); @@ -1943,12 +1916,9 @@ static void _init_stack_base_with_selector(EngineState *s, Selector selector) { s->stack_base[1] = NULL_REG; } -EngineState *g_EngineState = 0; - -static EngineState *_game_run(EngineState *s, int restoring) { +static EngineState *_game_run(EngineState *&s, int restoring) { EngineState *successor = NULL; int game_is_finished = 0; - g_EngineState = s; do { s->_executionStackPosChanged = false; run_vm(s, (successor || restoring) ? 1 : 0); @@ -1976,7 +1946,6 @@ static EngineState *_game_run(EngineState *s, int restoring) { script_free_vm_memory(s); delete s; s = successor; - g_EngineState = s; if (script_abort_flag == 2) { sciprintf("Restarting with replay()\n"); @@ -2012,7 +1981,7 @@ int game_run(EngineState **_s) { return 1; } // and ENGAGE! - *_s = s = _game_run(s, 0); + _game_run(*_s, 0); sciprintf(" Game::play() finished.\n"); @@ -2059,11 +2028,12 @@ const char *obj_get_name(EngineState *s, reg_t pos) { return name; } + void quit_vm() { script_abort_flag = 1; // Terminate VM - g_debugstate_valid = 0; - g_debug_seeking = 0; - g_debug_step_running = 0; + debugState.isValid = false; + debugState.seeking = kDebugSeekNothing; + debugState.runningStep = 0; } void shrink_execution_stack(EngineState *s, uint size) { @@ -2075,5 +2045,15 @@ void shrink_execution_stack(EngineState *s, uint size) { s->_executionStack.erase(iter, s->_executionStack.end()); } +reg_t* ObjVarRef::getPointer(EngineState *s) const { + Object *o = obj_get(s, obj); + if (!o) return 0; + return &(o->_variables[varindex]); +} + +reg_t* ExecStack::getVarPointer(EngineState *s) const { + assert(type == EXEC_STACK_TYPE_VARSELECTOR); + return addr.varp.getPointer(s); +} } // End of namespace Sci diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 5bfbe71ce9..a3fabbe44b 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -198,13 +198,27 @@ struct selector_map_t { Selector points; /**< Used by AvoidPath() */ Selector syncCue; /**< Used by DoSync() */ - Selector syncTime; /**< Used by DoSync() */ + Selector syncTime; + + Selector printLang; /**< Used for i18n */ + Selector subtitleLang; + Selector parseLang; +}; + +// A reference to an object's variable. +// The object is stored as a reg_t, the variable as an index into _variables +struct ObjVarRef { + reg_t obj; + int varindex; + + reg_t* getPointer(EngineState *s) const; }; + struct ViewObject { reg_t obj; - reg_t *signalp; /* Used only indirectly */ - reg_t *underBitsp; /* The same goes for the handle storage */ + ObjVarRef signalp; /* Used only indirectly */ + ObjVarRef underBitsp; /* The same goes for the handle storage */ int underBits; /* Copy of the underbits: Needed for cleanup */ int x, y; @@ -231,10 +245,12 @@ enum ExecStackType { struct ExecStack { reg_t objp; reg_t sendp; /**< Pointer to the object containing the invoked method */ + union { - reg_t *varp; /**< Variable pointer for read/write access */ + ObjVarRef varp; /**< Variable pointer for r/w access */ reg_t pc; /**< Not accurate for the TOS element */ } addr; + StackPtr fp; /**< Frame pointer */ StackPtr sp; /**< Stack pointer */ int argc; @@ -246,6 +262,8 @@ struct ExecStack { Selector selector; /**< The selector which was used to call or -1 if not applicable */ int origin; /**< The stack frame position the call was made from, or -1 if it was the initial call. */ ExecStackType type; + + reg_t* getVarPointer(EngineState *s) const; }; @@ -273,8 +291,8 @@ struct Breakpoint { }; /** - * Set this to 1 to abort script execution immediately. Aborting will leave the - * debug exec stack intact. + * Set this to 1 to abort script execution immediately. Aborting will + * leave the debug exec stack intact. * Set it to 2 to force a replay afterwards. */ extern int script_abort_flag; @@ -293,31 +311,36 @@ extern int script_step_counter; /** * Executes function pubfunct of the specified script. - * Parameters: (EngineState *) s: The state which is to be executed with - * (uint16) script: The script which is called - * (uint16) pubfunct: The exported script function which is to be called - * (StackPtr) sp: Stack pointer position - * (reg_t) calling_obj: The heap address of the object which executed the call - * (uint16) argc: Number of arguments supplied - * (StackPtr) argp: Pointer to the first supplied argument - * Returns : (ExecStack *): A pointer to the new exec stack TOS entry + * @param[in] s The state which is to be executed with + * @param[in] script The script which is called + * @param[in] pubfunct The exported script function which is to + * be called + * @param[in] sp Stack pointer position + * @param[in] calling_obj The heap address of the object that + * executed the call + * @param[in] argc Number of arguments supplied + * @param[in] argp Pointer to the first supplied argument + * @return A pointer to the new exec stack TOS entry */ -ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, - uint16 argc, StackPtr argp); +ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, + StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp); /** * Executes a "send" or related operation to a selector. - * Parameters: (EngineState *) s: The EngineState to operate on - * (reg_t) send_obj: Heap address of the object to send to - * (reg_t) work_obj: Heap address of the object initiating the send - * (StackPtr) sp: Stack pointer position - * (int) framesize: Size of the send as determined by the "send" operation - * (StackPtr) argp: Pointer to the beginning of the heap block containing the - * data to be sent. This area is a succession of one or more - * sequences of [selector_number][argument_counter] and then - * "argument_counter" word entries with the parameter values. - * Returns : (ExecStack *): A pointer to the new execution stack TOS entry + * @param[in] s The EngineState to operate on + * @param[in] send_obj Heap address of the object to send to + * @param[in] work_obj Heap address of the object initiating the send + * @param[in] sp Stack pointer position + * @param[in] framesize Size of the send as determined by the "send" + * operation + * @param[in] argp Pointer to the beginning of the heap block + * containing the data to be sent. This area is a + * succession of one or more sequences of + * [selector_number][argument_counter] and then + * "argument_counter" word entries with the + * parameter values. + * @return A pointer to the new execution stack TOS entry */ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp); @@ -328,267 +351,300 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, /** * Adds an entry to the top of the execution stack. * - * @param s The state with which to execute - * @param pc The initial program counter - * @param sp The initial stack pointer - * @param objp Pointer to the beginning of the current object - * @param argc Number of parameters to call with - * @param argp Heap pointer to the first parameter - * @param selector The selector by which it was called or - * NULL_SELECTOR if n.a. For debugging. - * @param sendp Pointer to the object which the message was sent to. - * Equal to objp for anything but super. - * @param origin Number of the execution stack element this entry was created by - * (usually the current TOS number, except for multiple sends). - * @param local_segment The segment to use for local variables, - * or SCI_XS_CALLEE_LOCALS to use obj's segment. - * @return a pointer to the new exec stack TOS entry - */ -ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t objp, int argc, - StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId local_segment); + * @param[in] s The state with which to execute + * @param[in] pc The initial program counter + * @param[in] sp The initial stack pointer + * @param[in] objp Pointer to the beginning of the current object + * @param[in] argc Number of parameters to call with + * @param[in] argp Heap pointer to the first parameter + * @param[in] selector The selector by which it was called or + * NULL_SELECTOR if n.a. For debugging. + * @param[in] sendp Pointer to the object which the message was + * sent to. Equal to objp for anything but super. + * @param[in] origin Number of the execution stack element this + * entry was created by (usually the current TOS + * number, except for multiple sends). + * @param[in] local_segment The segment to use for local variables, + * or SCI_XS_CALLEE_LOCALS to use obj's segment. + * @return A pointer to the new exec stack TOS entry + */ +ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, + reg_t objp, int argc, StackPtr argp, Selector selector, + reg_t sendp, int origin, SegmentId local_segment); /** * Adds one varselector access to the execution stack. - * Parameters: (EngineState *) s: The EngineState to use - * (reg_t) objp: Pointer to the object owning the selector - * (int) argc: 1 for writing, 0 for reading - * (StackPtr) argp: Pointer to the address of the data to write -2 - * (int) selector: Selector name - * (reg_t *) address: Heap address of the selector - * (int) origin: Stack frame which the access originated from - * Returns : (ExecStack *): Pointer to the new exec-TOS element * This function is called from send_selector only. + * @param[in] s The EngineState to use + * @param[in] objp Pointer to the object owning the selector + * @param[in] argc 1 for writing, 0 for reading + * @param[in] argp Pointer to the address of the data to write -2 + * @param[in] selector Selector name + * @param[in] address Heap address of the selector + * @param[in] origin Stack frame which the access originated from + * @return Pointer to the new exec-TOS element */ -ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, - Selector selector, reg_t *address, int origin); - +ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, + StackPtr argp, Selector selector, const ObjVarRef& address, + int origin); +/** + * This function executes SCI bytecode + * It executes the code on s->heap[pc] until it hits a 'ret' operation + * while (stack_base == stack_pos). Requires s to be set up correctly. + * @param[in] s The state to use + * @param[in] restoring 1 if s has just been restored, 0 otherwise + */ void run_vm(EngineState *s, int restoring); -/* Executes the code on s->heap[pc] until it hits a 'ret' operation while (stack_base == stack_pos) -** Parameters: (EngineState *) s: The state to use -** (int) restoring: 1 if s has just been restored, 0 otherwise -** Returns : (void) -** This function will execute SCI bytecode. It requires s to be set up -** correctly. -*/ +/** + * Handles a fatal error condition + * @param[in] s The state to recover from + * @param[in] line Source code line number the error occured in + * @param[in] file File the error occured in + */ void vm_handle_fatal_error(EngineState *s, int line, const char *file); -/* Handles a fatal error condition -** Parameters: (EngineState *) s: The state to recover from -** (int) line: Source code line number the error occured in -** (const char *) file: File the error occured in -*/ - - -void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, - int *restadjust, SegmentId *segids, reg_t **variables, reg_t **variables_base, - int *variables_nr, int bp); -/* Debugger functionality -** Parameters: (EngineState *) s: The state at which debugging should take place -** (reg_t *) pc: Pointer to the program counter -** (StackPtr *) sp: Pointer to the stack pointer -** (StackPtr *) pp: Pointer to the frame pointer -** (reg_t *) objp: Pointer to the object base pointer -** (int *) restadjust: Pointer to the &rest adjustment value -** (SegmentId *) segids: four-element array containing segment IDs for locals etc. -** (reg_t **) variables: four-element array referencing registers for globals etc. -** (reg_t **) variables_base: four-element array referencing -** register bases for temps etc. -** (int *) variables_nr: four-element array giving sizes for params etc. (may be NULL) -** (int) bp: Flag, set to 1 when a breakpoint is triggered -** Returns : (void) -*/ + +/** + * Debugger functionality + * @param[in] s The state at which debugging should take + * place + * @param[in] pc Pointer to the program counter + * @param[in] sp Pointer to the stack pointer + * @param[in] pp Pointer to the frame pointer + * @param[in] objp Pointer to the object base pointer + * @param[in] restadjust Pointer to the &rest adjustment value + * @param[in] segids four-element array containing segment IDs + * for locals etc. + * @param[in] variables four-element array referencing registers + * for globals etc. + * @param[in] variables_base four-element array referencing register + * bases for temps etc. + * @param[in] variables_nr four-element array giving sizes for params + * etc. (may be NULL) + * @param[in] bp Flag, set to 1 when a breakpoint is + * triggered + */ +void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, + reg_t *objp, int *restadjust, SegmentId *segids, reg_t **variables, + reg_t **variables_base, int *variables_nr, int bp); + +/** + * Initializes a EngineState block + * @param[in] s The state to initialize + * @return 0 on success, 1 if vocab.996 (the class table) is missing + * or corrupted + */ int script_init_engine(EngineState *s); -/* Initializes a EngineState block -** Parameters: (EngineState *) s: The state to initialize -** Returns : 0 on success, 1 if vocab.996 (the class table) is missing or corrupted -*/ +/** + * Sets the gamestate's save_dir to the parameter path + * @param[in] s The state to set + * @param[in] path Path where save_dir will point to + */ void script_set_gamestate_save_dir(EngineState *s, const char *path); -/* Sets the gamestate's save_dir to the parameter path -** Parameters: (EngineState *) s: The state to set -** (const char *) path: Path where save_dir will point to -** Returns : (void) -*/ +/** + * Frees all additional memory associated with a EngineState block + * @param[in] s The EngineState whose elements should be cleared + */ void script_free_engine(EngineState *s); -/* Frees all additional memory associated with a EngineState block -** Parameters: (EngineState *) s: The EngineState whose elements should be cleared -** Returns : (void) -*/ +/** + * Frees all script memory (heap, hunk, and class tables). + * This operation is implicit in script_free_engine(), but is required for + * restoring the game state. + * @param[in] s The EngineState to free + */ void script_free_vm_memory(EngineState *s); -/* Frees all script memory (heap, hunk, and class tables). -** Parameters: (EngineState *) s: The EngineState to free -** Returns : (void) -** This operation is implicit in script_free_engine(), but is required for restoring -** the game state. -*/ - - -SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid, reg_t **vptr, reg_t *fptr); -/* Looks up a selector and returns its type and value -** Parameters: (EngineState *) s: The EngineState to use -** (reg_t) obj: Address of the object to look the selector up in -** (Selector) selectorid: The selector to look up -** Returns : (SelectorType) kSelectorNone if the selector was not found in the object or its superclasses. -** kSelectorVariable if the selector represents an object-relative variable -** kSelectorMethod if the selector represents a method -** (reg_t *) *vptr: A pointer to the storage space associated with the selector, if -** it is a variable -** (reg_t) *fptr: A reference to the function described by that selector, if it is -** a valid function selector. -** *vptr is written to iff it is non-NULL and the selector indicates a property of the object. -** *fptr is written to iff it is non-NULL and the selector indicates a member function of that object. -*/ -enum { +/** + * Looks up a selector and returns its type and value + * varindex is written to iff it is non-NULL and the selector indicates a property of the object. + * @param[in] s The EngineState to use + * @param[in] obj Address of the object to look the selector up in + * @param[in] selectorid The selector to look up + * @param[out] varp A reference to the selector, if it is a + * variable. + * @param[out] fptr A reference to the function described by that + * selector, if it is a valid function selector. + * fptr is written to iff it is non-NULL and the + * selector indicates a member function of that + * object. + * @return kSelectorNone if the selector was not found in + * the object or its superclasses. + * kSelectorVariable if the selector represents an + * object-relative variable. + * kSelectorMethod if the selector represents a + * method + */ +SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid, + ObjVarRef *varp, reg_t *fptr); + +/** + * Parameters for script_get_segment() + */ +typedef enum { SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */ SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */ SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */ -}; +} SCRIPT_GET; -SegmentId script_get_segment(EngineState *s, int script_id, int load); -/* Determines the segment occupied by a certain script -** Parameters: (EngineState *) s: The state to operate on -** (int) script_id: The script in question -** (int) load: One of SCRIPT_GET_* -** Returns : The script's segment, or 0 on failure -*/ +/** + * Determines the segment occupied by a certain script + * @param[in] s The state to operate on + * @param[in] script_id The script in question + * @param[in] load One of SCRIPT_GET_* + * @return The script's segment, or 0 on failure + */ +SegmentId script_get_segment(EngineState *s, int script_id, SCRIPT_GET load); +/** + * Looks up an entry of the exports table of a script + * @param[in] s The state to operate on + * @param[in] script_nr The script to look up in + * @param[out] export_index The index of the export entry to look up + * @return The handle + */ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index); -/* Looks up an entry of the exports table of a script -** Parameters: (EngineState *) s: The state to operate on -** (int) script_nr: The script to look up in -** Returns : (int) export_index: index of the export entry to look up -*/ +/** + * Makes sure that a script and its superclasses get loaded to the heap. + * If the script already has been loaded, only the number of lockers is + * increased. All scripts containing superclasses of this script are loaded + * recursively as well, unless 'recursive' is set to zero. The + * complementary function is "script_uninstantiate()" below. + * @param[in] s The state to operate on + * @param[in] script_nr The script number to load + * @return The script's segment ID or 0 if out of heap + */ int script_instantiate(EngineState *s, int script_nr); -/* Makes sure that a script and its superclasses get loaded to the heap -** Parameters: (EngineState *) s: The state to operate on -** (int) script_nr: The script number to load -** Returns : (int) The script's segment ID or 0 if out of heap -** If the script already has been loaded, only the number of lockers is increased. -** All scripts containing superclasses of this script aret loaded recursively as well, -** unless 'recursive' is set to zero. -** The complementary function is "script_uninstantiate()" below. -*/ - +/** + * Decreases the numer of lockers of a script and unloads it if that number + * reaches zero. + * This function will recursively unload scripts containing its + * superclasses, if those aren't locked by other scripts as well. + * @param[in] s The state to operate on + * @param[in] script_nr The script number that is requestet to be unloaded + */ void script_uninstantiate(EngineState *s, int script_nr); -/* Decreases the numer of lockers of a script and unloads it if that number reaches zero -** Parameters: (EngineState *) s: The state to operate on -** (int) script_nr: The script number that is requestet to be unloaded -** Returns : (void) -** This function will recursively unload scripts containing its superclasses, if those -** aren't locked by other scripts as well. -*/ - +/** + * Initializes an SCI game + * This function must be run before script_run() is executed. Graphics data + * is initialized iff s->gfx_state != NULL. + * @param[in] s The state to operate on + * @return 0 on success, 1 if an error occured. + */ int game_init(EngineState *s); -/* Initializes an SCI game -** Parameters: (EngineState *) s: The state to operate on -** Returns : (int): 0 on success, 1 if an error occured. -** This function must be run before script_run() is executed. -** Graphics data is initialized iff s->gfx_state != NULL. -*/ +/** + * Initializes the graphics part of an SCI game + * This function may only be called if game_init() did not initialize + * the graphics data. + * @param[in] s The state to initialize the graphics in + * @return 0 on success, 1 if an error occured + */ int game_init_graphics(EngineState *s); -/* Initializes the graphics part of an SCI game -** Parameters: (EngineState *) s: The state to initialize the graphics in -** Returns : (int) 0 on success, 1 if an error occured -** This function may only be called if game_init() did not initialize -** the graphics data. -*/ +/** + * Initializes the sound part of an SCI game + * This function may only be called if game_init() did not initialize + * the sound data. + * @param[in] s The state to initialize the sound in + * @param[in] sound_flags Flags to pass to the sound subsystem + * @return 0 on success, 1 if an error occured + */ int game_init_sound(EngineState *s, int sound_flags); -/* Initializes the sound part of an SCI game -** Parameters: (EngineState *) s: The state to initialize the sound in -** (int) sound_flags: Flags to pass to the sound subsystem -** Returns : (int) 0 on success, 1 if an error occured -** This function may only be called if game_init() did not initialize -** the graphics data. -*/ - +/** + * Runs an SCI game + * This is the main function for SCI games. It takes a valid state, loads + * script 0 to it, finds the game object, allocates a stack, and runs the + * init method of the game object. In layman's terms, this runs an SCI game. + * Note that, EngineState *s may be changed during the game, e.g. if a game + * state is restored. + * @param[in] s Pointer to the pointer of the state to operate on + * @return 0 on success, 1 if an error occured. + */ int game_run(EngineState **s); -/* Runs an SCI game -** Parameters: (EngineState **) s: Pointer to the pointer of the state to operate on -** Returns : (int): 0 on success, 1 if an error occured. -** This is the main function for SCI games. It takes a valid state, loads script 0 to it, -** finds the game object, allocates a stack, and runs the init method of the game object. -** In layman's terms, this runs an SCI game. -** By the way, *s may be changed during the game, e.g. if a game state is restored. -*/ +/** + * Restores an SCI game state and runs the game + * This restores a savegame; otherwise, it behaves just like game_run(). + * @param[in] s Pointer to the pointer of the state to + * operate on + * @param[in] savegame_name Name of the savegame to restore + * @return 0 on success, 1 if an error occured. + */ int game_restore(EngineState **s, char *savegame_name); -/* Restores an SCI game state and runs the game -** Parameters: (EngineState **) s: Pointer to the pointer of the state to operate on -** (char *) savegame_name: Name of the savegame to restore -** Returns : (int): 0 on success, 1 if an error occured. -** This restores a savegame; otherwise, it behaves just like game_run(). -*/ +/** + * Uninitializes an initialized SCI game + * This function should be run after each script_run() call. + * @param[in] s The state to operate on + * @return 0 on success, 1 if an error occured. + */ int game_exit(EngineState *s); -/* Uninitializes an initialized SCI game -** Parameters: (EngineState *) s: The state to operate on -** Returns : (int): 0 on success, 1 if an error occured. -** This function should be run after each script_run() call. -*/ +/** + * Instructs the virtual machine to abort + */ void quit_vm(); -/* Instructs the virtual machine to abort -** Paramteres: (void) -** Returns : (void) -*/ +/** + * Allocates "kernel" memory and returns a handle suitable to be passed on + * to SCI scripts + * @param[in] s Pointer to the EngineState to operate on + * @param[in] type A free-form type description string (static) + * @param[in] space The space to allocate + * @return The handle + */ reg_t kalloc(EngineState *s, const char *type, int space); -/* Allocates "kernel" memory and returns a handle suitable to be passed on to SCI scripts -** Parameters: (EngineState *) s: Pointer to the EngineState to operate on -** (const char *) type: A free-form type description string (static) -** (int) space: The space to allocate -** Returns : (reg_t) The handle -*/ +/** + * Returns a pointer to "kernel" memory based on the handle + * @param[in] s Pointer to the EngineState to operate on + * @param[in] handle The handle to use + * @return A pointer to the allocated memory + */ byte *kmem(EngineState *s, reg_t handle); -/* Returns a pointer to "kernel" memory based on the handle -** Parameters: (EngineState *) s: Pointer to the EngineState to operate on -** (reg_t) handle: The handle to use -** Returns : (byte *) A pointer to the allocated memory -*/ - +/** + * Frees all "kernel" memory associated with a handle + * @param[in] s Pointer to the EngineState to operate on + * @param[in] handle The handle to free + * @return 0 on success, 1 otherwise + */ int kfree(EngineState *s, reg_t handle); -/* Frees all "kernel" memory associated with a handle -** Parameters: (EngineState *) s: Pointer to the EngineState to operate on -** (reg_t) handle: The handle to free -** Returns : (int) 0 on success, 1 otherwise -*/ +/** + * Determines the name of an object + * @param[in] s Pointer to the EngineState to operate on + * @param[in] pos Location of the object whose name we want to inspect + * @return A name for that object, or a string describing an error + * that occured while looking it up. The string is stored + * in a static buffer and need not be freed (neither may + * it be modified). + */ const char *obj_get_name(EngineState *s, reg_t pos); -/* Determines the name of an object -** Parameters: (EngineState *) s: Pointer to the EngineState to operate on -** (reg_t) pos: Location of the object whose name we want to -** inspect -** Returns : (const char *) A name for that object, or a string describing -** an error that occured while looking it up -** The string is stored in a static buffer and need not be freed (neither -** may it be modified). -*/ +/** + * Retrieves an object from the specified location + * @param[in] s Pointer to the EngineState to operate on + * @param[in] offset The object's offset + * @return The object in question, or NULL if there is none + */ Object *obj_get(EngineState *s, reg_t offset); -/* Retrieves an object from the specified location -** Parameters: (EngineState *) s: Pointer to the EngineState to operate on -** (reg_t) offset: The object's offset -** Returns : (Object *) The object in question, or NULL if there is none -*/ +/** + * Shrink execution stack to size. + * Contains an assert it is not already smaller. + */ void shrink_execution_stack(EngineState *s, uint size); -/* Shrink execution stack to size. -** Contains an assert it is not already smaller. -*/ } // End of namespace Sci diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 40a5d464ac..cf7ba2573c 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -48,6 +48,14 @@ struct reg_t { bool operator!=(const reg_t &x) const { return (offset != x.offset) || (segment != x.segment); } + + uint16 toUint16() const { + return offset; + } + + int16 toSint16() const { + return (int16) offset; + } }; #define PRINT_REG(r) (0xffff) & (unsigned) (r).segment, (unsigned) (r).offset diff --git a/engines/sci/gfx/font.cpp b/engines/sci/gfx/font.cpp index 3aa1747cab..0f1a19f1c0 100644 --- a/engines/sci/gfx/font.cpp +++ b/engines/sci/gfx/font.cpp @@ -104,7 +104,7 @@ bool gfxr_font_calculate_size(Common::Array<TextFragment> &fragments, gfx_bitmap } if (last_breakpoint == 0) { - GFXWARN("Warning: maxsize %d too small for '%s'\n", max_width, text); + warning("[GFX] maxsize %d too small for '%s'", max_width, text); } if (last_breakpoint > maxwidth) @@ -197,7 +197,7 @@ gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int cha int colors_nr = !!fg0 + !!fg1 + !!bg; if (colors_nr == 0) { - GFXWARN("Pixmap would have zero colors, resetting!\n"); + warning("[GFX] Pixmap would have zero colors, resetting"); colors_nr = 3; hack = 1; fg0 = fg1 = bg = &dummy; diff --git a/engines/sci/gfx/font.h b/engines/sci/gfx/font.h index 935414f550..fe0d81d135 100644 --- a/engines/sci/gfx/font.h +++ b/engines/sci/gfx/font.h @@ -30,6 +30,8 @@ namespace Sci { +/** @name Font operations and stuctures */ +/** @{ */ struct TextFragment { const char *offset; @@ -39,90 +41,109 @@ struct TextFragment { TextFragment(const char *o) : offset(o), length(0) {} }; - -struct gfx_bitmap_font_t { /* gfx_bitmap_font_t: Bitmap font information */ - int ID; /* Unique resource ID */ - - int chars_nr; /* Numer of available characters */ - - int *widths; /* chars_nr character widths, in pixels */ - - int row_size; /* Byte size of each pixel row. For unscaled fonts, this is - ** always 1, 2, or 4. Otherwise, it's a multiple of 4. - */ - - int line_height; /* Height of each text line (usually identical to height) */ - int height; /* Height for all characters, in pixel rows */ - int char_size; /* Amount of memory occupied by one character in data */ - - byte *data; /* Font data, consisting of 'chars_nr' entries of 'height' rows - ** of 'row_size' bytes. For each character ch, its first byte - ** (the topmost row) is located at (data + (charsize * ch)), and - ** its pixel width is widths[ch], provided that (ch < chars_nr). - */ - +/** + * Bitmap font information. + */ +struct gfx_bitmap_font_t { + int ID; /**< Unique resource ID */ + int chars_nr; /**< Numer of available characters */ + int *widths; /**< chars_nr character widths, in pixels */ + int row_size; /** + * Byte size of each pixel row. For unscaled fonts, + * this is always 1, 2, or 4. Otherwise, it's a + * multiple of 4. + */ + int line_height; /** + * Height of each text line (usually identical to + * height) + */ + int height; /**< Height for all characters, in pixel rows */ + int char_size; /** + * Amount of memory occupied by one character + * in data + */ + byte *data; /** + * Font data, consisting of 'chars_nr' entries + * of 'height' rows of 'row_size' bytes. For each + * character ch, its first byte (the topmost row) + * is located at (data + (charsize * ch)), and its + * pixel width is widths[ch], provided that + * (ch < chars_nr). + */ }; -/*******************/ -/* Font operations */ -/*******************/ - -/* SCI0, SCI01 and SCI1 all use the same font format. */ +/** + * Font handling flags. + * + * SCI0, SCI01 and SCI1 all use the same font format. + */ enum fontFlags { - kFontCountWhitespace = 1 << 0, // In SQ3, whitespace is included in text size - kFontNoNewlines = 1 << 1, // Don't treat newline characters - kFontIgnoreLF = 1 << 2 // Interpret CR LF sequences as a single newline, rather than two + kFontCountWhitespace = 1 << 0, //!< In SQ3, whitespace is included in text size + kFontNoNewlines = 1 << 1, //!< Don't treat newline characters + kFontIgnoreLF = 1 << 2 //!< Interpret CR LF sequences as a single newline, rather than two }; +/** + * Generates a bitmap font data structure from a resource. + * + * @param[in] id Resource ID of the resulting font + * @param[in] resource Pointer to the resource data + * @param[in] size Size of the resource block + * @return The resulting font structure, or NULL on error + */ gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size); -/* Generates a bitmap font data structure from a resource -** Parameters: (int) id: Resource ID of the resulting font -** (byte *) resource: Pointer to the resource data -** (int) size: Size of the resource block -** Returns : (gfx_bitmap_font_t *) The resulting font structure, or -** NULL on error -*/ +/** + * Frees a previously allocated font structure. + * + * @param font The font to free + */ void gfxr_free_font(gfx_bitmap_font_t *font); -/* Frees a previously allocated font structure -** Parameters: (gfx_bitmap_font_t *) font: The font to free -** Returns : (void) -*/ +/** + * Calculates the size that would be occupied by drawing a specified + * text. + * + * This function assumes 320x200 mode. + * + * @param[in] font The font to calculate with + * @param[in] max_width Maximum pixel width allowed for the output + * @param[in] text The text to calculate for + * @param[in] flags Any text formatting flags + * @param[out] fragments A newly allocated array of text_fragments, + * containing the start and size of each string + * segment. + * @param[out] width The resulting width + * @param[out] height The resulting height + * @param[out] line_height Pixel height of a single line of text + * @param[out] last_offset Pixel offset after the last drawn line + * @return true if successful, false otherwise + */ bool gfxr_font_calculate_size(Common::Array<TextFragment> &fragments, gfx_bitmap_font_t *font, int max_width, const char *text, int *width, int *height, int *line_height, int *last_offset, int flags); -/* Calculates the size that would be occupied by drawing a specified text -** Parameters: (gfx_bitmap_font_t *) font: The font to calculate with -** (int) max_width: Maximum pixel width allowed for the output -** (const char *) text: The text to calculate for -** (int) flags: Any text formatting flags -** Returns : (text_fragment *) a newly allocated array of text_fragments, -** containing the start and size of each string -** segment -** (int) *width: The resulting width -** (int) *height: The resulting height -** (int) *line_height: Pixel height of a single line of text -** (int) *last_offset: Pixel offset after the last drawn line -** This function assumes 320x200 mode. -*/ - -gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text, int characters, - PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg); -/* Draws text in a specific font to a pixmap -** Parameters: (gfx_bitmap_font_t *) font: The font to use for drawing -** (char *) text: The start of the text to draw -** (int) characters: The number of characters to draw -** (gfx_pixmap_color_t *) fg0: The first foreground color -** (gfx_pixmap_color_t *) fg1: The second foreground color -** (gfx_pixmap_color_t *) bg: The background color -** Returns : (gfx_pixmap_t *) The result pixmap, or NULL on error -** The results are written to the pixmap's index buffer. Contents of the -** foreground and background fields are copied into a newly allocated font -** structure, so that the pixmap may be translated directly. -** If any of the colors is null, it will be assumed to be transparent. -** In color index mode, the specified colors have to be preallocated. -*/ + +/** + * Draws text in a specific font to a pixmap. + * + * The results are written to the pixmap's index buffer. Contents of the + * foreground and background fields are copied into a newly allocated font + * structure, so that the pixmap may be translated directly. If any of the + * colors is null, it will be assumed to be transparent. + * In color index mode, the specified colors have to be preallocated. + * + * @param[in] font The font to use for drawing + * @param[in] text The start of the text to draw + * @param[in] characters The number of characters to draw + * @param[in] fg0 The first foreground color + * @param[in] fg1 The second foreground color + * @param[in] bg The background color + * @return The result pixmap, or NULL on error + */ +gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text, + int characters, PaletteEntry *fg0, PaletteEntry *fg1, + PaletteEntry *bg); +/** @} */ } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index f905244011..04ee5a9a4b 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/system.h" +#include "graphics/cursorman.h" #include "graphics/primitives.h" #include "graphics/surface.h" @@ -284,7 +285,7 @@ byte *GfxDriver::createCursor(gfx_pixmap_t *pointer) { int GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) { if ((pointer == NULL) || (hotspot == NULL)) { - g_system->showMouse(false); + CursorMan.showMouse(false); } else { byte *cursorData = createCursor(pointer); @@ -298,8 +299,8 @@ int GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) { if (!pointer->palette) color_key = 63; - g_system->setMouseCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); - g_system->showMouse(true); + CursorMan.replaceCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); + CursorMan.showMouse(true); delete[] cursorData; cursorData = 0; diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h index 4017dc3918..cc8a5208d4 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -40,170 +40,202 @@ enum gfx_buffer_t { }; -/* Principial graphics driver architecture -** --------------------------------------- -** -** All graphics drivers must provide -** - One visual front buffer (the actually visible thing) -** - Two dynamic back buffers: -** + visual -** + priority -** - Two static buffers (containing the background image and picviews): -** + visual -** + priority -** -** The control buffer is handled outside the graphics driver architecture. -** Graphics are drawn by first setting the static buffers, then updating -** the back buffers (from the static buffers), adding all picviews and other -** widgets, and finally updating the front buffer. -** -** All coordinates refer to the scaled coordinate system. -** Invalid parameters should produce an error message. -** Support for some valid parameter values is optional (like different line -** modes). If an unsupported but valid parameter is specified, the function -** must use a reasonable default value. -*/ - +/** + * Graphics driver. + * + * Principial graphics driver architecture: + * + * All graphics drivers must provide + * - One visual front buffer (the actually visible thing) + * - Two dynamic back buffers: + * - visual + * - priority + * - Two static buffers (containing the background image and picviews): + * - visual + * - priority + * + * The control buffer is handled outside the graphics driver architecture. + * Graphics are drawn by first setting the static buffers, then updating + * the back buffers (from the static buffers), adding all picviews and other + * widgets, and finally updating the front buffer. + * + * All coordinates refer to the scaled coordinate system. + * Invalid parameters should produce an error message. + * Support for some valid parameter values is optional (like different line + * modes). If an unsupported but valid parameter is specified, the function + * must use a reasonable default value. + */ class GfxDriver { public: - /*** Initialization ***/ - + /** @name Initialization */ + /** @{ */ + /** + * Attempts to initialize a specific graphics mode. + * + * The scaling factors apply to the standard SCI resolution of 320x200 + * pixels and is used for internal representation of graphical data. + * The physical resolution set by the graphics driver may be different + * for practical reasons. + * Must also set _mode, preferably with the gfx_new_mode() function + * specified in gfx_tools.h. + * + * @param[in] xfact Horizontal scaling factor + * @param[in] yfact Vertical scaling factor + * @param[in] bytespp Any of GFX_COLOR_MODE_*. GFX_COLOR_MODE_INDEX + * implies color index mode. + * @return GFX_OK on success, GFX_ERROR if the mode could + * not be set, or GFX_FATAL if the graphics target + * is unuseable. + */ GfxDriver(int xfact, int yfact, Graphics::PixelFormat mode); - /* Attempts to initialize a specific graphics mode - ** Parameters: (int x int) xres, yres: Horizontal and vertical scaling - ** factors - ** (PixelFormat) mode: The mode to use - ** Returns : (int) GFX_OK on success, GFX_ERROR if the mode could not be - ** set, or GFX_FATAL if the graphics target is unuseable. - ** The scaling factors apply to the standard SCI resolution of 320x200 pixels - ** and is used for internal representation of graphical data. The physical - ** resolution set by the graphics driver may be different for practical - ** reasons. - ** Must also set _mode, preferably with the gfx_new_mode() function - ** specified in gfx_tools.h. - */ + /** + * Uninitializes the current graphics mode. + * + * This function frees all memory allocated by the graphics driver, + * including mode and palette information, uninstalls all console + * commands introduced by preceeding init() or init_specific() + * commands, and does any clean-up work (like closing visuals or + * returning to text mode) required by the graphics infrastructure used. + */ ~GfxDriver(); - /* Uninitializes the current graphics mode - ** This function frees all memory allocated by the graphics driver, - ** including mode and palette information, uninstalls all console commands - ** introduced by preceeding init() or init_specific() commands, and does any - ** clean-up work (like closing visuals or returning to text mode) required by - ** the graphics infrastructure used. - */ - - - /*** Drawing operations ***/ - + /** @} */ + + /** @name Drawing operations */ + /** @{ */ + + /** + * Draws a single line to the back buffer. + * + * Note that color.priority is relevant and must be drawn if + * (color.mask & GFX_MASK_PRIORITY). Support for line modes other than + * GFX_LINE_MODE_FAST is optional. For non-fine lines, the coordinates + * provided describe the upper left corner of the pixels of the line + * to draw.line_style support is optional, if + * GFX_CAPABILITY_STIPPLED_LINES is not set. + * + * @param[in] start Starting point of the line to draw + * @param[in] end End point of the line to draw + * @param[in] color The color to draw with + * @param[in] line_mode Any of the line modes + * @param[in] line_style Any of the line styles + * @return GFX_OK or GFX_FATAL + */ int drawLine(Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); - /* Draws a single line to the back buffer. - ** Parameters: (Common::Point) start: Starting point of the line to draw - ** (Common::Point) end: End point of the line to draw - ** (gfx_color_t *) color: The color to draw with - ** (int) line_mode: Any of the line modes - ** (int) line_style: Any of the line styles - ** Returns : (int) GFX_OK or GFX_FATAL - ** Note that color.priority is relevant and must be drawn if - ** (color.mask & GFX_MASK_PRIORITY). - ** Support for line modes other than GFX_LINE_MODE_FAST is optional. - ** For non-fine lines, the coordinates provided describe the upper left - ** corner of the pixels of the line to draw. - ** line_style support is optional, if GFX_CAPABILITY_STIPPLED_LINES is not - ** set. - */ + /** + * Draws a single filled and possibly shaded rectangle to the back + * buffer. + * + * Note that color.priority is relevant and must be drawn if + * (color.mask & GFX_MASK_PRIORITY). color2 is relevant only if + * shade_mode is not GFX_SHADE_FLAT. Support for shade modes other + * than GFX_SHADE_FLAT is optional. + * + * @param[in] rect The rectangle to draw + * @param[in] color1 The first color to draw with + * @param[in] color2 The second color to draw with + * @param[in] shade_mode Any of GFX_SHADE_*. + * @return GFX_OK or GFX_FATAL + */ int drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color2, gfx_rectangle_fill_t shade_mode); - /* Draws a single filled and possibly shaded rectangle to the back buffer. - ** Parameters: (rect_t *) rect: The rectangle to draw - ** (gfx_color_t *) color1, color2: The colors to draw with - ** (int) shade_mode: Any of GFX_SHADE_*. - ** Returns : (int) GFX_OK or GFX_FATAL - ** Note that color.priority is relevant and must be drawn if - ** (color.mask & GFX_MASK_PRIORITY). - ** color2 is relevant only if shade_mode is not GFX_SHADE_FLAT. - ** Support for shade modes other than GFX_SHADE_FLAT is optional. - */ - - /*** Pixmap operations ***/ - + /** @} */ + + /** @name Pixmap operations */ + /** @{ */ + + /** + * Draws part of a pixmap to the static or back buffer. + * + * @param[in] pxm The pixmap to draw + * @param[in] priority The priority to draw with, or GFX_NO_PRIORITY + * to draw on top of everything without setting the + * priority back buffer. + * @param[in] src The pixmap-relative source rectangle + * @param[in] dest The destination rectangle + * @param[in] buffer One of GFX_BUFFER_STATIC and GFX_BUFFER_BACK + * @return GFX_OK or GFX_FATAL, or GFX_ERROR if pxm was + * not (but should have been) registered. + */ int drawPixmap(gfx_pixmap_t *pxm, int priority, rect_t src, rect_t dest, gfx_buffer_t buffer); - /* Draws part of a pixmap to the static or back buffer - ** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw - ** (int) priority: The priority to draw with, or GFX_NO_PRIORITY - ** to draw on top of everything without setting the - ** priority back buffer - ** (rect_t) src: The pixmap-relative source rectangle - ** (rect_t) dest: The destination rectangle - ** (int) buffer: One of GFX_BUFFER_STATIC and GFX_BUFFER_BACK - ** Returns : (int) GFX_OK or GFX_FATAL, or GFX_ERROR if pxm was not - ** (but should have been) registered. - */ + /** + * Grabs an image from the visual or priority back buffer. + * + * This function is now mandatory. + * + * @param[in] src The rectangle to grab + * @param[in] pxm The pixmap structure the data is to be written to + * @param[in] map GFX_MASK_VISUAL or GFX_MASK_PRIORITY + * @return GFX_OK, GFX_FATAL, or GFX_ERROR for invalid map + * values pxm may be assumed to be empty and + * pre-allocated with an appropriate memory size. + */ int grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map); - /* Grabs an image from the visual or priority back buffer - ** Parameters: (rect_t) src: The rectangle to grab - ** (gfx_pixmap_t *) pxm: The pixmap structure the data is to - ** be written to - ** (int) map: GFX_MASK_VISUAL or GFX_MASK_PRIORITY - ** Returns : (int) GFX_OK, GFX_FATAL, or GFX_ERROR for invalid map values - ** pxm may be assumed to be empty and pre-allocated with an appropriate - ** memory size. - ** This function is now mandatory. - */ - - - /*** Buffer operations ***/ - + /** @} */ + + /** @name Buffer operations */ + /** @{ */ + + /** + * Updates the front buffer or the back buffers. + * + * This function updates either the visual front buffer, or the two + * back buffers, by copying the specified source region to the + * destination region. + * For heuristical reasons, it may be assumed that the x and y fields + * of src and dest will be identical in /most/ cases.If they aren't, + * the priority map will not be required to be copied. + * + * @param[in] src: Source rectangle + * @param[in] dest: Destination point + * @param[in] buffer: One of GFX_BUFFER_FRONT or GFX_BUFFER_BACK + * @return GFX_OK, GFX_ERROR or GFX_FATAL + */ int update(rect_t src, Common::Point dest, gfx_buffer_t buffer); - /* Updates the front buffer or the back buffers - ** Parameters: (rect_t) src: Source rectangle - ** (Common::Point) dest: Destination point - ** (int) buffer: One of GFX_BUFFER_FRONT or GFX_BUFFER_BACK - ** Returns : (int) GFX_OK, GFX_ERROR or GFX_FATAL - ** This function updates either the visual front buffer, or the two back - ** buffers, by copying the specified source region to the destination - ** region. - ** For heuristical reasons, it may be assumed that the x and y fields of - ** src and dest will be identical in /most/ cases. - ** If they aren't, the priority map will not be required to be copied. - */ + /** + * Sets the contents of the static visual and priority buffers. + * + * pic and priority may be modified or written to freely. They may also + * be used as the actual static buffers, since they are not freed and + * reallocated between calls to set_static_buffer() and update(), + * unless exit() was called in between. + * Note that later version of the driver interface may disallow + * modifying pic and priority. pic and priority are always scaled to + * the appropriate resolution + * + * @param[in] pic The image defining the new content of the + * visual back buffer + * @param[in] priority The priority map containing the new content of + * the priority back buffer in the index buffer + * @return GFX_OK or GFX_FATAL + */ int setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority); - /* Sets the contents of the static visual and priority buffers - ** Parameters: (gfx_pixmap_t *) pic: The image defining the new content - ** of the visual back buffer - ** (gfx_pixmap_t *) priority: The priority map containing - ** the new content of the priority back buffer - ** in the index buffer - ** Returns : (int) GFX_OK or GFX_FATAL - ** pic and priority may be modified or written to freely. They may also be - ** used as the actual static buffers, since they are not freed and re- - ** allocated between calls to set_static_buffer() and update(), unless - ** exit() was called in between. - ** Note that later version of the driver interface may disallow modifying - ** pic and priority. - ** pic and priority are always scaled to the appropriate resolution - */ - - - /*** Mouse pointer operations ***/ - + /** @} */ + + /** @name Mouse pointer operations */ + /** @{ */ + + /** + * Sets a new mouse pointer. + * + * If pointer is not NULL, it will have been scaled to the appropriate + * size and registered as a pixmap (if neccessary) beforehand. If this + * function is called for a target that supports only two-color + * pointers, the image is a color index image, where only color index + * values 0, 1, and GFX_COLOR_INDEX_TRANSPARENT are used. + * + * @param[in] pointer The pointer to set, or NULL to set no pointer. + * @param[in] hotspot The coordinates of the hotspot, or NULL to set + * no pointer. + * @return GFX_OK or GFX_FATAL + */ int setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot); - /* Sets a new mouse pointer. - ** Parameters: (gfx_pixmap_t *) pointer: The pointer to set, or NULL to set - ** no pointer - ** (Common::Point *) hotspot: The coordinates of the hotspot, - ** or NULL to set no pointer - ** Returns : (int) GFX_OK or GFX_FATAL - ** If pointer is not NULL, it will have been scaled to the appropriate - ** size and registered as a pixmap (if neccessary) beforehand. - ** If this function is called for a target that supports only two-color - ** pointers, the image is a color index image, where only color index values - ** 0, 1, and GFX_COLOR_INDEX_TRANSPARENT are used. - */ + /** @} */ gfx_mode_t *getMode() { return _mode; } byte *getVisual0() { return _visual[0]; } @@ -213,7 +245,7 @@ private: gfx_pixmap_t *_priority[2]; byte *_visual[2]; - gfx_mode_t *_mode; /* Currently active mode, NULL if no mode is active */ + gfx_mode_t *_mode; /**< Currently active mode, NULL if no mode is active */ }; } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_gui.cpp b/engines/sci/gfx/gfx_gui.cpp index f73a13d6dd..fb05c0fe29 100644 --- a/engines/sci/gfx/gfx_gui.cpp +++ b/engines/sci/gfx/gfx_gui.cpp @@ -266,7 +266,7 @@ static rect_t _move_and_extend_rect(rect_t rect, Common::Point point, int yplus) return gfx_rect(rect.x + point.x, rect.y + point.y, rect.width + 1, rect.height + yplus); } -GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, char *text, +GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, const char *text, int font, gfx_alignment_t align, char framed, char inverse, int flags, char gray_text) { gfx_color_t *color1, *color2, *bgcolor; @@ -294,7 +294,7 @@ GfxList *_sciw_add_text_to_list(GfxList *list, GfxPort *port, rect_t zone, char return list; } -GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, char selected, char inverse, char grayed_out) { +GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font, char selected, char inverse, char grayed_out) { gfx_color_t *frame_col = (inverse) ? &(port->_bgcolor) : &(port->_color); GfxList *list; @@ -332,7 +332,7 @@ GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *tex return list; } -GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, +GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font, gfx_alignment_t align, char framed, char inverse) { GfxList *list = gfxw_new_list(_move_and_extend_rect(zone, Common::Point(port->zone.x, port->zone.y), 2), 0); @@ -344,7 +344,7 @@ GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text, return _sciw_add_text_to_list(list, port, zone, text, font, align, framed, inverse, 0, port->gray_text); } -GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, unsigned int cursor, +GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, const char *text, int font, unsigned int cursor, char inverse) { GfxText *text_handle; @@ -440,7 +440,7 @@ GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, i return list; } -GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, char **entries_list, +GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, const char **entries_list, int entries_nr, int list_top, int selection, char inverse) { GfxList *list; diff --git a/engines/sci/gfx/gfx_gui.h b/engines/sci/gfx/gfx_gui.h index e712d30660..68342aa0c0 100644 --- a/engines/sci/gfx/gfx_gui.h +++ b/engines/sci/gfx/gfx_gui.h @@ -23,8 +23,6 @@ * */ -/* SCI-specific widget handling */ - #ifndef SCI_INCLUDE_SCI_WIDGETS_H #define SCI_INCLUDE_SCI_WIDGETS_H @@ -34,152 +32,196 @@ namespace Sci { class Menu; -// The following flags are applicable to windows in SCI0 +/* SCI-specific widget handling */ + +/** + * Flags for windows in SCI0. + */ enum windowFlags { - kWindowTransparent = 0x01, // 0000 0001 - kWindowNoFrame = 0x02, // 0000 0010 - a window without a frame - // Add title bar to window (10 pixels high, framed, text is centered and written in white on dark gray) - kWindowTitle = 0x04, // 0000 0100 - // bits 3-6 are unused - kWindowDontDraw = 0x80, // 1000 0000 - don't draw anything - kWindowNoDropShadow = 0x1000000, // 0001 0000 0000 0000 0000 0000 0000 (not in SCI) + kWindowTransparent = 0x01, //!< 0000 0001 + kWindowNoFrame = 0x02, //!< 0000 0010 - a window without a frame + kWindowTitle = 0x04, /** + * 0000 0100 - Add title bar to + * window (10 pixels high, framed, + * text is centered and written in + * white on dark gray), bits 3-6 + * are unused + */ + kWindowDontDraw = 0x80, //!< 1000 0000 - don't draw anything + kWindowNoDropShadow = 0x1000000, //!< 0001 0000 0000 0000 0000 0000 0000 (not in SCI) kWindowAutoRestore = 0x2000000 }; +/** Button and frame control flags. */ enum controlStateFlags { - kControlStateEnabled = 0x0001, // 0001 - enabled buttons (used by the interpreter) - kControlStateDisabled = 0x0004, // 0010 - grayed out buttons (used by the interpreter) - kControlStateFramed = 0x0008, // 1000 - widgets surrounded by a frame (used by the interpreter) - kControlStateDitherFramed = 0x1000 // 0001 0000 0000 0000 - widgets surrounded by a dithered frame (used in kgraphics) + kControlStateEnabled = 0x0001, //!< 0001 - enabled buttons (used by the interpreter) + kControlStateDisabled = 0x0004, //!< 0010 - grayed out buttons (used by the interpreter) + kControlStateFramed = 0x0008, //!< 1000 - widgets surrounded by a frame (used by the interpreter) + kControlStateDitherFramed = 0x1000 //!< 0001 0000 0000 0000 - widgets surrounded by a dithered frame (used in kgraphics) }; -void sciw_set_status_bar(EngineState *s, GfxPort *status_bar, const Common::String &text, int fgcolor, int bgcolor); -/* Sets the contents of a port used as status bar -** Parmeters: (EngineState *) s: The affected game state -** (GfxPort *) status_bar: The status bar port -** (const char *) text: The text to draw -** Returns : (void) -*/ - -GfxPort *sciw_new_window(EngineState *s, rect_t area, int font, gfx_color_t color, gfx_color_t bgcolor, - int title_font, gfx_color_t title_color, gfx_color_t title_bg_color, - const char *title, int flags); -/* Creates a new SCI style window -** Parameters: (EngineState *) s: The affected game state -** (rect_t) area: The screen area to frame (not including a potential window title) -** (int) font: Default font number to use -** (gfx_color_t) color: The foreground color to use for drawing -** (gfx_color_t) bgcolor: The background color to use -** (int) title_font: The font to use for the title bar (if any) -** (gfx_color_t) title_color: Color to use for the title bar text -** (gfx_color_t) title_bg_color: Color to use for the title bar background -** (const char *) title: The text to write into the title bar -** (int) flags: Any ORred combination of window flags -** Returns : (GfxPort *) A newly allocated port with the requested characteristics -*/ - -/*---------------------*/ -/*** Control widgets ***/ -/*---------------------*/ - -GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, char selected, char inverse, char gray); -/* Creates a new button control list -** Parameters: (GfxPort *) port: The port containing the color values to use for the -** button (the button is /not/ appended to the port there) -** (reg_t) ID: Button's ID -** (rect_t) zone: The area occupied by the button -** (char *) text: The text to write into the button -** (int) font: The font to use for the button -** (char) selected: Whether the button should be marked as being selected by the keyboard focus -** (char) inverse: Whether to inverse the color scheme -** (char) gray: Whether the button should be grayed out -** Returns : (GfxList *) The button -*/ - -GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, - gfx_alignment_t align, char frame, char inverse); -/* Creates a new text control list -** Parameters: (GfxPort *) port: The port containing the color values to use -** (reg_t) ID: Text widget ID -** (rect_t) zone: Area occupied by the text -** (char *) text: The text -** (int) font: The font the text is to be drawn in -** (gfx_alignment_t) align: Horizontal text alignment to use -** (char) frame: Whether a dithered frame should surround the text -** (char) inverse: Whether the text colors should be inversed -** Returns : (GfxList *) The text control widget list -*/ - -GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, char *text, int font, unsigned int cursor, - char inverse); -/* Creates a new edit control list -** Parameters: (GfxPort *) port: The port containing the color values to use -** (reg_t) ID: Text widget ID -** (rect_t) zone: Area occupied by the text -** (char *) text: The text -** (int) font: The font the text is to be drawn in -** (int) cursor: Cursor position -** (char) inverse: Whether the edit widget should be reversed -** Returns : (GfxList *) An appropriate widget list -*/ - -GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, int loop, int cel, - char frame, char inverse); -/* Creates a new icon control list -** Parameters: (GfxPort *) port: The port containing the color values to use -** (reg_t) ID: Text widget ID -** (rect_t) zone: Area occupied by the text -** (int x int x int) view, loop, cel: The cel to display -** (char) frame: Whether the widget should be surrounded by a frame -** (char) lina inverse: Whether colors should be inversed -** Returns : (GfxList *) An appropriate widget list -*/ - -GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr, char **entries_list, - int entries_nr, int list_top, int selection, char inverse); -/* Creates a new list control list -** Parameters: (GfxPort *) port: The port containing the color values to use -** (int) ID: Text widget ID -** (rect_t) zone: Area occupied by the text -** (int) font_nr: number of the font to use -** (char **) entries_list: List of strings to contain within the list -** (int) entries_nr: Number of entries in entries_list -** (int) list_top: First list item that is visible -** (int) selection: The list item that is selected -** (char) invserse: The usual meaning -** Returns : (GfxList *) An appropriate widget list -*/ - -/*---------------------*/ -/*** Menubar widgets ***/ -/*---------------------*/ - -void sciw_set_menubar(EngineState *s, GfxPort *status_bar, Menubar *menubar, int selection); -/* Draws the menu bar -** Parameters: (EngineState *) s: The state to operate on -** (GfxPort *) status_bar: The status bar port to modify -** (Menubar *) menubar: The menu bar to use -** (int) selection: Number of the menu to hightlight, or -1 for 'none' -** Returns : (void) -*/ - -GfxPort *sciw_new_menu(EngineState *s, GfxPort *status_bar, Menubar *menubar, int selection); -/* Creates a menu port -** Parameters: (EngineState *) s: The state to operate on -** (GfxPort *) status_bar: The status bar -** (Menubar *) menubar: The menu bar to use -** (int) selection: Number of the menu to interpret -** Returns : (GfxPort *) The result port -*/ - -GfxPort *sciw_toggle_item(GfxPort *menu_port, Menu *menu, int selection, bool selected); -/* Toggle the selection of a menu item from a menu port -** Parameters: (GfxPort *) menu_port: The port to modify -** (Menu *) menu: The menu the menu port corresponds to -** (int) selection: Number of the menu entry to unselect, or -1 to do a NOP -** (bool) selected: Whether to set the item's state to selected or not -** Returns : (GfxPort *) The modified menu -*/ +/** + * Sets the contents of a port used as status bar. + * + * @param[in] s The affected EngineState + * @param[in] status_bar The status bar port + * @param[in] text The text to draw + * @param[in] fgcolor The foreground color + * @param[in] bgcolor The background color + */ +void sciw_set_status_bar(EngineState *s, GfxPort *status_bar, + const Common::String &text, int fgcolor, int bgcolor); + +/** + * Creates a new SCI style window. + * + * @param[in] s The affected EngineState + * @param[in] area The screen area to frame (not including a + * potential window title) + * @param[in] font Default font number to use + * @param[in] color The foreground color to use for drawing + * @param[in] bgcolor The background color to use + * @param[in] title_font The font to use for the title bar (if any) + * @param[in] title_color Color to use for the title bar text + * @param[in] title_bg_color Color to use for the title bar background + * @param[in] title The text to write into the title bar + * @param[in] flags Any ORred combination of window flags + * @return A newly allocated port with the requested characteristics + */ +GfxPort *sciw_new_window(EngineState *s, rect_t area, int font, + gfx_color_t color, gfx_color_t bgcolor, int title_font, + gfx_color_t title_color, gfx_color_t title_bg_color, + const char *title, int flags); + + +/** @name Control widgets */ +/** @{ */ +/** + * Creates a new button control list. + * + * @param[in] port The port containing the color values to use for the + * button (the button is /not/ appended to the port + * there) + * @param[in] ID Button's ID + * @param[in] zone The area occupied by the button + * @param[in] text The text to write into the button + * @param[in] font The font to use for the button + * @param[in] selected Whether the button should be marked as being + * selected by the keyboard focus + * @param[in] inverse Whether to inverse the color scheme + * @param[in] gray Whether the button should be grayed out + * @return The button + */ +GfxList *sciw_new_button_control(GfxPort *port, reg_t ID, rect_t zone, + const char *text, int font, char selected, char inverse, char gray); + +/** + * Creates a new text control list. + * + * @param[in] port The port containing the color values to use + * @param[in] ID Text widget ID + * @param[in] zone Area occupied by the text + * @param[in] text The text + * @param[in] font The font the text is to be drawn in + * @param[in] align Horizontal text alignment to use + * @param[in] frame Whether a dithered frame should surround the text + * @param[in] inverse Whether the text colors should be inversed + * @return The text control widget list + */ +GfxList *sciw_new_text_control(GfxPort *port, reg_t ID, rect_t zone, + const char *text, int font, gfx_alignment_t align, char frame, + char inverse); + +/** + * Creates a new edit control list. + * + * @param[in] port The port containing the color values to use + * @param[in] ID Text widget ID + * @param[in] zone Area occupied by the text + * @param[in] text The text + * @param[in] font The font the text is to be drawn in + * @param[in] cursor Cursor position + * @param[in] inverse Whether the edit widget should be reversed + * @return An appropriate widget list + */ +GfxList *sciw_new_edit_control(GfxPort *port, reg_t ID, rect_t zone, + const char *text, int font, unsigned int cursor, char inverse); + +/** + * Creates a new icon control list. + * + * @param[in] port The port containing the color values to use + * @param[in] ID Text widget ID + * @param[in] zone Area occupied by the text + * @param[in] view The view index + * @param[in] loop The loop index + * @param[in] cel The cel to display + * @param[in] frame Whether the widget should be surrounded by a frame + * @param[in] inverse Whether colors should be inversed + * @return An appropriate widget list + */ +GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, + int view, int loop, int cel, char frame, char inverse); + +/** + * Creates a new list control list. + * + * @param[in] port: The port containing the color values to use + * @param[in] ID: Text widget ID + * @param[in] zone: Area occupied by the text + * @param[in] font_nr: Number of the font to use + * @param[in] entries_list: List of strings to contain within the list + * @param[in] entries_nr: Number of entries in entries_list + * @param[in] list_top: First list item that is visible + * @param[in] selection: The list item that is selected + * @param[in] inverse: The usual meaning + * @return An appropriate widget list + */ +GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, + int font_nr, const char **entries_list, int entries_nr, + int list_top, int selection, char inverse); +/** @} */ + +/** @name Menubar widgets */ +/** @{ */ + +/** + * Draws the menu bar. + * + * @param[in] s: The EngineState to operate on + * @param[in] status_bar: The status bar port to modify + * @param[in] menubar: The menu bar to use + * @param[in] selection: Number of the menu to hightlight, or -1 for + * 'none' + */ +void sciw_set_menubar(EngineState *s, GfxPort *status_bar, Menubar *menubar, + int selection); + +/** + * Creates a menu port. + * + * @param[in] s The state to operate on + * @param[in] status_bar The status bar + * @param[in] menubar The menu bar to use + * @param[in] selection Number of the menu to interpret + * @return The result port + */ +GfxPort *sciw_new_menu(EngineState *s, GfxPort *status_bar, + Menubar *menubar, int selection); + +/** + * Toggle the selection of a menu item from a menu port. + * + * @param[in] menu_port The port to modify + * @param[in] menu The menu the menu port corresponds to + * @param[in] selection Number of the menu entry to unselect, or -1 to do + * a NOP + * @param[in] selected Whether to set the item's state to selected or not + * @return The modified menu + */ +GfxPort *sciw_toggle_item(GfxPort *menu_port, Menu *menu, int selection, + bool selected); +/** @} */ } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_options.h b/engines/sci/gfx/gfx_options.h index 393627a1a2..2e2b853562 100644 --- a/engines/sci/gfx/gfx_options.h +++ b/engines/sci/gfx/gfx_options.h @@ -42,20 +42,20 @@ namespace Sci { -/* Dirty rectangle heuristics: */ - -/* One: Redraw one rectangle surrounding the dirty area (insert is O(1)) */ -#define GFXOP_DIRTY_FRAMES_ONE 1 - -/* Clusters: Accumulate dirty rects, merging those that overlap (insert is O(n)) */ -#define GFXOP_DIRTY_FRAMES_CLUSTERS 2 +/** Dirty rectangle heuristics. */ +enum { + GFXOP_DIRTY_FRAMES_ONE = 1, /**< One: Redraw one rectangle surrounding the dirty area (insert is O(1)) */ + GFXOP_DIRTY_FRAMES_CLUSTERS = 2 /**< Clusters: Accumulate dirty rects, merging those that overlap (insert is O(n)) */ +}; +/** + * All user options to the rendering pipeline + * + * See note in sci_conf.h for config_entry_t before changing types of + * variables + */ struct gfx_options_t { #ifdef CUSTOM_GRAPHICS_OPTIONS - /* gfx_options_t: Contains all user options to the rendering pipeline */ - /* See note in sci_conf.h for config_entry_t before changing types of - ** variables */ - int buffer_pics_nr; /* Number of unused pics to buffer */ /* SCI0 pic resource options */ diff --git a/engines/sci/gfx/gfx_res_options.h b/engines/sci/gfx/gfx_res_options.h index f01f93d21b..a595c56606 100644 --- a/engines/sci/gfx/gfx_res_options.h +++ b/engines/sci/gfx/gfx_res_options.h @@ -23,8 +23,6 @@ * */ -/* Configuration options for per-resource customisations */ - #ifndef SCI_GFX_GFX_RES_OPTIONS_H #define SCI_GFX_GFX_RES_OPTIONS_H @@ -35,13 +33,16 @@ #include "sci/gfx/gfx_resmgr.h" namespace Sci { +/** @name Configuration options for per-resource customisations */ +/** @{ */ struct gfx_res_pattern_t { int min, max; }; -/* GFX resource assignments */ - +/** + * GFX resource assignments. + */ struct gfx_res_assign_t { union { struct { @@ -52,23 +53,24 @@ struct gfx_res_assign_t { }; -/* GFX resource modifications */ - +/** + * GFX resource modifications/ + */ struct gfx_res_conf_t { - int type; /* Resource type-- only one allowed */ + int type; /**< Resource type-- only one allowed */ /* If any of the following is 0, it means that there is no restriction. ** Otherwise, one of the patterns associated with them must match. */ - int patterns_nr; /* Number of patterns (only 'view' patterns for views) */ - int loops_nr, cels_nr; /* Number of loop/cel patterns, for views only. + int patterns_nr; /**< Number of patterns (only 'view' patterns for views) */ + int loops_nr, cels_nr; /**< Number of loop/cel patterns, for views only. ** For pics, loops_nr identifies the palette. */ gfx_res_pattern_t *patterns; union { gfx_res_assign_t assign; - byte factor[3]; /* divide by 16 to retrieve factor */ - } conf; /* The actual configuration */ + byte factor[3]; /**< divide by 16 to retrieve factor */ + } conf; /**< The actual configuration */ gfx_res_conf_t *next; }; @@ -84,16 +86,20 @@ struct gfx_res_fullconf_t { struct gfx_options_t; +/** + * Configures a graphical pixmap according to config options. + * + * Modifies pxm as considered appropriate by configuration options. Does + * not do anything in colour index mode. + * + * @param[in] options The options according to which configuration + * should be performed + * @param[in] pxm The pixmap to configure + * @return 0 on success, non-zero otherwise + */ int gfx_get_res_config(gfx_options_t *options, gfx_pixmap_t *pxm); -/* Configures a graphical pixmap according to config options -** Parameters: (gfx_options_t *) options: The options according to which -** configuration should be performed -** (gfx_resource_type_t) pxm: The pixmap to configure -** Returns : (int) 0 on success, non-zero otherwise -** Modifies pxm as considered appropriate by configuration options. Does -** not do anything in colour index mode. -*/ +/** @} */ } // End of namespace Sci #endif diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp index 229470a658..1b76c65ff4 100644 --- a/engines/sci/gfx/gfx_resmgr.cpp +++ b/engines/sci/gfx/gfx_resmgr.cpp @@ -59,15 +59,15 @@ GfxResManager::GfxResManager(int version, bool isVGA, gfx_options_t *options, Gf if (_version < SCI_VERSION_01_VGA || !_isVGA) { _staticPalette = gfx_sci0_pic_colors->getref(); } else if (_version == SCI_VERSION_1_1) { - GFXDEBUG("Palettes are not yet supported in this SCI version\n"); + debugC(2, kDebugLevelGraphics, "Palettes are not yet supported in this SCI version\n"); #ifdef ENABLE_SCI32 } else if (_version == SCI_VERSION_32) { - GFXDEBUG("Palettes are not yet supported in this SCI version\n"); + debugC(2, kDebugLevelGraphics, "Palettes are not yet supported in this SCI version\n"); #endif } else { - Resource *res = resManager->findResource(kResourceTypePalette, 999, 0); + Resource *res = resManager->findResource(ResourceId(kResourceTypePalette, 999), 0); if (res && res->data) - _staticPalette = gfxr_read_pal1(res->id, res->data, res->size); + _staticPalette = gfxr_read_pal1(res->id.number, res->data, res->size); } } @@ -77,7 +77,7 @@ GfxResManager::~GfxResManager() { } int GfxResManager::calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic, int flags, int default_palette, int nr) { - Resource *res = _resManager->findResource(kResourceTypePic, nr, 0); + Resource *res = _resManager->findResource(ResourceId(kResourceTypePic, nr), 0); int need_unscaled = unscaled_pic != NULL; gfxr_pic0_params_t style, basic_style; @@ -97,18 +97,18 @@ int GfxResManager::calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic if (need_unscaled) { if (_version == SCI_VERSION_1_1) - gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, _staticPalette, _portBounds); + gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id.number, _staticPalette, _portBounds); else - gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, _isVGA, _staticPalette, _portBounds); + gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id.number, _isVGA, _staticPalette, _portBounds); } if (scaled_pic && scaled_pic->undithered_buffer) memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size); if (_version == SCI_VERSION_1_1) - gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, _staticPalette, _portBounds); + gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id.number, _staticPalette, _portBounds); else - gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, _isVGA, _staticPalette, _portBounds); + gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id.number, _isVGA, _staticPalette, _portBounds); if (!_isVGA) { if (need_unscaled) @@ -201,7 +201,7 @@ void gfxr_free_resource(gfx_resource_t *resource, int type) { break; default: - GFXWARN("Attempt to free invalid resource type %d\n", type); + warning("[GFX] Attempt to free invalid resource type %d", type); } free(resource); @@ -474,7 +474,7 @@ gfxr_pic_t *GfxResManager::addToPic(int old_nr, int new_nr, int flags, int old_d res = resMap.contains(old_nr) ? resMap[old_nr] : NULL; if (!res) { - GFXWARN("Attempt to add pic %d to non-existing pic %d\n", new_nr, old_nr); + warning("[GFX] Attempt to add pic %d to non-existing pic %d", new_nr, old_nr); return NULL; } } @@ -525,7 +525,7 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { res = resMap.contains(nr) ? resMap[nr] : NULL; if (!res || res->mode != hash) { - Resource *viewRes = _resManager->findResource(kResourceTypeView, nr, 0); + Resource *viewRes = _resManager->findResource(ResourceId(kResourceTypeView, nr), 0); if (!viewRes || !viewRes->data) return NULL; @@ -579,26 +579,26 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { *loop = CLIP<int>(*loop, 0, view->loops_nr - 1); if (*loop < 0) { - GFXWARN("View %d has no loops\n", nr); + warning("[GFX] View %d has no loops", nr); return NULL; } loop_data = view->loops + (*loop); if (loop_data == NULL) { - GFXWARN("Trying to load invalid loop %d of view %d\n", *loop, nr); + warning("[GFX] Trying to load invalid loop %d of view %d", *loop, nr); return NULL; } *cel = CLIP<int>(*cel, 0, loop_data->cels_nr - 1); if (*cel < 0) { - GFXWARN("View %d loop %d has no cels\n", nr, *loop); + warning("[GFX] View %d loop %d has no cels", nr, *loop); return NULL; } cel_data = loop_data->cels[*cel]; if (loop_data == NULL) { - GFXWARN("Trying to load invalid view/loop/cel %d/%d/%d\n", nr, *loop, *cel); + warning("[GFX] Trying to load invalid view/loop/cel %d/%d/%d", nr, *loop, *cel); return NULL; } @@ -622,11 +622,11 @@ gfx_bitmap_font_t *GfxResManager::getFont(int num, bool scaled) { res = resMap.contains(num) ? resMap[num] : NULL; if (!res || res->mode != hash) { - Resource *fontRes = _resManager->findResource(kResourceTypeFont, num, 0); + Resource *fontRes = _resManager->findResource(ResourceId(kResourceTypeFont, num), 0); if (!fontRes || !fontRes->data) return NULL; - gfx_bitmap_font_t *font = gfxr_read_font(fontRes->id, fontRes->data, fontRes->size); + gfx_bitmap_font_t *font = gfxr_read_font(fontRes->id.number, fontRes->data, fontRes->size); if (!res) { res = (gfx_resource_t *)malloc(sizeof(gfx_resource_t)); @@ -659,12 +659,12 @@ gfx_pixmap_t *GfxResManager::getCursor(int num) { res = resMap.contains(num) ? resMap[num] : NULL; if (!res || res->mode != hash) { - Resource *cursorRes = _resManager->findResource(kResourceTypeCursor, num, 0); + Resource *cursorRes = _resManager->findResource(ResourceId(kResourceTypeCursor, num), 0); if (!cursorRes || !cursorRes->data) return NULL; if (_version >= SCI_VERSION_1_1) { - GFXWARN("Attempt to retrieve cursor in SCI1.1 or later\n"); + warning("[GFX] Attempt to retrieve cursor in SCI1.1 or later"); return NULL; } diff --git a/engines/sci/gfx/gfx_resmgr.h b/engines/sci/gfx/gfx_resmgr.h index c5878bf529..1f0f58dce9 100644 --- a/engines/sci/gfx/gfx_resmgr.h +++ b/engines/sci/gfx/gfx_resmgr.h @@ -49,7 +49,7 @@ enum gfx_resource_type_t { GFX_RESOURCE_TYPE_PALETTE, /* FIXME: Add PAL resource */ - GFX_RESOURCE_TYPES_NR /* Number of resource types that are to be supported */ + GFX_RESOURCE_TYPES_NR /**< Number of resource types that are to be supported */ }; #define GFX_RESOURCE_TYPE_0 GFX_RESOURCE_TYPE_VIEW @@ -58,12 +58,13 @@ enum gfx_resource_type_t { #define GFXR_RES_TYPE(id) (id >> 16) #define GFXR_RES_NR(id) (id & 0xffff) - +/** Graphics resource */ struct gfx_resource_t { - int ID; /* Resource ID */ - int lock_sequence_nr; /* See description of lock_counter in GfxResManager */ - int mode; /* A mode type hash */ + int ID; /**< Resource ID */ + int lock_sequence_nr; /**< See description of lock_counter in GfxResManager */ + int mode; /**< A mode type hash */ + /** Scaled pic */ union { gfx_pixmap_t *pointer; gfxr_view_t *view; @@ -71,6 +72,7 @@ struct gfx_resource_t { gfxr_pic_t *pic; } scaled_data; + /** Original pic */ union { gfx_pixmap_t *pointer; gfxr_view_t *view; @@ -85,152 +87,204 @@ struct gfx_options_t; typedef Common::HashMap<int, gfx_resource_t *> IntResMap; - +/** Graphics resource manager */ class GfxResManager { public: - GfxResManager(int version, bool isVGA, gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager); + GfxResManager(int version, bool isVGA, gfx_options_t *options, + GfxDriver *driver, ResourceManager *resManager); ~GfxResManager(); - /* Calculates a unique hash value for the specified options/type setup - ** Parameters: (gfx_resource_type_t) type: The type the hash is to be generated for - ** Returns : (int) A hash over the values of the options entries, covering entries iff - ** they are relevant for the specified type - ** Covering more entries than relevant may slow down the system when options are changed, - ** while covering less may result in invalid cached data being used. - ** Only positive values may be returned, as negative values are used internally by the generic - ** resource manager code. - ** Also, only the lower 20 bits are available to the interpreter. - ** (Yes, this isn't really a "hash" in the traditional sense...) - */ + /** + * Calculates a unique hash value for the specified options/type + * setup. + * + * Covering more entries than relevant may slow down the system when + * options are changed, while covering less may result in invalid + * cached data being used. + * Only positive values may be returned, as negative values are used + * internally by the generic resource manager code. + * Also, only the lower 20 bits are available to the interpreter. + * (Yes, this isn't really a "hash" in the traditional sense...) + * + * @param[in] type The type the hash is to be generated for + * @return A hash over the values of the options entries, + * covering entries iff they are relevant for the + * specified type. + */ int getOptionsHash(gfx_resource_type_t type); - /* 'Tags' all resources for deletion - ** Paramters: (void) - ** Returns : (void) - ** Tagged resources are untagged if they are referenced. - */ + /** + * 'Tags' all resources for deletion. + * + * Tagged resources are untagged if they are referenced. + */ void tagResources() { _tagLockCounter++; } - /* Retrieves an SCI0/SCI01 mouse cursor - ** Parameters: (int) num: The cursor number - ** Returns : (gfx_font_t *) The approprate cursor as a pixmap, or NULL on error - */ + /** + * Retrieves an SCI0/SCI01 mouse cursor. + * + * @param[in] num The cursor number + * @return The approprate cursor as a pixmap, or NULL on error + */ gfx_pixmap_t *getCursor(int num); - /* Retrieves the static palette from the interpreter-specific code - ** Parameters: (int *) colors_nr: Number of colors to use - ** (int) nr: The palette to read - ** Returns : (Palette *) static palette - ** if a static palette must be used, NULL otherwise - */ + /** + * Retrieves the static palette from the interpreter-specific code. + * + * @param[in] colors_nr Number of colors to use + * @param[in] num The palette to read + * @return Static palette if a static palette must be + * used, NULL otherwise + */ Palette *getPalette(int *colors_nr, int num = 999); - /* Retrieves a font - ** Parameters: (int) nr: The font number - ** (int) scaled: Whether the font should be font-scaled - ** Returns : (gfx_font_t *) The appropriate font, or NULL on error - */ + /** + * Retrieves a font. + * + * @param[in] num The font number + * @param[in] scaled Whether the font should be font-scaled + * @return The appropriate font, or NULL on error + */ gfx_bitmap_font_t *getFont(int num, bool scaled = false); - /* Retrieves a translated view cel - ** Parameters: - ** (int) nr: The view number - ** (int *) loop: Pointer to a variable containing the loop number - ** (int *) cel: Pointer to a variable containing the cel number - ** (int) palette: The palette to use - ** Returns : (gfx_view_t *) The relevant view, or NULL if nr was invalid - ** loop and cel are given as pointers in order to allow the underlying variables to be - ** modified if they are invalid (this is relevant for SCI version 0, where invalid - ** loop and cel numbers have to be interpreted as 'maximum' or 'minimum' by the interpreter) - */ + /** + * Retrieves a translated view cel. + * + * @param[in] nr The view number + * @param[in] loop Pointer to a variable containing the loop number + * @param[in] cel Pointer to a variable containing the cel number + * @param[in] palette The palette to use + * @return The relevant view, or NULL if nr was invalid + * loop and cel are given as pointers in order to + * allow the underlying variables to be modified + * if they are invalid (this is relevant for SCI + * version 0, where invalid loop and cel numbers + * have to be interpreted as 'maximum' or 'minimum' + * by the interpreter) + */ gfxr_view_t *getView(int nr, int *loop, int *cel, int palette); - /* Retrieves a displayable (translated) pic resource - ** Parameters: (int) nr: Number of the pic resource - ** (int) maps: The maps to translate (ORred GFX_MASK_*) - ** (int) flags: Interpreter-dependant pic flags - ** (int) default_palette: The default palette to use for drawing (if applicable) - ** (bool) scaled: Whether to return the scaled maps, or the unscaled - ** ones (which may be identical) for some special operations. - ** Returns : (gfxr_pic_t *) The appropriate pic resource with all maps as index (but not - ** neccessarily translated) data. - */ - gfxr_pic_t *getPic(int num, int maps, int flags, int default_palette, bool scaled = false); - - - /* Retrieves a displayable (translated) pic resource written ontop of an existing pic - ** Parameters: (int) old_nr: Number of the pic resource to write on - ** (int) new_nr: Number of the pic resource that is to be added - ** (int) flags: Interpreter-dependant pic flags - ** (int) default_palette: The default palette to use for drawing (if applicable) - ** (int) scaled: Whether to return the scaled maps, or the unscaled - ** ones (which may be identical) for some special operations. - ** Returns : (gfxr_pic_t *) The appropriate pic resource with all maps as index (but not - ** neccessarily translated) data. - ** This function invalidates the cached pic pointed to by old_nr in the cache. While subsequent - ** addToPic() writes will still modify the 'invalidated' pic, gfxr_get_pic() operations will - ** cause it to be removed from the cache and to be replaced by a clean version. - */ - gfxr_pic_t *addToPic(int old_nr, int new_nr, int flags, int old_default_palette, int default_palette); - - /* Calculate a picture - ** Parameters: (gfxr_pic_t *) scaled_pic: The pic structure that is to be written to - ** (gfxr_pic_t *) unscaled_pic: The pic structure the unscaled pic is to be written to, - ** or NULL if it isn't needed. - ** (int) flags: Pic drawing flags (interpreter dependant) - ** (int) default_palette: The default palette to use for pic drawing (interpreter dependant) - ** (int) nr: pic resource number - ** Returns : (int) GFX_ERROR if the resource could not be found, GFX_OK otherwise - */ - int calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic, int flags, int default_palette, int nr); - - /* Determines whether support for pointers with more than two colors is required - ** Returns : (bool) false if no support for multi-colored pointers is required, true - ** otherwise - */ + /** + * Retrieves a displayable (translated) pic resource. + * + * @param[in] num Number of the pic resource + * @param[in] maps The maps to translate (ORred GFX_MASK_*) + * @param[in] flags Interpreter-dependant pic flags + * @param[in] default_palette The default palette to use for drawing + * (if applicable) + * @param[in] scaled Whether to return the scaled maps, or + * the unscaled ones (which may be + * identical) for some special operations. + * @return The appropriate pic resource with all + * maps as index (but not neccessarily + * translated) data. + */ + gfxr_pic_t *getPic(int num, int maps, int flags, int default_palette, + bool scaled = false); + + + /** + * Retrieves a displayable (translated) pic resource written ontop of + * an existing pic. + * + * This function invalidates the cached pic pointed to by old_nr in the + * cache. While subsequent addToPic() writes will still modify the + * 'invalidated' pic, gfxr_get_pic() operations will cause it to be + * removed from the cache and to be replaced by a clean version. + * + * @param[in] old_nr Number of the pic resource to write on + * @param[in] new_nr Number of the pic resource that is to + * be added + * @param[in] flags Interpreter-dependant pic flags + * @param[in] old_default_palette The default palette of the pic before + * translation + * @param[in] default_palette The default palette to use for drawing + * (if applicable) + * @return The appropriate pic resource with all + * maps as index (but not neccessarily + * translated) data. + */ + gfxr_pic_t *addToPic(int old_nr, int new_nr, int flags, + int old_default_palette, int default_palette); + + /** + * Calculate a picture + * + * @param[in] scaled_pic The pic structure that is to be + * written to + * @param[in] unscaled_pic The pic structure the unscaled pic is + * to be written to, or NULL if it isn't + * needed. + * @param[in] flags Pic drawing flags (interpreter + * dependant) + * @param[in] default_palette The default palette to use for pic + * drawing (interpreter dependant) + * @param[in] nr pic resource number + * @return GFX_ERROR if the resource could not be + * found, GFX_OK otherwise + */ + int calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic, + int flags, int default_palette, int nr); + + /** + * Determines whether support for pointers with more than two colors + * is required. + * + * @return false if no support for multi-colored pointers is required, + * true otherwise + */ bool multicoloredPointers() { return _version > SCI_VERSION_1; } - /* Frees all resources currently allocated - ** Parameter: (void) - ** Returns : (void) - ** This function is intended to be used primarily for debugging. - */ + /** + * Frees all resources currently allocated. + * + * This function is intended to be used primarily for debugging. + */ void freeAllResources(); - /* Frees all tagged resources. - ** Parameters: (void) - ** Returns : (void) - ** Resources are tagged by calling gfx_tag_resources(), and untagged by calling the - ** approprate dereferenciation function. - ** Note that this function currently only affects view resources, as pic resources are - ** treated differently, while font and cursor resources are relatively rare. - */ + /** + * Frees all tagged resources. + * + * Resources are tagged by calling gfx_tag_resources(), and untagged by + * calling the approprate dereferenciation function. + * Note that this function currently only affects view resources, as + * pic resources are treated differently, while font and cursor + * resources are relatively rare. + */ void freeTaggedResources(); - /* Frees a previously allocated resource manager, and all allocated resources. - ** Parameters: (void) - ** Return : (void) - */ + /** + * Frees a previously allocated resource manager, and all allocated + * resources. + */ void freeResManager(); - const PaletteEntry &getColor(int color) { return _staticPalette->getColor(color); } + /** + * Retrieves a color from the static palette + */ + const PaletteEntry &getColor(int color) + { + return _staticPalette->getColor(color); + } - // Set static palette and merge it into the global palette + /** + * Set static palette and merge it into the global palette + */ void setStaticPalette(Palette *newPalette); - /* - ** Sets the picture port bounds - */ + /** + * Sets the picture port bounds + */ void changePortBounds(int x1, int y1, int x2, int y2) { _portBounds = Common::Rect(x1, y1, x2, y2); } @@ -252,7 +306,15 @@ public: } #endif - int getColorCount() { return _staticPalette ? _staticPalette->size() : 0; } + /** + * Gets the number of colors in the static palette. + * + * @return Number of pallete entries + */ + int getColorCount() + { + return _staticPalette ? _staticPalette->size() : 0; + } private: int _version; @@ -260,11 +322,11 @@ private: gfx_options_t *_options; GfxDriver *_driver; Palette *_staticPalette; - int _lockCounter; /* Global lock counter; increased for each new resource allocated. - ** The newly allocated resource will then be assigned the new value - ** of the lock_counter, as will any resources referenced afterwards. - */ - int _tagLockCounter; /* lock counter value at tag time */ + int _lockCounter; /**< Global lock counter; increased for each new + * resource allocated. The newly allocated resource will + * then be assigned the new value of the lock_counter, + * as will any resources referenced afterwards. */ + int _tagLockCounter; /**< lock counter value at tag time */ Common::Rect _portBounds; IntResMap _resourceMaps[GFX_RESOURCE_TYPES_NR]; diff --git a/engines/sci/gfx/gfx_resource.h b/engines/sci/gfx/gfx_resource.h index 8ce4a8ea83..780060bc4f 100644 --- a/engines/sci/gfx/gfx_resource.h +++ b/engines/sci/gfx/gfx_resource.h @@ -23,7 +23,9 @@ * */ -/* SCI Resource library */ +/** @file gfx_resource.h + * SCI Resource library. + */ #ifndef SCI_GFX_GFX_RESOURCE_H #define SCI_GFX_GFX_RESOURCE_H @@ -44,6 +46,7 @@ namespace Sci { #define GFXR_DITHER_MODE_D16 0 /* Sierra SCI style */ #define GFXR_DITHER_MODE_F256 1 /* Flat color interpolation */ #define GFXR_DITHER_MODE_D256 2 /* 256 color dithering */ + /* Dithering patterns */ #define GFXR_DITHER_PATTERN_SCALED 0 /* Dither per pixel on the 320x200 grid */ #define GFXR_DITHER_PATTERN_1 1 /* Dither per pixel on the target */ @@ -64,52 +67,53 @@ namespace Sci { extern int sci0_palette; -/* (gfx_pic_0.c) The 16 EGA base colors */ +/** The 16 EGA base colors */ extern Palette* gfx_sci0_image_pal[]; extern gfx_pixmap_color_t gfx_sci0_image_colors[][16]; -/* (gfx_pic_0.c) The 256 interpolated colors (initialized when -** gfxr_init_pic() is called for the first time, or when gfxr_init_static_palette() is called) -*/ +/** + * The 256 interpolated colors (initialized when gfxr_init_pic() is called + * for the first time, or when gfxr_init_static_palette() is called) + */ extern Palette* gfx_sci0_pic_colors; - struct gfxr_pic0_params_t { gfx_line_mode_t line_mode; /* one of GFX_LINE_MODE_* */ gfx_brush_mode_t brush_mode; }; +/** A SCI resource pic */ struct gfxr_pic_t { - int ID; /* pic number (NOT resource ID, just number) */ + int ID; /**< pic number (NOT resource ID, just number) */ gfx_mode_t *mode; - gfx_pixmap_t *visual_map; - gfx_pixmap_t *priority_map; - gfx_pixmap_t *control_map; - + gfx_pixmap_t *visual_map; /**< Visual part of pic */ + gfx_pixmap_t *priority_map; /**< Priority map for pic */ + gfx_pixmap_t *control_map; /**< Control map for pic */ + + /** + * Auxiliary map. + * Bit 0: Vis + * Bit 1: Pri + * Bit 2: Ctrl + * Bit 3-5: 'filled' (all three bits are set to 1) + */ byte aux_map[GFXR_AUX_MAP_SIZE]; - /* Auxiliary map details: - ** Bit 0: Vis - ** Bit 1: Pri - ** Bit 2: Ctrl - ** Bit 3-5: 'filled' (all three bits are set to 1) - */ - // rect_t bounds; // unused - void *undithered_buffer; /* copies visual_map->index_data before dithering */ + void *undithered_buffer; /**< copies visual_map->index_data before dithering */ int undithered_buffer_size; int *priorityTable; }; - +/** A animation loop */ struct gfxr_loop_t { - int cels_nr; - gfx_pixmap_t **cels; + int cels_nr; /**< Number of 'cels' or frames in the animation */ + gfx_pixmap_t **cels; /**< Pointer to the pixmaps for the cels */ }; - +/** A graphics view */ struct gfxr_view_t { int ID; @@ -122,172 +126,197 @@ struct gfxr_view_t { int translation[GFX_SCI0_IMAGE_COLORS_NR]; }; +/** + * Initializes the static 256 color palette. + */ void gfxr_init_static_palette(); -/* Initializes the static 256 color palette -** Parameters: (void) -** Returns : (void) -*/ - -gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1); -/* Initializes a gfxr_pic_t for a specific mode -** Parameters: (gfx_mode_t *) mode: The specific graphics mode -** (int) ID: The ID to assign to the resulting pixmaps -** Returns : (gfxr_pic_t *) The allocated pic resource, or NULL on error. -** This function allocates memory for use by resource drawer functions. -*/ -void gfxr_free_pic(gfxr_pic_t *pic); -/* Uninitializes a pic resource -** Parameters: (gfxr_pic_t *) pic: The pic to free -** Returns : (void) -*/ - -void gfxr_free_view(gfxr_view_t *view); -/* Frees all memory associated with a view -** Paremeters: (gfxr_view_t *) view: The view to free -** Returns : (void) -*/ +/** @name Resource picture management functions */ +/** @{ */ +/** + * Initializes a gfxr_pic_t for a specific mode. + * + * This function allocates memory for use by resource drawer functions. + * + * @param[in] mode The specific graphics mode + * @param[in] ID The ID to assign to the resulting pixmaps + * @param[in] sci1 true if a SCI1 pic, false otherwise + * @return The allocated pic resource, or NULL on error. + */ +gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, bool sci1); +/** + * Uninitializes a pic resource. + * + * @param[in] pic The pic to free + */ +void gfxr_free_pic(gfxr_pic_t *pic); +/** + * Frees all memory associated with a view. + * + * @param[in] view The view to free + */ +void gfxr_free_view(gfxr_view_t *view); +/** @} */ +/** @name SCI0 resource picture operations */ +/** @{ */ -/*********************/ -/* SCI0 operations */ -/*********************/ +/** + * Clears all pic buffers of one pic/ + * + * This function should be called before gfxr_draw_pic0, unless cumulative + * drawing is intended + * + * @param[in] pic The picture to clear + * @param[in] titlebar_size How much space to reserve for the title bar + */ +void gfxr_clear_pic0(gfxr_pic_t *pic, int titlebar_size); +/** + * Draws a pic resource (all formats prior to SCI1.1). + * + * The result is stored in gfxr_visual_map, gfxr_priority_map, and + * gfxr_control_map. The palette entry of gfxr_visual_map is never used. + * Note that the picture will not be drawn dithered; use gfxr_dither_pic0 + * for that. + * + * @param[in] pic The pic to draw to + * @param[in] fill_normally If 1, the pic is drawn normally; if 0, all + * fill operations will fill with black + * @param[in] default_palette The default palette to use for drawing + * @param[in] size Resource size + * @param[in] resource Pointer to the resource data + * @param[in] style The drawing style + * @param[in] resid The resource ID + * @param[in] sci1 true if SCI1, false otherwise + * @param[in] static_pal The static palette + * @param[in] portBounds The bounds of the port being drawn to + */ +void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, + int default_palette, int size, byte *resource, + gfxr_pic0_params_t *style, int resid, int sci1, + Palette *static_pal, Common::Rect portBounds); -void gfxr_clear_pic0(gfxr_pic_t *pic, int titlebar_size); -/* Clears all pic buffers of one pic -** Parameters: (gfxr_pic_t) pic: The picture to clear -** (int) titlebar_size: How much space to reserve for the title bar -** Returns : (void) -** This function should be called before gfxr_draw_pic0, unless cumulative -** drawing is intended -*/ - - -void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, int default_palette, - int size, byte *resource, gfxr_pic0_params_t *style, int resid, int sci1, - Palette *static_pal, Common::Rect portBounds); -/* Draws a pic resource (all formats prior to SCI1.1) -** Parameters: (gfxr_pic_t *) pic: The pic to draw to -** (int) fill_normally: If 1, the pic is drawn normally; if 0, all -** fill operations will fill with black -** (int) default_palette: The default palette to use for drawing -** (int) size: Resource size -** (byte *) resource: Pointer to the resource data -** (gfxr_pic0_params_t *) style: The drawing style -** (int) resid: The resource ID -** (int) sci1: Nonzero if SCI1 -** (Palette *) static_pal: The static palette -** (int) static_pal_nr: Number of entries in static palette -** Returns : (void) -** The result is stored in gfxr_visual_map, gfxr_priority_map, and gfxr_control_map. -** The palette entry of gfxr_visual_map is never used. -** Note that the picture will not be drawn dithered; use gfxr_dither_pic0 for that. -*/ - -void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally, int default_palette, - int size, byte *resource, gfxr_pic0_params_t *style, int resid, - Palette *static_pal, Common::Rect portBounds); -/* Draws a pic resource (SCI1.1) -** Parameters: (gfxr_pic_t *) pic: The pic to draw to -** (int) fill_normally: If 1, the pic is drawn normally; if 0, all -** fill operations will fill with black -** (int) default_palette: The default palette to use for drawing -** (int) size: Resource size -** (byte *) resource: Pointer to the resource data -** (gfxr_pic0_params_t *) style: The drawing style -** (int) resid: The resource ID -** (Palette *) static_pal: The static palette -** (int) static_pal_nr: Number of entries in static palette -** Returns : (void) -** The result is stored in gfxr_visual_map, gfxr_priority_map, and gfxr_control_map. -** The palette entry of gfxr_visual_map is never used. -** Note that the picture will not be drawn dithered; use gfxr_dither_pic0 for that. -*/ +/** + * Draws a pic resource (SCI1.1). + * + * The result is stored in gfxr_visual_map, gfxr_priority_map, and + * gfxr_control_map. The palette entry of gfxr_visual_map is never used. + * Note that the picture will not be drawn dithered; use gfxr_dither_pic11 + * for that. + * + * @param[in] pic The pic to draw to + * @param[in] fill_normally If 1, the pic is drawn normally; if 0, all + * fill operations will fill with black + * @param[in] default_palette The default palette to use for drawing + * @param[in] size Resource size + * @param[in] resource Pointer to the resource data + * @param[in] style The drawing style + * @param[in] resid The resource ID + * @param[in] static_pal The static palette + * @param[in] portBounds Bounds of the port being drawn to + */ +void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally, + int default_palette, int size, byte *resource, + gfxr_pic0_params_t *style, int resid, Palette *static_pal, + Common::Rect portBounds); +/** + * Removes artifacts from a scaled pic. + * + * Using information from the (correctly rendered) src pic, this function + * implements some heuristics to remove artifacts from dest. Must be used + * before dither_pic0 is called, because it operates on the index buffer. + * + * @param[in] dest The scaled pic + * @param[in] src An unscaled pic + */ void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src); -/* Removes artifacts from a scaled pic -** Parameters: (gfxr_pic_t *) dest: The scaled pic -** (gfxr_pic_t *) src: An unscaled pic -** Returns : (void) -** Using information from the (correctly rendered) src pic, this function implements -** some heuristics to remove artifacts from dest. Must be used before dither_pic0 is -** called, because it operates on the index buffer. -*/ +/** + * Dithers a gfxr_visual_map. + * + * @param[in] pic The pic to dither + * @param[in] mode One of GFXR_DITHER_MODE + * @param[in] pattern One of GFXR_DITHER_PATTERN + */ void gfxr_dither_pic0(gfxr_pic_t *pic, int mode, int pattern); -/* Dithers a gfxr_visual_map -** Parameters: (gfxr_pic_t *) pic: The pic to dither -** (int) mode: One of GFXR_DITHER_MODE -** (int) pattern: One of GFXR_DITHER_PATTERN -** Returns : (void) -*/ +/** + * Calculates a SCI0 view. + * + * @param[in] id Resource ID of the view + * @param[in] resource Pointer to the resource to read + * @param[in] size Size of the resource + * @param[in] palette The palette to use + * @return The resulting view + */ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette); -/* Calculates an SCI0 view -** Parameters: (int) id: Resource ID of the view -** (byte *) resource: Pointer to the resource to read -** (int) size: Size of the resource -** (int) palette: The palette to use -** Returns : (gfxr_view_t *) The resulting view -*/ - -gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, bool isSci01); -/* Calculates n SCI cursor -** Parameters: (int) id: The cursor's resource ID -** (byte *) resource: Pointer to the resource data -** (int) size: Resource size -** (bool) isSci01: Set to true to load a SCI1 cursor -** Returns : (gfx_pixmap_t *) A newly allocated pixmap containing an index -** color representation of the cursor -*/ - -/*********************/ -/* SCI1 operations */ -/*********************/ +/** + * Calculates a SCI cursor. + * + * @param[in] id The cursor's resource ID + * @param[in] resource Pointer to the resource data + * @param[in] size Resource size + * @param[in] isSci01 Set to true to load a SCI1 cursor + * @return A newly allocated pixmap containing an index color + * representation of the cursor + */ +gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, + bool isSci01); +/** @} */ + + +/** @name SCI1/1.1 resource picture operations */ +/** @{ */ + +/** + * Reads an SCI1 palette. + * + * @param[in] id Resource ID for the palette (or the view it was + * found in) + * @param[in] resource Source data + * @param[in] size Size of the memory block pointed to by resource + * @return Palette with the colors + */ Palette *gfxr_read_pal1(int id, byte *resource, int size); -/* Reads an SCI1 palette -** Parameters: (int) id: Resource ID for the palette (or the view it was found in) -** (int *) colors_nr: Pointer to the variable the number of colors -** will be stored in -** (byte *) resource: Source data -** (int) size: Size of the memory block pointed to by resource -** Returns : (Palette *) *colors_nr Palette with the colors -*/ +/** + * Reads an SCI1 palette. + * + * @param[in] file Palette file + * @return Palette with the colors + */ Palette *gfxr_read_pal1_amiga(Common::File &file); -/* Reads an SCI1 palette -** Parameters: (int *) colors_nr: Pointer to the variable the number of colors -** will be stored in -** (FILE *) f: Palette file -** Returns : (Palette *) Palette with the colors -*/ +/** + * Reads an SCI1.1 palette. + * + * @param[in] id Resource ID for the palette (or the view it was + * found in) + * @param[in] resource Source data + * @param[in] size Size of the memory block pointed to by resource + * @return Palette with the colors + */ Palette *gfxr_read_pal11(int id, byte *resource, int size); -/* Reads an SCI1.1 palette -** Parameters: (int) id: Resource ID for the palette (or the view it was found in) -** (int *) colors_nr: Pointer to the variable the number of colors -** will be stored in -** (byte *) resource: Source data -** (int) size: Size of the memory block pointed to by resource -** Returns : (Palette *) Palette with the colors -*/ +/** + * Calculates an SCI1 view. + * + * @param[in] id Resource ID of the view + * @param[in] resource Pointer to the resource to read + * @param[in] size Size of the resource + * @param[in] static_pal The static palette + * @param[in] isSci11 true if SCI1.1, false otherwise + * @return The resulting view + */ gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal, bool isSci11); -/* Calculates an SCI1 view -** Parameters: (int) id: Resource ID of the view -** (byte *) resource: Pointer to the resource to read -** (int) size: Size of the resource -** (Palette *) static_pal: The static palette -** (int) static_pal_nr: Number of entries in static palette -** Returns : (gfxr_view_t *) The resulting view -*/ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *resource, byte *cel_base, int size, gfxr_view_t *view, bool isAmiga, bool isSci11); - +/** @} */ } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_state_internal.h b/engines/sci/gfx/gfx_state_internal.h index c184492054..3f00b5213c 100644 --- a/engines/sci/gfx/gfx_state_internal.h +++ b/engines/sci/gfx/gfx_state_internal.h @@ -34,14 +34,16 @@ namespace Sci { -#define GFXW_FLAG_VISIBLE (1<<0) -#define GFXW_FLAG_OPAQUE (1<<1) -#define GFXW_FLAG_CONTAINER (1<<2) -#define GFXW_FLAG_DIRTY (1<<3) -#define GFXW_FLAG_TAGGED (1<<4) -#define GFXW_FLAG_MULTI_ID (1<<5) /**< Means that the ID used herein may be used more than once, i.e. is not unique */ -#define GFXW_FLAG_IMMUNE_TO_SNAPSHOTS (1<<6) /**< Snapshot restoring doesn't kill this widget, and +5 bonus to saving throws vs. Death Magic */ -#define GFXW_FLAG_NO_IMPLICIT_SWITCH (1<<7) /**< Ports: Don't implicitly switch to this port when disposing windows */ +enum gfxw_flag_t { + GFXW_FLAG_VISIBLE = (1<<0), + GFXW_FLAG_OPAQUE = (1<<1), + GFXW_FLAG_CONTAINER = (1<<2), + GFXW_FLAG_DIRTY = (1<<3), + GFXW_FLAG_TAGGED = (1<<4), + GFXW_FLAG_MULTI_ID = (1<<5), /**< Means that the ID used herein may be used more than once, i.e. is not unique */ + GFXW_FLAG_IMMUNE_TO_SNAPSHOTS = (1<<6), /**< Snapshot restoring doesn't kill this widget, and +5 bonus to saving throws vs. Death Magic */ + GFXW_FLAG_NO_IMPLICIT_SWITCH = (1<<7) /**< Ports: Don't implicitly switch to this port when disposing windows */ +}; struct gfxw_snapshot_t { int serial; /**< The first serial number to kill */ @@ -82,6 +84,7 @@ struct GfxPort; typedef int gfxw_bin_op(GfxWidget *, GfxWidget *); +/** SCI graphics widget */ struct GfxWidget { public: int _magic; /**< Extra check after typecasting */ @@ -101,27 +104,28 @@ public: /** * The widget automatically removes itself from its owner, if it has one. - * Deleting a container will recursively free all of its - * contents. + * Deleting a container will recursively free all of its contents. */ virtual ~GfxWidget(); /** * Draws the widget. * - * The widget is drawn iff it is flagged as dirty. Invoking this operation on - * a container widget will recursively draw all of its contents. + * The widget is drawn iff it is flagged as dirty. Invoking this operation + * on a container widget will recursively draw all of its contents. * - * @param pos The position to draw to (added to the widget's internal position) + * @param[in] pos The position to draw to (added to the widget's + * internal position) */ virtual int draw(const Common::Point &pos) = 0; /** * Tags the specified widget. * - * If invoked on a container widget, this will also tag all of the container's - * contents (but not the contents' contents!) - * FIXME: Actually, the code in GfxContainer::tag contradicts the last claim! + * If invoked on a container widget, this will also tag all of the + * container's contents (but not the contents' contents!) + * FIXME: Actually, the code in GfxContainer::tag contradicts the last + * claim! */ virtual void tag() { _flags |= GFXW_FLAG_TAGGED; @@ -130,10 +134,10 @@ public: /** * Prints a string representation of the widget with sciprintf. * - * Will recursively print all of the widget's contents if the widget contains - * further sub-widgets + * Will recursively print all of the widget's contents if the widget + * contains further sub-widgets * - * @param indentation Number of double spaces to indent + * @param[in] indentation Number of double spaces to indent */ virtual void print(int indentation) const; @@ -143,55 +147,63 @@ public: * This comparison only applies to some widgets; compare_to(a,a)=0 is not * guaranteed. It may be used for sorting for all widgets. * - * @param other other widget - * @return <0, 0, or >0 if other is, respectively, less than, equal - * to, or greater than self + * @param other The other widget + * @return <0, 0, or >0 if other is, respectively, less than, equal + * to, or greater than self */ gfxw_bin_op *compare_to; /** * Compares two compareable widgets for equality. * - * This operation checks whether two widgets describe the same graphical data. - * It is used to determine whether a new widget should be discarded because it - * describes the same graphical data as an old widget that has already been - * drawn. For lists, it also checks whether all contents are in an identical - * order. + * This operation checks whether two widgets describe the same graphical + * data. It is used to determine whether a new widget should be discarded + * because it describes the same graphical data as an old widget that has + * already been drawn. For lists, it also checks whether all contents are + * in an identical order. * - * @param other other widget - * @return false if the widgets are not equal, true if they match + * @param[in] other The other widget + * @return false if the widgets are not equal, true if they match */ gfxw_bin_op *equals; /** - * Determine whether other should replace this even though they are equivalent. + * Determine whether other should replace this even though they are + * equivalent. * * When 'equals' returns true, this means that no new widget will be added. * However, in some cases newer widgets may contain information that should - * cause the older widget to be removed nonetheless; this is indicated by this - * function. + * cause the older widget to be removed nonetheless; this is indicated by + * this function. * - * @param other other widget - * @return false if this should be kept, true if this should be replaced by the 'other' + * @param[in] other The other widget + * @return false if this should be kept, true if this should be + * replaced by the 'other' */ gfxw_bin_op *should_replace; /** - * Tests whether drawing this after other would reduce all traces of other. + * Tests whether drawing this after other would reduce all traces of + * other. * - * /a superarea_of b <=> for each pixel of b there exists an opaque pixel in a at the same location + * /a superarea_of b <=> for each pixel of b there exists an opaque pixel + * in a at the same location * - * @param other the widget to compare for containment - * @return true if this is superarea_of other, false otherwise + * @param[in] other The widget to compare for containment + * @return true if this is superarea_of other, false otherwise */ gfxw_bin_op *superarea_of; /** * Sets the visual for the widget - * This function is called by container->add() and need not be invoked explicitly. - * It also makes sure that dirty rectangles are passed to parent containers. + * + * This function is called by container->add() and need not be invoked + * explicitly. It also makes sure that dirty rectangles are passed to + * parent containers. + * + * @param[in] visual GfxVisual to set for the widget */ - virtual int setVisual(GfxVisual *); + virtual int setVisual(GfxVisual *visual); //protected: void printIntern(int indentation) const; @@ -200,6 +212,7 @@ public: #define GFXW_IS_BOX(widget) ((widget)->_type == GFXW_BOX) +/** SCI box widget */ struct GfxBox : public GfxWidget { gfx_color_t _color1, _color2; gfx_box_shade_t _shadeType; @@ -213,6 +226,7 @@ public: #define GFXW_IS_PRIMITIVE(widget) ((widget)->_type == GFXW_RECT || (widget)->_type == GFXW_LINE) +/** SCI graphics primitive */ struct GfxPrimitive : public GfxWidget { gfx_color_t _color; gfx_line_mode_t _lineMode; @@ -227,6 +241,7 @@ public: #define GFXW_IS_VIEW(widget) ((widget)->_type == GFXW_VIEW || (widget)->_type == GFXW_STATIC_VIEW \ || (widget)->_type == GFXW_DYN_VIEW || (widget)->_type == GFXW_PIC_VIEW) +/** SCI graphics view */ struct GfxView : public GfxWidget { Common::Point _pos; /**< Implies the value of 'bounds' in GfxWidget */ gfx_color_t _color; @@ -242,10 +257,12 @@ public: }; #define GFXW_IS_DYN_VIEW(widget) ((widget)->_type == GFXW_DYN_VIEW || (widget)->_type == GFXW_PIC_VIEW) +/** SCI dynamic view */ struct GfxDynView : public GfxView { /* FIXME: This code is specific to SCI */ rect_t draw_bounds; /* The correct position to draw to */ - void *under_bitsp, *signalp; + ObjVarRef under_bitsp; + ObjVarRef signalp; int under_bits, signal; int _z; /**< The z coordinate: Added to y, but used for sorting */ int sequence; /**< Sequence number: For sorting */ @@ -264,6 +281,7 @@ public: #define GFXW_IS_TEXT(widget) ((widget)->_type == GFXW_TEXT) +/** SCI text widget */ struct GfxText : public GfxWidget { int _font; int lines_nr, lineheight, lastline_width; @@ -292,7 +310,7 @@ typedef int gfxw_unary_container_op(GfxContainer *); typedef int gfxw_container_op(GfxContainer *, GfxWidget *); typedef int gfxw_rect_op(GfxContainer *, rect_t, int); - +/** SCI container widget */ struct GfxContainer : public GfxWidget { rect_t zone; /**< The writeable zone (absolute) for contained objects */ DirtyRectList _dirtyRects; /**< List of dirty rectangles */ @@ -323,7 +341,7 @@ public: #define GFXW_IS_LIST(widget) ((widget)->_type == GFXW_LIST || (widget)->_type == GFXW_SORTED_LIST) #define GFXW_IS_SORTED_LIST(widget) ((widget)->_type == GFXW_SORTED_LIST) - +/** SCI graphics list */ struct GfxList : public GfxContainer { public: GfxList(rect_t area, bool sorted); @@ -333,6 +351,7 @@ public: }; #define GFXW_IS_VISUAL(widget) ((widget)->_type == GFXW_VISUAL) +/** SCI graphic visual */ struct GfxVisual : public GfxContainer { Common::Array<GfxPort *> _portRefs; /**< References to ports */ int _font; /**< Default font */ @@ -352,6 +371,7 @@ public: }; #define GFXW_IS_PORT(widget) ((widget)->_type == GFXW_PORT) +/** SCI graphics port */ struct GfxPort : public GfxContainer { GfxList *_decorations; /**< optional window decorations - drawn before the contents */ GfxWidget *port_bg; /**< Port background widget or NULL */ @@ -365,16 +385,20 @@ struct GfxPort : public GfxContainer { byte gray_text; /**< Whether text is 'grayed out' (dithered) */ public: - /* Creates a new port widget with the default settings - ** Paramaters: (GfxVisual *) visual: The visual the port is added to - ** (GfxPort *) predecessor: The port's predecessor - ** (rect_t) area: The screen area covered by the port (absolute position) - ** (gfx_color_t) fgcolor: Foreground drawing color - ** (gfx_color_t) bgcolor: Background color - ** A port differentiates itself from a list in that it contains additional information, - ** and an optional title (stored in a display list). - ** Ports are assigned implicit IDs identifying their position within the port stack. - */ + /** + * Creates a new port widget with the default settings + * + * A port differentiates itself from a list in that it contains additional + * information, and an optional title (stored in a display list). + * Ports are assigned implicit IDs identifying their position within the + * port stack. + * + * @param[in] visual The visual the port is added to + * @param[in] area The screen area covered by the port (absolute + * position) + * @param[in] fgcolor Foreground drawing color + * @param[in] bgcolor Background color + */ GfxPort(GfxVisual *visual, rect_t area, gfx_color_t fgcolor, gfx_color_t bgcolor); ~GfxPort(); diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h index e1d56ee26d..4d9a39934d 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -37,13 +37,7 @@ namespace Sci { #define GFX_DEBUG /* General output macros */ -# define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error -# define GFXWARN sciprintf("GFX Warning: %s, L%d:", __FILE__, __LINE__); warning -# ifdef GFX_DEBUG -# define GFXDEBUG sciprintf("GFX-debug: %s, L%d:", __FILE__, __LINE__); sciprintf -# else /* !GFX_DEBUG */ -# define GFXDEBUG if (0) printf -# endif /* !GFX_DEBUG */ +#define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error /***********************/ /*** Data structures ***/ @@ -57,34 +51,37 @@ namespace Sci { ** enabled */ #define GFX_MODE_FLAG_REVERSE_ALPHA (1<<1) -/** Graphics mode description */ -struct gfx_mode_t { +/** Graphics mode description + * + * Color masks: + * Each of the mask/shift pairs describe where the corresponding color + * values are stored for the described mode. Internally, color + * calculations are done by using 32 bit values for r, g, b, a. After + * the internal values have been calculated, they are shifted RIGHT + * by the xxx_shift amount described above, then ANDed with the + * corresponding color mask; finally, all three results are ORred to- + * gether. The alpha values are used as appropriate; if alpha_mask is + * zero, then images use a special alpha map. + */ - int xfact, yfact; /* Horizontal and vertical scaling factors */ - int xsize, ysize; /* Horizontal and vertical size */ - int bytespp; /* Bytes per pixel */ +struct gfx_mode_t { - uint32 flags; /* GFX_MODE_FLAG_* Flags- see above */ + int xfact, yfact; /**< Horizontal and vertical scaling factors */ + int xsize, ysize; /**< Horizontal and vertical size */ + int bytespp; /**< Bytes per pixel */ + uint32 flags; /**< GFX_MODE_FLAG_* Flags- see above */ - Palette *palette; // Palette or NULL to indicate non-palette mode. - // Palette mode is only supported for bytespp = 1 + /** + * Palette or NULL to indicate non-palette mode. + * Palette mode is only supported for bytespp = 1 + */ + Palette *palette; - /* Color masks */ // TODO: remove those uint32 red_mask, green_mask, blue_mask, alpha_mask; short red_shift, green_shift, blue_shift, alpha_shift; Graphics::PixelFormat format; - - /* Each of the mask/shift pairs describe where the corresponding color - ** values are stored for the described mode. Internally, color - ** calculations are done by using 32 bit values for r, g, b, a. After - ** the internal values have been calculated, they are shifted RIGHT - ** by the xxx_shift amount described above, then ANDed with the - ** corresponding color mask; finally, all three results are ORred to- - ** gether. The alpha values are used as appropriate; if alpha_mask is - ** zero, then images use a special alpha map. */ - }; @@ -93,16 +90,16 @@ struct gfx_mode_t { /** Pixmap-specific color entries */ struct gfx_pixmap_color_t{ - int global_index; /* Global index color or GFX_COLOR_INDEX_UNMAPPED. */ - uint8 r, g, b; /* Real color */ + int global_index; /**< Global index color or GFX_COLOR_INDEX_UNMAPPED. */ + uint8 r, g, b; /**< Real color */ }; /** Full color */ struct gfx_color_t { PaletteEntry visual; - uint8 alpha; /* transparency = (1-opacity) */ + uint8 alpha; /**< transparency = (1-opacity) */ int8 priority, control; - byte mask; /* see mask values below */ + byte mask; /**< see mask values below */ }; @@ -113,11 +110,15 @@ struct rect_t { int width, height; /* width, height: (x,y,width,height)=(5,5,1,1) occupies 1 pixel */ }; -/* Generates a rect_t from index data -** Parameters: (int x int) x,y: Upper left point of the rectangle -** (int x int) width, height: Horizontal and vertical extension of the rectangle -** Returns : (rect_t) A rectangle matching the supplied parameters -*/ +/** + * Generates a rect_t from index data + * + * @param[in] x Left side of the rectangle + * @param[in] y Top side of the rectangle + * @param[in] width Horizontal extent of the rectangle + * @param[in] height Verical extent of the rectangle + * @return A rectangle matching the supplied parameters + */ static inline rect_t gfx_rect(int x, int y, int width, int height) { rect_t rect; @@ -129,11 +130,16 @@ static inline rect_t gfx_rect(int x, int y, int width, int height) { return rect; } -// Temporary helper functions to ease the transition from rect_t to Common::Rect +/** + * Temporary helper function to ease the transition from rect_t to Common::Rect + */ static inline rect_t toSCIRect(Common::Rect in) { return gfx_rect(in.left, in.top, in.width(), in.height()); } +/** + * Temporary helper function to ease the transition from rect_t to Common::Rect + */ static inline Common::Rect toCommonRect(rect_t in) { return Common::Rect(in.x, in.y, in.x + in.width, in.y + in.height); } @@ -142,10 +148,13 @@ static inline Common::Rect toCommonRect(rect_t in) { #define OVERLAP(a, b, z, zl) (a.z >= b.z && a.z < (b.z + b.zl)) -/* Determines whether two rects overlap -** Parameters: (rect_t x rect_t) a,b: The two rect_ts to check for overlap -** Returns : (int) 1 if they overlap, 0 otherwise -*/ +/** + * Determines whether two rects overlap + * + * @param[in] a First rect to check for overlap + * @param[in] b Second rect to check for overlap + * @return 1 if they overlap, 0 otherwise + */ static inline int gfx_rects_overlap(rect_t a, rect_t b) { return (OVERLAP(a, b, x, width) || OVERLAP(b, a, x, width)) && (OVERLAP(a, b, y, height) || OVERLAP(b, a, y, height)); } @@ -159,86 +168,95 @@ extern rect_t gfx_rect_fullscreen; #define GFX_PIC_COLORS 256 -#define GFX_PIXMAP_FLAG_SCALED_INDEX (1<<0) /* Index data is scaled already */ -#define GFX_PIXMAP_FLAG_INSTALLED (1<<2) /* Pixmap has been registered */ -#define GFX_PIXMAP_FLAG_PALETTIZED (1<<6) /* Indicates a palettized view */ +#define GFX_PIXMAP_FLAG_SCALED_INDEX (1<<0) /* Index data is scaled already */ +#define GFX_PIXMAP_FLAG_INSTALLED (1<<2) /* Pixmap has been registered */ +#define GFX_PIXMAP_FLAG_PALETTIZED (1<<6) /* Indicates a palettized view */ #define GFX_PIXMAP_COLOR_KEY_NONE -1 /* No transpacency colour key */ #define GFX_CURSOR_TRANSPARENT 255 // Cursor colour key -struct gfx_pixmap_t { /* gfx_pixmap_t: Pixel map */ +/** Pixel map */ +struct gfx_pixmap_t { - /*** Meta information ***/ - int ID; /* Resource ID, or GFX_RESID_NONE for anonymous graphical data */ - short loop, cel; /* loop and cel number for views */ + /** @name Meta information + * @{*/ + int ID; /**< Resource ID, or GFX_RESID_NONE for anonymous graphical data */ + short loop; /**< loop number for view */ + short cel; /**< cel number for view */ + /** @}*/ - - /*** Color map ***/ + /** @name Color map + * @{*/ Palette *palette; - int colors_nr() const { return palette ? palette->size() : 0; } - /* color entries, or NULL if the - ** default palette is to be used. - ** A maximum of 255 colors is allowed; color - ** index 0xff is reserved for transparency. - ** As a special exception, 256 colors are - ** allowed for background pictures (which do - ** not use transparency) - */ - uint32 flags; - - /*** Hot spot ***/ - int xoffset, yoffset; /* x and y coordinates of the 'hot spot' (unscaled) */ - /*** Index data ***/ - int index_width, index_height; /* width and height of the indexed original image */ - byte *index_data; /* Color-index data, or NULL if read from an - ** external source - */ - - /*** Drawable data ***/ - int width, height; /* width and height of the actual image */ - int data_size; /* Amount of allocated memory */ - byte *data; /* Drawable data, or NULL if not converted. */ - - byte *alpha_map; /* Byte map with alpha values. It is used only if the - ** graphics mode's alpha_mask is zero. - */ + /** + * color entries, or NULL if the default palette is to be used. A maximum + * of 255 colors is allowed; color index 0xff is reserved for transparency. + * As a special exception, 256 colors are allowed for background pictures + * (which do not use transparency) + */ + int colors_nr() const { return palette ? palette->size() : 0; } - int color_key; - int palette_revision; // Revision of palette at the time data was generated + uint32 flags; + /* @} */ + + /** @name Hot spot + * x and y coordinates of the 'hot spot' (unscaled) + * @{*/ + int xoffset, yoffset; + /** @} */ + + /** @name Index data + * @{ + */ + int index_width; /**< width of the indexed original image */ + int index_height; /**< height of the indexed original image */ + byte *index_data; /**< Color-index data, or NULL if read from an external source */ + /** @} */ + + /** @name Drawable data + * @{ + */ + int width; /**< width of the actual image */ + int height; /**< height of the actual image */ + int data_size; /**< Amount of allocated memory */ + byte *data; /**< Drawable data, or NULL if not converted. */ + + byte *alpha_map; /**< Byte map with alpha values. It is used only if the graphics mode's alpha_mask is zero. */ + + int color_key; /**< The color to make transparent */ + int palette_revision; /**< Revision of palette at the time data was generated */ + /** @} */ }; -/***********************/ -/*** Constant values ***/ -/***********************/ -/* Return values */ +/** @name Constant values + * @{ */ + +/** Return values */ enum gfx_return_value_t { - GFX_OK = 0, /* Indicates "operation successful" */ - GFX_ERROR = -1, /* Indicates "operation failed" */ - GFX_FATAL = -2 - /* Fatal error: Used by graphics drivers to indicate that they were unable to - ** do anything useful - */ + GFX_OK = 0, /**< Indicates "operation successful" */ + GFX_ERROR = -1, /**< Indicates "operation failed" */ + GFX_FATAL = -2 /**< Fatal error: Used by graphics drivers to indicate + that they were unable to do anything useful */ }; - -enum gfx_map_mask_t {/* Map masks */ +/** Map masks */ +enum gfx_map_mask_t { GFX_MASK_NONE = 0, GFX_MASK_VISUAL = 1, GFX_MASK_PRIORITY = 2, GFX_MASK_CONTROL = 4 }; -/* 'no priority' mode */ +/** 'no priority' mode */ enum { GFX_NO_PRIORITY = -1 }; -/* Text alignment values */ - +/** Text alignment values */ enum gfx_alignment_t { ALIGN_RIGHT = -1, ALIGN_TOP = -1, @@ -249,16 +267,16 @@ enum gfx_alignment_t { enum gfx_line_mode_t { - GFX_LINE_MODE_CORRECT, /* Scaled separately */ - GFX_LINE_MODE_FAST, /* Scaled by (xfact+yfact)/2 */ - GFX_LINE_MODE_FINE /* Always drawn at width 1 */ + GFX_LINE_MODE_CORRECT, /**< Scaled separately */ + GFX_LINE_MODE_FAST, /**< Scaled by (xfact+yfact)/2 */ + GFX_LINE_MODE_FINE /**< Always drawn at width 1 */ }; enum gfx_brush_mode_t { - GFX_BRUSH_MODE_SCALED, /* Just scale the brush pixels */ - GFX_BRUSH_MODE_ELLIPSES, /* Replace pixels with ellipses */ - GFX_BRUSH_MODE_RANDOM_ELLIPSES, /* Replace pixels with ellipses moved and re-scaled randomly */ - GFX_BRUSH_MODE_MORERANDOM /* Distribute randomly */ + GFX_BRUSH_MODE_SCALED, /**< Just scale the brush pixels */ + GFX_BRUSH_MODE_ELLIPSES, /**< Replace pixels with ellipses */ + GFX_BRUSH_MODE_RANDOM_ELLIPSES, /**< Replace pixels with ellipses moved and re-scaled randomly */ + GFX_BRUSH_MODE_MORERANDOM /**< Distribute randomly */ }; @@ -269,18 +287,19 @@ enum gfx_line_style_t { enum gfx_rectangle_fill_t { - GFX_SHADE_FLAT, /* Don't shade */ - GFX_SHADE_VERTICALLY, /* Shade vertically */ - GFX_SHADE_HORIZONTALLY /* Shade horizontally */ + GFX_SHADE_FLAT, /**< Don't shade */ + GFX_SHADE_VERTICALLY, /**< Shade vertically */ + GFX_SHADE_HORIZONTALLY /**< Shade horizontally */ }; enum gfx_color_mode_t { - GFX_COLOR_MODE_AUTO = 0, /* Auto-detect- handled by the gfxop library */ - GFX_COLOR_MODE_INDEX = 1, /* Index mode */ - GFX_COLOR_MODE_HIGH = 2, /* High color mode (15bpp or 16 bpp) */ - GFX_COLOR_MODE_TRUE = 4 /* True color mode (24 bpp padded to 32 bpp) */ + GFX_COLOR_MODE_AUTO = 0, /**< Auto-detect- handled by the gfxop library */ + GFX_COLOR_MODE_INDEX = 1, /**< Index mode */ + GFX_COLOR_MODE_HIGH = 2, /**< High color mode (15bpp or 16 bpp) */ + GFX_COLOR_MODE_TRUE = 4 /**< True color mode (24 bpp padded to 32 bpp) */ }; +/** @} */ } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_tools.cpp b/engines/sci/gfx/gfx_tools.cpp index 4e570f5931..b835084b0c 100644 --- a/engines/sci/gfx/gfx_tools.cpp +++ b/engines/sci/gfx/gfx_tools.cpp @@ -163,7 +163,7 @@ gfx_pixmap_t *gfx_pixmap_alloc_index_data(gfx_pixmap_t *pixmap) { int size; if (pixmap->index_data) { - GFXWARN("Attempt to allocate pixmap index data twice!\n"); + warning("[GFX] Attempt to allocate pixmap index data twice"); return pixmap; } @@ -180,7 +180,7 @@ gfx_pixmap_t *gfx_pixmap_alloc_index_data(gfx_pixmap_t *pixmap) { gfx_pixmap_t *gfx_pixmap_free_index_data(gfx_pixmap_t *pixmap) { if (!pixmap->index_data) { - GFXWARN("Attempt to free pixmap index data twice!\n"); + warning("[GFX] Attempt to free pixmap index data twice"); return pixmap; } @@ -193,7 +193,7 @@ gfx_pixmap_t *gfx_pixmap_alloc_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode) { int size; if (pixmap->data) { - GFXWARN("Attempt to allocate pixmap data twice!\n"); + warning("[GFX] Attempt to allocate pixmap data twice"); return pixmap; } @@ -215,7 +215,7 @@ gfx_pixmap_t *gfx_pixmap_alloc_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode) { gfx_pixmap_t *gfx_pixmap_free_data(gfx_pixmap_t *pixmap) { if (!pixmap->data) { - GFXWARN("Attempt to free pixmap data twice!\n"); + warning("[GFX] Attempt to free pixmap data twice"); return pixmap; } diff --git a/engines/sci/gfx/gfx_tools.h b/engines/sci/gfx/gfx_tools.h index 8582dfa565..9b4ce32e89 100644 --- a/engines/sci/gfx/gfx_tools.h +++ b/engines/sci/gfx/gfx_tools.h @@ -23,9 +23,6 @@ * */ -/* SCI graphics subsystem helper functions */ - - #ifndef SCI_GFX_GFX_TOOLS_H #define SCI_GFX_GFX_TOOLS_H @@ -36,162 +33,198 @@ namespace Sci { +/** @name SCI graphics subsystem helper functions */ +/** @{ */ + enum gfx_xlate_filter_t { GFX_XLATE_FILTER_NONE, GFX_XLATE_FILTER_LINEAR, GFX_XLATE_FILTER_TRILINEAR }; +/** + * Allocates a new gfx_mode_t structure with the specified parameters + * + * @param[in] xfact Horizontal scaling factors + * @param[in] yfact Vertical scaling factors + * @param[in] format Pixel format description + * @param[in] palette Number of palette colors, 0 if we're not in palette mode + * @param[in] flags GFX_MODE_FLAG_* values ORred together, or just 0 + * @return A newly allocated gfx_mode_t structure + */ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags); -/* Allocates a new gfx_mode_t structure with the specified parameters -** Parameters: (int x int) xfact x yfact: Horizontal and vertical scaling factors -** (Graphics::PixelFormat) format: pixel format description -** (int) palette: Number of palette colors, 0 if we're not in palette mode -** (int) flags: GFX_MODE_FLAG_* values ORred together, or just 0 -** Returns : (gfx_mode_t *) A newly allocated gfx_mode_t structure -*/ - +/** + * Clips a rect_t + * + * @param[in] box Pointer to the box to clip + * @param[in] maxx Maximum allowed width + * @param[in] maxy Maximum allowed height + */ void gfx_clip_box_basic(rect_t *box, int maxx, int maxy); -/* Clips a rect_t -** Parameters: (rect_t *) box: Pointer to the box to clip -** (int x int) maxx, maxy: Maximum allowed width and height -** Returns : (void) -*/ - +/** + * Frees all memory allocated by a mode structure + * @param[in] mode The mode to free + */ void gfx_free_mode(gfx_mode_t *mode); -/* Frees all memory allocated by a mode structure -** Parameters: (gfx_mode_t *) mode: The mode to free -** Returns : (void) -*/ - +/** + * Creates a new pixmap structure + * + * The following fiels are initialized: + * ID, loop, cel, index_width, index_height, xl, yl, data <- NULL, + * alpha_map <- NULL, internal.handle <- 0, internal.info <- NULL, + * colors <- NULL, index_scaled <- 0 + * + * @param[in] xl Width (in SCI coordinates) of the pixmap + * @param[in] yl Height (in SCI coordinates) of the pixmap + * @param[in] resid The pixmap's resource ID, or GFX_RESID_NONE + * @param[in] loop For views: The pixmap's loop number + * @param[in] cel For cels: The pixmap's cel number + * @return The newly allocated pixmap + */ gfx_pixmap_t *gfx_new_pixmap(int xl, int yl, int resid, int loop, int cel); -/* Creates a new pixmap structure -** Parameters: (int x int) xl x yl: The dimensions (in SCI coordinates) of the pixmap -** (int) resid: The pixmap's resource ID, or GFX_RESID_NONE -** (int) loop: For views: The pixmap's loop number -** (int) cel: For cels: The pixmap's cel number -** Returns : (gfx_pixmap_t *) The newly allocated pixmap -** The following fiels are initialized: -** ID, loop, cel, index_width, index_height, xl, yl, data <- NULL, -** alpha_map <- NULL, internal.handle <- 0, internal.info <- NULL, colors <- NULL, -** index_scaled <- 0 -*/ +/** + * Clones a pixmap, minus its index data, palette and driver-specific + * handles + * + * @param[in] pixmap The pixmap to clone + * @param[in] mode The mode to be applied to the pixmap + * @return The clone + */ gfx_pixmap_t *gfx_clone_pixmap(gfx_pixmap_t *pixmap, gfx_mode_t *mode); -/* Clones a pixmap, minus its index data, palette and driver-specific handles -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to clone -** (gfx_mode_t *) mode: The mode to be applied to the pixmap -** Returns : (gfx_pixmap_t *) The clone -*/ - +/** + * Allocates the index_data field of a pixmap + * + * @param[in] pixmap The pixmap to allocate for + * @return The pixmap + */ gfx_pixmap_t *gfx_pixmap_alloc_index_data(gfx_pixmap_t *pixmap); -/* Allocates the index_data field of a pixmap -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to allocate for -** Returns : (gfx_pixmap_t *) pixmap -*/ +/** + * Frees the index_data field of a pixmap + * + * @param[in] pixmap The pixmap to modify + * @return The pixmap + */ gfx_pixmap_t *gfx_pixmap_free_index_data(gfx_pixmap_t *pixmap); -/* Frees the index_data field of a pixmap -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to modify -** Returns : (gfx_pixmap_t *) pixmap -*/ +/** + * Allocates the data field of a pixmap + * + * @param[in] pixmap The pixmap to allocate for + * @param[in] mode The mode the memory is to be allocated for + * @return The pixmap + */ gfx_pixmap_t *gfx_pixmap_alloc_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode); -/* Allocates the data field of a pixmap -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to allocate for -** (gfx_mode_t *) mode: The mode the memory is to be allocated for -** Returns : (gfx_pixmap_t *) pixmap -*/ +/** + * Frees the memory allocated for a pixmap's data field + * + * @param[in] pixmap The pixmap to modify + * @return The pixmap + */ gfx_pixmap_t *gfx_pixmap_free_data(gfx_pixmap_t *pixmap); -/* Frees the memory allocated for a pixmap's data field -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap to modify -** Returns : (gfx_pixmap_t *) pixmap -*/ +/** + * Frees all memory associated with a pixmap + * + * @param[in] pxm The pixmap to free + */ void gfx_free_pixmap(gfx_pixmap_t *pxm); -/* Frees all memory associated with a pixmap -** Parameters: (gfx_pixmap_t *) pxm: The pixmap to free -** Returns : (void) -*/ - -void gfx_draw_line_pixmap_i(gfx_pixmap_t *pxm, Common::Point start, Common::Point end, int color); -/* Draws a line to a pixmap's index data buffer -** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw to -** (Common::Point) start: Starting point of the line to draw -** (Common::Point) end: End point of the line to draw -** (int) color: The byte value to write -** Returns : (void) -** Remember, this only draws to the /index/ buffer, not to the drawable buffer. -** The line is not clipped. Invalid x, y, x1, y1 values will result in memory corruption. -*/ +/** + * Draws a line to a pixmap's index data buffer + * + * Remember, this only draws to the /index/ buffer, not to the drawable buffer. + * The line is not clipped. Invalid x, y, x1, y1 values will result in memory + * corruption. + * + * @param[in] pxm The pixmap to draw to + * @param[in] start Starting point of the line to draw + * @param[in] end End point of the line to draw + * @param[in] color The byte value to write + */ +void gfx_draw_line_pixmap_i(gfx_pixmap_t *pxm, Common::Point start, + Common::Point end, int color); + +/** + * Draws a filled rectangular area to a pixmap's index buffer + * + * This function only draws to the index buffer. + * + * @param[in] pxm The pixmap to draw to + * @param[in] box The box to fill + * @param[in] color The color to use for drawing + */ void gfx_draw_box_pixmap_i(gfx_pixmap_t *pxm, rect_t box, int color); -/* Draws a filled rectangular area to a pixmap's index buffer -** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw to -** (rect_t) box: The box to fill -** (int) color: The color to use for drawing -** Returns : (void) -** This function only draws to the index buffer. -*/ +/** + * Copies part of a pixmap to another pixmap, with clipping + * + * @param[in] dest The destination pixmap + * @param[in] src The source pixmap + * @param[in] box The area to copy + */ void gfx_copy_pixmap_box_i(gfx_pixmap_t *dest, gfx_pixmap_t *src, rect_t box); -/* Copies part of a pixmap to another pixmap, with clipping -** Parameters: (gfx_pixmap_t *) dest: The destination pixmap -** (gfx_pixmap_t *) src: The source pixmap -** (rect_t) box: The area to copy -** Returns : (void) -*/ +/** + * Translates a pixmap's index data to drawable graphics data + * + * @param[in] pxm The pixmap to translate + * @param[in] mode The mode according which to scale + * @param[in] filter How to filter the data + */ void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t filter); -/* Translates a pixmap's index data to drawable graphics data -** Parameters: (gfx_pixmap_t *) pxm: The pixmap to translate -** (gfx_mode_t *) mode: The mode according which to scale -** (gfx_xlate_filter_t) filter: How to filter the data -** Returns : (void) -*/ -#define GFX_CROSSBLIT_FLAG_DATA_IS_HOMED (1<<0) -/* Means that the first byte in the visual data refers to the -** point corresponding to (dest.x, dest.y) */ +#define GFX_CROSSBLIT_FLAG_DATA_IS_HOMED (1<<0) /**< Means that the first byte in the visual data refers to the point corresponding to (dest.x, dest.y) */ +/** + * Transfers the non-transparent part of a pixmap to a linear pixel + * buffer. + * + * A 'linear buffer' in this context means a data buffer containing an entire + * screen (visual or priority), with fixed offsets between each data row, and + * linear access. + * + * @param[in] mode The graphics mode of the target buffer + * @param[in] pxm The pixmap to transfer + * @param[in] priority The pixmap's priority + * @param[in] src_coords The source coordinates within the pixmap + * @param[in] dest_coords The destination coordinates (no scaling) + * @param[in] dest Memory position of the upper left pixel of + * the linear pixel buffer + * @param[in] dest_line_width Byte offset of the very first pixel in the + * second line of the linear pixel buffer, + * relative to dest. + * @param[in] priority_dest Destination buffer for the pixmap's priority + * values + * @param[in] priority_line_width Byte offset of the first pixel in the second + * line of the priority buffer + * @param[in] priority_skip Amount of bytes allocated by each priority + * value + * @param[in] flags Any crossblit flags + * @return GFX_OK, or GFX_ERROR if the specified mode + * was invalid or unsupported + */ int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority, rect_t src_coords, rect_t dest_coords, byte *dest, int dest_line_width, byte *priority_dest, int priority_line_width, int priority_skip, int flags); -/* Transfers the non-transparent part of a pixmap to a linear pixel buffer -** Parameters: (gfx_mode_t *) mode: The graphics mode of the target buffer -** (gfx_pixmap_t *) pxm: The pixmap to transfer -** (int priority): The pixmap's priority -** (rect_t) src_coords: The source coordinates within the pixmap -** (rect_t) dest_coords: The destination coordinates (no scaling) -** (byte *) dest: Memory position of the upper left pixel of the -** linear pixel buffer -** (int) dest_line_width: Byte offset of the very first pixel in the -** second line of the linear pixel buffer, -** relative to dest. -** (byte *) priority_dest: Destination buffer for the pixmap's priority -** values -** (int) priority_line_width: Byte offset of the first pixel in the -** second line of the priority buffer -** (int) priority_skip: Amount of bytes allocated by each priority value -** (int) flags: Any crossblit flags -** Returns : (int) GFX_OK, or GFX_ERROR if the specified mode was invalid or unsupported -** A 'linear buffer' in this context means a data buffer containing an entire -** screen (visual or priority), with fixed offsets between each data row, and -** linear access. -*/ + +/** + * Scales the index data associated with a pixmap + * + * @param[in] pixmap The pixmap whose index data should be scaled + * @param[in] mode The mode to scale it to + * @return The pixmap + */ gfx_pixmap_t *gfx_pixmap_scale_index_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode); -/* Scales the index data associated with a pixmap -** Parameters: (gfx_pixmap_t *) pixmap: The pixmap whose index data should be scaled -** (gfx_mode_t *) mode: The mode to scale it to -** Returns : (gfx_pixmap_t *) pixmap -*/ +/** @} */ } // End of namespace Sci #endif // SCI_GFX_GFX_TOOLS_H diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp index 08600c94b2..2207309f48 100644 --- a/engines/sci/gfx/gfx_widgets.cpp +++ b/engines/sci/gfx/gfx_widgets.cpp @@ -681,10 +681,10 @@ int GfxDynView::draw(const Common::Point &pos) { else error("GfxDynView::print: Invalid type %d", _type); - sciprintf(" SORT=%d z=%d seq=%d (%d/%d/%d)@(%d,%d)[p:%d,c:%d]; sig[%04x@%p]", force_precedence, _z, + sciprintf(" SORT=%d z=%d seq=%d (%d/%d/%d)@(%d,%d)[p:%d,c:%d]; sig[%04x@%04X:%04X[%d]]", force_precedence, _z, sequence, _view, _loop, _cel, _pos.x, _pos.y, (_color.mask & GFX_MASK_PRIORITY) ? _color.priority : -1, - (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1, signal, signalp); + (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1, signal, signalp.obj.segment, signalp.obj.offset, signalp.varindex); } static int _gfxwop_dyn_view_equals(GfxWidget *widget, GfxWidget *other) { @@ -794,9 +794,9 @@ GfxDynView::GfxDynView(GfxState *state, Common::Point pos_, int z_, int view_, i draw_bounds = gfx_rect(_pos.x - xalignmod, _pos.y - yalignmod - z_, width, height); _bounds = gfx_rect(_pos.x - offset.x - xalignmod, _pos.y - offset.y - yalignmod - z_, width, height); - under_bitsp = NULL; + under_bitsp.obj = NULL_REG; under_bits = 0; - signalp = NULL; + signalp.obj = NULL_REG; signal = 0; _z = z_; sequence = sequence_; @@ -1270,7 +1270,7 @@ static int _gfxwop_list_equals(GfxWidget *widget, GfxWidget *other) { return 0; if (!GFXW_IS_LIST(widget)) { - GFXWARN("_gfxwop_list_equals(): Method called on non-list!\n"); + warning("[GFX] _gfxwop_list_equals(): Method called on non-list"); widget->print(0); sciprintf("\n"); return 0; @@ -1508,7 +1508,7 @@ GfxPort::~GfxPort() { } if (_visual->_portRefs[_ID] != this) { - GFXWARN("While freeing port %d: Port is at %p, but port list indicates %p", _ID, (void *)this, (void *)_visual->_portRefs[_ID]); + warning("[GFX] While freeing port %d: Port is at %p, but port list indicates %p", _ID, (void *)this, (void *)_visual->_portRefs[_ID]); } else _visual->_portRefs[_ID] = NULL; @@ -1542,7 +1542,7 @@ int GfxPort::setVisual(GfxVisual *visual) { if (_decorations) if (_decorations->setVisual(visual)) { - GFXWARN("Setting the visual for decorations failed for port "); + warning("[GFX] Setting the visual for decorations failed for port "); this->print(1); return 1; } @@ -1631,7 +1631,7 @@ GfxPort *gfxw_remove_port(GfxVisual *visual, GfxPort *port) { VERIFY_WIDGET(port); if (!visual->_contents) { - GFXWARN("Attempt to remove port from empty visual\n"); + warning("[GFX] Attempt to remove port from empty visual"); return NULL; } @@ -1671,7 +1671,7 @@ GfxWidget *gfxw_set_id(GfxWidget *widget, int ID, int subID) { return widget; } -GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, void *under_bitsp, int signal, void *signalp) { +GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, const ObjVarRef& under_bitsp, int signal, const ObjVarRef& signalp) { if (!widget) return NULL; diff --git a/engines/sci/gfx/gfx_widgets.h b/engines/sci/gfx/gfx_widgets.h index 6c8e848664..80129152cb 100644 --- a/engines/sci/gfx/gfx_widgets.h +++ b/engines/sci/gfx/gfx_widgets.h @@ -23,7 +23,6 @@ * */ -/* Graphical state management */ #ifndef SCI_GFX_GFX_WIDGETS_H #define SCI_GFX_GFX_WIDGETS_H @@ -34,6 +33,8 @@ #include "sci/gfx/operations.h" namespace Sci { +/** @name Widget Graphical State Management */ +/** @{ */ struct GfxState; struct GfxBox; @@ -155,241 +156,324 @@ extern Common::Point gfxw_point_zero; /*-- Primitive types --*/ +/** + * Creates a new box + * + * The graphics state, if non-NULL, is used here for some optimizations. + * + * @param[in] state The (optional) state + * @param[in] area The box's dimensions, relative to its container + * widget + * @param[in] color1 The primary color + * @param[in] color2 The secondary color (ignored if shading is disabled) + * @param[in] shade_type The shade type for the box + * @return The resulting box widget + */ GfxBox *gfxw_new_box(GfxState *state, rect_t area, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type); -/* Creates a new box -** Parameters: (GfxState *) state: The (optional) state -** (rect_t) area: The box's dimensions, relative to its container widget -** (gfx_color_t) color1: The primary color -** (gfx_color_t) color1: The secondary color (ignored if shading is disabled) -** (gfx_box_shade_t) shade_type: The shade type for the box -** Returns : (GfxBox *) The resulting box widget -** The graphics state- if non-NULL- is used here for some optimizations. -*/ -GfxPrimitive *gfxw_new_rect(rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); -/* Creates a new rectangle -** Parameters: (rect_t) rect: The rectangle area -** (gfx_color_t) color: The rectangle's color -** (gfx_line_mode_t) line_mode: The line mode for the lines that make up the rectangle -** (gfx_line_style_t) line_style: The rectangle's lines' style -** Returns : (GfxPrimitive *) The newly allocated rectangle widget (a Primitive) -*/ +/** + * Creates a new rectangle + * + * @param[in] rect The rectangle area + * @param[in] color The rectangle's color + * @param[in] line_mode The line mode for the lines that make up the + * rectangle + * @param[in] line_style The rectangle's lines' style + * @return The newly allocated rectangle widget (a Primitive) + */ +GfxPrimitive *gfxw_new_rect(rect_t rect, gfx_color_t color, + gfx_line_mode_t line_mode, gfx_line_style_t line_style); -GfxPrimitive *gfxw_new_line(Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); -/* Creates a new line -** Parameters: (Common::Point * Common::Point) (start, line): The line origin and end point -** (gfx_color_t) color: The line's color -** (gfx_line_mode_t) line_mode: The line mode to use for drawing -** (gfx_line_style_t) line_style: The line style -** Returns : (GfxPrimitive *) The newly allocated line widget (a Primitive) -*/ +/** + * Creates a new line + * + * @param[in] start The line's origin + * @param[in] end The line's end point + * @param[in] color The line's color + * @param[in] line_mode The line mode to use for drawing + * @param[in] line_style The line style + * @return The newly allocated line widget (a Primitive) + */ +GfxPrimitive *gfxw_new_line(Common::Point start, Common::Point end, + gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); +/** View flags */ +enum { + GFXW_VIEW_FLAG_STATIC = (1 << 0), /**< Whether the view should be static */ + GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET = (1 << 1) /**< Whether the view should _not_ apply its x/y offset modifyers */ +}; -/* Whether the view should be static */ -#define GFXW_VIEW_FLAG_STATIC (1 << 0) - -/* Whether the view should _not_ apply its x/y offset modifyers */ -#define GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET (1 << 1) - -GfxView *gfxw_new_view(GfxState *state, Common::Point pos, int view, int loop, int cel, int palette, int priority, int control, - gfx_alignment_t halign, gfx_alignment_t valign, int flags); -/* Creates a new view (a cel, actually) -** Parameters: (GfxState *) state: The graphics state -** (Common::Point) pos: The position to place the view at -** (int x int x int) view, loop, cel: The global cel ID -** (int) priority: The priority to use for drawing, or -1 for none -** (int) control: The value to write to the control map, or -1 for none -** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and vertical -** cel alignment -** (int) flags: Any combination of GFXW_VIEW_FLAGs -** Returns : (gfxw_cel_t *) A newly allocated cel according to the specs -*/ +/** + * Creates a new view (a cel, actually) + * + * @param[in] state The graphics state + * @param[in] pos The position to place the view at + * @param[in] view The global cel ID + * @param[in] loop The global cel ID + * @param[in] cel The global cel ID + * @param[in] palette The palette to use + * @param[in] priority The priority to use for drawing, or -1 for none + * @param[in] control The value to write to the control map, or -1 for none + * @param[in] halign Horizontal cel alignment + * @param[in] valign Vertical cel alignment + * @param[in] flags Any combination of GFXW_VIEW_FLAGs + * @return A newly allocated cel according to the specs + */ +GfxView *gfxw_new_view(GfxState *state, Common::Point pos, int view, int loop, + int cel, int palette, int priority, int control, gfx_alignment_t halign, + gfx_alignment_t valign, int flags); -GfxDynView *gfxw_new_dyn_view(GfxState *state, Common::Point pos, int z, int view, int loop, int cel, int palette, - int priority, int control, gfx_alignment_t halign, gfx_alignment_t valign, int sequence); -/* Creates a new dyn view -** Parameters: (GfxState *) state: The graphics state -** (Common::Point) pos: The position to place the dynamic view at -** (int) z: The z coordinate -** (int x int x int) view, loop, cel: The global cel ID -** (int) priority: The priority to use for drawing, or -1 for none -** (int) control: The value to write to the control map, or -1 for none -** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and vertical -** cel alignment -** (int) sequence: Sequence number: When sorting dynviews, this number is -** considered last for sorting (ascending order) -** Returns : (gfxw_cel_t *) A newly allocated cel according to the specs -** Dynamic views are non-pic views with a unique global identifyer. This allows for drawing -** optimizations when they move or change shape. -*/ -GfxText *gfxw_new_text(GfxState *state, rect_t area, int font, const char *text, gfx_alignment_t halign, - gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2, - gfx_color_t bgcolor, int flags); -/* Creates a new text widget -** Parameters: (GfxState *) state: The state the text is to be calculated from -** (rect_t) area: The area the text is to be confined to (the yl value is only -** relevant for text aligment, though) -** (int) font: The number of the font to use -** (gfx_alignment_t x gfx_alignment_t) halign, valign: Horizontal and -** vertical text alignment -** (gfx_color_t x gfx_color_t) color1, color2: Text foreground colors (if not equal, -** The foreground is dithered between them) -** (gfx_color_t) bgcolor: Text background color -** (int) flags: GFXR_FONT_FLAGs, orred together (see gfx_resource.h) -** Returns : (GfxText *) The resulting text widget -*/ +/** + * Creates a new dyn view + * + * Dynamic views are non-pic views with a unique global identifyer. This allows for drawing optimizations when they move or change shape. + * + * @param[in] state The graphics state + * @param[in] pos The position to place the dynamic view at + * @param[in] z The z coordinate + * @param[in] view The global cel ID + * @param[in] loop The global cel ID + * @param[in] cel The global cel ID + * @param[in] palette The palette to use + * @param[in] priority The priority to use for drawing, or -1 for none + * @param[in] control The value to write to the control map, or -1 for none + * @param[in] halign Horizontal cel alignment + * @param[in] valign Vertical cel alignment + * @param[in] sequence Sequence number: When sorting dynviews, this number is + * considered last for sorting (ascending order) + * @return A newly allocated cel according to the specs + */ +GfxDynView *gfxw_new_dyn_view(GfxState *state, Common::Point pos, int z, + int view, int loop, int cel, int palette, int priority, int control, + gfx_alignment_t halign, gfx_alignment_t valign, int sequence); +/** + * Creates a new text widget + * + * @param[in] state The state the text is to be calculated from + * @param[in] area The area the text is to be confined to (the yl value is + * only relevant for text aligment, though) + * @param[in] font The number of the font to use + * @param[in] text String to put in text widget + * @param[in] halign Horizontal text alignment + * @param[in] valign Vertical text alignment + * @param[in] color1 Text foreground colors (if not equal, the foreground is + * dithered between them) + * @param[in] color2 Text foreground colors (if not equal, the foreground is + * dithered between them) + * @param[in] bgcolor Text background color + * @param[in] flags GFXR_FONT_FLAGs, orred together (see gfx_resource.h) + * @return The resulting text widget + */ +GfxText *gfxw_new_text(GfxState *state, rect_t area, int font, const char *text, + gfx_alignment_t halign, gfx_alignment_t valign, gfx_color_t color1, + gfx_color_t color2, gfx_color_t bgcolor, int flags); + +/** + * Determines text widget meta-information + * + * @param[in] state The state to operate on + * @param[in] text The widget to query + * @param[out] lines_nr Number of lines used in the text + * @param[out] lineheight Pixel height (SCI scale) of each text line + * @param[out] offset Pixel offset (SCI scale) of the space after the last + * character in the last line + */ void gfxw_text_info(GfxState *state, GfxText *text, int *lines_nr, int *lineheight, int *offset); -/* Determines text widget meta-information -** Parameters: (GfxState *) state: The state to operate on -** (gfx_text_t *) text: The widget to query -** Returns : (int) lines_nr: Number of lines used in the text -** (int) lineheight: Pixel height (SCI scale) of each text line -** (int) offset: Pixel offset (SCI scale) of the space after the -** last character in the last line -*/ +/** + * Sets a widget's ID + * + * A widget ID is unique within the container it is stored in, if and only if it + * was added to that container with gfxw_add(). This function handles widget == + * NULL gracefully (by doing nothing and returning NULL). + * + * @param[in] widget The widget whose ID should be set + * @param[in] ID The ID to set + * @param[in] subID The ID to set + * @return The widget + */ GfxWidget *gfxw_set_id(GfxWidget *widget, int ID, int subID); -/* Sets a widget's ID -** Parmaeters: (GfxWidget *) widget: The widget whose ID should be set -** (int x int) ID, subID: The ID to set -** Returns : (GfxWidget *) widget -** A widget ID is unique within the container it is stored in, if and only if it was -** added to that container with gfxw_add(). -** This function handles widget = NULL gracefully (by doing nothing and returning NULL). -*/ +/** + * Finds a widget with a specific ID in a container and removes it from there + * + * Search is non-recursive; widgets with IDs hidden in subcontainers will not + * be found. + * + * @param[in] container The container to search in + * @param[in] ID The ID to look for + * @param[in] subID The subID to look for, or GFXW_NO_ID for any + * @return The resulting widget or NULL if no match was found + */ GfxWidget *gfxw_remove_id(GfxContainer *container, int ID, int subID); -/* Finds a widget with a specific ID in a container and removes it from there -** Parameters: (GfxContainer *) container: The container to search in -** (int) ID: The ID to look for -** (int) subID: The subID to look for, or GFXW_NO_ID for any -** Returns : (GfxWidget *) The resulting widget or NULL if no match was found -** Search is non-recursive; widgets with IDs hidden in subcontainers will not be found. -*/ +/** + * Initializes a dyn view's interpreter attributes + * + * @param[in] widget The widget affected + * @param[in] under_bits Interpreter-dependant data + * @param[in] under_bitsp Interpreter-dependant data + * @param[in] signal Interpreter-dependant data + * @param[in] signalp Interpreter-dependant data + * @return The widget + */ +GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, + const ObjVarRef& under_bitsp, int signal, const ObjVarRef& signalp); -GfxDynView *gfxw_dyn_view_set_params(GfxDynView *widget, int under_bits, void *under_bitsp, int signal, void *signalp); -/* Initializes a dyn view's interpreter attributes -** Parameters: (GfxDynView *) widget: The widget affected -** (int x void * x int x void *) under_bits, inder_bitsp, signal, signalp: Interpreter-dependant data -** Returns : (GfxDynView *) widget -*/ - +/** + * Makes a widget invisible without removing it from the list of widgets + * + * Has no effect on invisible widgets + * + * @param[in] widget The widget to invisibilize + * @return The widget + */ GfxWidget *gfxw_hide_widget(GfxWidget *widget); -/* Makes a widget invisible without removing it from the list of widgets -** Parameters: (GfxWidget *) widget: The widget to invisibilize -** Returns : (GfxWidget *) widget -** Has no effect on invisible widgets -*/ +/** + * Makes an invisible widget reappear + * + * Does not affect visible widgets + * + * @param[in] widget The widget to show again + * @return The widget + */ GfxWidget *gfxw_show_widget(GfxWidget *widget); -/* Makes an invisible widget reappear -** Parameters: (GfxWidget *) widget: The widget to show again -** Returns : (GfxWidget *) widget -** Does not affect visible widgets -*/ +/** + * Marks a widget as "abandoned" + * + * @param[in] widget The widget to abandon + * @return The widget + */ GfxWidget *gfxw_abandon_widget(GfxWidget *widget); -/* Marks a widget as "abandoned" -** Parameters: (GfxWidget *) widget: The widget to abandon -** Returns : (GfxWidget *) widget -*/ - -/*-- Container types --*/ -#define GFXW_LIST_UNSORTED 0 -#define GFXW_LIST_SORTED 1 +/** Container types */ +enum { + GFXW_LIST_UNSORTED = 0, + GFXW_LIST_SORTED = 1 +}; +/** + * Creates a new list widget + * + * List widgets are also referred to as Display Lists. + * + * @param[in] area The area covered by the list (absolute position) + * @param[in] sorted Whether the list should be a sorted list + * @return A newly allocated list widget + */ GfxList *gfxw_new_list(rect_t area, int sorted); -/* Creates a new list widget -** Parameters: (rect_t) area: The area covered by the list (absolute position) -** (int) sorted: Whether the list should be a sorted list -** Returns : (GfxList *) A newly allocated list widget -** List widgets are also referred to as Display Lists. -*/ +/** + * Retrieves the default port from a visual + * + * The 'default port' is the last port to be instantiated; usually the topmost + * or highest-ranking port. + * + * @param[in] visual The visual the port should be retrieved from + * @return The default port, or NULL if no port is present + */ GfxPort *gfxw_find_default_port(GfxVisual *visual); -/* Retrieves the default port from a visual -** Parameters: (GfxVisual *) visual: The visual the port should be retrieved from -** Returns : (GfxPort *) The default port, or NULL if no port is present -** The 'default port' is the last port to be instantiated; usually the topmost -** or highest-ranking port. -*/ +/** + * Sets rectangle to be restored upon port removal + * + * @param[in] visual The visual to operate on + * @param[in] window The affected window + * @param[in] auto_rect The area to restore + */ void gfxw_port_set_auto_restore(GfxVisual *visual, GfxPort *window, rect_t auto_rect); -/* Sets rectangle to be restored upon port removal -** Parameters: (state_t *) s: The state to operate on -** (GfxPort *) window: The affected window -** (rect_t) auto_rect: The area to restore -** Returns : (void) -*/ +/** + * Removes a port from a visual + * + * @param[in] visual The visual the port should be removed from + * @param[in] port The port to remove + * @return port's parent port, or NULL if it had none + */ GfxPort *gfxw_remove_port(GfxVisual *visual, GfxPort *port); -/* Removes a port from a visual -** Parameters: (GfxVisual *) visual: The visual the port should be removed from -** (GfxPort *) port: The port to remove -** Returns : (GfxPort *) port's parent port, or NULL if it had none -*/ +/** + * Removes the widget from the specified port + * + * @param[in] container The container it should be removed from + * @param[in] widget The widget to remove + */ void gfxw_remove_widget_from_container(GfxContainer *container, GfxWidget *widget); -/* Removes the widget from the specified port -** Parameters: (GfxContainer *) container: The container it should be removed from -** (GfxWidget *) widget: The widget to remove -** Returns : (void) -*/ +/** + * Makes a "snapshot" of a visual + * + * It's not really a full qualified snaphot, though. See gfxw_restore_snapshot + * for a full discussion. This operation also increases the global serial number + * counter by one. + * + * @param[in] visual The visual a snapshot is to be taken of + * @param[in] area The area a snapshot should be taken of + * @return The resulting, newly allocated snapshot + */ gfxw_snapshot_t *gfxw_make_snapshot(GfxVisual *visual, rect_t area); -/* Makes a "snapshot" of a visual -** Parameters: (GfxVisual *) visual: The visual a snapshot is to be taken of -** (rect_t) area: The area a snapshot should be taken of -** Returns : (gfxw_snapshot_t *) The resulting, newly allocated snapshot -** It's not really a full qualified snaphot, though. See gfxw_restore_snapshot -** for a full discussion. -** This operation also increases the global serial number counter by one. -*/ +/** + * Predicate to test whether a widget would be destroyed by applying a snapshot + * + * @param[in] snapshot The snapshot to test against + * @param[in] widget The widget to test + * @return An appropriate boolean value + */ int gfxw_widget_matches_snapshot(gfxw_snapshot_t *snapshot, GfxWidget *widget); -/* Predicate to test whether a widget would be destroyed by applying a snapshot -** Parameters: (gfxw_snapshot_t *) snapshot: The snapshot to test against -** (GfxWidget *) widget: The widget to test -** Retunrrs : (int) An appropriate boolean value -*/ +/** + * Restores a snapshot to a visual + * + * The snapshot is not really restored; only more recent widgets touching + * the snapshotted area are destroyed. + * + * @param[in] visual The visual to operate on + * @param[in] snapshot The snapshot to restore + * @return The snapshot (still needs to be freed) + */ gfxw_snapshot_t *gfxw_restore_snapshot(GfxVisual *visual, gfxw_snapshot_t *snapshot); -/* Restores a snapshot to a visual -** Parameters: (GfxVisual *) visual: The visual to operate on -** (gfxw_snapshot_t *) snapshot: The snapshot to restore -** Returns : (gfxw_snapshot_t *) snapshot (still needs to be freed) -** The snapshot is not really restored; only more recent widgets touching -** the snapshotted area are destroyed. -*/ +/** + * As widget->widfree(widget), but destroys all overlapping widgets + * + * This operation calls widget->widfree(widget), but it also destroys all + * widgets with a higher or equal priority drawn after this widget. + * + * @param[in] widget The widget to use + */ void gfxw_annihilate(GfxWidget *widget); -/* As widget->widfree(widget), but destroys all overlapping widgets -** Parameters: (GfxWidget *) widget: The widget to use -** Returns : (void) -** This operation calls widget->widfree(widget), but it also destroys -** all widgets with a higher or equal priority drawn after this widget. -*/ +/** + * Turns a dynview into a picview + * + * The only changes are in function and type variables, actually. + * + * @param[in] dynview The victim + * @return The victim, after his transformation + */ GfxDynView *gfxw_picviewize_dynview(GfxDynView *dynview); -/* Turns a dynview into a picview -** Parameters: (GfxDynView *) dynview: The victim -** Returns : (GfxDynView *) The victim, after his transformation -** The only changes are in function and type variables, actually. -*/ -void gfxw_port_auto_restore_background(GfxVisual *visual, GfxPort *window, rect_t auto_rect); -/* Tags a window widget as automatically restoring the visual background upon removal -** Parameters: (gfx_visual_t *) visual: The base visual -** (GfxPort *) window: The window to tag -** (rect_t) auto_rect: The background to remember -** Also records the specified background rectangle, for later recovery -*/ +/** + * Tags a window widget as automatically restoring the visual background + * upon removal. + * + * Also records the specified background rectangle, for later recovery. + * + * @param[in] visual The base visual + * @param[in] window The window to tag + * @param[in] auto_rect The background to remember + + */ +void gfxw_port_auto_restore_background(GfxVisual *visual, GfxPort *window, + rect_t auto_rect); +/** @} */ } // End of namespace Sci #endif // SCI_GFX_GFX_WIDGETS_H diff --git a/engines/sci/gfx/menubar.h b/engines/sci/gfx/menubar.h index 02d99332d9..44ecd8f1bb 100644 --- a/engines/sci/gfx/menubar.h +++ b/engines/sci/gfx/menubar.h @@ -50,9 +50,7 @@ struct EngineState; /* The number of pixels added to the left of the first menu */ #define MENU_BOX_CENTER_PADDING 10 -/* Number of pixels to leave in between the left and the right centered text content in boxes -** that use right centered content -*/ +/* Number of pixels to leave in between the left and the right centered text content in boxes that use right centered content */ #define MENU_BOX_LEFT_PADDING 0 /* Number of pixels to pad to the left */ @@ -88,16 +86,16 @@ enum MenuType { class MenuItem : public Common::Serializable { public: - MenuType _type; /* Normal or hbar */ - Common::String _keytext; /* right-centered part of the text (the key) */ + MenuType _type; /**< Normal or hbar */ + Common::String _keytext; /**< right-centered part of the text (the key) */ int _flags; - byte _said[MENU_SAID_SPEC_SIZE]; /* Said spec for this item */ + byte _said[MENU_SAID_SPEC_SIZE]; /**< Said spec for this item */ reg_t _saidPos; Common::String _text; reg_t _textPos; - int _modifiers; /* Hotkey for this item */ - int _key; /* Hotkey for this item */ + int _modifiers; /**< Hotkey for this item */ + int _key; /**< Hotkey for this item */ int _enabled; int _tag; @@ -108,9 +106,10 @@ public: /** * Determines whether a message/modifiers key pair matches a menu item's key parameters. - * @param message The message to match - * @param modifiers The modifier flags to match - * @return true on match, false otherwise + * + * @param[in] message The message to match + * @param[in] modifiers The modifier flags to match + * @return true on match, false otherwise */ bool matchKey(int message, int modifiers); }; @@ -156,59 +155,68 @@ public: /** * Adds a menu to the menubar. - * Parameters: (GfxState *) state: The state the fonts are stored in - * (char *) title: The menu title - * (char *) entries: A string of menu entries - * (int) font: The font which is to be used for drawing - * (reg_t) entries_base: Segmented VM address of the entries string - * Returns : (void) + * * The menu entries use the following special characters: * '`' : Right justify the following part * ':' : End of this entry * '#' : Function key (replaced by 'F') * '^' : Control key (replaced by \002, which looks like "CTRL") * '=' : Initial tag value - * and the special string "--!", which represents a horizontal bar in the menu. + * and the special string "--!", which represents a horizontal bar in the + * menu. + * + * @param[in] state The state the fonts are stored in + * @param[in] title The menu title + * @param[in] entries A string of menu entries + * @param[in] font The font which is to be used for drawing + * @param[in] entries_base Segmented VM address of the entries string */ void addMenu(GfxState *state, const char *title, const char *entries, int font, reg_t entries_base); /** - * Sets the (currently unidentified) foo and bar values. - * Parameters: (state_t *) s: The current state - * (int) menu: The menu number to edit - * (int) item: The menu item to change - * (int) attribute: The attribute to modify - * (int) value: The value the attribute should be set to - * Returns : (int) 0 on success, 1 if either menu or item were invalid + * Sets the attributes for a menu item. + * + * @param[in] s The current state + * @param[in] menu The menu number to edit + * @param[in] item The menu item to change + * @param[in] attribute The attribute to modify + * @param[in] value The value the attribute should be set to + * @return 0 on success, 1 if either menu or item were invalid */ int setAttribute(EngineState *s, int menu, int item, int attribute, reg_t value); /** - * Sets the (currently unidentified) foo and bar values. - * Parameters: (int) menu: The menu number - * (int) item: The menu item to read - * (int) attribute: The attribute to read from - * Returns : (int) The attribute value, or -1 on error + * Gets an attribute for a menuitem. + * + * @param[in] menu The menu number + * @param[in] item The menu item to read + * @param[in] attribute The attribute to read from + * @return The attribute value, or -1 on error */ reg_t getAttribute(int menu, int item, int attribute) const; /** * Determines whether the specified menu entry may be activated. - * @return true if the menu item may be selected, false otherwise + * + * @return true if the menu item may be selected, false otherwise */ bool itemValid(int menu, int item) const; /** * Maps the pointer position to a (menu,item) tuple. - * @param pointerPos the current pointer position - * @param menu_nr the current menu (updated by this function if necessary) - * @param item_nr the current menu item (updated by this function if necessary) - * @param port the port of the currently active menu (if any) - * @return true if the pointer is outside a valid port, false otherwise. + * + * @param[in] pointerPos the current pointer position + * @param[in] menu_nr the current menu (updated by this function if + * necessary) + * @param[in] item_nr the current menu item (updated by this function + * if necessary) + * @param[in] port the port of the currently active menu (if any) + * @return true if the pointer is outside a valid port, + * false otherwise. */ bool mapPointer(const Common::Point &pointerPos, int &menu_nr, int &item_nr, GfxPort *port) const; diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index a730717ef8..1f7c4ed479 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -281,13 +281,13 @@ gfx_pixmap_t *_gfxr_get_cel(GfxState *state, int nr, int *loop, int *cel, int pa return NULL; if (*loop >= view->loops_nr || *loop < 0) { - GFXWARN("Attempt to get cel from loop %d/%d inside view %d\n", *loop, view->loops_nr, nr); + warning("[GFX] Attempt to get cel from loop %d/%d inside view %d", *loop, view->loops_nr, nr); return NULL; } indexed_loop = view->loops + *loop; if (*cel >= indexed_loop->cels_nr || *cel < 0) { - GFXWARN("Attempt to get cel %d/%d from view %d/%d\n", *cel, indexed_loop->cels_nr, nr, *loop); + warning("[GFX] Attempt to get cel %d/%d from view %d/%d", *cel, indexed_loop->cels_nr, nr, *loop); return NULL; } @@ -414,7 +414,8 @@ static void init_aux_pixmap(gfx_pixmap_t **pixmap) { int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, ResourceManager *resManager, Graphics::PixelFormat mode, int xfact, int yfact) { - int initialized = 0; + //int color_depth = bpp ? bpp : 1; + //int initialized = 0; BASIC_CHECKS(GFX_FATAL); @@ -662,7 +663,7 @@ static int line_clip(rect_t *line, rect_t clip, int xfact, int yfact) { return line_check_bar(&(line->x), &(line->width), clip.x, clip.width); } else { // "normal" line - float start = 0.0, end = 1.0; + float start = 0.0f, end = 1.0f; float xv = (float)line->width; float yv = (float)line->height; @@ -682,7 +683,7 @@ static int line_clip(rect_t *line, rect_t clip, int xfact, int yfact) { line->width = (int)(xv * (end - start)); line->height = (int)(yv * (end - start)); - return (start > 1.0 || end < 0.0); + return (start > 1.0f || end < 0.0f); } } @@ -806,7 +807,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common if (line_style == GFX_LINE_STYLE_STIPPLED) { if (start.x != end.x && start.y != end.y) { - GFXWARN("Attempt to draw stippled line which is neither an hbar nor a vbar: (%d,%d) -- (%d,%d)\n", start.x, start.y, end.x, end.y); + warning("[GFX] Attempt to draw stippled line which is neither an hbar nor a vbar: (%d,%d) -- (%d,%d)", start.x, start.y, end.x, end.y); return GFX_ERROR; } return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode); @@ -902,7 +903,7 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) { GfxDriver *drv = state->driver; int reverse = 0; // switch color1 and color2 - float mod_offset = 0.0, mod_breadth = 1.0; // 0.0 to 1.0: Color adjustment + float mod_offset = 0.0f, mod_breadth = 1.0f; // 0.0 to 1.0: Color adjustment gfx_rectangle_fill_t driver_shade_type; rect_t new_box; @@ -928,7 +929,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t return GFX_OK; if (box.width <= 1 || box.height <= 1) { - GFXDEBUG("Attempt to draw box with size %dx%d\n", box.width, box.height); + debugC(2, kDebugLevelGraphics, "Attempt to draw box with size %dx%d", box.width, box.height); return GFX_OK; } @@ -976,7 +977,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t return drv->drawFilledRect(new_box, color1, color1, GFX_SHADE_FLAT); } else { if (PALETTE_MODE) { - GFXWARN("Attempting to draw shaded box in palette mode!\n"); + warning("[GFX] Attempting to draw shaded box in palette mode"); return GFX_ERROR; } @@ -1183,7 +1184,7 @@ int gfxop_set_pointer_cursor(GfxState *state, int nr) { gfx_pixmap_t *new_pointer = state->gfxResMan->getCursor(nr); if (!new_pointer) { - GFXWARN("Attempt to set invalid pointer #%d\n", nr); + warning("[GFX] Attempt to set invalid pointer #%d\n", nr); return GFX_ERROR; } @@ -1200,12 +1201,12 @@ int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::P gfx_pixmap_t *new_pointer = _gfxr_get_cel(state, nr, &real_loop, &real_cel, 0); if (!new_pointer) { - GFXWARN("Attempt to set invalid pointer #%d\n", nr); + warning("[GFX] Attempt to set invalid pointer #%d", nr); return GFX_ERROR; } if (real_loop != loop || real_cel != cel) { - GFXDEBUG("Changed loop/cel from %d/%d to %d/%d in view %d\n", loop, cel, real_loop, real_cel, nr); + debugC(2, kDebugLevelGraphics, "Changed loop/cel from %d/%d to %d/%d in view %d\n", loop, cel, real_loop, real_cel, nr); } // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the user. Some scalers don't seem to support this. @@ -1227,7 +1228,7 @@ int gfxop_set_pointer_position(GfxState *state, Common::Point pos) { state->pointer_pos = pos; if (pos.x > 320 || pos.y > 200) { - GFXWARN("Attempt to place pointer at invalid coordinates (%d, %d)\n", pos.x, pos.y); + warning("[GFX] Attempt to place pointer at invalid coordinates (%d, %d)", pos.x, pos.y); return 0; // Not fatal } @@ -1420,8 +1421,9 @@ static sci_event_t scummvm_get_event(GfxDriver *drv) { // Debug console if (ev.kbd.flags == Common::KBD_CTRL && ev.kbd.keycode == Common::KEYCODE_d) { // Open debug console - ((Sci::SciEngine*)g_engine)->getDebugger()->attach(); - ((Sci::SciEngine*)g_engine)->getDebugger()->onFrame(); + Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); + con->attach(); + con->onFrame(); // Clear keyboard event input.type = SCI_EVT_NONE; @@ -1620,7 +1622,7 @@ int gfxop_lookup_view_get_loops(GfxState *state, int nr) { view = state->gfxResMan->getView(nr, &loop, &cel, 0); if (!view) { - GFXWARN("Attempt to retrieve number of loops from invalid view %d\n", nr); + warning("[GFX] Attempt to retrieve number of loops from invalid view %d", nr); return 0; } @@ -1636,10 +1638,10 @@ int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop) { view = state->gfxResMan->getView(nr, &real_loop, &cel, 0); if (!view) { - GFXWARN("Attempt to retrieve number of cels from invalid/broken view %d\n", nr); + warning("[GFX] Attempt to retrieve number of cels from invalid/broken view %d", nr); return 0; } else if (real_loop != loop) { - GFXWARN("Loop number was corrected from %d to %d in view %d\n", loop, real_loop, nr); + warning("[GFX] Loop number was corrected from %d to %d in view %d", loop, real_loop, nr); } return view->loops[real_loop].cels_nr; @@ -1651,7 +1653,7 @@ int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel) { gfxr_view_t *testView = state->gfxResMan->getView(nr, loop, cel, 0); if (!testView) { - GFXWARN("Attempt to verify loop/cel values for invalid view %d\n", nr); + warning("[GFX] Attempt to verify loop/cel values for invalid view %d", nr); return GFX_ERROR; } @@ -1666,7 +1668,7 @@ int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel) { gfxr_view_t *testView = state->gfxResMan->getView(nr, &loop_v, &cel_v, 0); if (!testView) { - GFXWARN("Attempt to verify loop/cel values for invalid view %d\n", nr); + warning("[GFX] Attempt to verify loop/cel values for invalid view %d", nr); return GFX_ERROR; } @@ -1688,7 +1690,7 @@ int gfxop_get_cel_parameters(GfxState *state, int nr, int loop, int cel, int *wi view = state->gfxResMan->getView(nr, &loop, &cel, 0); if (!view) { - GFXWARN("Attempt to get cel parameters for invalid view %d\n", nr); + warning("[GFX] Attempt to get cel parameters for invalid view %d", nr); return GFX_ERROR; } @@ -1712,7 +1714,7 @@ static int _gfxop_draw_cel_buffer(GfxState *state, int nr, int loop, int cel, Co view = state->gfxResMan->getView(nr, &loop, &cel, palette); if (!view) { - GFXWARN("Attempt to draw loop/cel %d/%d in invalid view %d\n", loop, cel, nr); + warning("[GFX] Attempt to draw loop/cel %d/%d in invalid view %d\n", loop, cel, nr); return GFX_ERROR; } pxm = view->loops[loop].cels[cel]; @@ -1994,7 +1996,7 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { } if (handle->lines.empty()) { - GFXDEBUG("Skipping draw_text operation because number of lines is zero\n"); + debugC(2, kDebugLevelGraphics, "Skipping draw_text operation because number of lines is zero\n"); return GFX_OK; } diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index ed71c32b65..d567934ceb 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -93,10 +93,10 @@ typedef Common::List<rect_t> DirtyRectList; struct GfxState { gfx_options_t *options; - Common::Point pointer_pos; /* Mouse pointer coordinates */ + Common::Point pointer_pos; /**< Mouse pointer coordinates */ - rect_t clip_zone_unscaled; /* The current UNSCALED clipping zone */ - rect_t clip_zone; /* The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */ + rect_t clip_zone_unscaled; /**< The current UNSCALED clipping zone */ + rect_t clip_zone; /**< The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */ GfxDriver *driver; @@ -104,543 +104,639 @@ struct GfxState { GfxResManager *gfxResMan; - gfx_pixmap_t *priority_map; /* back buffer priority map (unscaled) */ - gfx_pixmap_t *static_priority_map; /* static buffer priority map (unscaled) */ - gfx_pixmap_t *control_map; /* back buffer control map (only exists unscaled in the first place) */ + gfx_pixmap_t *priority_map; /**< back buffer priority map (unscaled) */ + gfx_pixmap_t *static_priority_map; /**< static buffer priority map (unscaled) */ + gfx_pixmap_t *control_map; /**< back buffer control map (only exists unscaled in the first place) */ - int tag_mode; /* Set to 1 after a new pic is drawn and the resource manager - ** has tagged all resources. Reset after the next front buffer - ** update is done, when all resources that are still tagged are - ** flushed. */ + int tag_mode; /**< Set to 1 after a new pic is drawn and the resource manager has tagged all resources. Reset after the next front buffer update is done, when all resources that are still tagged are flushed. */ - int disable_dirty; /* Set to 1 to disable dirty rect accounting */ + int disable_dirty; /**< Set to 1 to disable dirty rect accounting */ - int pic_nr; /* Number of the current pic */ - int palette_nr; /* Palette number of the current pic */ + int pic_nr; /**< Number of the current pic */ + int palette_nr; /**< Palette number of the current pic */ Common::List<sci_event_t> _events; - gfx_pixmap_t *fullscreen_override; /* An optional override picture which must have unscaled - ** full-screen size, which overrides all other visibility, and - ** which is generally slow */ + gfx_pixmap_t *fullscreen_override; /**< An optional override picture which must have unscaled full-screen size, which overrides all other visibility, and which is generally slow */ - gfxr_pic_t *pic, *pic_unscaled; /* The background picture and its unscaled equivalent */ - rect_t pic_port_bounds; /* Picture port bounds */ + gfxr_pic_t *pic, *pic_unscaled; /**< The background picture and its unscaled equivalent */ + rect_t pic_port_bounds; /**< Picture port bounds */ - DirtyRectList _dirtyRects; /* Dirty rectangles */ + DirtyRectList _dirtyRects; /**< Dirty rectangles */ }; -/**************************/ -/* Fundamental operations */ -/**************************/ - -int gfxop_init(int version, bool isVGA, GfxState *state, - gfx_options_t *options, ResourceManager *resManager, - Graphics::PixelFormat mode, int xfact = 1, int yfact = 1); -/* Initializes a graphics mode -** Parameters: (int) version: The interpreter version -** (GfxState *) state: The state to initialize -** (int x int) xfact, yfact: Horizontal and vertical scale factors -** (PixelFormat) mode: Graphics mode to use -** (gfx_options_t *) options: Rendering options -** (void *) misc_info: Additional information for the interpreter -** part of the resource loader -** Returns : (int) GFX_OK on success, GFX_ERROR if that particular mode is -** unavailable, or GFX_FATAL if the graphics driver is unable -** to provide any useful graphics support -*/ +/** @name Fundamental operations */ +/** @{ */ + +/** + * Initializes a graphics mode. + * + * @param[in] version The interpreter version + * @param[in] isVGA true if using VGA resolution + * @param[in] state The state to initialize + * @param[in] xfact Horizontal scale factor + * @param[in] yfact Vertical scale factors + * @param[in] mode Graphics mode to use + * @param[in] options Rendering options + * @param[in] resManager Resource manager to use + * @return GFX_OK on success, GFX_ERROR if that particular mode + * is unavailable, or GFX_FATAL if the graphics driver + * is unable to provide any useful graphics support + */ +int gfxop_init(int version, bool isVGA, GfxState *state, + gfx_options_t *options, ResourceManager *resManager, + Graphics::PixelFormat mode, int xfact = 1, int yfact = 1); + +/** + * Deinitializes a currently active driver. + * + * @param[in] state The state encapsulating the driver in question + * @return GFX_OK + */ int gfxop_exit(GfxState *state); -/* Deinitializes a currently active driver -** Parameters: (GfxState *) state: The state encapsulating the driver in question -** Returns : (int) GFX_OK -*/ +/** + * Calculates a bit mask calculated from some pixels on the specified + * map. + * + * @param[in] state The state containing the pixels to scan + * @param[in] area The area to check + * @param[in] map The GFX_MASKed map(s) to test + * @return An integer value where, for each 0 <= i <= 15, bit i is set + * iff there exists a map for which the corresponding bit was + * set in the 'map' parameter and for which there exists a + * pixel within the specified area so that the pixel's lower 4 + * bits, interpreted as an integer value, equal i. (Short + * version: This is an implementation of "on_control()"). + */ int gfxop_scan_bitmask(GfxState *state, rect_t area, gfx_map_mask_t map); -/* Calculates a bit mask calculated from some pixels on the specified map -** Parameters: (GfxState *) state: The state containing the pixels to scan -** (rect_t) area: The area to check -** (gfx_map_mask_t) map: The GFX_MASKed map(s) to test -** Returns : (int) An integer value where, for each 0<=i<=15, bit #i is set -** iff there exists a map for which the corresponding bit was set -** in the 'map' parameter and for which there exists a pixel within -** the specified area so that the pixel's lower 4 bits, interpreted -** as an integer value, equal i. -** (Short version: This is an implementation of "on_control()"). -*/ +/** + * Sets the currently visible map. + * + * 'visible_map' can be any of GFX_MASK_VISUAL, GFX_MASK_PRIORITY and + * GFX_MASK_CONTROL; the appropriate map (as far as its contents are known to + * the graphics subsystem) is then subsequently drawn to the screen at each + * update. If this is set to anything other than GFX_MASK_VISUAL, slow + * full-screen updates are performed. Mostly useful for debugging. The screen + * needs to be updated for the changes to take effect. + * + * @param[in] state The state to modify + * @param[in] map The GFX_MASK to set + * @return GFX_OK, or GFX_ERROR if map was invalid + */ int gfxop_set_visible_map(GfxState *state, gfx_map_mask_t map); -/* Sets the currently visible map -** Parameters: (GfxState *) state: The state to modify -** (gfx_map_mask_t) map: The GFX_MASK to set -** Returns : (int) GFX_OK, or GFX_ERROR if map was invalid -** 'visible_map' can be any of GFX_MASK_VISUAL, GFX_MASK_PRIORITY and GFX_MASK_CONTROL; the appropriate -** map (as far as its contents are known to the graphics subsystem) is then subsequently drawn to the -** screen at each update. If this is set to anything other than GFX_MASK_VISUAL, slow full-screen updates -** are performed. Mostly useful for debugging. -** The screen needs to be updated for the changes to take effect. -*/ +/** + * Sets a new clipping zone. + * + * @param[in] state The affected state + * @param[in] zone The new clipping zone + * @return GFX_OK + */ int gfxop_set_clip_zone(GfxState *state, rect_t zone); -/* Sets a new clipping zone -** Parameters: (GfxState *) state: The affected state -** (rect_t) zone: The new clipping zone -** Returns : (int) GFX_OK -*/ +/** @} */ + -/******************************/ -/* Generic drawing operations */ -/******************************/ +/** @name Generic drawing operations */ +/** @{ */ +/** + * Renders a clipped line to the back buffer. + * + * @param[in] state The state affected + * @param[in] start Starting point of the line + * @param[in] end End point of the line + * @param[in] color The color to use for drawing + * @param[in] line_mode Any valid line mode to use + * @param[in] line_style The line style to use + * @return GFX_OK or GFX_FATAL + */ int gfxop_draw_line(GfxState *state, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style); -/* Renders a clipped line to the back buffer -** Parameters: (GfxState *) state: The state affected -** (Common::Point) start: Starting point of the line -** (Common::Point) end: End point of the line -** (gfx_color_t) color: The color to use for drawing -** (gfx_line_mode_t) line_mode: Any valid line mode to use -** (gfx_line_style_t) line_style: The line style to use -** Returns : (int) GFX_OK or GFX_FATAL -*/ -int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, - gfx_line_style_t line_style); -/* Draws a non-filled rectangular box to the back buffer -** Parameters: (GfxState *) state: The affected state -** (rect_t) rect: The rectangular area the box is drawn to -** (gfx_color_t) color: The color the box is to be drawn in -** (gfx_line_mode_t) line_mode: The line mode to use -** (gfx_line_style_t) line_style: The line style to use for the box -** Returns : (int) GFX_OK or GFX_FATAL -** Boxes drawn in thin lines will surround the minimal area described by rect. -*/ +/** + * Draws a non-filled rectangular box to the back buffer. + * + * Boxes drawn in thin lines will surround the minimal area described by rect. + * + * @param[in] state The affected state + * @param[in] rect The rectangular area the box is drawn to + * @param[in] color The color the box is to be drawn in + * @param[in] line_mode The line mode to use + * @param[in] line_style The line style to use for the box + * @return GFX_OK or GFX_FATAL + */ +int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, + gfx_line_mode_t line_mode, gfx_line_style_t line_style); -int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2, - gfx_box_shade_t shade_type); -/* Draws a filled box to the back buffer -** Parameters: (GfxState *) state: The affected state -** (rect_t) box: The area to draw to -** (gfx_color_t) color1: The primary color to use for drawing -** (gfx_color_t) color2: The secondary color to draw in -** (gfx_box_shade_t) shade_type: The shading system to use -** (e.g. GFX_BOX_SHADE_FLAT) -** Returns : (int) GFX_OK or GFX_FATAL -** The draw mask, control, and priority values are derived from color1. -*/ +/** + * Draws a filled box to the back buffer. + * + * The draw mask, control, and priority values are derived from color1. + * + * @param[in] state The affected state + * @param[in] box The area to draw to + * @param[in] color1 The primary color to use for drawing + * @param[in] color2 The secondary color to draw in + * @param[in] shade_type The shading system to use (e.g. GFX_BOX_SHADE_FLAT) + * @return GFX_OK or GFX_FATAL + */ +int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, + gfx_color_t color2, gfx_box_shade_t shade_type); +/** + * Fills a box in the back buffer with a specific color. + * + * This is a simple wrapper function for gfxop_draw_box + * + * @param[in] state The state to draw to + * @param[in] box The box to fill + * @param[in] color The color to use for filling + * @return GFX_OK or GFX_FATAL + */ int gfxop_fill_box(GfxState *state, rect_t box, gfx_color_t color); -/* Fills a box in the back buffer with a specific color -** Parameters: (GfxState *) state: The state to draw to -** (rect_t) box: The box to fill -** (gfx_color_t) color: The color to use for filling -** Returns : (int) GFX_OK or GFX_FATAL -** This is a simple wrapper function for gfxop_draw_box -*/ +/** + * Copies a box from the static buffer to the back buffer. + * + * @param[in] state The affected state + * @param[in] box The box to propagate from the static buffer + * @return GFX_OK or GFX_FATAL + */ int gfxop_clear_box(GfxState *state, rect_t box); -/* Copies a box from the static buffer to the back buffer -** Parameters: (GfxState *) state: The affected state -** (rect_t) box: The box to propagate from the static buffer -** Returns : (int) GFX_OK or GFX_FATAL -*/ +/** + * Updates all dirty rectangles. + * + * In order to track dirty rectangles, they must be enabled in the options. This + * function instructs the resource manager to free all tagged data on certain + * occasions (see gfxop_new_pic). + * + * @param[in] state The relevant state + * @return GFX_OK or GFX_FATAL if reported by the driver + */ int gfxop_update(GfxState *state); -/* Updates all dirty rectangles -** Parameters: (GfxState) *state: The relevant state -** Returns : (int) GFX_OK or GFX_FATAL if reported by the driver -** In order to track dirty rectangles, they must be enabled in the options. -** This function instructs the resource manager to free all tagged data -** on certain occasions (see gfxop_new_pic). -*/ +/** + * Propagates a box from the back buffer to the front (visible) buffer. + * + * This function instructs the resource manager to free all tagged data on + * certain occasions (see gfxop_new_pic). When called with dirty rectangle + * management enabled, it will automatically propagate all dirty rectangles as + * well, UNLESS dirty frame accounting has been disabled explicitly. + * + * @param[in] state The affected state + * @param[in] box The box to propagate to the front buffer + * @return GFX_OK or GFX_FATAL + */ int gfxop_update_box(GfxState *state, rect_t box); -/* Propagates a box from the back buffer to the front (visible) buffer -** Parameters: (GfxState *) state: The affected state -** (rect_t) box: The box to propagate to the front buffer -** Returns : (int) GFX_OK or GFX_FATAL -** This function instructs the resource manager to free all tagged data -** on certain occasions (see gfxop_new_pic). -** When called with dirty rectangle management enabled, it will automatically -** propagate all dirty rectangles as well, UNLESS dirty frame accounting has -** been disabled explicitly. -*/ +/** + * Enables dirty frame accounting. + * + * Dirty frame accounting is enabled by default. + * + * @param[in] state The state dirty frame accounting is to be enabled in + * @return GFX_OK or GFX_ERROR if state was invalid + */ int gfxop_enable_dirty_frames(GfxState *state); -/* Enables dirty frame accounting -** Parameters: (GfxState *) state: The state dirty frame accounting is to be enabled in -** Returns : (int) GFX_OK or GFX_ERROR if state was invalid -** Dirty frame accounting is enabled by default. -*/ +/** + * Disables dirty frame accounting. + * + * @param[in] state The state dirty frame accounting is to be disabled in + * @return GFX_OK or GFX_ERROR if state was invalid + */ int gfxop_disable_dirty_frames(GfxState *state); -/* Disables dirty frame accounting -** Parameters: (GfxState *) state: The state dirty frame accounting is to be disabled in -** Returns : (int) GFX_OK or GFX_ERROR if state was invalid -*/ +/** @} */ -/********************/ -/* Color operations */ -/********************/ - -int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, int a, - int priority, int control); -/* Maps an r/g/b value to a color and sets a gfx_color_t structure -** Parameters: (GfxState *) state: The current state -** (gfx_color_t *) color: Pointer to the structure to write to -** (int x int x int) r,g,b: The red/green/blue color intensity values -** of the result color (0x00 (minimum) to 0xff (max)) -** If any of these values is less than zero, the -** resulting color will not affect the visual map when -** used for drawing -** (int) a: The alpha (transparency) value, with 0x00 meaning absolutely -** opaque and 0xff meaning fully transparent. Alpha blending support -** is optional for drivers, so these are the only two values that -** are guaranteed to work as intended. Any value in between them -** must guarantee the following opaqueness: -** opaqueness(x-1) >= opaqueness(x) >= opaqueness (x+1) -** (i.e. ([0,255], less-transparent-than) must define a partial order) -** (int) priority: The priority to use for drawing, or -1 for none -** (int) control: The control to use for drawing, or -1 to disable drawing to the -** control map -** Returns : (int) GFX_OK or GFX_ERROR if state is invalid -** In palette mode, this may allocate a new color. Use gfxop_free_color() described below to -** free that color. -*/ +/** @name Color operations */ +/** @{ */ + +/** + * Maps an r/g/b value to a color and sets a gfx_color_t structure. + * + * In palette mode, this may allocate a new color. Use gfxop_free_color() to + * free that color. If any of the r/g/b values are less than zero, the resulting + * color will not affect the visual map when used for drawing + * + * @param[in] state The current state + * @param[in] color Pointer to the structure to write to + * @param[in] r The red color intensity values of the result color + * @param[in] g The green color intensity values of the result color + * @param[in] b The blue color intensity values of the result color + * @param[in] a The alpha (transparency) value, with 0x00 meaning + * absolutely opaque and 0xff meaning fully transparent. + * Alpha blending support is optional for drivers, so these + * are the only two values that are guaranteed to work as + * intended. Any value in between them must guarantee the + * following opaqueness: opaqueness(x-1) >= opaqueness(x) + * >= opaqueness (x+1) (i.e. ([0,255], + * less-transparent-than) must define a partial order) + * @param[in] priority The priority to use for drawing, or -1 for none + * @param[in] control The control to use for drawing, or -1 to disable drawing + * to the control map + * @return GFX_OK or GFX_ERROR if state is invalid + */ +int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, + int a, int priority, int control); +/** + * Designates a color as a 'system color'. + * + * system colors are permanent colors that cannot be deallocated. as such, they must be used with caution. + * + * @param[in] state The affected state + * @param[in] index The index for the new system color + * @param[in] color The color to designate as a system color + * @return GFX_OK or GFX_ERROR if state is invalid + */ int gfxop_set_system_color(GfxState *state, unsigned int index, gfx_color_t *color); -/* Designates a color as a 'system color' -** Parameters: (GfxState *) state: The affected state -** (unsigned int) index: The index for the new system color -** (gfx_color_t *) color: The color to designate as a system color -** Returns : (int) GFX_OK or GFX_ERROR if state is invalid -** System colors are permanent colors that cannot be deallocated. As such, they must be used -** with caution. -*/ +/** + * Frees a color allocated by gfxop_set_color(). + * + * This function is a no-op in non-index mode, or if color is a system color. + * + * @param[in] state The state affected + * @param[in] color The color to de-allocate + * @return GFX_OK or GFX_ERROR if state is invalid + */ int gfxop_free_color(GfxState *state, gfx_color_t *color); -/* Frees a color allocated by gfxop_set_color() -** Parmaeters: (GfxState *) state: The state affected -** (gfx_color_t *) color: The color to de-allocate -** Returns : (int) GFX_OK or GFX_ERROR if state is invalid -** This function is a no-op in non-index mode, or if color is a system color. -*/ - +/** @} */ -/**********************/ -/* Pointer and IO ops */ -/**********************/ +/** @name Pointer and IO ops */ +/** @{ */ +/** + * Suspends program execution for the specified amount of milliseconds. + * + * The mouse pointer will be redrawn continually, if applicable + * + * @param[in] state The state affected + * @param[in] msecs The amount of milliseconds to wait + * @return GFX_OK or GFX_ERROR + */ int gfxop_sleep(GfxState *state, uint32 msecs); -/* Suspends program execution for the specified amount of milliseconds -** Parameters: (GfxState *) state: The state affected -** (uint32) usecs: The amount of milliseconds to wait -** Returns : (int) GFX_OK or GFX_ERROR -** The mouse pointer will be redrawn continually, if applicable -*/ +/** + * Sets the mouse pointer to a cursor resource. + * + * @param[in] state The affected state + * @param[in] nr Number of the cursor resource to use + * @return GFX_OK, GFX_ERROR if the resource did not exist and was not + * GFXOP_NO_POINTER, or GFX_FATAL on fatal error conditions. + * Use nr = GFX_NO_POINTER to disable the mouse pointer + * (default). + */ int gfxop_set_pointer_cursor(GfxState *state, int nr); -/* Sets the mouse pointer to a cursor resource -** Parameters: (GfxState *) state: The affected state -** (int) nr: Number of the cursor resource to use -** Returns : (int) GFX_OK, GFX_ERROR if the resource did not -** exist and was not GFXOP_NO_POINTER, or GFX_FATAL on -** fatal error conditions. -** Use nr = GFX_NO_POINTER to disable the mouse pointer (default). -*/ +/** + * Sets the mouse pointer to a view resource. + * + * Use gfxop_set_pointer_cursor(state, GFXOP_NO_POINTER) to disable the pointer. + * + * @param[in] state The affected state + * @param[in] nr Number of the view resource to use + * @param[in] loop View loop to use + * @param[in] cel View cel to use + * @param[in] hotspot Manually set hotspot to use, or NULL for default. + * @return GFX_OK or GFX_FATAL + */ int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::Point *hotspot); -/* Sets the mouse pointer to a view resource -** Parameters: (GfxState *) state: The affected state -** (int) nr: Number of the view resource to use -** (int) loop: View loop to use -** (int) cel: View cel to use -** (Common::Point *) hotspot: Manually set hotspot to use, or NULL for default. -** Returns : (int) GFX_OK or GFX_FATAL -** Use gfxop_set_pointer_cursor(state, GFXOP_NO_POINTER) to disable the -** pointer. -*/ +/** + * Teleports the mouse pointer to a specific position. + * + * Depending on the graphics driver, this operation may be without any effect + * + * @param[in] state The state the pointer is in + * @param[in] pos The position to teleport it to + * @return Any error code or GFX_OK + */ int gfxop_set_pointer_position(GfxState *state, Common::Point pos); -/* Teleports the mouse pointer to a specific position -** Parameters: (GfxState *) state: The state the pointer is in -** (Common::Point) pos: The position to teleport it to -** Returns : (int) Any error code or GFX_OK -** Depending on the graphics driver, this operation may be without -** any effect -*/ +/** + * Retrieves the next input event from the driver. + * + * @param[in] state The affected state + * @param[in] mask The event mask to poll from (see uinput.h) + * @return The next event in the driver's event queue, or a NONE event + * if no event matching the mask was found. + */ sci_event_t gfxop_get_event(GfxState *state, unsigned int mask); -/* Retrieves the next input event from the driver -** Parameters: (GfxState *) state: The affected state -** (int) mask: The event mask to poll from (see uinput.h) -** Returns : (sci_event_t) The next event in the driver's event queue, or -** a NONE event if no event matching the mask was found. -*/ +/** @} */ +/** @name View operations */ +/** @{ */ -/*******************/ -/* View operations */ -/*******************/ - +/** + * Determines the number of loops associated with a view. + * + * @param[in] state The state to use + * @param[in] nr Number of the view to investigate + * @return The number of loops, or GFX_ERROR if the view didn't exist + */ int gfxop_lookup_view_get_loops(GfxState *state, int nr); -/* Determines the number of loops associated with a view -** Parameters: (GfxState *) state: The state to use -** (int) nr: Number of the view to investigate -** Returns : (int) The number of loops, or GFX_ERROR if the view didn't exist -*/ +/** + * Determines the number of cels associated stored in a loop. + * + * @param[in] state The state to look up in + * @param[in] nr Number of the view to look up in + * @param[in] loop Number of the loop the number of cels of are to be + * investigated + * @return The number of cels in that loop, or GFX_ERROR if either the + * view or the loop didn't exist + */ int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop); -/* Determines the number of cels associated stored in a loop -** Parameters: (GfxState *) state: The state to look up in -** (int) nr: Number of the view to look up in -** (int) loop: Number of the loop the number of cels of -** are to be investigated -** Returns : (int) The number of cels in that loop, or GFX_ERROR if either -** the view or the loop didn't exist -*/ +/** + * Clips the view/loop/cel position of a cel. + * + * *loop is clipped first, then *cel. The resulting setup will be a valid view + * configuration. + * + * @param[in] state The state to use + * @param[in] nr Number of the view to use + * @param[in] loop Pointer to the variable storing the loop number to verify + * @param[in] cel Pointer to the variable storing the cel number to check + * @return GFX_OK or GFX_ERROR if the view didn't exist + */ int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel); -/* Clips the view/loop/cel position of a cel -** Parameters: (GfxState *) state: The state to use -** (int) nr: Number of the view to use -** (int *) loop: Pointer to the variable storing the loop -** number to verify -** (int *) cel: Pointer to the variable storing the cel -** number to check -** Returns : (int) GFX_OK or GFX_ERROR if the view didn't exist -** *loop is clipped first, then *cel. The resulting setup will be a valid -** view configuration. -*/ +/** + * Resets loop/cel values to zero if they have become invalid. + * + * @param[in] state The state to use + * @param[in] nr Number of the view to use + * @param[in] loop Pointer to the variable storing the loop number to verify + * @param[in] cel Pointer to the variable storing the cel number to check + * @return GFX_OK or GFX_ERROR if the view didn't exist *loop is + * clipped first, then *cel. The resulting setup will be a + * valid view configuration. + */ int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel); -/* Resets loop/cel values to zero if they have become invalid -** Parameters: (GfxState *) state: The state to use -** (int) nr: Number of the view to use -** (int *) loop: Pointer to the variable storing the loop -** number to verify -** (int *) cel: Pointer to the variable storing the cel -** number to check -** Returns : (int) GFX_OK or GFX_ERROR if the view didn't exist -** *loop is clipped first, then *cel. The resulting setup will be a valid -** view configuration. -*/ +/** + * Retrieves the width and height of a cel. + * + * @param[in] state The state to use + * @param[in] nr Number of the view + * @param[in] loop Loop number to examine + * @param[in] cel The cel (inside the loop) to look up + * @param[in] width The variable the width will be stored in + * @param[in] height The variable the height will be stored in + * @param[in] offset The variable the cel's x/y offset will be stored in + * @return GFX_OK if the lookup succeeded, GFX_ERROR if the + * nr/loop/cel combination was invalid + */ int gfxop_get_cel_parameters(GfxState *state, int nr, int loop, int cel, int *width, int *height, Common::Point *offset); -/* Retrieves the width and height of a cel -** Parameters: (GfxState *) state: The state to use -** (int) nr: Number of the view -** (int) loop: Loop number to examine -** (int) cel: The cel (inside the loop) to look up -** (int *) width: The variable the width will be stored in -** (int *) height: The variable the height will be stored in -** (Common::Point *) offset: The variable the cel's x/y offset will be stored in -** Returns : (int) GFX_OK if the lookup succeeded, GFX_ERROR if the nr/loop/cel -** combination was invalid -*/ -int gfxop_draw_cel(GfxState *state, int nr, int loop, int cel, Common::Point pos, - gfx_color_t color, int palette); -/* Draws (part of) a cel to the back buffer -** Parameters: (GfxState *) state: The state encapsulating the driver to draw with -** (int) nr: Number of the view to draw -** (int) loop: Loop of the cel to draw -** (int) cel: The cel number of the cel to draw -** (Common::Point) pos: The positino the cel is to be drawn to -** (gfx_color_t color): The priority and control values to use for drawing -** (int) palette: The palette to use -** Returns : (int) GFX_OK or GFX_FATAL -*/ +/** + * Draws (part of) a cel to the back buffer. + * + * @param[in] state The state encapsulating the driver to draw with + * @param[in] nr Number of the view to draw + * @param[in] loop Loop of the cel to draw + * @param[in] cel The cel number of the cel to draw + * @param[in] pos The positino the cel is to be drawn to + * @param[in] color The priority and control values to use for drawing + * @param[in] palette The palette to use + * @return GFX_OK or GFX_FATAL + */ +int gfxop_draw_cel(GfxState *state, int nr, int loop, int cel, + Common::Point pos, gfx_color_t color, int palette); -int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel, Common::Point pos, - gfx_color_t color, int palette); -/* Draws a cel to the static buffer; no clipping is performed -** Parameters: (GfxState *) state: The state encapsulating the driver to draw with -** (int) nr: Number of the view to draw -** (int) loop: Loop of the cel to draw -** (int) cel: The cel number of the cel to draw -** (Common::Point) pos: The positino the cel is to be drawn to -** (gfx_color_t color): The priority and control values to use for drawing -** (int) palette: The palette to use -** Returns : (int) GFX_OK or GFX_FATAL -** Let me repeat, no clipping (except for the display borders) is performed. -*/ +/** + * Draws a cel to the static buffer; no clipping is performed. + * + * No clipping (except for the display borders) is performed. + * + * @param[in] state The state encapsulating the driver to draw with + * @param[in] nr Number of the view to draw + * @param[in] loop Loop of the cel to draw + * @param[in] cel The cel number of the cel to draw + * @param[in] pos The positino the cel is to be drawn to + * @param[in] color The priority and control values to use for drawing + * @param[in] palette The palette to use + * @return GFX_OK or GFX_FATAL + */ +int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel, + Common::Point pos, gfx_color_t color, int palette); -int gfxop_draw_cel_static_clipped(GfxState *state, int nr, int loop, int cel, Common::Point pos, - gfx_color_t color, int palette); -/* Draws (part of) a clipped cel to the static buffer -** Parameters: (GfxState *) state: The state encapsulating the driver to draw with -** (int) nr: Number of the view to draw -** (int) loop: Loop of the cel to draw -** (int) cel: The cel number of the cel to draw -** (Common::Point) pos: The positino the cel is to be drawn to -** (gfx_color_t color): The priority and control values to use for drawing -** (int) palette: The palette to use -** Returns : (int) GFX_OK or GFX_FATAL -** This function does clip. -*/ +/** + * Draws (part of) a clipped cel to the static buffer. + * + * This function does clip. + * + * @param[in] state The state encapsulating the driver to draw with + * @param[in] nr Number of the view to draw + * @param[in] loop Loop of the cel to draw + * @param[in] cel The cel number of the cel to draw + * @param[in] pos The positino the cel is to be drawn to + * @param[in] color The priority and control values to use for drawing + * @param[in] palette The palette to use + * @return GFX_OK or GFX_FATAL + */ +int gfxop_draw_cel_static_clipped(GfxState *state, int nr, int loop, int cel, + Common::Point pos, gfx_color_t color, int palette); +/** @} */ -/******************/ -/* Pic operations */ -/******************/ -/* These operations are exempt from clipping */ +/** @name Pic operations + * These operations are exempt from clipping */ +/** @{ */ +/** + * Draws a pic and writes it over the static buffer. + * + * This function instructs the resource manager to tag all data as "unused". + * See the resource manager tag functions for a full description. + * + * @param[in] state The state affected + * @param[in] nr Number of the pic to draw + * @param[in] flags Interpreter-dependant flags to use for drawing + * @param[in] default_palette The default palette for drawing + * @return GFX_OK or GFX_FATAL + */ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette); -/* Draws a pic and writes it over the static buffer -** Parameters: (GfxState *) state: The state affected -** (int) nr: Number of the pic to draw -** (int) flags: Interpreter-dependant flags to use for drawing -** (int) default_palette: The default palette for drawing -** Returns : (int) GFX_OK or GFX_FATAL -** This function instructs the resource manager to tag all data as "unused". -** See the resource manager tag functions for a full description. -*/ +/** + * Retrieves all meta-information assigned to the current pic. + * + * @param[in] state The state affected + * @return NULL if the pic doesn't exist or has no meta-information, + * the meta-info otherwise. This meta-information is referred + * to as 'internal data' in the pic code + */ int *gfxop_get_pic_metainfo(GfxState *state); -/* Retrieves all meta-information assigned to the current pic -** Parameters: (GfxState *) state: The state affected -** Returns : (int *) NULL if the pic doesn't exist or has no meta-information, -** the meta-info otherwise -** This meta-information is referred to as 'internal data' in the pic code -*/ +/** + * Adds a pic to the static buffer. + * + * @param[in] state The state affected + * @param[in] nr Number of the pic to add + * @param[in] flags Interpreter-dependant flags to use for drawing + * @param[in] default_palette The default palette for drawing + * @return GFX_OK or GFX_FATAL + */ int gfxop_add_to_pic(GfxState *state, int nr, int flags, int default_palette); -/* Adds a pic to the static buffer -** Parameters: (GfxState *) state: The state affected -** (int) nr: Number of the pic to add -** (int) flags: Interpreter-dependant flags to use for drawing -** (int) default_palette: The default palette for drawing -** Returns : (int) GFX_OK or GFX_FATAL -*/ - +/** @} */ +/** @name Text operations */ +/** @{ */ -/*******************/ -/* Text operations */ -/*******************/ - - +/** + * Returns the fixed line height for one specified font. + * + * @param[in] state The state to work on + * @param[in] font_nr Number of the font to inspect + * @return GFX_ERROR, GFX_FATAL, or the font line height + */ int gfxop_get_font_height(GfxState *state, int font_nr); -/* Returns the fixed line height for one specified font -** Parameters: (GfxState *) state: The state to work on -** (int) font_nr: Number of the font to inspect -** Returns : (int) GFX_ERROR, GFX_FATAL, or the font line height -*/ +/** + * Calculates the width and height of a specified text in a specified + * font. + * + * @param[in] state The state to use + * @param[in] font_nr Font number to use for the calculation + * @param[in] text The text to examine + * @param[in] flags ORred GFXR_FONT_FLAGs + * @param[in] maxwidth The maximum pixel width to allow for the text + * @param[out] width The resulting width + * @param[out] height The resulting height + * @param[out] lines_nr Number of lines used in the text + * @param[out] lineheight Pixel height (SCI scale) of each text line + * @param[out] lastline_width Pixel offset (SCI scale) of the space after + * the last character in the last line + * @return GFX_OK or GFX_ERROR if the font didn't exist + */ int gfxop_get_text_params(GfxState *state, int font_nr, const char *text, int maxwidth, int *width, int *height, int flags, int *lines_nr, int *lineheight, int *lastline_width); -/* Calculates the width and height of a specified text in a specified font -** Parameters: (GfxState *) state: The state to use -** (int) font_nr: Font number to use for the calculation -** (const char *) text: The text to examine -** (int) flags: ORred GFXR_FONT_FLAGs -** (int) maxwidth: The maximum pixel width to allow for the text -** Returns : (int) GFX_OK or GFX_ERROR if the font didn't exist -** (int) *width: The resulting width -** (int) *height: The resulting height -** (int) *lines_nr: Number of lines used in the text -** (int) *lineheight: Pixel height (SCI scale) of each text line -** (int) *lastline_wdith: Pixel offset (SCI scale) of the space -** after the last character in the last line -*/ -TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &text, int maxwidth, - gfx_alignment_t halign, gfx_alignment_t valign, gfx_color_t color1, - gfx_color_t color2, gfx_color_t bg_color, int flags); -/* Generates a new text handle that can be used to draw any text -** Parameters: (GfxState *) state: The state to use -** (int) font_nr: Font number to use for the calculation -** (const char *) text: The text to examine -** (int) maxwidth: The maximum pixel width to allow for the text -** (gfx_alignment_t) halign: The horizontal text alignment -** (gfx_alignment_t) valign: The vertical text alignment -** (gfx_color_t x gfx_color_t) color1, color2: The text's foreground colors -** (the function will dither between those two) -** (gfx_color_t) bg_color: The background color -** (int) flags: ORred GFXR_FONT_FLAGs -** Returns : (TextHandle *) A newly allocated TextHandle, or -** NULL if font_nr was invalid -** The control and priority values for the text will be extracted from color1. -** Note that the colors must have been allocated properly, or the text may display in -** incorrect colors. -*/ +/** + * Generates a new text handle that can be used to draw any text. + * + * The control and priority values for the text will be extracted from color1. + * Note that the colors must have been allocated properly, or the text may + * display in incorrect colors. + * + * @param[in] state The state to use + * @param[in] font_nr Font number to use for the calculation + * @param[in] text The text to examine + * @param[in] maxwidth: The maximum pixel width to allow for the text + * @param[in] halign The horizontal text alignment + * @param[in] valign The vertical text alignment + * @param[in] color1 The text's foreground colors (the function will dither + * between color1 and 2) + * @param[in] color2 The text's foreground colors (the function will dither + * between color1 and 2) + * @param[in] bg_color The background color + * @param[in] flags ORred GFXR_FONT_FLAGs + * @return A newly allocated TextHandle, or NULL if font_nr was + * invalid + */ +TextHandle *gfxop_new_text(GfxState *state, int font_nr, + const Common::String &text, int maxwidth, gfx_alignment_t halign, + gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2, + gfx_color_t bg_color, int flags); +/** + * Frees a previously allocated text handle and all related resources. + * + * @param[in] state The state to use + * @param[in] handle The handle to free + * @return GFX_OK + */ int gfxop_free_text(GfxState *state, TextHandle *handle); -/* Frees a previously allocated text handle and all related resources -** Parameters: (GfxState *) state: The state to use -** (TextHandle *) handle: The handle to free -** Returns : (int) GFX_OK -*/ +/** + * Draws text stored in a text handle. + * + * @param[in] state The target state + * @param[in] handle The text handle to use for drawing + * @param[in] zone The rectangular box to draw to. In combination with + * halign and valign, this defines where the text is drawn + * to. + * @return GFX_OK or GFX_FATAL + */ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone); -/* Draws text stored in a text handle -** Parameters: (GfxState *) state: The target state -** (TextHandle *) handle: The text handle to use for drawing -** (rect_t) zone: The rectangular box to draw to. In combination with -** halign and valign, this defines where the text is -** drawn to. -** Returns : (int) GFX_OK or GFX_FATAL -*/ +/** @} */ -/****************************/ -/* Manual pixmap operations */ -/****************************/ +/** @name Manual pixmap operations */ +/** @{ */ +/** + * Grabs a screen section from the back buffer and stores it in a pixmap. + * + * Obviously, this only affects the visual map + * + * @param[in] state The affected state + * @param[in] area The area to grab + * Returns A result pixmap, or NULL on error + */ gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area); -/* Grabs a screen section from the back buffer and stores it in a pixmap -** Parameters: (GfxState *) state: The affected state -** (rect_t) area: The area to grab -** Returns : (gfx_pixmap_t *) A result pixmap, or NULL on error -** Obviously, this only affects the visual map -*/ -int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::Point pos); -/* Draws part of a pixmap to the screen -** Parameters: (GfxState *) state: The affected state -** (gfx_pixmap_t *) pxm: The pixmap to draw -** (rect_t) zone: The segment of the pixmap to draw -** (Common::Point) pos: The position the pixmap should be drawn to -** Returns : (int) GFX_OK or any error code -*/ +/** + * Draws part of a pixmap to the screen. + * + * @param[in] state The affected state + * @param[in] pxm The pixmap to draw + * @param[in] zone The segment of the pixmap to draw + * @param[in] pos The position the pixmap should be drawn to + * @return GFX_OK or any error code + */ +int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, + Common::Point pos); +/** + * Frees a pixmap returned by gfxop_grab_pixmap(). + * + * @param[in] state The affected state + * @param[in] pxm The pixmap to free + * @return GFX_OK, or GFX_ERROR if the state was invalid + */ int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm); -/* Frees a pixmap returned by gfxop_grab_pixmap() -** Parameters: (GfxState *) state: The affected state -** (gfx_pixmap_t *) pxm: The pixmap to free -** Returns : (int) GFX_OK, or GFX_ERROR if the state was invalid -*/ +/** @} */ -/******************************/ -/* Dirty rectangle operations */ -/******************************/ + +/** @name Dirty rectangle operations */ +/** @{ */ /** * Adds a dirty rectangle to 'base' according to a strategy. - * @param list the list to add to - * @param box the dirty frame to addable - * @param strategy the dirty frame heuristic to use (see gfx_options.h) + * + * @param[in] list the list to add to + * @param[in] box the dirty frame to addable + * @param[in] strategy the dirty frame heuristic to use (see gfx_options.h) */ void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy); +/** + * Clips a rectangle against another one. + * + * @param[in] rect The rectangle to clip + * @param[in] clipzone The outer bounds rect must be in + * @return 1 if rect is empty now, 0 otherwise + */ int _gfxop_clip(rect_t *rect, rect_t clipzone); -/* Clips a rectangle against another one -** Parameters: (rect_t *) rect: The rectangle to clip -** (rect_t) clipzone: The outer bounds rect must be in -** Reuturns : (int) 1 if rect is empty now, 0 otherwise -*/ +/** @} */ } // End of namespace Sci diff --git a/engines/sci/gfx/palette.h b/engines/sci/gfx/palette.h index 127871bce4..65d1cac18e 100644 --- a/engines/sci/gfx/palette.h +++ b/engines/sci/gfx/palette.h @@ -42,15 +42,18 @@ struct PaletteEntry { : r(R), g(G), b(B), parent_index(-1), refcount(PALENTRY_FREE) { } - // Color data + /** @name Color data */ + /** @{ */ byte r, g, b; + /** @} */ - // Index in parent palette, or -1 + /** Index in parent palette, or -1 */ int parent_index; - // Number of references from child palettes. (This includes palettes - // of pixmaps.) - // Special values: PALENTRY_LOCKED, PALENTRY_FREE + /** + * Number of references from child palettes. (This includes palettes + * of pixmaps.) + * Special values: PALENTRY_LOCKED, PALENTRY_FREE */ int refcount; }; @@ -98,10 +101,9 @@ private: Palette *_parent; - bool _dirty; // Palette has changed - int _refcount; // Number of pixmaps (or other objects) using this palette - int _revision; // When this is incremented, all child references are - // invalidated + bool _dirty; /**< Palette has changed */ + int _refcount; /**< Number of pixmaps (or other objects) using this palette */ + int _revision; /**< When this is incremented, all child references are invalidated */ }; diff --git a/engines/sci/gfx/res_pic.cpp b/engines/sci/gfx/res_pic.cpp index bb9e8a75a7..2c91cb579f 100644 --- a/engines/sci/gfx/res_pic.cpp +++ b/engines/sci/gfx/res_pic.cpp @@ -152,7 +152,7 @@ void gfxr_init_static_palette() { } -gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1) { +gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, bool sci1) { gfxr_pic_t *pic = (gfxr_pic_t*)malloc(sizeof(gfxr_pic_t)); pic->mode = mode; @@ -798,7 +798,7 @@ static void _gfxr_draw_line(gfxr_pic_t *pic, int x, int y, int ex, int ey, int c line.height = ey - y; if (x > 319 || y > 199 || x < 0 || y < 0 || ex > 319 || ey > 199 || ex < 0 || ey < 0) { - GFXWARN("While building pic: Attempt to draw line (%d,%d) to (%d,%d): cmd was %d\n", x, y, ex, ey, cmd); + warning("[GFX] While building pic: Attempt to draw line (%d,%d) to (%d,%d): cmd was %d", x, y, ex, ey, cmd); return; } @@ -1088,7 +1088,7 @@ void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src) { assert(src->mode->yfact == 1); if (bound_x == 1 && bound_y == 1) { - GFXWARN("attempt to remove artifacts from unscaled pic!\n"); + warning("[GFX] attempt to remove artifacts from unscaled pic"); return; } @@ -1431,7 +1431,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, switch (opx) { case PIC_SCI1_OPX_SET_PALETTE_ENTRIES: - GFXWARN("SCI1 Set palette entried not implemented\n"); + warning("[GFX] SCI1 Set palette entried not implemented"); goto end_op_loop; case PIC_SCI0_OPX_SET_PALETTE_ENTRIES: @@ -1580,7 +1580,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, pic->priorityTable = (int*)malloc(16 * sizeof(int)); } else { // This occurs in the title screen of Longbow, perhaps with the animated Robin sprite - GFXWARN("pic->priorityTable is not NULL (%p); this only occurs with overlaid pics, otherwise it's a bug", (void *)pic->priorityTable); + warning("[GFX] pic->priorityTable is not NULL (%p); this only occurs with overlaid pics, otherwise it's a bug", (void *)pic->priorityTable); } pri_table = pic->priorityTable; @@ -1626,13 +1626,13 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, return; default: - GFXWARN("Unknown op %02x\n", op); + warning("[GFX] Unknown op %02x", op); return; } end_op_loop: {} } - GFXWARN("Reached end of pic resource %04x\n", resid); + warning("[GFX] Reached end of pic resource %04x", resid); } void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource, @@ -1674,7 +1674,7 @@ void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size, view->index_height, 1); } else { - GFXWARN("No view was contained in SCI1.1 pic resource"); + warning("[GFX] No view was contained in SCI1.1 pic resource"); } gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr, resource + vector_data_ptr, style, resid, 1, static_pal, portBounds); diff --git a/engines/sci/gfx/res_view.cpp b/engines/sci/gfx/res_view.cpp index f5f151cd3c..b30c57f38d 100644 --- a/engines/sci/gfx/res_view.cpp +++ b/engines/sci/gfx/res_view.cpp @@ -232,7 +232,7 @@ static int decompress_sci_view(int id, int loop, int cel, byte *resource, byte * /* if (writepos - bytes < 0) { - GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n", + warning("[GFX] View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x", id, loop, cel, writepos - bytes, pixmap_size, pos - 1); bytes = pixmap_size - writepos; } @@ -246,7 +246,7 @@ static int decompress_sci_view(int id, int loop, int cel, byte *resource, byte * assert(op || literal_pos + bytes <= size); if (!mirrored && (writepos + bytes > pixmap_size)) { - GFXWARN("Writing out of bounds: %d bytes at %d > size %d\n", bytes, writepos, pixmap_size); + warning("[GFX] Writing out of bounds: %d bytes at %d > size %d", bytes, writepos, pixmap_size); } if (mirrored) { @@ -302,14 +302,14 @@ static int decompress_sci_view_amiga(int id, int loop, int cel, byte *resource, writepos += 2 * xl; if (writepos >= pixmap_size && bytes) { - GFXWARN("View %02x:(%d/%d) writing out of bounds\n", id, loop, cel); + warning("[GFX] View %02x:(%d/%d) writing out of bounds", id, loop, cel); break; } } } } else { if (writepos + bytes > pixmap_size) { - GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n", + warning("[GFX] View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x", id, loop, cel, writepos - bytes, pixmap_size, pos - 1); bytes = pixmap_size - writepos; } @@ -319,7 +319,7 @@ static int decompress_sci_view_amiga(int id, int loop, int cel, byte *resource, } if (writepos < pixmap_size) { - GFXWARN("View %02x:(%d/%d) not enough pixel data in view\n", id, loop, cel); + warning("[GFX] View %02x:(%d/%d) not enough pixel data in view", id, loop, cel); return 1; } @@ -331,7 +331,7 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso int yl = READ_LE_UINT16(cel_base + 2); int pixmap_size = xl * yl; int xdisplace = isSci11 ? READ_LE_UINT16(cel_base + 4) : (int8) cel_base[4]; - int ydisplace = isSci11 ? READ_LE_UINT16(cel_base + 6) : (int8) cel_base[5]; + int ydisplace = isSci11 ? READ_LE_UINT16(cel_base + 6) : cel_base[5]; int runlength_offset = isSci11 ? READ_LE_UINT16(cel_base + 24) : 8; int literal_offset = isSci11 ? READ_LE_UINT16(cel_base + 28) : 8; gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel)); diff --git a/engines/sci/gfx/seq_decoder.h b/engines/sci/gfx/seq_decoder.h index 16574007fe..b9feadb5f3 100644 --- a/engines/sci/gfx/seq_decoder.h +++ b/engines/sci/gfx/seq_decoder.h @@ -28,6 +28,9 @@ namespace Sci { +/** + * Decoder for image sequences + */ class SeqDecoder { public: SeqDecoder() : _fileStream(0), _palette(0) { } @@ -37,7 +40,9 @@ public: gfx_pixmap_t *getFrame(bool &hasNext); private: - bool decodeFrame(byte *runlength_data, int runlength_size, byte *literal_data, int literal_size, byte *dest, int xl, int yl, int color_key); + bool decodeFrame(byte *runlength_data, int runlength_size, + byte *literal_data, int literal_size, byte *dest, int xl, int yl, + int color_key); Common::SeekableReadStream *_fileStream; Palette *_palette; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 01be4c5ba6..52c079e829 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -56,13 +56,6 @@ const char *sci_version_types[] = { const int sci_max_resource_nr[] = {65536, 1000, 2048, 2048, 2048, 65536, 65536, 65536}; -enum SolFlags { - kSolFlagCompressed = 1 << 0, - kSolFlagUnknown = 1 << 1, - kSolFlag16Bit = 1 << 2, - kSolFlagIsSigned = 1 << 3 -}; - static const char *sci_error_types[] = { "No error", "I/O error", @@ -94,15 +87,15 @@ static const char *resourceTypeSuffixes[] = { }; const char *getResourceTypeName(ResourceType restype) { - return resourceTypeNames[restype]; + if (restype != kResourceTypeInvalid) + return resourceTypeNames[restype]; + else + return "invalid"; } //-- Resource main functions -- Resource::Resource() { data = NULL; - number = 0; - type = kResourceTypeInvalid; - id = 0; size = 0; file_offset = 0; status = kResStatusNoMalloc; @@ -131,56 +124,45 @@ void Resource::unalloc() { ResourceSource *ResourceManager::addExternalMap(const char *file_name) { ResourceSource *newsrc = new ResourceSource(); - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - newsrc->source_type = kSourceExtMap; newsrc->location_name = file_name; newsrc->scanned = false; newsrc->associated_map = NULL; + _sources.push_back(newsrc); return newsrc; } ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { ResourceSource *newsrc = new ResourceSource(); - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - newsrc->source_type = type; newsrc->scanned = false; newsrc->location_name = filename; newsrc->volume_number = number; newsrc->associated_map = map; + _sources.push_back(newsrc); return newsrc; } ResourceSource *ResourceManager::addPatchDir(const char *dirname) { ResourceSource *newsrc = new ResourceSource(); - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - newsrc->source_type = kSourceDirectory; newsrc->scanned = false; newsrc->location_name = dirname; + _sources.push_back(newsrc); return 0; } ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { - ResourceSource *seeker = _sources; - - while (seeker) { - if ((seeker->source_type == kSourceVolume || seeker->source_type == kSourceAudioVolume) - && seeker->associated_map == map && seeker->volume_number == volume_nr) - return seeker; - seeker = seeker->next; + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { + ResourceSource *src = *it; + if ((src->source_type == kSourceVolume || src->source_type == kSourceAudioVolume) + && src->associated_map == map && src->volume_number == volume_nr) + return src; } return NULL; @@ -198,19 +180,19 @@ bool ResourceManager::loadPatch(Resource *res, Common::File &file) { res->header = new byte[res->headerSize]; if ((res->data == NULL) || ((res->headerSize > 0) && (res->header == NULL))) { - error("Can't allocate %d bytes needed for loading %s.%i", res->size + res->headerSize, resourceTypeNames[res->type], res->number); + error("Can't allocate %d bytes needed for loading %s", res->size + res->headerSize, res->id.toString().c_str()); } unsigned int really_read; if (res->headerSize > 0) { really_read = file.read(res->header, res->headerSize); if (really_read != res->headerSize) - error("Read %d bytes from %s.%i but expected %d", really_read, resourceTypeNames[res->type], res->number, res->headerSize); + error("Read %d bytes from %s but expected %d", really_read, res->id.toString().c_str(), res->headerSize); } really_read = file.read(res->data, res->size); if (really_read != res->size) - error("Read %d bytes from %s.%i but expected %d", really_read, resourceTypeNames[res->type], res->number, res->size); + error("Read %d bytes from %s but expected %d", really_read, res->id.toString().c_str(), res->size); res->status = kResStatusAllocated; return true; @@ -228,20 +210,11 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { return loadPatch(res, file); } -bool ResourceManager::loadFromAudioVolume(Resource *res) { - Common::File file; - const char *filename = res->source->location_name.c_str(); - if (file.open(filename) == false) { - warning("Failed to open audio volume %s", filename); - res->unalloc(); - return false; - } - - file.seek(res->file_offset, SEEK_SET); - - int type = file.readByte() & 0x7f; - if (type != res->type) { - warning("Resource type mismatch loading %s.%i from %s", resourceTypeNames[res->type], res->number, filename); +bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) { + ResourceType type = (ResourceType)(file.readByte() & 0x7f); + if (((res->id.type == kResourceTypeAudio || res->id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) + || ((res->id.type == kResourceTypeSync || res->id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { + warning("Resource type mismatch loading %s from %s", res->id.toString().c_str(), file.getName()); res->unalloc(); return false; } @@ -263,6 +236,21 @@ bool ResourceManager::loadFromAudioVolume(Resource *res) { return loadPatch(res, file); } +bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) { + res->data = new byte[res->size]; + + if (res->data == NULL) { + error("Can't allocate %d bytes needed for loading %s", res->size, res->id.toString().c_str()); + } + + unsigned int really_read = file.read(res->data, res->size); + if (really_read != res->size) + warning("Read %d bytes from %s but expected %d", really_read, res->id.toString().c_str(), res->size); + + res->status = kResStatusAllocated; + return true; +} + Common::File *ResourceManager::getVolumeFile(const char *filename) { Common::List<Common::File *>::iterator it = _volumeFiles.begin(); Common::File *file; @@ -301,8 +289,7 @@ void ResourceManager::loadResource(Resource *res) { if (res->source->source_type == kSourcePatch && loadFromPatchFile(res)) return; - if (res->source->source_type == kSourceAudioVolume && loadFromAudioVolume(res)) - return; + // Either loading from volume or patch loading failed file = getVolumeFile(res->source->location_name.c_str()); if (!file) { @@ -311,18 +298,25 @@ void ResourceManager::loadResource(Resource *res) { return; } file->seek(res->file_offset, SEEK_SET); - int error = decompress(res, file); - if (error) { - warning("Error %d occured while reading %s.%03d from resource file: %s", - error, getResourceTypeName(res->type), res->number, sci_error_types[error]); - res->unalloc(); - } + if (res->source->source_type == kSourceAudioVolume) { + if (_sciVersion < SCI_VERSION_1_1) + loadFromAudioVolumeSCI1(res, *file); + else + loadFromAudioVolumeSCI11(res, *file); + } else { + int error = decompress(res, file); + if (error) { + warning("Error %d occured while reading %s from resource file: %s", + error, res->id.toString().c_str(), sci_error_types[error]); + res->unalloc(); + } + } } -Resource *ResourceManager::testResource(ResourceType type, int number) { - if (_resMap.contains(RESOURCE_HASH(type, number))) - return _resMap.getVal(RESOURCE_HASH(type, number)); +Resource *ResourceManager::testResource(ResourceId id) { + if (_resMap.contains(id)) + return _resMap.getVal(id); return NULL; } @@ -347,7 +341,7 @@ int ResourceManager::guessSciVersion() { int i; for (i = 0; i < 1000; i++) { - res = testResource(kResourceTypeView, i); + res = testResource(ResourceId(kResourceTypeView, i)); if (!res) continue; @@ -371,7 +365,7 @@ int ResourceManager::guessSciVersion() { // Try the same thing with pics for (i = 0; i < 1000; i++) { - res = testResource(kResourceTypePic, i); + res = testResource(ResourceId(kResourceTypePic, i)); if (!res) continue; @@ -414,72 +408,63 @@ int ResourceManager::addAppropriateSources() { addSource(map, kSourceVolume, name.c_str(), number); } addPatchDir("."); - // TODO: add RESOURCE.AUD and RESOURCE.SFX for SCI1.1 games if (Common::File::exists("MESSAGE.MAP")) addSource(addExternalMap("MESSAGE.MAP"), kSourceVolume, "RESOURCE.MSG", 0); return 1; } int ResourceManager::addInternalSources() { - if (testResource(kResourceTypeMap, 65535)) { - ResourceSource *src = addSource(NULL, kSourceIntMap, "65535.MAP", 65535); + Common::List<ResourceId> *resources = listResources(kResourceTypeMap); + Common::List<ResourceId>::iterator itr = resources->begin(); + + while (itr != resources->end()) { + ResourceSource *src = addSource(NULL, kSourceIntMap, "MAP", itr->number); - if (Common::File::exists("RESOURCE.SFX")) + if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) addSource(src, kSourceAudioVolume, "RESOURCE.SFX", 0); else if (Common::File::exists("RESOURCE.AUD")) addSource(src, kSourceAudioVolume, "RESOURCE.AUD", 0); + + itr++; } return 1; } -int ResourceManager::scanNewSources(ResourceSource *source) { - if (!source) - return SCI_ERROR_NO_RESOURCE_FILES_FOUND; - - int resource_error = 0; - if (source->next) - scanNewSources(source->next); - - if (!source->scanned) { - source->scanned = true; - switch (source->source_type) { - case kSourceDirectory: - readResourcePatches(source); - break; - case kSourceExtMap: - if (_mapVersion < SCI_VERSION_1) - resource_error = readResourceMapSCI0(source); - else - resource_error = readResourceMapSCI1(source); +void ResourceManager::scanNewSources() { + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { + ResourceSource *source = *it; - if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) { - // FIXME: Try reading w/o resource.map - resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND; - } - - if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { - // Initialize empty resource manager - _resMap.clear(); - resource_error = 0; + if (!source->scanned) { + source->scanned = true; + switch (source->source_type) { + case kSourceDirectory: + readResourcePatches(source); + break; + case kSourceExtMap: + if (_mapVersion < SCI_VERSION_1) + readResourceMapSCI0(source); + else + readResourceMapSCI1(source); + break; + case kSourceExtAudioMap: + readAudioMapSCI1(source); + break; + case kSourceIntMap: + readAudioMapSCI11(source); + break; + default: + break; } - break; - case kSourceIntMap: - if (source->volume_number == 65535) - resource_error = readMap65535(source); - break; - default: - break; } } - return resource_error; } -void ResourceManager::freeResourceSources(ResourceSource *rss) { - if (rss) { - freeResourceSources(rss->next); - delete rss; - } +void ResourceManager::freeResourceSources() { + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) + delete *it; + + _sources.clear(); } ResourceManager::ResourceManager(int version, int maxMemory) { @@ -488,8 +473,8 @@ ResourceManager::ResourceManager(int version, int maxMemory) { _memoryLRU = 0; _LRU.clear(); _resMap.clear(); - _sources = NULL; _sciVersion = version; + _audioMapSCI1 = NULL; addAppropriateSources(); @@ -503,19 +488,19 @@ ResourceManager::ResourceManager(int version, int maxMemory) { debug("Using resource map version %d %s", _mapVersion, sci_version_types[_mapVersion]); debug("Using volume version %d %s", _volVersion, sci_version_types[_volVersion]); - scanNewSources(_sources); + scanNewSources(); addInternalSources(); - scanNewSources(_sources); + scanNewSources(); if (version == SCI_VERSION_AUTODETECT) switch (_mapVersion) { case SCI_VERSION_0: - if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) { + if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB))) { version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; - } else if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) { + } else if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB))) { version = guessSciVersion(); if (version != SCI_VERSION_01_VGA) { - version = testResource(kResourceTypeVocab, 912) ? SCI_VERSION_0 : SCI_VERSION_01; + version = testResource(ResourceId(kResourceTypeVocab, 912)) ? SCI_VERSION_0 : SCI_VERSION_01; } } else { version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; @@ -525,7 +510,7 @@ ResourceManager::ResourceManager(int version, int maxMemory) { version = _mapVersion; break; case SCI_VERSION_1: { - Resource *res = testResource(kResourceTypeScript, 0); + Resource *res = testResource(ResourceId(kResourceTypeScript, 0)); _sciVersion = version = SCI_VERSION_1_EARLY; loadResource(res); @@ -579,12 +564,12 @@ ResourceManager::ResourceManager(int version, int maxMemory) { ResourceManager::~ResourceManager() { // freeing resources - Common::HashMap<uint32, Resource *>::iterator itr = _resMap.begin(); + ResourceMap::iterator itr = _resMap.begin(); while (itr != _resMap.end()) { delete itr->_value; itr ++; } - freeResourceSources(_sources); + freeResourceSources(); _resMap.empty(); Common::List<Common::File *>::iterator it = _volumeFiles.begin(); @@ -628,8 +613,7 @@ void ResourceManager::printLRU() { while (it != _LRU.end()) { res = *it; - debug("\t%s.%03d: %d bytes", getResourceTypeName(res->type), - res->number, res->size); + debug("\t%s: %d bytes", res->id.toString().c_str(), res->size); mem += res->size; entries ++; it ++; @@ -638,15 +622,10 @@ void ResourceManager::printLRU() { debug("Total: %d entries, %d bytes (mgr says %d)", entries, mem, _memoryLRU); } -void ResourceManager::freeOldResources(int last_invulnerable) { - while (_maxMemory < _memoryLRU && (!last_invulnerable || !_LRU.empty())) { +void ResourceManager::freeOldResources() { + while (_maxMemory < _memoryLRU) { + assert(!_LRU.empty()); Resource *goner = *_LRU.reverse_begin(); - if (!goner) { - debug("Internal error: mgr->lru_last is NULL!"); - debug("LRU-mem= %d", _memoryLRU); - debug("lru_first = %p", (void *)*_LRU.begin()); - printLRU(); - } removeFromLRU(goner); goner->unalloc(); #ifdef SCI_VERBOSE_RESMGR @@ -655,17 +634,30 @@ void ResourceManager::freeOldResources(int last_invulnerable) { } } -Resource *ResourceManager::findResource(ResourceType type, int number, bool lock) { +Common::List<ResourceId> *ResourceManager::listResources(ResourceType type, int mapNumber) { + Common::List<ResourceId> *resources = new Common::List<ResourceId>; + + ResourceMap::iterator itr = _resMap.begin(); + while (itr != _resMap.end()) { + if ((itr->_value->id.type == type) && ((mapNumber == -1) || (itr->_value->id.number == mapNumber))) + resources->push_back(itr->_value->id); + itr++; + } + + return resources; +} + +Resource *ResourceManager::findResource(ResourceId id, bool lock) { Resource *retval; - if (number >= sci_max_resource_nr[_sciVersion]) { - int modded_number = number % sci_max_resource_nr[_sciVersion]; - sciprintf("[resmgr] Requested invalid resource %s.%d, mapped to %s.%d\n", - getResourceTypeName(type), number, getResourceTypeName(type), modded_number); - number = modded_number; + if (id.number >= sci_max_resource_nr[_sciVersion]) { + ResourceId moddedId = ResourceId(id.type, id.number % sci_max_resource_nr[_sciVersion], id.tuple); + sciprintf("[resmgr] Requested invalid resource %s, mapped to %s\n", + id.toString().c_str(), moddedId.toString().c_str()); + id = moddedId; } - retval = testResource(type, number); + retval = testResource(id); if (!retval) return NULL; @@ -677,6 +669,8 @@ Resource *ResourceManager::findResource(ResourceType type, int number, bool lock // Unless an error occured, the resource is now either // locked or allocated, but never queued or freed. + freeOldResources(); + if (lock) { if (retval->status == kResStatusAllocated) { retval->status = kResStatusLocked; @@ -689,28 +683,19 @@ Resource *ResourceManager::findResource(ResourceType type, int number, bool lock addToLRU(retval); } - freeOldResources(retval->status == kResStatusAllocated); - if (retval->data) return retval; else { - sciprintf("Resmgr: Failed to read %s.%03d\n", getResourceTypeName(retval->type), retval->number); + sciprintf("Resmgr: Failed to read %s\n", retval->id.toString().c_str()); return NULL; } } -void ResourceManager::unlockResource(Resource *res, int resnum, ResourceType restype) { - if (!res) { - if (restype == kResourceTypeInvalid) - sciprintf("Resmgr: Warning: Attempt to unlock non-existant resource %03d.%03d!\n", restype, resnum); - else - sciprintf("Resmgr: Warning: Attempt to unlock non-existant resource %s.%03d!\n", getResourceTypeName(restype), resnum); - return; - } +void ResourceManager::unlockResource(Resource *res) { + assert(res); if (res->status != kResStatusLocked) { - sciprintf("Resmgr: Warning: Attempt to unlock unlocked resource %s.%03d\n", - getResourceTypeName(res->type), res->number); + warning("[Resmgr] Attempt to unlock unlocked resource %s", res->id.toString().c_str()); return; } @@ -720,20 +705,21 @@ void ResourceManager::unlockResource(Resource *res, int resnum, ResourceType res addToLRU(res); } - freeOldResources(0); + freeOldResources(); } int ResourceManager::detectMapVersion() { Common::File file; byte buff[6]; - ResourceSource *rsrc = _sources; - // looking for extarnal map among sources - while (rsrc) { + ResourceSource *rsrc= 0; + + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { + rsrc = *it; + if (rsrc->source_type == kSourceExtMap) { file.open(rsrc->location_name); break; } - rsrc = rsrc->next; } if (file.isOpen() == false) { warning("Failed to open resource map file"); @@ -787,14 +773,14 @@ int ResourceManager::detectMapVersion() { int ResourceManager::detectVolVersion() { Common::File file; - ResourceSource *rsrc = _sources; - // looking for a volume among sources - while (rsrc) { + ResourceSource *rsrc; + for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { + rsrc = *it; + if (rsrc->source_type == kSourceVolume) { file.open(rsrc->location_name); break; } - rsrc = rsrc->next; } if (file.isOpen() == false) { warning("Failed to open volume file"); @@ -865,7 +851,7 @@ int ResourceManager::detectVolVersion() { void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) { Common::File file; Resource *newrsc; - uint32 resId = RESOURCE_HASH(restype, resnumber); + ResourceId resId = ResourceId(restype, resnumber); byte patchtype, patch_data_offset; int fsize; @@ -895,23 +881,13 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, } // Prepare destination, if neccessary if (_resMap.contains(resId) == false) { - // FIXME: code duplication - switch (restype) { - case kResourceTypeSync: - newrsc = new ResourceSync; - break; - default: - newrsc = new Resource; - break; - } + newrsc = new Resource; _resMap.setVal(resId, newrsc); } else newrsc = _resMap.getVal(resId); // Overwrite everything, because we're patching newrsc->id = resId; - newrsc->number = resnumber; newrsc->status = kResStatusNoMalloc; - newrsc->type = restype; newrsc->source = source; newrsc->size = fsize - patch_data_offset - 2; newrsc->headerSize = patch_data_offset; @@ -1001,14 +977,12 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { type = (ResourceType)(id >> 11); number = id & 0x7FF; - uint32 resId = RESOURCE_HASH(type, number); + ResourceId resId = ResourceId(type, number); // adding a new resource if (_resMap.contains(resId) == false) { res = new Resource; - res->id = resId;//id; res->file_offset = offset & (((~bMask) << 24) | 0xFFFFFF); - res->number = number; - res->type = type; + res->id = resId; res->source = getVolume(map, offset >> bShift); _resMap.setVal(resId, res); } @@ -1026,7 +1000,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { memset(resMap, 0, sizeof(resource_index_t) * 32); byte type = 0, prevtype = 0; byte nEntrySize = _mapVersion == SCI_VERSION_1_1 ? SCI11_RESMAP_ENTRIES_SIZE : SCI1_RESMAP_ENTRIES_SIZE; - uint32 resId; + ResourceId resId; // Read resource type and offsets to resource offsets block from .MAP file // The last entry has type=0xFF (0x1F) and offset equals to map file length @@ -1067,22 +1041,12 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { perror(""); return SCI_ERROR_RESMAP_NOT_FOUND; } - resId = RESOURCE_HASH(type, number); + resId = ResourceId((ResourceType)type, number); // adding new resource only if it does not exist if (_resMap.contains(resId) == false) { - switch (type) { - case kResourceTypeSync: - res = new ResourceSync; - break; - default: - res = new Resource; - break; - } - + res = new Resource; _resMap.setVal(resId, res); - res->type = (ResourceType)type; - res->number = number; - res->id = resId;//res->number | (res->type << 16); + res->id = resId; res->source = getVolume(map, volume_nr); res->file_offset = off; } @@ -1091,71 +1055,249 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { return 0; } -int ResourceManager::readMap65535(ResourceSource *map) { - // Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): - // ========= - // 6-byte entries: - // w nEntry - // dw offset +void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) { + // Adding new resource only if it does not exist + if (_resMap.contains(resId) == false) { + Resource *res = new Resource; + _resMap.setVal(resId, res); + res->id = resId; + res->source = src; + res->file_offset = offset; + res->size = size; + } +} + +void ResourceManager::removeAudioResource(ResourceId resId) { + // Remove resource, unless it was loaded from a patch + if (_resMap.contains(resId)) { + Resource *res = _resMap.getVal(resId); - // Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX): - // ========= - // 5-byte entries: - // w nEntry - // tb offset (cumulative) + if (res->source->source_type == kSourceAudioVolume) { + if (res->lockers == 0) { + _resMap.erase(resId); + delete res; + } else { + warning("Failed to remove resource %s (still in use)", resId.toString().c_str()); + } + } + } +} - Resource *mapRes = findResource(kResourceTypeMap, map->volume_number, false); +// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): +// ========= +// 6-byte entries: +// w nEntry +// dw offset + +// Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX): +// ========= +// 5-byte entries: +// w nEntry +// tb offset (cumulative) + +// Early SCI1.1 MAP structure: +// =============== +// 10-byte entries: +// b noun +// b verb +// b cond +// b seq +// dw offset +// w syncSize + syncAscSize + +// Late SCI1.1 MAP structure: +// =============== +// Header: +// dw baseOffset +// Followed by 7 or 11-byte entries: +// b noun +// b verb +// b cond +// b seq +// tb cOffset (cumulative offset) +// w syncSize (iff seq has bit 7 set) +// w syncAscSize (iff seq has bit 6 set) + +int ResourceManager::readAudioMapSCI11(ResourceSource *map) { + bool isEarly = true; + uint32 offset = 0; + Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); if (!mapRes) { - warning("Failed to open 65535.MAP"); + warning("Failed to open %i.MAP", map->volume_number); return SCI_ERROR_RESMAP_NOT_FOUND; } ResourceSource *src = getVolume(map, 0); - if (!src) { - warning("No audio resource files found"); + if (!src) return SCI_ERROR_NO_RESOURCE_FILES_FOUND; + + byte *ptr = mapRes->data; + + if (map->volume_number == 65535) { + // Heuristic to detect late SCI1.1 map format + if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) + isEarly = false; + + while (ptr < mapRes->data + mapRes->size) { + uint16 n = READ_LE_UINT16(ptr); + ptr += 2; + + if (n == 0xffff) + break; + + if (isEarly) { + offset = READ_LE_UINT32(ptr); + ptr += 4; + } else { + offset += READ_LE_UINT24(ptr); + ptr += 3; + } + + addResource(ResourceId(kResourceTypeAudio, n), src, offset); + } + } else { + // Heuristic to detect late SCI1.1 map format + if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff)) + isEarly = false; + + if (!isEarly) { + offset = READ_LE_UINT32(ptr); + ptr += 4; + } + + while (ptr < mapRes->data + mapRes->size) { + uint32 n = READ_BE_UINT32(ptr); + int syncSize = 0; + ptr += 4; + + if (n == 0xffffffff) + break; + + if (isEarly) { + offset = READ_LE_UINT32(ptr); + ptr += 4; + } else { + offset += READ_LE_UINT24(ptr); + ptr += 3; + } + + if (isEarly || (n & 0x80)) { + syncSize = READ_LE_UINT16(ptr); + ptr += 2; + + if (syncSize > 0) + addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize); + } + + if (n & 0x40) { + syncSize += READ_LE_UINT16(ptr); + ptr += 2; + } + + addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize); + } } - bool isEarly = true; + return 0; +} - byte *ptr = mapRes->data; - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) - isEarly = false; +// AUDIOnnn.MAP contains 10-byte entries: +// w nEntry +// dw offset+volume (as in resource.map) +// dw size +// ending with 10 0xFFs - uint32 offset = 0; +int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { + Common::File file; + + if (!file.open(map->location_name)) + return SCI_ERROR_RESMAP_NOT_FOUND; + + while (1) { + uint16 n = file.readUint16LE(); + uint32 offset = file.readUint32LE(); + uint32 size = file.readUint32LE(); - while (ptr < mapRes->data + mapRes->size) { - uint16 n = READ_LE_UINT16(ptr); - ptr += 2; + if (file.ioFailed()) { + warning("Error while reading %s", map->location_name.c_str()); + return SCI_ERROR_RESMAP_NOT_FOUND; + } if (n == 0xffff) break; - if (isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; + byte volume_nr = offset >> 28; // most significant 4 bits + offset &= 0x0fffffff; // least significant 28 bits + + ResourceSource *src = getVolume(map, volume_nr); + + if (src) { + if (unload) + removeAudioResource(ResourceId(kResourceTypeAudio, n)); + else + addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); } else { - offset += READ_LE_UINT24(ptr); - ptr += 3; + warning("Failed to find audio volume %i", volume_nr); } + } - uint32 resId = RESOURCE_HASH(kResourceTypeAudio, n); - // Adding new resource only if it does not exist - if (_resMap.contains(resId) == false) { - Resource *res = new Resource; - _resMap.setVal(resId, res); - res->type = kResourceTypeAudio; - res->number = n; - res->id = resId; - res->source = src; - res->file_offset = offset; + return 0; +} + +void ResourceManager::setAudioLanguage(int language) { + if (_audioMapSCI1) { + if (_audioMapSCI1->volume_number == language) { + // This language is already loaded + return; } + + // We already have a map loaded, so we unload it first + readAudioMapSCI1(_audioMapSCI1, true); + + // Remove all volumes that use this map from the source list + Common::List<ResourceSource *>::iterator it = _sources.begin(); + while (it != _sources.end()) { + ResourceSource *src = *it; + if (src->associated_map == _audioMapSCI1) { + it = _sources.erase(it); + delete src; + } else { + ++it; + } + } + + // Remove the map itself from the source list + _sources.remove(_audioMapSCI1); + delete _audioMapSCI1; + + _audioMapSCI1 = NULL; } - return 0; + char filename[9]; + snprintf(filename, 9, "AUDIO%03d", language); + + Common::String fullname = Common::String(filename) + ".MAP"; + if (!Common::File::exists(fullname)) { + warning("No audio map found for language %i", language); + return; + } + + _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language); + + // Search for audio volumes for this language and add them to the source list + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??"); + for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { + const Common::String name = (*x)->getName(); + const char *dot = strrchr(name.c_str(), '.'); + int number = atoi(dot + 1); + + addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number); + } + + scanNewSources(); } int ResourceManager::readResourceInfo(Resource *res, Common::File *file, @@ -1206,9 +1348,7 @@ int ResourceManager::readResourceInfo(Resource *res, Common::File *file, // check if there were errors while reading if (file->ioFailed()) return SCI_ERROR_IO_ERROR; - res->id = RESOURCE_HASH(type, number); - res->type = type; - res->number = number; + res->id = ResourceId(type, number); res->size = szUnpacked; // checking compression method switch (wCompression) { @@ -1277,8 +1417,7 @@ int ResourceManager::decompress(Resource *res, Common::File *file) { break; #endif default: - warning("Resource %s #%d: Compression method %d not supported", - getResourceTypeName(res->type), res->number, compression); + warning("Resource %s: Compression method %d not supported", res->id.toString().c_str(), compression); return SCI_ERROR_UNKNOWN_COMPRESSION; } @@ -1292,469 +1431,4 @@ int ResourceManager::decompress(Resource *res, Common::File *file) { return error; } -void ResourceSync::startSync(EngineState *s, reg_t obj) { - _syncTime = _syncCue = -1; - PUT_SEL32V(obj, syncCue, 0); - _ptr = (uint16 *)data; - //syncStarted = true; // not used -} - -void ResourceSync::nextSync(EngineState *s, reg_t obj) { - if (_ptr) { - _syncTime = (int16)READ_LE_UINT16(_ptr); - if (_syncTime == -1) { - stopSync(); - } else { - _syncCue = (int16)READ_LE_UINT16(_ptr + 1); - _ptr += 2; - } - PUT_SEL32V(obj, syncTime, _syncTime); - PUT_SEL32V(obj, syncCue, _syncCue); - } -} -//-------------------------------- -void ResourceSync::stopSync() { - _ptr = 0; - _syncCue = -1; - //syncStarted = false; // not used -} - - -AudioResource::AudioResource(ResourceManager *resMgr, int sciVersion) { - _resMgr = resMgr; - _sciVersion = sciVersion; - _audioRate = 11025; - _lang = 0; - _audioMapSCI1 = 0; - _audioMapSCI11 = 0; -} - -AudioResource::~AudioResource() { - if (_sciVersion < SCI_VERSION_1_1) { - if (_audioMapSCI1) { - delete[] _audioMapSCI1; - _audioMapSCI1 = 0; - } - } else { - if (_audioMapSCI11) - _resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap); - } -} - -// Used in SCI1 games -void AudioResource::setAudioLang(int16 lang) { - if (lang != -1) { - _lang = lang; - - char filename[40]; - sprintf(filename, "AUDIO%03d.MAP", _lang); - - Common::File* audioMapFile = new Common::File(); - if (audioMapFile->open(filename)) { - // The audio map is freed in the destructor - _audioMapSCI1 = new byte[audioMapFile->size()]; - audioMapFile->read(_audioMapSCI1, audioMapFile->size()); - audioMapFile->close(); - delete audioMapFile; - } else { - _audioMapSCI1 = 0; - } - } -} - -int AudioResource::getAudioPosition() { - if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) { - return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks - } else { - return -1; // Sound finished - } -} - -bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size) { - // AUDIO00X.MAP contains 10-byte entries: - // w nEntry - // dw offset+volume (as in resource.map) - // dw size - // ending with 10 0xFFs - uint16 n; - uint32 off; - - if (_audioMapSCI1 == 0) - return false; - - byte *ptr = _audioMapSCI1; - while ((n = READ_LE_UINT16(ptr)) != 0xFFFF) { - if (n == audioNumber) { - off = READ_LE_UINT32(ptr + 2); - size = READ_LE_UINT32(ptr + 6); - volume = off >> 28; - offset = off & 0x0FFFFFFF; - return true; - } - ptr += 10; - } - - return false; -} - -bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) { - // Map structure: - // =============== - // Header: - // dw baseOffset - // Followed by 7 or 11-byte entries: - // b noun - // b verb - // b cond - // b seq - // tb cOffset (cumulative offset) - // w syncSize (iff seq has bit 7 set) - // w syncAscSize (iff seq has bit 6 set) - - uint32 n; - offset = 0; - - byte *ptr = _audioMapSCI11->data; - - offset = READ_LE_UINT32(ptr); - ptr += 4; - - while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { - n = READ_BE_UINT32(ptr); - ptr += 4; - - if (n == 0xffffffff) - break; - - offset += READ_LE_UINT24(ptr); - ptr += 3; - - int syncSkip = 0; - - if (n & 0x80) { - n ^= 0x80; - - if (getSync) { - if (size) - *size = READ_LE_UINT16(ptr); - } else { - syncSkip = READ_LE_UINT16(ptr); - } - - ptr += 2; - - if (n & 0x40) { - n ^= 0x40; - - if (!getSync) - syncSkip += READ_LE_UINT16(ptr); - - ptr += 2; - } - - offset += syncSkip; - - if (n == audioNumber) - return true; - - } else { - if (n == audioNumber) - return !getSync; - } - - offset -= syncSkip; - } - - return false; -} - -bool AudioResource::findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) { - // Map structure: - // =============== - // 10-byte entries: - // b noun - // b verb - // b cond - // b seq - // dw offset - // w syncSize + syncAscSize - - uint32 n; - offset = 0; - - byte *ptr = _audioMapSCI11->data; - - while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { - n = READ_BE_UINT32(ptr); - ptr += 4; - - if (n == 0xffffffff) - break; - - offset = READ_LE_UINT32(ptr); - ptr += 4; - - int syncSize = READ_LE_UINT16(ptr); - ptr += 2; - - if (n == audioNumber) { - if (getSync) { - if (size) - *size = syncSize; - return true; - } else { - offset += syncSize; - return true; - } - } - } - - return false; -} - -bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) { - if (_audioMapSCI11 && _audioMapSCI11->number != volume) { - _resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap); - _audioMapSCI11 = 0; - } - - if (!_audioMapSCI11) { - _audioMapSCI11 = _resMgr->findResource(kResourceTypeMap, volume, 1); - } - - byte *ptr = _audioMapSCI11->data; - - if (volume == 65535) - return false; - - // In early SCI1.1 the map is terminated with 10x 0xff, in late SCI1.1 - // with 11x 0xff. If we look at the 11th last byte in an early SCI1.1 - // map, this will be the high byte of the Sync length of the last entry. - // As Sync resources are relative small, we should never encounter a - // Sync with a size of 0xffnn. As such, the following heuristic should be - // sufficient to tell these map formats apart. - if (_audioMapSCI11->size >= 11 && (ptr[_audioMapSCI11->size - 11] == 0xff)) - return findAudEntrySCI11Late(audioNumber, offset, getSync, size); - else { - return findAudEntrySCI11Early(audioNumber, offset, getSync, size); - } - - return false; -} - -// FIXME: Move this to sound/adpcm.cpp? -// Note that the 16-bit version is also used in coktelvideo.cpp -static const uint16 tableDPCM16[128] = { - 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, - 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120, - 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0, - 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, - 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280, - 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0, - 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, - 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, - 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0, - 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480, - 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, - 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, - 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 -}; - -static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21}; - -static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { - int16 *out = (int16 *) soundBuf; - - int32 s = 0; - for (uint32 i = 0; i < n; i++) { - byte b = audioStream.readByte(); - if (b & 0x80) - s -= tableDPCM16[b & 0x7f]; - else - s += tableDPCM16[b]; - - s = CLIP<int32>(s, -32768, 32767); - *out++ = TO_BE_16(s); - } -} - -static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) { - if (b & 8) - s -= tableDPCM8[7 - (b & 7)]; - else - s += tableDPCM8[b & 7]; - s = CLIP<int32>(s, 0, 255); - *soundBuf = s; -} - -static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { - int32 s = 0x80; - - for (uint i = 0; i < n; i++) { - byte b = audioStream.readByte(); - - deDPCM8Nibble(soundBuf++, s, b >> 4); - deDPCM8Nibble(soundBuf++, s, b & 0xf); - } -} - -// Sierra SOL audio file reader -// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { - if (headerSize != 11 && headerSize != 12) { - warning("SOL audio header of size %i not supported", headerSize); - return false; - } - - audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) - audioRate = audioStream->readUint16LE(); - audioFlags = audioStream->readByte(); - - size = audioStream->readUint32LE(); - return true; -} - -static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) { - byte *buffer; - - // Convert the SOL stream flags to our own format - flags = 0; - if (audioFlags & kSolFlag16Bit) - flags |= Audio::Mixer::FLAG_16BITS; - if (!(audioFlags & kSolFlagIsSigned)) - flags |= Audio::Mixer::FLAG_UNSIGNED; - - if (audioFlags & kSolFlagCompressed) { - buffer = new byte[size * 2]; - - if (audioFlags & kSolFlag16Bit) - deDPCM16(buffer, *audioStream, size); - else - deDPCM8(buffer, *audioStream, size); - - size *= 2; - } else { - // We assume that the sound data is raw PCM - buffer = (byte *)malloc(size); - audioStream->read(buffer, size); - } - - return buffer; -} - -Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 volume, int *sampleLen) { - Audio::AudioStream *audioStream = 0; - uint32 offset; - uint32 size; - bool found = false; - byte *data = 0; - char filename[40]; - byte flags = 0; - - // Try to load from resource manager - if (volume == 65535) { - Sci::Resource* audioRes = _resMgr->findResource(kResourceTypeAudio, audioNumber, false); - - if (_sciVersion < SCI_VERSION_1_1) { - size = audioRes->size; - data = audioRes->data; - } else { - byte audioFlags; - - Common::MemoryReadStream *headerStream = - new Common::MemoryReadStream(audioRes->header, audioRes->headerSize, false); - - if (readSOLHeader(headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) { - Common::MemoryReadStream *dataStream = - new Common::MemoryReadStream(audioRes->data, audioRes->size, false); - data = readSOLAudio(dataStream, size, audioFlags, flags); - delete dataStream; - } - delete headerStream; - } - - if (data) { - audioStream = Audio::makeLinearInputStream(data, size, _audioRate, - flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - } - } else { - // Load it from the audio file - if (_sciVersion < SCI_VERSION_1_1) { - byte sci1Volume; - found = findAudEntrySCI1(audioNumber, sci1Volume, offset, size); - sprintf(filename, "AUDIO%03d.%03d", _lang, sci1Volume); - flags |= Audio::Mixer::FLAG_UNSIGNED; - } else { - found = findAudEntrySCI11(audioNumber, volume, offset); - strcpy(filename, "RESOURCE.AUD"); - } - - if (found) { - #if 0 - // TODO: This tries to load directly from the KQ5CD audio file with MP3/OGG/FLAC - // compression. Once we got a tool to compress this file AND update the map file - // at the same time, we can use this code to play compressed audio. - if (_sciVersion < SCI_VERSION_1_1) { - uint32 start = offset * 1000 / _audioRate; - uint32 duration = size * 1000 / _audioRate; - - // Try to load compressed - audioStream = Audio::AudioStream::openStreamFile(filename, start, duration); - } - #endif - - if (!audioStream) { - // Compressed file load failed, try to load original raw data - Common::File* audioFile = new Common::File(); - if (audioFile->open(filename)) { - audioFile->seek(offset); - - if (_sciVersion < SCI_VERSION_1_1) { - data = (byte *)malloc(size); - audioFile->read(data, size); - } else { - byte type = audioFile->readByte() & 0x7f; - byte audioFlags; - - if (type != kResourceTypeAudio) { - warning("Resource type mismatch"); - delete audioFile; - return NULL; - } - - byte headerSize = audioFile->readByte(); - - if (readSOLHeader(audioFile, headerSize, size, _audioRate, audioFlags)) - data = readSOLAudio(audioFile, size, audioFlags, flags); - - if (!data) { - delete audioFile; - return NULL; - } - } - - audioFile->close(); - - if (data) { - audioStream = Audio::makeLinearInputStream(data, size, _audioRate, - flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - } - } - - delete audioFile; - } - } else { - warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff, - (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff); - } - } - - if (audioStream) { - *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; - return audioStream; - } - - return NULL; -} - } // End of namespace Sci diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 219979b383..77c92840ee 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -72,19 +72,14 @@ enum { enum ResSourceType { kSourceDirectory = 0, - kSourcePatch = 1, - kSourceVolume = 2, - kSourceExtMap = 3, - kSourceIntMap = 4, - kSourceAudioVolume = 5, - kSourceMask = 127 + kSourcePatch, + kSourceVolume, + kSourceExtMap, + kSourceIntMap, + kSourceAudioVolume, + kSourceExtAudioMap }; -#define RESSOURCE_ADDRESSING_BASIC 0 -#define RESSOURCE_ADDRESSING_EXTENDED 128 -#define RESSOURCE_ADDRESSING_MASK 128 - -#define RESOURCE_HASH(type, number) (uint32)((type<<16) | number) #define SCI0_RESMAP_ENTRIES_SIZE 6 #define SCI1_RESMAP_ENTRIES_SIZE 6 #define SCI11_RESMAP_ENTRIES_SIZE 5 @@ -136,11 +131,60 @@ struct ResourceSource { Common::String location_name; // FIXME: Replace by FSNode ? int volume_number; ResourceSource *associated_map; - ResourceSource *next; }; class ResourceManager; +class ResourceId { +public: + ResourceType type; + uint16 number; + uint32 tuple; // Only used for audio36 and sync36 + + ResourceId() : type(kResourceTypeInvalid), number(0), tuple(0) { }; + + ResourceId(ResourceType type_, uint16 number_, uint32 tuple_ = 0) : type(type_), number(number_), tuple(tuple_) { + if ((type < kResourceTypeView) || (type > kResourceTypeInvalid)) + type = kResourceTypeInvalid; + } + + ResourceId(ResourceType type_, uint16 number_, byte noun, byte verb, byte cond, byte seq) : type(type_), number(number_) { + tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq; + + if ((type < kResourceTypeView) || (type > kResourceTypeInvalid)) + type = kResourceTypeInvalid; + } + + Common::String toString() { + char buf[32]; + + snprintf(buf, 32, "%s.%i", getResourceTypeName(type), number); + Common::String retStr = buf; + + if (tuple != 0) { + snprintf(buf, 32, "(%i, %i, %i, %i)", tuple >> 24, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff); + retStr += buf; + } + + return retStr; + } +}; + +struct ResourceIdHash : public Common::UnaryFunction<ResourceId, uint> { + uint operator()(ResourceId val) const { return ((uint)((val.type << 16) | val.number)) ^ val.tuple; } +}; + +struct ResourceIdEqualTo : public Common::BinaryFunction<ResourceId, ResourceId, bool> { + bool operator()(const ResourceId &x, const ResourceId &y) const { return (x.type == y.type) && (x.number == y.number) && (x.tuple == y.tuple); } +}; + +struct ResourceIdLess : public Common::BinaryFunction<ResourceId, ResourceId, bool> { + bool operator()(const ResourceId &x, const ResourceId &y) const { + return (x.type < y.type) || ((x.type == y.type) && (x.number < y.number)) + || ((x.type == y.type) && (x.number == y.number) && (x.tuple < y.tuple)); + } +}; + /** Class for storing resources in memory */ class Resource { friend class ResourceManager; @@ -153,9 +197,7 @@ public: // to let the rest of the engine compile without changes public: byte *data; - uint16 number; - ResourceType type; - uint32 id; //!< contains number and type. + ResourceId id; uint32 size; byte *header; uint32 headerSize; @@ -166,6 +208,7 @@ protected: ResourceSource *source; }; +typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash, ResourceIdEqualTo> ResourceMap; class ResourceManager { public: @@ -188,26 +231,22 @@ public: /** * Looks up a resource's data. - * @param type: The resource type to look for - * @param number: The resource number to search + * @param id: The resource type to look for * @param lock: non-zero iff the resource should be locked * @return (Resource *): The resource, or NULL if it doesn't exist * @note Locked resources are guaranteed not to have their contents freed until * they are unlocked explicitly (by unlockResource). */ - Resource *findResource(ResourceType type, int number, bool lock); + Resource *findResource(ResourceId id, bool lock); /* Unlocks a previously locked resource ** (Resource *) res: The resource to free - ** (int) number: Number of the resource to check (ditto) - ** (ResourceType) type: Type of the resource to check (for error checking) ** Returns : (void) */ - void unlockResource(Resource *res, int restype, ResourceType resnum); + void unlockResource(Resource *res); /* Tests whether a resource exists - ** (ResourceType) type: Type of the resource to check - ** (int) number: Number of the resource to check + ** (ResourceId) id: Id of the resource to check ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise ** This function may often be much faster than finding the resource ** and should be preferred for simple tests. @@ -215,16 +254,27 @@ public: ** it should be used with care, as it may be unallocated. ** Use scir_find_resource() if you want to use the data contained in the resource. */ - Resource *testResource(ResourceType type, int number); + Resource *testResource(ResourceId id); + + /** + * Returns a list of all resources of the specified type. + * @param type: The resource type to look for + * @param mapNumber: For audio36 and sync36, limit search to this map + * @return: The resource list + */ + Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1); + + void setAudioLanguage(int language); protected: int _maxMemory; //!< Config option: Maximum total byte number allocated - ResourceSource *_sources; + Common::List<ResourceSource *> _sources; int _memoryLocked; //!< Amount of resource bytes in locked memory int _memoryLRU; //!< Amount of resource bytes under LRU control Common::List<Resource *> _LRU; //!< Last Resource Used list - Common::HashMap<uint32, Resource *> _resMap; + ResourceMap _resMap; Common::List<Common::File *> _volumeFiles; //!< list of opened volume files + ResourceSource *_audioMapSCI1; //!< Currently loaded audio map for SCI1 /** * Add a path to the resource manager's list of sources. @@ -263,19 +313,22 @@ protected: * used during startup. May be NULL. * @return One of SCI_ERROR_*. */ - int scanNewSources(ResourceSource *source); + void scanNewSources(); int addAppropriateSources(); int addInternalSources(); - void freeResourceSources(ResourceSource *rss); + void freeResourceSources(); Common::File *getVolumeFile(const char *filename); void loadResource(Resource *res); bool loadPatch(Resource *res, Common::File &file); bool loadFromPatchFile(Resource *res); - bool loadFromAudioVolume(Resource *res); - void freeOldResources(int last_invulnerable); + bool loadFromAudioVolumeSCI1(Resource *res, Common::File &file); + bool loadFromAudioVolumeSCI11(Resource *res, Common::File &file); + void freeOldResources(); int decompress(Resource *res, Common::File *file); int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression); + void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0); + void removeAudioResource(ResourceId resId); /**--- Resource map decoding functions ---*/ int detectMapVersion(); @@ -283,21 +336,32 @@ protected: /** * Reads the SCI0 resource.map file from a local directory. + * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ int readResourceMapSCI0(ResourceSource *map); /** * Reads the SCI1 resource.map file from a local directory. + * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ int readResourceMapSCI1(ResourceSource *map); /** - * Reads the SCI1.1 65535.map resource + * Reads SCI1.1 audio map resources + * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ - int readMap65535(ResourceSource *map); + int readAudioMapSCI11(ResourceSource *map); + + /** + * Reads SCI1 audio map files + * @param map The map + * @param unload Unload the map instead of loading it + * @return 0 on success, an SCI_ERROR_* code otherwise + */ + int readAudioMapSCI1(ResourceSource *map, bool unload = false); /**--- Patch management functions ---*/ @@ -314,60 +378,6 @@ protected: int guessSciVersion(); }; -/** - * Used for lip and animation syncing in CD talkie games - */ -class ResourceSync : public Resource { -public: - ResourceSync() {} - ~ResourceSync() {} - - void startSync(EngineState *s, reg_t obj); - void nextSync(EngineState *s, reg_t obj); - void stopSync(); - -protected: - uint16 *_ptr; - int16 _syncTime, _syncCue; - //bool _syncStarted; // not used -}; - -/** - * Used for speech playback and digital music playback - * in CD talkie games - */ -class AudioResource { -public: - AudioResource(ResourceManager *resMgr, int sciVersion); - ~AudioResource(); - - void setAudioRate(uint16 audioRate) { _audioRate = audioRate; } - void setAudioLang(int16 lang); - - Audio::SoundHandle* getAudioHandle() { return &_audioHandle; } - int getAudioPosition(); - - Audio::AudioStream* getAudioStream(uint32 audioNumber, uint32 volume, int *sampleLen); - - void stop() { g_system->getMixer()->stopHandle(_audioHandle); } - void pause() { g_system->getMixer()->pauseHandle(_audioHandle, true); } - void resume() { g_system->getMixer()->pauseHandle(_audioHandle, false); } - -private: - Audio::SoundHandle _audioHandle; - uint16 _audioRate; - int16 _lang; - byte *_audioMapSCI1; - Resource *_audioMapSCI11; - ResourceManager *_resMgr; - int _sciVersion; - - bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size); - bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync = false, uint32 *size = NULL); - bool findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size); - bool findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size); -}; - } // End of namespace Sci #endif // SCI_SCICORE_RESOURCE_H diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index adcf302f51..c5bf3f5a32 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -29,6 +29,7 @@ #include "engines/advancedDetector.h" #include "sci/sci.h" +#include "sci/debug.h" #include "sci/console.h" #include "sci/engine/state.h" @@ -164,7 +165,6 @@ Common::Error SciEngine::run() { // SCI1 if (flags & GF_SCI0_OLD || - flags & GF_SCI0_OLDGFXFUNCS || flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set"); } @@ -176,7 +176,6 @@ Common::Error SciEngine::run() { } if (flags & GF_SCI0_OLD || - flags & GF_SCI0_OLDGFXFUNCS || flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set"); } @@ -261,7 +260,19 @@ Common::Error SciEngine::run() { return Common::kNoError; } +// Invoked by error() when a severe error occurs GUI::Debugger *SciEngine::getDebugger() { + ExecStack *xs = &(_gamestate->_executionStack.back()); + debugState.runningStep = 0; // Stop multiple execution + debugState.seeking = kDebugSeekNothing; // Stop special seeks + xs->addr.pc.offset = debugState.old_pc_offset; + xs->sp = debugState.old_sp; + + return _console; +} + +// Used to obtain the engine's console in order to print messages to it +Console *SciEngine::getSciDebugger() { return _console; } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 7cadfd0d7b..ea50976df4 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -96,18 +96,10 @@ enum SciGameFlags { */ GF_SCI0_OLD = (1 << 0), - /* Applies to all versions before 0.000.502 - ** Old SCI versions used to interpret the third DrawPic() parameter inversely, - ** with the opposite default value (obviously). - ** Also, they used 15 priority zones from 42 to 200 instead of 14 priority - ** zones from 42 to 190. - */ - GF_SCI0_OLDGFXFUNCS = (1 << 1), - /* Applies to all versions before 0.000.629 ** Older SCI versions had simpler code for GetTime() */ - GF_SCI0_OLDGETTIME = (1 << 2), + GF_SCI0_OLDGETTIME = (1 << 1), // ---------------------------------------------------------------------------- @@ -118,21 +110,22 @@ enum SciGameFlags { /* ** Used to distinguish SCI1 EGA games */ - GF_SCI1_EGA = (1 << 3), + GF_SCI1_EGA = (1 << 2), /* Applies to all SCI1 versions after 1.000.200 ** In late SCI1 versions, the argument of lofs[as] instructions ** is absolute rather than relative. */ - GF_SCI1_LOFSABSOLUTE = (1 << 4), + GF_SCI1_LOFSABSOLUTE = (1 << 3), /* Applies to all versions from 1.000.510 onwards ** kDoSound() is different than in earlier SCI1 versions. */ - GF_SCI1_NEWDOSOUND = (1 << 5) + GF_SCI1_NEWDOSOUND = (1 << 4) }; class SciEngine : public Engine { + friend class Console; public: SciEngine(OSystem *syst, const SciGameDescription *desc); ~SciEngine(); @@ -141,6 +134,7 @@ public: virtual Common::Error run(); void pauseEngineIntern(bool pause); virtual GUI::Debugger *getDebugger(); + Console *getSciDebugger(); const char* getGameID() const; int getResourceVersion() const; diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index 7e3395b7d3..95d79b3666 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -47,6 +47,15 @@ class SfxPlayer; SfxPlayer *player = NULL; // FIXME: Avoid non-const global vars +/* Plays a song iterator that found a PCM through a PCM device, if possible +** Parameters: (SongIterator *) it: The iterator to play +** (SongHandle) handle: Debug handle +** Returns : (int) 0 if the effect will not be played, nonzero if it will +** This assumes that the last call to 'it->next()' returned SI_PCM. +*/ +static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle); + + #pragma mark - @@ -337,53 +346,54 @@ int sfx_get_player_polyphony() { SfxState::SfxState() { _it = NULL; _flags = 0; - memset(&_songlib, 0, sizeof(_songlib)); _song = NULL; _suspended = 0; - _soundSync = 0; - _audioResource = 0; + _syncResource = NULL; + _audioRate = 11025; } SfxState::~SfxState() { + if (_syncResource) + _resMgr->unlockResource(_syncResource); } void SfxState::freezeTime() { /* Freezes the top song delay time */ const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - song_t *song = _song; + Song *song = _song; while (song) { song->_delay = song->_wakeupTime.frameDiff(ctime); if (song->_delay < 0) song->_delay = 0; - song = song->next_playing; + song = song->_nextPlaying; } } void SfxState::thawTime() { /* inverse of freezeTime() */ const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - song_t *song = _song; + Song *song = _song; while (song) { song->_wakeupTime = ctime.addFrames(song->_delay); - song = song->next_playing; + song = song->_nextPlaying; } } #if 0 // Unreferenced - removed static void _dump_playing_list(SfxState *self, char *msg) { - song_t *song = self->_song; + Song *song = self->_song; fprintf(stderr, "[] Song list : [ "); song = *(self->_songlib.lib); while (song) { - fprintf(stderr, "%08lx:%d ", song->handle, song->status); - song = song->next_playing; + fprintf(stderr, "%08lx:%d ", song->handle, song->_status); + song = song->_nextPlaying; } fprintf(stderr, "]\n"); @@ -391,7 +401,7 @@ static void _dump_playing_list(SfxState *self, char *msg) { while (song) { fprintf(stderr, "%08lx ", song->handle); - song = song->next_playing; + song = song->_nextPlaying; } fprintf(stderr, "]\n"); @@ -400,15 +410,15 @@ static void _dump_playing_list(SfxState *self, char *msg) { #if 0 static void _dump_songs(SfxState *self) { - song_t *song = self->_song; + Song *song = self->_song; fprintf(stderr, "Cue iterators:\n"); song = *(self->_songlib.lib); while (song) { fprintf(stderr, " **\tHandle %08x (p%d): status %d\n", - song->handle, song->priority, song->status); - SIMSG_SEND(song->it, SIMSG_PRINT(1)); - song = song->next; + song->handle, song->_priority, song->_status); + SIMSG_SEND(song->_it, SIMSG_PRINT(1)); + song = song->_next; } if (player) { @@ -418,32 +428,32 @@ static void _dump_songs(SfxState *self) { } #endif -bool SfxState::isPlaying(song_t *song) { - song_t *playing_song = _song; +bool SfxState::isPlaying(Song *song) { + Song *playing_song = _song; /* _dump_playing_list(this, "is-playing");*/ while (playing_song) { if (playing_song == song) return true; - playing_song = playing_song->next_playing; + playing_song = playing_song->_nextPlaying; } return false; } -void SfxState::setSongStatus(song_t *song, int status) { +void SfxState::setSongStatus(Song *song, int status) { const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); switch (status) { case SOUND_STATUS_STOPPED: // Reset - song->it->init(); + song->_it->init(); break; case SOUND_STATUS_SUSPENDED: case SOUND_STATUS_WAITING: - if (song->status == SOUND_STATUS_PLAYING) { + if (song->_status == SOUND_STATUS_PLAYING) { // Update delay, set wakeup_time song->_delay += song->_wakeupTime.frameDiff(ctime); song->_wakeupTime = ctime; @@ -454,7 +464,7 @@ void SfxState::setSongStatus(song_t *song, int status) { /* otherwise... */ case SOUND_STATUS_PLAYING: - if (song->status == SOUND_STATUS_STOPPED) { + if (song->_status == SOUND_STATUS_STOPPED) { // Starting anew song->_wakeupTime = ctime; } @@ -471,12 +481,12 @@ void SfxState::setSongStatus(song_t *song, int status) { return; } - song->status = status; + song->_status = status; } /* Update internal state iff only one song may be played */ void SfxState::updateSingleSong() { - song_t *newsong = song_lib_find_active(_songlib); + Song *newsong = _songlib.findFirstActive(); if (newsong != _song) { freezeTime(); /* Store song delay time */ @@ -485,11 +495,11 @@ void SfxState::updateSingleSong() { player->stop(); if (newsong) { - if (!newsong->it) + if (!newsong->_it) return; /* Restore in progress and not ready for this yet */ /* Change song */ - if (newsong->status == SOUND_STATUS_WAITING) + if (newsong->_status == SOUND_STATUS_WAITING) setSongStatus(newsong, SOUND_STATUS_PLAYING); /* Change instrument mappings */ @@ -497,7 +507,7 @@ void SfxState::updateSingleSong() { /* Turn off sound */ } if (_song) { - if (_song->status == SOUND_STATUS_PLAYING) + if (_song->_status == SOUND_STATUS_PLAYING) setSongStatus(newsong, SOUND_STATUS_WAITING); } @@ -506,25 +516,25 @@ void SfxState::updateSingleSong() { debugMessage += " New song:"; } else { char tmp[50]; - sprintf(tmp, " pausing %08lx, now playing ", _song->handle); + sprintf(tmp, " pausing %08lx, now playing ", _song->_handle); debugMessage += tmp; } if (newsong) { char tmp[20]; - sprintf(tmp, "%08lx\n", newsong->handle); + sprintf(tmp, "%08lx\n", newsong->_handle); debugMessage += tmp; } else { debugMessage += " none\n"; } - debugC(2, kDebugLevelSound, debugMessage.c_str()); + debugC(2, kDebugLevelSound, "%s", debugMessage.c_str()); _song = newsong; thawTime(); /* Recover song delay time */ if (newsong && player) { - SongIterator *clonesong = newsong->it->clone(newsong->_delay); + SongIterator *clonesong = newsong->_it->clone(newsong->_delay); player->add_iterator(clonesong, newsong->_wakeupTime.msecs()); } @@ -533,11 +543,11 @@ void SfxState::updateSingleSong() { void SfxState::updateMultiSong() { - song_t *oldfirst = _song; - song_t *oldseeker; - song_t *newsong = song_lib_find_active(_songlib); - song_t *newseeker; - song_t not_playing_anymore; /* Dummy object, referenced by + Song *oldfirst = _song; + Song *oldseeker; + Song *newsong = _songlib.findFirstActive(); + Song *newseeker; + Song not_playing_anymore; /* Dummy object, referenced by ** songs which are no longer ** active. */ @@ -548,30 +558,28 @@ void SfxState::updateMultiSong() { return; for (newseeker = newsong; newseeker; - newseeker = newseeker->next_playing) { - if (!newseeker || !newseeker->it) + newseeker = newseeker->_nextPlaying) { + if (!newseeker || !newseeker->_it) return; /* Restore in progress and not ready for this yet */ } /* First, put all old songs into the 'stopping' list and ** mark their 'next-playing' as not_playing_anymore. */ for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->next_stopping) { - oldseeker->next_stopping = oldseeker->next_playing; - oldseeker->next_playing = ¬_playing_anymore; + oldseeker = oldseeker->_nextStopping) { + oldseeker->_nextStopping = oldseeker->_nextPlaying; + oldseeker->_nextPlaying = ¬_playing_anymore; - if (oldseeker == oldseeker->next_playing) { + if (oldseeker == oldseeker->_nextPlaying) { error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); } } /* Second, re-generate the new song queue. */ - for (newseeker = newsong; newseeker; - newseeker = newseeker->next_playing) { - newseeker->next_playing - = song_lib_find_next_active(_songlib, newseeker); + for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { + newseeker->_nextPlaying = _songlib.findNextActive(newseeker); - if (newseeker == newseeker->next_playing) { + if (newseeker == newseeker->_nextPlaying) { error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); } } @@ -582,21 +590,21 @@ void SfxState::updateMultiSong() { /* Third, stop all old songs */ for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->next_stopping) - if (oldseeker->next_playing == ¬_playing_anymore) { + oldseeker = oldseeker->_nextStopping) + if (oldseeker->_nextPlaying == ¬_playing_anymore) { setSongStatus(oldseeker, SOUND_STATUS_SUSPENDED); - debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx\n", oldseeker->handle); + debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx\n", oldseeker->_handle); - if (player && oldseeker->it) - player->iterator_message(SongIterator::Message(oldseeker->it->ID, SIMSG_STOP)); - oldseeker->next_playing = NULL; /* Clear this pointer; we don't need the tag anymore */ + if (player && oldseeker->_it) + player->iterator_message(SongIterator::Message(oldseeker->_it->ID, SIMSG_STOP)); + oldseeker->_nextPlaying = NULL; /* Clear this pointer; we don't need the tag anymore */ } - for (newseeker = newsong; newseeker; newseeker = newseeker->next_playing) { - if (newseeker->status != SOUND_STATUS_PLAYING && player) { - debugC(2, kDebugLevelSound, "[SFX] Adding song %lx\n", newseeker->it->ID); + for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { + if (newseeker->_status != SOUND_STATUS_PLAYING && player) { + debugC(2, kDebugLevelSound, "[SFX] Adding song %lx\n", newseeker->_it->ID); - SongIterator *clonesong = newseeker->it->clone(newseeker->_delay); + SongIterator *clonesong = newseeker->_it->clone(newseeker->_delay); player->add_iterator(clonesong, g_system->getMillis()); } setSongStatus(newseeker, SOUND_STATUS_PLAYING); @@ -615,7 +623,7 @@ void SfxState::update() { updateSingleSong(); } -int sfx_play_iterator_pcm(SongIterator *it, song_handle_t handle) { +static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle) { #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Playing PCM: %08lx\n", handle); #endif @@ -632,11 +640,11 @@ int sfx_play_iterator_pcm(SongIterator *it, song_handle_t handle) { #define DELAY (1000000 / SFX_TICKS_PER_SEC) void SfxState::sfx_init(ResourceManager *resmgr, int flags) { - song_lib_init(&_songlib); + _songlib._lib = 0; _song = NULL; _flags = flags; - _soundSync = NULL; - _audioResource = NULL; + _syncResource = NULL; + _syncOffset = 0; player = NULL; @@ -670,6 +678,8 @@ void SfxState::sfx_init(ResourceManager *resmgr, int flags) { delete player; player = NULL; } + + _resMgr = resmgr; } void SfxState::sfx_exit() { @@ -682,13 +692,7 @@ void SfxState::sfx_exit() { g_system->getMixer()->stopAll(); - song_lib_free(_songlib); - - // Delete audio resources for CD talkie games - if (_audioResource) { - delete _audioResource; - _audioResource = 0; - } + _songlib.freeSounds(); } void SfxState::sfx_suspend(bool suspend) { @@ -716,11 +720,11 @@ void SfxState::sfx_suspend(bool suspend) { _suspended = suspend; } -int SfxState::sfx_poll(song_handle_t *handle, int *cue) { +int SfxState::sfx_poll(SongHandle *handle, int *cue) { if (!_song) return 0; /* No milk today */ - *handle = _song->handle; + *handle = _song->_handle; #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Polling any (%08lx)\n", *handle); @@ -728,12 +732,12 @@ int SfxState::sfx_poll(song_handle_t *handle, int *cue) { return sfx_poll_specific(*handle, cue); } -int SfxState::sfx_poll_specific(song_handle_t handle, int *cue) { +int SfxState::sfx_poll_specific(SongHandle handle, int *cue) { const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - song_t *song = _song; + Song *song = _song; - while (song && song->handle != handle) - song = song->next_playing; + while (song && song->_handle != handle) + song = song->_nextPlaying; if (!song) return 0; /* Song not playing */ @@ -745,7 +749,7 @@ int SfxState::sfx_poll_specific(song_handle_t handle, int *cue) { return 0; /* Patience, young hacker! */ byte buf[8]; - int result = songit_next(&(song->it), buf, cue, IT_READER_MASK_ALL); + int result = songit_next(&(song->_it), buf, cue, IT_READER_MASK_ALL); switch (result) { @@ -783,8 +787,8 @@ int SfxState::sfx_poll_specific(song_handle_t handle, int *cue) { /* Song basics */ /*****************/ -void SfxState::sfx_add_song(SongIterator *it, int priority, song_handle_t handle, int number) { - song_t *song = song_lib_find(_songlib, handle); +void SfxState::sfx_add_song(SongIterator *it, int priority, SongHandle handle, int number) { + Song *song = _songlib.findSong(handle); #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Adding song: %08lx at %d, it=%p\n", handle, priority, it); @@ -807,37 +811,37 @@ void SfxState::sfx_add_song(SongIterator *it, int priority, song_handle_t handle setSongStatus( song, SOUND_STATUS_STOPPED); fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle); - if (song->status == SOUND_STATUS_PLAYING || song->status == SOUND_STATUS_SUSPENDED) { + if (song->_status == SOUND_STATUS_PLAYING || song->_status == SOUND_STATUS_SUSPENDED) { delete it; error("Unexpected (error): Song %ld still playing/suspended (%d)", - handle, song->status); + handle, song->_status); return; } else { - song_lib_remove(_songlib, handle); /* No duplicates */ + _songlib.removeSong(handle); /* No duplicates */ } } - song = song_new(handle, it, priority); - song->resource_num = number; - song->hold = 0; - song->loops = 0; + song = new Song(handle, it, priority); + song->_resourceNum = number; + song->_hold = 0; + song->_loops = 0; song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - song_lib_add(_songlib, song); + _songlib.addSong(song); _song = NULL; /* As above */ update(); return; } -void SfxState::sfx_remove_song(song_handle_t handle) { +void SfxState::sfx_remove_song(SongHandle handle) { #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Removing song: %08lx\n", handle); #endif - if (_song && _song->handle == handle) + if (_song && _song->_handle == handle) _song = NULL; - song_lib_remove(_songlib, handle); + _songlib.removeSong(handle); update(); } @@ -849,8 +853,8 @@ void SfxState::sfx_remove_song(song_handle_t handle) { #define ASSERT_SONG(s) if (!(s)) { warning("Looking up song handle %08lx failed in %s, L%d", handle, __FILE__, __LINE__); return; } -void SfxState::sfx_song_set_status(song_handle_t handle, int status) { - song_t *song = song_lib_find(_songlib, handle); +void SfxState::sfx_song_set_status(SongHandle handle, int status) { + Song *song = _songlib.findSong(handle); ASSERT_SONG(song); #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Setting song status to %d" @@ -862,11 +866,11 @@ void SfxState::sfx_song_set_status(song_handle_t handle, int status) { update(); } -void SfxState::sfx_song_set_fade(song_handle_t handle, fade_params_t *params) { +void SfxState::sfx_song_set_fade(SongHandle handle, fade_params_t *params) { #ifdef DEBUG_SONG_API static const char *stopmsg[] = {"??? Should not happen", "Do not stop afterwards", "Stop afterwards"}; #endif - song_t *song = song_lib_find(_songlib, handle); + Song *song = _songlib.findSong(handle); ASSERT_SONG(song); @@ -877,52 +881,52 @@ void SfxState::sfx_song_set_fade(song_handle_t handle, fade_params_t *params) { stopmsg[fade->action]); #endif - SIMSG_SEND_FADE(song->it, params); + SIMSG_SEND_FADE(song->_it, params); update(); } -void SfxState::sfx_song_renice(song_handle_t handle, int priority) { - song_t *song = song_lib_find(_songlib, handle); +void SfxState::sfx_song_renice(SongHandle handle, int priority) { + Song *song = _songlib.findSong(handle); ASSERT_SONG(song); #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Renicing song %08lx to %d\n", handle, priority); #endif - song->priority = priority; + song->_priority = priority; update(); } -void SfxState::sfx_song_set_loops(song_handle_t handle, int loops) { - song_t *song = song_lib_find(_songlib, handle); +void SfxState::sfx_song_set_loops(SongHandle handle, int loops) { + Song *song = _songlib.findSong(handle); SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_LOOPS(loops)); ASSERT_SONG(song); - song->loops = loops; + song->_loops = loops; #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Setting loops on %08lx to %d\n", handle, loops); #endif - songit_handle_message(&(song->it), msg); + songit_handle_message(&(song->_it), msg); if (player/* && player->send_iterator_message*/) /* FIXME: The above should be optional! */ player->iterator_message(msg); } -void SfxState::sfx_song_set_hold(song_handle_t handle, int hold) { - song_t *song = song_lib_find(_songlib, handle); +void SfxState::sfx_song_set_hold(SongHandle handle, int hold) { + Song *song = _songlib.findSong(handle); SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_HOLD(hold)); ASSERT_SONG(song); - song->hold = hold; + song->_hold = hold; #ifdef DEBUG_SONG_API fprintf(stderr, "[sfx-core] Setting hold on %08lx to %d\n", handle, hold); #endif - songit_handle_message(&(song->it), msg); + songit_handle_message(&(song->_it), msg); if (player/* && player->send_iterator_message*/) /* FIXME: The above should be optional! */ @@ -934,9 +938,9 @@ static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 3, 2, 0, 3, 0 }; -static const song_handle_t midi_send_base = 0xffff0000; +static const SongHandle midi_send_base = 0xffff0000; -Common::Error SfxState::sfx_send_midi(song_handle_t handle, int channel, +Common::Error SfxState::sfx_send_midi(SongHandle handle, int channel, int command, int arg1, int arg2) { byte buffer[5]; @@ -994,8 +998,191 @@ void SfxState::sfx_all_stop() { fprintf(stderr, "[sfx-core] All stop\n"); #endif - song_lib_free(_songlib); + _songlib.freeSounds(); update(); } +int SfxState::startAudio(uint16 module, uint32 number) { + int sampleLen; + Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); + + if (audioStream) { + g_system->getMixer()->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); + return sampleLen; + } + + return 0; +} + +int SfxState::getAudioPosition() { + if (g_system->getMixer()->isSoundHandleActive(_audioHandle)) + return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks + else + return -1; // Sound finished +} + +enum SolFlags { + kSolFlagCompressed = 1 << 0, + kSolFlagUnknown = 1 << 1, + kSolFlag16Bit = 1 << 2, + kSolFlagIsSigned = 1 << 3 +}; + +// FIXME: Move this to sound/adpcm.cpp? +// Note that the 16-bit version is also used in coktelvideo.cpp +static const uint16 tableDPCM16[128] = { + 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, + 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120, + 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0, + 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, + 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280, + 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0, + 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, + 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, + 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0, + 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480, + 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700, + 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, + 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + +static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21}; + +static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int16 *out = (int16 *) soundBuf; + + int32 s = 0; + for (uint32 i = 0; i < n; i++) { + byte b = audioStream.readByte(); + if (b & 0x80) + s -= tableDPCM16[b & 0x7f]; + else + s += tableDPCM16[b]; + + s = CLIP<int32>(s, -32768, 32767); + *out++ = TO_BE_16(s); + } +} + +static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) { + if (b & 8) + s -= tableDPCM8[7 - (b & 7)]; + else + s += tableDPCM8[b & 7]; + s = CLIP<int32>(s, 0, 255); + *soundBuf = s; +} + +static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) { + int32 s = 0x80; + + for (uint i = 0; i < n; i++) { + byte b = audioStream.readByte(); + + deDPCM8Nibble(soundBuf++, s, b >> 4); + deDPCM8Nibble(soundBuf++, s, b & 0xf); + } +} + +// Sierra SOL audio file reader +// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio +static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { + if (headerSize != 11 && headerSize != 12) { + warning("SOL audio header of size %i not supported", headerSize); + return false; + } + + audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) + audioRate = audioStream->readUint16LE(); + audioFlags = audioStream->readByte(); + + size = audioStream->readUint32LE(); + return true; +} + +static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) { + byte *buffer; + + // Convert the SOL stream flags to our own format + flags = 0; + if (audioFlags & kSolFlag16Bit) + flags |= Audio::Mixer::FLAG_16BITS; + if (!(audioFlags & kSolFlagIsSigned)) + flags |= Audio::Mixer::FLAG_UNSIGNED; + + if (audioFlags & kSolFlagCompressed) { + buffer = (byte *)malloc(size * 2); + + if (audioFlags & kSolFlag16Bit) + deDPCM16(buffer, *audioStream, size); + else + deDPCM8(buffer, *audioStream, size); + + size *= 2; + } else { + // We assume that the sound data is raw PCM + buffer = (byte *)malloc(size); + audioStream->read(buffer, size); + } + + return buffer; +} + +Audio::AudioStream* SfxState::getAudioStream(uint32 number, uint32 volume, int *sampleLen) { + Audio::AudioStream *audioStream = 0; + uint32 size = 0; + byte *data = 0; + byte flags = 0; + Sci::Resource* audioRes; + + if (volume == 65535) { + audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio, number), false); + if (!audioRes) { + warning("Failed to find audio entry %i", number); + return NULL; + } + } else { + audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio36, volume, number), false); + if (!audioRes) { + warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (number >> 24) & 0xff, + (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff); + return NULL; + } + } + + byte audioFlags; + + if (audioRes->headerSize > 0) { + // SCI1.1 + Common::MemoryReadStream *headerStream = + new Common::MemoryReadStream(audioRes->header, audioRes->headerSize, false); + + if (readSOLHeader(headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) { + Common::MemoryReadStream *dataStream = + new Common::MemoryReadStream(audioRes->data, audioRes->size, false); + data = readSOLAudio(dataStream, size, audioFlags, flags); + delete dataStream; + } + delete headerStream; + } else { + // SCI1 + size = audioRes->size; + data = (byte *)malloc(size); + assert(data); + memcpy(data, audioRes->data, size); + flags = Audio::Mixer::FLAG_UNSIGNED; + } + + if (data) { + audioStream = Audio::makeLinearInputStream(data, size, _audioRate, + flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); + if (audioStream) { + *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + return audioStream; + } + } + + return NULL; +} + } // End of namespace Sci diff --git a/engines/sci/sfx/core.h b/engines/sci/sfx/core.h index 69e30b43d8..e7eba85c99 100644 --- a/engines/sci/sfx/core.h +++ b/engines/sci/sfx/core.h @@ -47,11 +47,12 @@ class SfxState { public: // FIXME, make private SongIterator *_it; /**< The song iterator at the heart of things */ uint _flags; /**< SFX_STATE_FLAG_* */ - songlib_t _songlib; /**< Song library */ - song_t *_song; /**< Active song, or start of active song chain */ + SongLibrary _songlib; /**< Song library */ + Song *_song; /**< Active song, or start of active song chain */ bool _suspended; /**< Whether we are suspended */ - ResourceSync *_soundSync; /**< Used by kDoSync for speech syncing in CD talkie games */ - AudioResource *_audioResource; /**< Used for audio resources in CD talkie games */ + Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */ + uint _syncOffset; + ResourceManager *_resMgr; public: SfxState(); @@ -77,17 +78,17 @@ public: /* Polls the sound server for cues etc. ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise - ** (song_handle_t) *handle: The affected handle + ** (SongHandle) *handle: The affected handle ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) */ - int sfx_poll(song_handle_t *handle, int *cue); + int sfx_poll(SongHandle *handle, int *cue); /* Polls the sound server for cues etc. - ** Parameters: (song_handle_t) handle: The handle to poll + ** Parameters: (SongHandle) handle: The handle to poll ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) */ - int sfx_poll_specific(song_handle_t handle, int *cue); + int sfx_poll_specific(SongHandle handle, int *cue); /* Determines the current global volume settings ** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume) @@ -111,15 +112,15 @@ public: /* Adds a song to the internal sound library ** Parameters: (SongIterator *) it: The iterator describing the song ** (int) priority: Initial song priority (higher <-> more important) - ** (song_handle_t) handle: The handle to associate with the song + ** (SongHandle) handle: The handle to associate with the song */ - void sfx_add_song(SongIterator *it, int priority, song_handle_t handle, int resnum); + void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum); /* Deletes a song and its associated song iterator from the song queue - ** Parameters: (song_handle_t) handle: The song to remove + ** Parameters: (SongHandle) handle: The song to remove */ - void sfx_remove_song(song_handle_t handle); + void sfx_remove_song(SongHandle handle); /**********************/ @@ -128,53 +129,66 @@ public: /* Sets the song status, i.e. whether it is playing, suspended, or stopped. - ** Parameters: (song_handle_t) handle: Handle of the song to modify + ** Parameters: (SongHandle) handle: Handle of the song to modify ** (int) status: The song status the song should assume ** WAITING and PLAYING are set implicitly and essentially describe the same state ** as far as this function is concerned. */ - void sfx_song_set_status(song_handle_t handle, int status); + void sfx_song_set_status(SongHandle handle, int status); /* Sets the new song priority - ** Parameters: (song_handle_t) handle: The handle to modify + ** Parameters: (SongHandle) handle: The handle to modify ** (int) priority: The priority to set */ - void sfx_song_renice(song_handle_t handle, int priority); + void sfx_song_renice(SongHandle handle, int priority); /* Sets the number of loops for the specified song - ** Parameters: (song_handle_t) handle: The song handle to reference + ** Parameters: (SongHandle) handle: The song handle to reference ** (int) loops: Number of loops to set */ - void sfx_song_set_loops(song_handle_t handle, int loops); + void sfx_song_set_loops(SongHandle handle, int loops); /* Sets the number of loops for the specified song - ** Parameters: (song_handle_t) handle: The song handle to reference + ** Parameters: (SongHandle) handle: The song handle to reference ** (int) hold: Number of loops to setn */ - void sfx_song_set_hold(song_handle_t handle, int hold); + void sfx_song_set_hold(SongHandle handle, int hold); /* Instructs a song to be faded out - ** Parameters: (song_handle_t) handle: The song handle to reference + ** Parameters: (SongHandle) handle: The song handle to reference ** (fade_params_t *) fade_setup: The precise fade-out configuration to use */ - void sfx_song_set_fade(song_handle_t handle, fade_params_t *fade_setup); + void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup); // Previously undocumented: - Common::Error sfx_send_midi(song_handle_t handle, int channel, + Common::Error sfx_send_midi(SongHandle handle, int channel, int command, int arg1, int arg2); + // Functions for digital sound + void setAudioRate(uint16 rate) { _audioRate = rate; } + Audio::SoundHandle* getAudioHandle() { return &_audioHandle; } + int getAudioPosition(); + int startAudio(uint16 module, uint32 tuple); + void stopAudio() { g_system->getMixer()->stopHandle(_audioHandle); } + void pauseAudio() { g_system->getMixer()->pauseHandle(_audioHandle, true); } + void resumeAudio() { g_system->getMixer()->pauseHandle(_audioHandle, false); } + protected: void freezeTime(); void thawTime(); - bool isPlaying(song_t *song); - void setSongStatus(song_t *song, int status); + bool isPlaying(Song *song); + void setSongStatus(Song *song, int status); void updateSingleSong(); void updateMultiSong(); void update(); -}; +private: + uint16 _audioRate; + Audio::SoundHandle _audioHandle; + Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen); +}; } // End of namespace Sci diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp index 1743b787fc..ad33bc8dfb 100644 --- a/engines/sci/sfx/iterator.cpp +++ b/engines/sci/sfx/iterator.cpp @@ -68,8 +68,8 @@ BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id) #define SCI0_PCM_DATA_OFFSET 0x2c #define CHECK_FOR_END_ABSOLUTE(offset) \ - if (offset > self->_data.size()) { \ - warning("Reached end of song without terminator (%x/%x) at %d", offset, self->_data.size(), __LINE__); \ + if (offset > _data.size()) { \ + warning("Reached end of song without terminator (%x/%x) at %d", offset, _data.size(), __LINE__); \ return SI_FINISHED; \ } @@ -145,8 +145,7 @@ void SongIteratorChannel::resetSynthChannels() { } } -static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, - int *result, SongIteratorChannel *channel, int flags) { +int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags) { byte cmd; int paramsleft; int midi_op; @@ -154,7 +153,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, channel->state = SI_STATE_DELTA_TIME; - cmd = self->_data[channel->offset++]; + cmd = _data[channel->offset++]; if (!(cmd & 0x80)) { /* 'Running status' mode */ @@ -177,12 +176,12 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, fprintf(stderr, "[IT]: off=%x, cmd=%02x, takes %d args ", channel->offset - 1, cmd, paramsleft); fprintf(stderr, "[%02x %02x <%02x> %02x %02x %02x]\n", - self->_data[channel->offset-3], - self->_data[channel->offset-2], - self->_data[channel->offset-1], - self->_data[channel->offset], - self->_data[channel->offset+1], - self->_data[channel->offset+2]); + _data[channel->offset-3], + _data[channel->offset-2], + _data[channel->offset-1], + _data[channel->offset], + _data[channel->offset+1], + _data[channel->offset+2]); } #endif @@ -190,7 +189,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, CHECK_FOR_END(paramsleft); - memcpy(buf + 1, self->_data.begin() + channel->offset, paramsleft); + memcpy(buf + 1, _data.begin() + channel->offset, paramsleft); *result = 1 + paramsleft; channel->offset += paramsleft; @@ -208,24 +207,24 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, /* Next, check if the channel is allowed */ && (!((1 << midi_channel) & channel->playmask))) return /* Execute next command */ - self->nextCommand(buf, result); + nextCommand(buf, result); if (cmd == SCI_MIDI_EOT) { /* End of track? */ channel->resetSynthChannels(); - /* fprintf(stderr, "eot; loops = %d, notesplayed=%d\n", self->loops, channel->notes_played);*/ - if (self->loops > 1 /* && channel->notes_played*/) { + /* fprintf(stderr, "eot; loops = %d, notesplayed=%d\n", loops, channel->notes_played);*/ + if (_loops > 1 /* && channel->notes_played*/) { /* If allowed, decrement the number of loops */ if (!(flags & PARSE_FLAG_LOOPS_UNLIMITED)) - *result = --self->loops; + *result = --_loops; #ifdef DEBUG_DECODING - fprintf(stderr, "%s L%d: (%p):%d Looping ", __FILE__, __LINE__, self, channel->id); + fprintf(stderr, "%s L%d: (%p):%d Looping ", __FILE__, __LINE__, this, channel->id); if (flags & PARSE_FLAG_LOOPS_UNLIMITED) fprintf(stderr, "(indef.)"); else - fprintf(stderr, "(%d)", self->loops); + fprintf(stderr, "(%d)", _loops); fprintf(stderr, " %x -> %x\n", channel->offset, channel->loop_offset); #endif @@ -234,15 +233,15 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, channel->state = SI_STATE_DELTA_TIME; channel->total_timepos = channel->loop_timepos; channel->last_cmd = 0xfe; - fprintf(stderr, "Looping song iterator %08lx.\n", self->ID); + fprintf(stderr, "Looping song iterator %08lx.\n", ID); return SI_LOOP; } else { channel->state = SI_STATE_FINISHED; #ifdef DEBUG_DECODING fprintf(stderr, "%s L%d: (%p):%d EOT because" " %d notes, %d loops\n", - __FILE__, __LINE__, self, channel->id, - channel->notes_played, self->loops); + __FILE__, __LINE__, this, channel->id, + channel->notes_played, _loops); #endif return SI_FINISHED; } @@ -253,7 +252,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, channel->loop_timepos = channel->total_timepos; return /* Execute next command */ - self->nextCommand(buf, result); + nextCommand(buf, result); } else { /* Used to be conditional <= 127 */ *result = buf[1]; /* Absolute cue */ @@ -264,37 +263,38 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, case SCI_MIDI_CUMULATIVE_CUE: if (flags & PARSE_FLAG_PARAMETRIC_CUE) - self->ccc += buf[2]; + _ccc += buf[2]; else { /* No parameter to CC */ - self->ccc++; + _ccc++; /* channel->offset--; */ } - *result = self->ccc; + *result = _ccc; return SI_RELATIVE_CUE; case SCI_MIDI_RESET_ON_SUSPEND: - self->resetflag = buf[2]; + _resetflag = buf[2]; break; case SCI_MIDI_SET_POLYPHONY: - self->polyphony[midi_channel] = buf[2]; + _polyphony[midi_channel] = buf[2]; #if 0 { + Sci1SongIterator *self1 = (Sci1SongIterator *)this; int i; int voices = 0; - for (i = 0; i < ((Sci1SongIterator *) self)->_numChannels; i++) { - voices += self->polyphony[i]; + for (i = 0; i < self1->_numChannels; i++) { + voices += _polyphony[i]; } sciprintf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices); sciprintf("[iterator-1] DEBUG: Polyphony = [ "); - for (i = 0; i < ((Sci1SongIterator *) self)->_numChannels; i++) - sciprintf("%d ", self->polyphony[i]); + for (i = 0; i < self1->_numChannels; i++) + sciprintf("%d ", _polyphony[i]); sciprintf("]\n"); sciprintf("[iterator-1] DEBUG: Importance = [ "); - for (i = 0; i < ((Sci1SongIterator *) self)->_numChannels; i++) - sciprintf("%d ", self->importance[i]); + for (i = 0; i < self1->_numChannels; i++) + sciprintf("%d ", _importance[i]); sciprintf("]\n"); } #endif @@ -309,7 +309,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, case SCI_MIDI_HOLD: { // Safe cast: This controller is only used in SCI1 - Sci1SongIterator *self1 = (Sci1SongIterator *)self; + Sci1SongIterator *self1 = (Sci1SongIterator *)this; if (buf[2] == self1->_hold) { channel->offset = channel->initial_offset; @@ -317,7 +317,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, channel->state = SI_STATE_COMMAND; channel->total_timepos = 0; - self1->_numLoopedChannels = self1->active_channels - 1; + self1->_numLoopedChannels = self1->_numActiveChannels - 1; return SI_LOOP; } @@ -330,7 +330,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, case 0x73: /* UNKNOWN NYI (happens in Hoyle) */ case 0xd1: /* UNKNOWN NYI (happens in KQ4 when riding the unicorn) */ return /* Execute next command */ - self->nextCommand(buf, result); + nextCommand(buf, result); case 0x01: /* modulation */ case 0x07: /* volume */ @@ -353,15 +353,15 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf, } } -static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *result, +int BaseSongIterator::processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags) { CHECK_FOR_END(0); switch (channel->state) { case SI_STATE_PCM: { - if (self->_data[channel->offset] == 0 - && self->_data[channel->offset + 1] == SCI_MIDI_EOT) + if (_data[channel->offset] == 0 + && _data[channel->offset + 1] == SCI_MIDI_EOT) /* Fake one extra tick to trick the interpreter into not killing the song iterator right away */ channel->state = SI_STATE_PCM_MAGIC_DELTA; else @@ -374,7 +374,7 @@ static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *resul int offset; uint size; int delay; - if (_sci0_get_pcm_data((Sci0SongIterator *) self, &format, &offset, &size)) + if (_sci0_get_pcm_data((Sci0SongIterator *)this, &format, &offset, &size)) return SI_FINISHED; /* 'tis broken */ channel->state = SI_STATE_FINISHED; delay = (size * 50 + format.rate - 1) / format.rate; /* number of ticks to completion*/ @@ -385,17 +385,17 @@ static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *resul case SI_STATE_UNINITIALISED: warning("Attempt to read command from uninitialized iterator"); - self->init(); - return self->nextCommand(buf, result); + init(); + return nextCommand(buf, result); case SI_STATE_FINISHED: return SI_FINISHED; case SI_STATE_DELTA_TIME: { int offset; - int ticks = _parse_ticks(self->_data.begin() + channel->offset, + int ticks = _parse_ticks(_data.begin() + channel->offset, &offset, - self->_data.size() - channel->offset); + _data.size() - channel->offset); channel->offset += offset; channel->delay += ticks; @@ -416,47 +416,36 @@ static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *resul channel->total_timepos += channel->timepos_increment; channel->timepos_increment = 0; - retval = _parse_sci_midi_command(self, buf, result, - channel, flags); + retval = parseMidiCommand(buf, result, channel, flags); if (retval == SI_FINISHED) { - if (self->active_channels) - --(self->active_channels); + if (_numActiveChannels) + --(_numActiveChannels); #ifdef DEBUG_DECODING fprintf(stderr, "%s L%d: (%p):%d Finished channel, %d channels left\n", - __FILE__, __LINE__, self, channel->id, - self->active_channels); + __FILE__, __LINE__, this, channel->id, + _numActiveChannels); #endif /* If we still have channels left... */ - if (self->active_channels) { - return self->nextCommand(buf, result); + if (_numActiveChannels) { + return nextCommand(buf, result); } /* Otherwise, we have reached the end */ - self->loops = 0; + _loops = 0; } return retval; } default: - warning("Invalid iterator state %d", channel->state); - error("Breakpoint in %s, line %d", __FILE__, __LINE__); + error("Invalid iterator state %d", channel->state); return SI_FINISHED; } } -static int _sci_midi_process(BaseSongIterator *self, byte *buf, int *result, - SongIteratorChannel *channel, int flags) { - return _sci_midi_process_state(self, buf, result, - channel, - flags); -} - int Sci0SongIterator::nextCommand(byte *buf, int *result) { - return _sci_midi_process(this, buf, result, - &channel, - PARSE_FLAG_PARAMETRIC_CUE); + return processMidi(buf, result, &_channel, PARSE_FLAG_PARAMETRIC_CUE); } static int _sci0_header_magic_p(byte *data, int offset, int size) { @@ -563,7 +552,7 @@ Audio::AudioStream *Sci0SongIterator::getAudioStream() { if (_sci0_get_pcm_data(this, &conf, &offset, &size)) return NULL; - channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */ + _channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */ return makeStream(_data.begin() + offset + SCI0_PCM_DATA_OFFSET, size, conf); } @@ -575,18 +564,18 @@ SongIterator *Sci0SongIterator::handleMessage(Message msg) { case _SIMSG_BASEMSG_PRINT: print_tabs_id(msg._arg.i, ID); fprintf(stderr, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d\n", - _deviceId, active_channels, _data.size(), loops); + _deviceId, _numActiveChannels, _data.size(), _loops); break; case _SIMSG_BASEMSG_SET_LOOPS: - loops = msg._arg.i; + _loops = msg._arg.i; break; case _SIMSG_BASEMSG_STOP: { songit_id_t sought_id = msg.ID; if (sought_id == ID) - channel.state = SI_STATE_FINISHED; + _channel.state = SI_STATE_FINISHED; break; } @@ -595,19 +584,19 @@ SongIterator *Sci0SongIterator::handleMessage(Message msg) { _deviceId = msg._arg.i; /* Set all but the rhytm channel mask bits */ - channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); + _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); for (i = 0; i < MIDI_CHANNELS; i++) if (_data[2 + (i << 1)] & _deviceId && i != MIDI_RHYTHM_CHANNEL) - channel.playmask |= (1 << i); + _channel.playmask |= (1 << i); } break; case _SIMSG_BASEMSG_SET_RHYTHM: - channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); + _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); if (msg._arg.i) - channel.playmask |= (1 << MIDI_RHYTHM_CHANNEL); + _channel.playmask |= (1 << MIDI_RHYTHM_CHANNEL); break; case _SIMSG_BASEMSG_SET_FADE: { @@ -629,33 +618,33 @@ SongIterator *Sci0SongIterator::handleMessage(Message msg) { } int Sci0SongIterator::getTimepos() { - return channel.total_timepos; + return _channel.total_timepos; } Sci0SongIterator::Sci0SongIterator(byte *data, uint size, songit_id_t id) : BaseSongIterator(data, size, id) { channel_mask = 0xffff; // Allocate all channels by default - channel.state = SI_STATE_UNINITIALISED; + _channel.state = SI_STATE_UNINITIALISED; for (int i = 0; i < MIDI_CHANNELS; i++) - polyphony[i] = data[1 + (i << 1)]; + _polyphony[i] = data[1 + (i << 1)]; init(); } void Sci0SongIterator::init() { fade.action = FADE_ACTION_NONE; - resetflag = 0; - loops = 0; + _resetflag = 0; + _loops = 0; priority = 0; - ccc = 0; /* Reset cumulative cue counter */ - active_channels = 1; - channel.init(0, SCI0_MIDI_OFFSET, _data.size()); - channel.resetSynthChannels(); + _ccc = 0; /* Reset cumulative cue counter */ + _numActiveChannels = 1; + _channel.init(0, SCI0_MIDI_OFFSET, _data.size()); + _channel.resetSynthChannels(); if (_data[0] == 2) /* Do we have an embedded PCM? */ - channel.state = SI_STATE_PCM; + _channel.state = SI_STATE_PCM; } SongIterator *Sci0SongIterator::clone(int delta) { @@ -682,7 +671,7 @@ static const int sci0_to_sci1_device_map[][2] = { {0xff, 0xff}, }; /* Maps bit number to device ID */ -static int _sci1_sample_init(Sci1SongIterator *self, const int offset) { +int Sci1SongIterator::initSample(const int offset) { Sci1Sample sample; int rate; int length; @@ -690,24 +679,24 @@ static int _sci1_sample_init(Sci1SongIterator *self, const int offset) { int end; CHECK_FOR_END_ABSOLUTE((uint)offset + 10); - if (self->_data[offset + 1] != 0) + if (_data[offset + 1] != 0) sciprintf("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero\n", - self->_data[offset + 1]); + _data[offset + 1]); - rate = (int16)READ_LE_UINT16(self->_data.begin() + offset + 2); - length = READ_LE_UINT16(self->_data.begin() + offset + 4); - begin = (int16)READ_LE_UINT16(self->_data.begin() + offset + 6); - end = (int16)READ_LE_UINT16(self->_data.begin() + offset + 8); + rate = (int16)READ_LE_UINT16(_data.begin() + offset + 2); + length = READ_LE_UINT16(_data.begin() + offset + 4); + begin = (int16)READ_LE_UINT16(_data.begin() + offset + 6); + end = (int16)READ_LE_UINT16(_data.begin() + offset + 8); CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length)); sample.delta = begin; sample.size = length; - sample._data = self->_data.begin() + offset + 10; + sample._data = _data.begin() + offset + 10; #ifdef DEBUG_VERBOSE fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n", - offset + 10, begin, end, self->_data.size(), length); + offset + 10, begin, end, _data.size(), length); #endif sample.format.format = SFX_PCM_FORMAT_U8; @@ -717,86 +706,85 @@ static int _sci1_sample_init(Sci1SongIterator *self, const int offset) { sample.announced = false; /* Insert into the sample list at the right spot, keeping it sorted by delta */ - Common::List<Sci1Sample>::iterator seeker = self->_samples.begin(); - while (seeker != self->_samples.end() && seeker->delta < begin) + Common::List<Sci1Sample>::iterator seeker = _samples.begin(); + while (seeker != _samples.end() && seeker->delta < begin) ++seeker; - self->_samples.insert(seeker, sample); + _samples.insert(seeker, sample); return 0; /* Everything's fine */ } -static int _sci1_song_init(Sci1SongIterator *self) { +int Sci1SongIterator::initSong() { int last_time; uint offset = 0; - self->_numChannels = 0; - self->_samples.clear(); -// self->_deviceId = 0x0c; + _numChannels = 0; + _samples.clear(); +// _deviceId = 0x0c; - if (self->_data[offset] == 0xf0) { - self->priority = self->_data[offset + 1]; + if (_data[offset] == 0xf0) { + priority = _data[offset + 1]; offset += 8; } - while (self->_data[offset] != 0xff - && self->_data[offset] != self->_deviceId) { + while (_data[offset] != 0xff + && _data[offset] != _deviceId) { offset++; CHECK_FOR_END_ABSOLUTE(offset + 1); - while (self->_data[offset] != 0xff) { + while (_data[offset] != 0xff) { CHECK_FOR_END_ABSOLUTE(offset + 7); offset += 6; } offset++; } - if (self->_data[offset] == 0xff) { + if (_data[offset] == 0xff) { sciprintf("[iterator-1] Song does not support" " hardware 0x%02x\n", - self->_deviceId); + _deviceId); return 1; } offset++; - while (self->_data[offset] != 0xff) { /* End of list? */ + while (_data[offset] != 0xff) { /* End of list? */ uint track_offset; int end; offset += 2; CHECK_FOR_END_ABSOLUTE(offset + 4); - track_offset = READ_LE_UINT16(self->_data.begin() + offset); - end = READ_LE_UINT16(self->_data.begin() + offset + 2); + track_offset = READ_LE_UINT16(_data.begin() + offset); + end = READ_LE_UINT16(_data.begin() + offset + 2); CHECK_FOR_END_ABSOLUTE(track_offset - 1); - if (self->_data[track_offset] == 0xfe) { - if (_sci1_sample_init(self, track_offset)) + if (_data[track_offset] == 0xfe) { + if (initSample(track_offset)) return 1; /* Error */ } else { /* Regular MIDI channel */ - if (self->_numChannels >= MIDI_CHANNELS) { + if (_numChannels >= MIDI_CHANNELS) { sciprintf("[iterator-1] Warning: Song has more than %d channels, cutting them off\n", MIDI_CHANNELS); break; /* Scan for remaining samples */ } else { - int channel_nr = self->_data[track_offset] & 0xf; - SongIteratorChannel &channel = - self->_channels[self->_numChannels++]; + int channel_nr = _data[track_offset] & 0xf; + SongIteratorChannel &channel = _channels[_numChannels++]; - if (self->_data[track_offset] & 0xf0) + if (_data[track_offset] & 0xf0) printf("Channel %d has mapping bits %02x\n", - channel_nr, self->_data[track_offset] & 0xf0); + channel_nr, _data[track_offset] & 0xf0); // Add 2 to skip over header bytes */ channel.init(channel_nr, track_offset + 2, track_offset + end); channel.resetSynthChannels(); - self->polyphony[self->_numChannels - 1] = self->_data[channel.offset - 1] & 15; - self->importance[self->_numChannels - 1] = self->_data[channel.offset - 1] >> 4; + _polyphony[_numChannels - 1] = _data[channel.offset - 1] & 15; + _importance[_numChannels - 1] = _data[channel.offset - 1] >> 4; channel.playmask = ~0; /* Enable all */ - self->channel_mask |= (1 << channel_nr); + channel_mask |= (1 << channel_nr); CHECK_FOR_END_ABSOLUTE(offset + end); } @@ -805,13 +793,13 @@ static int _sci1_song_init(Sci1SongIterator *self) { CHECK_FOR_END_ABSOLUTE(offset); } - /* Now ensure that samüle deltas are relative to the previous sample */ + /* Now ensure that sample deltas are relative to the previous sample */ last_time = 0; - self->active_channels = self->_numChannels; - self->_numLoopedChannels = 0; + _numActiveChannels = _numChannels; + _numLoopedChannels = 0; - for (Common::List<Sci1Sample>::iterator seeker = self->_samples.begin(); - seeker != self->_samples.end(); ++seeker) { + for (Common::List<Sci1Sample>::iterator seeker = _samples.begin(); + seeker != _samples.end(); ++seeker) { int prev_last_time = last_time; sciprintf("[iterator-1] Detected sample: %d Hz, %d bytes at time %d\n", seeker->format.rate, seeker->size, seeker->delta); @@ -899,7 +887,7 @@ int Sci1SongIterator::nextCommand(byte *buf, int *result) { sciprintf("[iterator-1] DEBUG: Initialising for %d\n", _deviceId); _initialised = true; - if (_sci1_song_init(this)) + if (initSong()) return SI_FINISHED; } @@ -937,17 +925,16 @@ int Sci1SongIterator::nextCommand(byte *buf, int *result) { } } else { /* Not a PCM */ - retval = _sci_midi_process(this, - buf, result, - &(_channels[chan]), - PARSE_FLAG_LOOPS_UNLIMITED); + retval = processMidi(buf, result, + &(_channels[chan]), + PARSE_FLAG_LOOPS_UNLIMITED); if (retval == SI_LOOP) { _numLoopedChannels++; _channels[chan].state = SI_STATE_PENDING; _channels[chan].delay = 0; - if (_numLoopedChannels == active_channels) { + if (_numLoopedChannels == _numActiveChannels) { int i; /* Everyone's ready: Let's loop */ @@ -1041,7 +1028,7 @@ SongIterator *Sci1SongIterator::handleMessage(Message msg) { /* Find an active channel so that we can ** get the correct time offset */ - _sci1_song_init(this); + initSong(); toffset -= _delayRemaining; _delayRemaining = 0; @@ -1049,7 +1036,7 @@ SongIterator *Sci1SongIterator::handleMessage(Message msg) { if (toffset > 0) return new_fast_forward_iterator(this, toffset); } else { - _sci1_song_init(this); + initSong(); _initialised = true; } @@ -1059,7 +1046,7 @@ SongIterator *Sci1SongIterator::handleMessage(Message msg) { case _SIMSG_BASEMSG_SET_LOOPS: if (msg.ID == ID) - loops = (msg._arg.i > 32767) ? 99 : 0; + _loops = (msg._arg.i > 32767) ? 99 : 0; /* 99 is arbitrary, but we can't use '1' because of ** the way we're testing in the decoding section. */ break; @@ -1093,26 +1080,26 @@ Sci1SongIterator::Sci1SongIterator(byte *data, uint size, songit_id_t id) channel_mask = 0; // Defer channel allocation for (int i = 0; i < MIDI_CHANNELS; i++) - polyphony[i] = 0; // Unknown + _polyphony[i] = 0; // Unknown init(); } void Sci1SongIterator::init() { fade.action = FADE_ACTION_NONE; - resetflag = 0; - loops = 0; + _resetflag = 0; + _loops = 0; priority = 0; - ccc = 127; + _ccc = 127; _deviceId = 0x00; // Default to Sound Blaster/Adlib for purposes of cue computation _numChannels = 0; _initialised = false; _delayRemaining = 0; - loops = 0; + _loops = 0; _hold = 0; - memset(polyphony, 0, sizeof(polyphony)); - memset(importance, 0, sizeof(importance)); + memset(_polyphony, 0, sizeof(_polyphony)); + memset(_importance, 0, sizeof(_importance)); } Sci1SongIterator::~Sci1SongIterator() { diff --git a/engines/sci/sfx/iterator.h b/engines/sci/sfx/iterator.h index 1a25b4afa1..547c479bbf 100644 --- a/engines/sci/sfx/iterator.h +++ b/engines/sci/sfx/iterator.h @@ -253,7 +253,6 @@ enum SongIteratorType { | IT_READER_MASK_CUE \ | IT_READER_MASK_PCM ) -int songit_next(SongIterator **it, byte *buf, int *result, int mask); /* Convenience wrapper around it->next ** Parameters: (SongIterator **it) Reference to the iterator to access ** (byte *) buf: The buffer to write to (needs to be able to @@ -270,8 +269,8 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask); ** to the lower layers) for 0, the cue value for SI_CUE, ** or the number of loops remaining for SI_LOOP. */ +int songit_next(SongIterator **it, byte *buf, int *result, int mask); -SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); /* Constructs a new song iterator object ** Parameters: (byte *) data: The song data to iterate over ** (uint) size: Number of bytes in the song @@ -280,26 +279,17 @@ SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id ** Returns : (SongIterator *) A newly allocated but uninitialized song ** iterator, or NULL if 'type' was invalid or unsupported */ +SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); -int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg); /* Handles a message to the song iterator ** Parameters: (SongIterator **): A reference to the variable storing the song iterator ** Returns : (int) Non-zero if the message was understood ** The song iterator may polymorph as result of msg, so a writeable reference is required. */ +int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg); -int sfx_play_iterator_pcm(SongIterator *it, unsigned long handle); -/* Plays a song iterator that found a PCM through a PCM device, if possible -** Parameters: (SongIterator *) it: The iterator to play -** (song_handle_t) handle: Debug handle -** Returns : (int) 0 if the effect will not be played, nonzero if it will -** This assumes that the last call to 'it->next()' returned SI_PCM. -*/ - - -SongIterator *new_fast_forward_iterator(SongIterator *it, int delta); /* Creates a new song iterator which fast-forwards ** Parameters: (SongIterator *) it: The iterator to wrap ** (int) delta: The number of ticks to skip @@ -307,6 +297,7 @@ SongIterator *new_fast_forward_iterator(SongIterator *it, int delta); ** which skips all delta times ** until 'delta' has been used up */ +SongIterator *new_fast_forward_iterator(SongIterator *it, int delta); diff --git a/engines/sci/sfx/iterator_internal.h b/engines/sci/sfx/iterator_internal.h index 88103ad8c9..7d5a17fd25 100644 --- a/engines/sci/sfx/iterator_internal.h +++ b/engines/sci/sfx/iterator_internal.h @@ -49,7 +49,7 @@ enum { struct SongIteratorChannel { int state; //!< State of this song iterator channel - int offset; //!< Offset into the data chunk */ + int offset; //!< Offset into the data chunk */ int end; //!< Last allowed byte in track */ int id; //!< Some channel ID */ @@ -64,14 +64,14 @@ struct SongIteratorChannel { int loop_offset; int initial_offset; - int playmask; //!< Active playmask (MIDI channels to play in here) */ - int notes_played; //!< #of notes played since the last loop start */ - int loop_timepos; //!< Total delay for this channel's loop marker */ - int total_timepos; //!< Number of ticks since the beginning, ignoring loops */ - int timepos_increment; //!< Number of ticks until the next command (to add) */ + int playmask; //!< Active playmask (MIDI channels to play in here) */ + int notes_played; //!< #of notes played since the last loop start */ + int loop_timepos; //!< Total delay for this channel's loop marker */ + int total_timepos; //!< Number of ticks since the beginning, ignoring loops */ + int timepos_increment; //!< Number of ticks until the next command (to add) */ - int saw_notes; //!< Bitmask of channels we have currently played notes on */ - byte last_cmd; //!< Last operation executed, for running status */ + int saw_notes; //!< Bitmask of channels we have currently played notes on */ + byte last_cmd; //!< Last operation executed, for running status */ public: void init(int id, int offset, int end); @@ -80,21 +80,24 @@ public: class BaseSongIterator : public SongIterator { public: - int polyphony[MIDI_CHANNELS]; //!< # of simultaneous notes on each - int importance[MIDI_CHANNELS]; //!< priority rating for each channel, 0 means unrated. + int _polyphony[MIDI_CHANNELS]; //!< # of simultaneous notes on each + int _importance[MIDI_CHANNELS]; //!< priority rating for each channel, 0 means unrated. - int ccc; //!< Cumulative cue counter, for those who need it - byte resetflag; //!< for 0x4C -- on DoSound StopSound, do we return to start? - int _deviceId; //!< ID of the device we generating events for - int active_channels; //!< Number of active channels + int _ccc; //!< Cumulative cue counter, for those who need it + byte _resetflag; //!< for 0x4C -- on DoSound StopSound, do we return to start? + int _deviceId; //!< ID of the device we generating events for + int _numActiveChannels; //!< Number of active channels Common::Array<byte> _data; //!< Song data - int loops; //!< Number of loops remaining - int recover_delay; + int _loops; //!< Number of loops remaining public: BaseSongIterator(byte *data, uint size, songit_id_t id); + +protected: + int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags); + int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags); }; /********************************/ @@ -103,7 +106,7 @@ public: class Sci0SongIterator : public BaseSongIterator { public: - SongIteratorChannel channel; + SongIteratorChannel _channel; public: Sci0SongIterator(byte *data, uint size, songit_id_t id); @@ -142,12 +145,12 @@ public: /* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING, ** channel_offset[i] points to a delta time object. */ - bool _initialised; /* Whether the MIDI channel setup has been initialised */ - int _numChannels; /* Number of channels actually used */ + bool _initialised; /**!< Whether the MIDI channel setup has been initialised */ + int _numChannels; /**!< Number of channels actually used */ Common::List<Sci1Sample> _samples; - int _numLoopedChannels; /* Number of channels that are ready to loop */ + int _numLoopedChannels; /**!< Number of channels that are ready to loop */ - int _delayRemaining; /* Number of ticks that haven't been polled yet */ + int _delayRemaining; /**!< Number of ticks that haven't been polled yet */ int _hold; public: @@ -162,6 +165,9 @@ public: SongIterator *clone(int delta); private: + int initSample(const int offset); + int initSong(); + int getSmallestDelta() const; void updateDelta(int delta); @@ -186,7 +192,7 @@ private: class FastForwardSongIterator : public SongIterator { protected: SongIterator *_delegate; - int _delta; /**< Remaining time */ + int _delta; /**!< Remaining time */ public: FastForwardSongIterator(SongIterator *capsit, int delta); @@ -208,8 +214,8 @@ enum { TEE_RIGHT = 1, TEE_LEFT_ACTIVE = (1<<0), TEE_RIGHT_ACTIVE = (1<<1), - TEE_LEFT_READY = (1<<2), /**< left result is ready */ - TEE_RIGHT_READY = (1<<3), /**< right result is ready */ + TEE_LEFT_READY = (1<<2), /**!< left result is ready */ + TEE_RIGHT_READY = (1<<3), /**!< right result is ready */ TEE_LEFT_PCM = (1<<4), TEE_RIGHT_PCM = (1<<5) }; @@ -221,7 +227,7 @@ class TeeSongIterator : public SongIterator { public: int _status; - bool _readyToMorph; /* One of TEE_MORPH_* above */ + bool _readyToMorph; /**!< One of TEE_MORPH_* above */ struct { SongIterator *it; @@ -229,8 +235,8 @@ public: int result; int retval; - byte channel_remap[MIDI_CHANNELS]; /* Remapping for channels */ + byte channel_remap[MIDI_CHANNELS]; } _children[2]; diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp index d5debdd995..41c7c63fc9 100644 --- a/engines/sci/sfx/softseq/adlib.cpp +++ b/engines/sci/sfx/softseq/adlib.cpp @@ -482,7 +482,7 @@ void MidiDriver_Adlib::setNote(int voice, int note, bool key) { if (bend < 8192) bend = 8192 - bend; - delta = pow(2.0, (float)(bend % 8192) / 8192.0); + delta = (float)pow(2.0, (bend % 8192) / 8192.0); if (bend > 8192) fre = (int)(ym3812_note[n] * delta); @@ -627,7 +627,7 @@ int MidiPlayer_Adlib::open(ResourceManager *resmgr) { assert(resmgr != NULL); // Load up the patch.003 file, parse out the instruments - Resource *res = resmgr->findResource(kResourceTypePatch, 3, 0); + Resource *res = resmgr->findResource(ResourceId(kResourceTypePatch, 3), 0); if (!res) { warning("ADLIB: Failed to load patch.003"); diff --git a/engines/sci/sfx/softseq/adlib.h b/engines/sci/sfx/softseq/adlib.h index 13cf1e2d95..38f755bec0 100644 --- a/engines/sci/sfx/softseq/adlib.h +++ b/engines/sci/sfx/softseq/adlib.h @@ -35,7 +35,7 @@ public: kRhythmKeys = 62 }; - MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0) { } + MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0) { } ~MidiDriver_Adlib() { } // MidiDriver diff --git a/engines/sci/sfx/songlib.cpp b/engines/sci/sfx/songlib.cpp index e1185aa039..3a6549a0d4 100644 --- a/engines/sci/sfx/songlib.cpp +++ b/engines/sci/sfx/songlib.cpp @@ -31,169 +31,169 @@ namespace Sci { #define debug_stream stderr -song_t *song_new(song_handle_t handle, SongIterator *it, int priority) { - song_t *retval; - retval = (song_t*) malloc(sizeof(song_t)); - -#ifdef SATISFY_PURIFY - memset(retval, 0, sizeof(song_t)); -#endif - - retval->handle = handle; - retval->priority = priority; - retval->next = NULL; - retval->_delay = 0; - retval->_wakeupTime = Audio::Timestamp(); - retval->it = it; - retval->status = SOUND_STATUS_STOPPED; - retval->next_playing = NULL; - retval->next_stopping = NULL; - retval->restore_behavior = RESTORE_BEHAVIOR_CONTINUE; - retval->restore_time = 0; +Song::Song() { + _handle = 0; + _priority = 0; + _status = SOUND_STATUS_STOPPED; - return retval; + _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; + _restoreTime = 0; + + _loops = 0; + _hold = 0; + + _it = 0; + _delay = 0; + + _next = NULL; + _nextPlaying = NULL; + _nextStopping = NULL; } -void song_lib_add(const songlib_t &songlib, song_t *song) { - song_t **seeker = NULL; - int pri = song->priority; +Song::Song(SongHandle handle, SongIterator *it, int priority) { + _handle = handle; + _priority = priority; + _status = SOUND_STATUS_STOPPED; - if (NULL == song) { - sciprintf("song_lib_add(): NULL passed for song\n"); - return; - } + _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; + _restoreTime = 0; + + _loops = 0; + _hold = 0; - if (*(songlib.lib) == NULL) { - *(songlib.lib) = song; - song->next = NULL; + _it = it; + _delay = 0; + _next = NULL; + _nextPlaying = NULL; + _nextStopping = NULL; +} + +void SongLibrary::addSong(Song *song) { + Song **seeker = NULL; + int pri = song->_priority; + + if (NULL == song) { + sciprintf("addSong(): NULL passed for song\n"); return; } - seeker = (songlib.lib); - while (*seeker && ((*seeker)->priority > pri)) - seeker = &((*seeker)->next); + seeker = &_lib; + while (*seeker && ((*seeker)->_priority > pri)) + seeker = &((*seeker)->_next); - song->next = *seeker; + song->_next = *seeker; *seeker = song; } -static void _songfree_chain(song_t *song) { - /* Recursively free a chain of songs */ - if (song) { - _songfree_chain(song->next); - delete song->it; - song->it = NULL; - free(song); +void SongLibrary::freeSounds() { + Song *next = _lib; + while (next) { + Song *song = next; + delete song->_it; + song->_it = NULL; + next = song->_next; + delete song; } -} - -void song_lib_init(songlib_t *songlib) { - songlib->lib = &(songlib->_s); - songlib->_s = NULL; -} - -void song_lib_free(const songlib_t &songlib) { - _songfree_chain(*(songlib.lib)); - *(songlib.lib) = NULL; + _lib = NULL; } -song_t *song_lib_find(const songlib_t &songlib, song_handle_t handle) { - song_t *seeker = *(songlib.lib); +Song *SongLibrary::findSong(SongHandle handle) { + Song *seeker = _lib; while (seeker) { - if (seeker->handle == handle) + if (seeker->_handle == handle) break; - seeker = seeker->next; + seeker = seeker->_next; } return seeker; } -song_t *song_lib_find_next_active(const songlib_t &songlib, song_t *other) { - song_t *seeker = other ? other->next : *(songlib.lib); +Song *SongLibrary::findNextActive(Song *other) { + Song *seeker = other ? other->_next : _lib; while (seeker) { - if ((seeker->status == SOUND_STATUS_WAITING) || - (seeker->status == SOUND_STATUS_PLAYING)) + if ((seeker->_status == SOUND_STATUS_WAITING) || + (seeker->_status == SOUND_STATUS_PLAYING)) break; - seeker = seeker->next; + seeker = seeker->_next; } /* Only return songs that have equal priority */ - if (other && seeker && other->priority > seeker->priority) + if (other && seeker && other->_priority > seeker->_priority) return NULL; return seeker; } -song_t *song_lib_find_active(const songlib_t &songlib) { - return song_lib_find_next_active(songlib, NULL); +Song *SongLibrary::findFirstActive() { + return findNextActive(NULL); } -int song_lib_remove(const songlib_t &songlib, song_handle_t handle) { +int SongLibrary::removeSong(SongHandle handle) { int retval; - song_t *goner = *(songlib.lib); + Song *goner = _lib; if (!goner) return -1; - if (goner->handle == handle) - *(songlib.lib) = goner->next; + if (goner->_handle == handle) + _lib = goner->_next; else { - while ((goner->next) && (goner->next->handle != handle)) - goner = goner->next; + while ((goner->_next) && (goner->_next->_handle != handle)) + goner = goner->_next; - if (goner->next) { /* Found him? */ - song_t *oldnext = goner->next; + if (goner->_next) { /* Found him? */ + Song *oldnext = goner->_next; - goner->next = goner->next->next; + goner->_next = goner->_next->_next; goner = oldnext; } else return -1; /* No. */ } - retval = goner->status; + retval = goner->_status; - delete goner->it; - free(goner); + delete goner->_it; + delete goner; return retval; } -void song_lib_resort(const songlib_t &songlib, song_t *song) { - if (*(songlib.lib) == song) - *(songlib.lib) = song->next; +void SongLibrary::resortSong(Song *song) { + if (_lib == song) + _lib = song->_next; else { - song_t *seeker = *(songlib.lib); + Song *seeker = _lib; - while (seeker->next && (seeker->next != song)) - seeker = seeker->next; + while (seeker->_next && (seeker->_next != song)) + seeker = seeker->_next; - if (seeker->next) - seeker->next = seeker->next->next; + if (seeker->_next) + seeker->_next = seeker->_next->_next; } - song_lib_add(songlib, song); + addSong(song); } -int song_lib_count(const songlib_t &songlib) { - song_t *seeker = *(songlib.lib); +int SongLibrary::countSongs() { + Song *seeker = _lib; int retval = 0; while (seeker) { retval++; - seeker = seeker->next; + seeker = seeker->_next; } return retval; } -void song_lib_set_restore_behavior(const songlib_t &songlib, song_handle_t handle, RESTORE_BEHAVIOR action) { - song_t *seeker = song_lib_find(songlib, handle); +void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) { + Song *seeker = findSong(handle); - seeker->restore_behavior = action; + seeker->_restoreBehavior = action; } } // End of namespace Sci diff --git a/engines/sci/sfx/songlib.h b/engines/sci/sfx/songlib.h index b9849fbfe3..53b32e6747 100644 --- a/engines/sci/sfx/songlib.h +++ b/engines/sci/sfx/songlib.h @@ -42,7 +42,7 @@ class SongIterator; #define SOUND_STATUS_WAITING 3 /* "waiting" means "tagged for playing, but not active right now" */ -typedef unsigned long song_handle_t; +typedef unsigned long SongHandle; enum RESTORE_BEHAVIOR { RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from @@ -50,123 +50,122 @@ enum RESTORE_BEHAVIOR { RESTORE_BEHAVIOR_RESTART /* continue it from where it was */ }; -struct song_t { - song_handle_t handle; - int resource_num; /* Resource number */ - int priority; /* Song priority (more important if priority is higher) */ - int status; /* See above */ +class Song { +public: + SongHandle _handle; + int _resourceNum; /**<! Resource number */ + int _priority; /**!< Song priority (more important if priority is higher) */ + int _status; /* See above */ - int restore_behavior; - int restore_time; + int _restoreBehavior; + int _restoreTime; /* Grabbed from the sound iterator, for save/restore purposes */ - int loops; - int hold; + int _loops; + int _hold; - SongIterator *it; - int _delay; /* Delay before accessing the iterator, in ticks */ + SongIterator *_it; + int _delay; /**!< Delay before accessing the iterator, in ticks */ - Audio::Timestamp _wakeupTime; /**< Timestamp indicating the next MIDI event */ + Audio::Timestamp _wakeupTime; /**!< Timestamp indicating the next MIDI event */ - song_t *next; /* Next song or NULL if this is the last one */ - song_t *next_playing; /* Next playing song; used by the - ** core song system */ - song_t *next_stopping; /* Next song pending stopping; used exclusively by - ** the core song system's _update_multi_song() */ -}; + Song *_next; /**!< Next song or NULL if this is the last one */ + + /** + * Next playing song. Used by the core song system. + */ + Song *_nextPlaying; + + /** + * Next song pending stopping. Used exclusively by the core song system's + * _update_multi_song() + */ + Song *_nextStopping; +public: -struct songlib_t { - song_t **lib; - song_t *_s; + Song(); + + /** + * Initializes a new song. + * @param handle the sound handle + * @param it the song + * @param priority the song's priority + * @return a freshly allocated song + */ + Song(SongHandle handle, SongIterator *it, int priority); }; -/**************************/ -/* Song library commands: */ -/**************************/ - -song_t *song_new(song_handle_t handle, SongIterator *it, int priority); -/* Initializes a new song -** Parameters: (song_handle_t) handle: The sound handle -** (SongIterator *) it: The song -** (int) priority: The song's priority -** Returns : (song_t *) A freshly allocated song -** Other values are set to predefined defaults. -*/ - - -void song_lib_init(songlib_t *songlib); -/* Initializes a static song library -** Parameters: (songlib_t *) songlib: Pointer to the library -** to initialize -** Returns : (void) -*/ - -void song_lib_free(const songlib_t &songlib); -/* Frees a song library -** Parameters: (songlib_t) songlib: The library to free -** Returns : (void) -*/ - -void song_lib_add(const songlib_t &songlib, song_t *song); -/* Adds a song to a song library. -** Parameters: (songlib_t) songlib: An existing sound library, or NULL -** (song_t *) song: The song to add -** Returns : (void) -*/ - -song_t *song_lib_find(const songlib_t &songlib, song_handle_t handle); -/* Looks up the song with the specified handle -** Parameters: (songlib_t) songlib: An existing sound library, may point to NULL -** (song_handle_t) handle: The sound handle to look for -** Returns : (song_t *) The song or NULL if it wasn't found -*/ - -song_t *song_lib_find_active(const songlib_t &songlib); -/* Finds the first song playing with the highest priority -** Parameters: (songlib_t) songlib: An existing sound library -** Returns : (song_t *) The song that should be played next, or NULL if there is none -*/ - -song_t *song_lib_find_next_active(const songlib_t &songlib, song_t *song); -/* Finds the next song playing with the highest priority -** Parameters: (songlib_t) songlib: The song library to operate on -** (song_t *) song: A song previously returned from the song library -** Returns : (song_t *) The next song to play relative to 'song', or -** NULL if none are left -** The functions 'song_lib_find_active' and 'song_lib_find_next_active -** allow to iterate over all songs that satisfy the requirement of -** being 'playable'. -*/ - -int song_lib_remove(const songlib_t &songlib, song_handle_t handle); -/* Removes a song from the library -** Parameters: (songlib_t) songlib: An existing sound library -** (song_handle_t) handle: Handle of the song to remove -** Returns : (int) The status of the song that was removed -*/ - -void song_lib_resort(const songlib_t &songlib, song_t *song); -/* Removes a song from the library and sorts it in again; for use after renicing -** Parameters: (songlib_t) songlib: An existing sound library -** (song_t *) song: The song to work on -** Returns : (void) -*/ - -int song_lib_count(const songlib_t &songlib); -/* Counts the number of songs in a song library -** Parameters: (songlib_t) songlib: The library to count -** Returns : (int) The number of songs -*/ - -void song_lib_set_restore_behavior(const songlib_t &songlib, song_handle_t handle, - RESTORE_BEHAVIOR action); -/* Determines what should be done with the song "handle" when -** restoring it from a saved game. -** Parameters: (songlib_t) songlib: The library that contains the song -** (song_handle_t) handle: Its handle -** (RESTORE_BEHAVIOR) action: The desired action -*/ + +class SongLibrary { +public: + Song *_lib; + +public: + SongLibrary() : _lib(0) {} + + /** Frees a song library. */ + void freeSounds(); + + /** + * Adds a song to a song library. + * @param song song to add + */ + void addSong(Song *song); + + /** + * Looks up the song with the specified handle. + * @param handle sound handle to look for + * @return the song or NULL if it wasn't found + */ + Song *findSong(SongHandle handle); + + /** + * Finds the first song playing with the highest priority. + * @return the song that should be played next, or NULL if there is none + */ + Song *findFirstActive(); + + /** + * Finds the next song playing with the highest priority. + * + * The functions 'findFirstActive' and 'findNextActive' + * allow to iterate over all songs that satisfy the requirement of + * being 'playable'. + * + * @param song a song previously returned from the song library + * @return the next song to play relative to 'song', or NULL if none are left + */ + Song *findNextActive(Song *song); + + /** + * Removes a song from the library. + * @param handle handle of the song to remove + * @return the status of the song that was removed + */ + int removeSong(SongHandle handle); + + /** + * Removes a song from the library and sorts it in again; for use after renicing. + * @param son song to work on + */ + void resortSong(Song *song); + + /** + * Counts the number of songs in a song library. + * @return the number of songs + */ + int countSongs(); + + /** + * Determines what should be done with the song "handle" when restoring + * it from a saved game. + * @param handle sound handle being restored + * @param action desired action + */ + void setSongRestoreBehavior(SongHandle handle, + RESTORE_BEHAVIOR action); +}; } // End of namespace Sci diff --git a/engines/sci/tools.cpp b/engines/sci/tools.cpp index 589ce298d7..d0e11aca09 100644 --- a/engines/sci/tools.cpp +++ b/engines/sci/tools.cpp @@ -70,7 +70,7 @@ void sciprintf(const char *fmt, ...) { // Display the result suitably if (g_redirect_sciprintf_to_gui) - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf("%s", buf); + ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf("%s", buf); printf("%s", buf); free(buf); diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index b12114d845..6616ac362d 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -62,7 +62,7 @@ int *vocab_get_classes(ResourceManager *resmgr, int* count) { int *c; unsigned int i; - if ((r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES, 0)) == NULL) + if ((r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == NULL) return 0; c = (int *)malloc(sizeof(int) * r->size / 2); @@ -77,7 +77,7 @@ int *vocab_get_classes(ResourceManager *resmgr, int* count) { int vocab_get_class_count(ResourceManager *resmgr) { Resource* r; - if ((r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES, 0)) == 0) + if ((r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == 0) return 0; return r->size / 4; @@ -115,11 +115,11 @@ bool Vocabulary::loadParserWords() { int currentwordpos = 0; // First try to load the SCI0 vocab resource. - Resource *resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB, 0); + Resource *resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB), 0); if (!resource) { warning("SCI0: Could not find a main vocabulary, trying SCI01"); - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB, 0); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB), 0); _vocabVersion = kVocabularySCI1; } @@ -198,9 +198,9 @@ bool Vocabulary::loadSuffixes() { Resource* resource = NULL; if (_vocabVersion == kVocabularySCI0) - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 1); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB), 1); else - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 1); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB), 1); if (!resource) return false; // No vocabulary found @@ -237,12 +237,12 @@ void Vocabulary::freeSuffixes() { Resource* resource = NULL; if (_vocabVersion == kVocabularySCI0) - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB, 0); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB), 0); else - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB), 0); if (resource) - _resmgr->unlockResource(resource, resource->number, kResourceTypeVocab); + _resmgr->unlockResource(resource); _parserSuffixes.clear(); } @@ -251,9 +251,9 @@ bool Vocabulary::loadBranches() { Resource *resource = NULL; if (_vocabVersion == kVocabularySCI0) - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES, 0); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES), 0); else - resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES, 0); + resource = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES), 0); _parserBranches.clear(); @@ -438,7 +438,7 @@ bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, ch void Vocabulary::printSuffixes() const { char word_buf[256], alt_buf[256]; - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); int i = 0; for (SuffixList::const_iterator suf = _parserSuffixes.begin(); suf != _parserSuffixes.end(); ++suf) { @@ -453,7 +453,7 @@ void Vocabulary::printSuffixes() const { } void Vocabulary::printParserWords() const { - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); int j = 0; for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) { @@ -488,7 +488,7 @@ void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int return; } - if (nodes[nr].type == PARSE_TREE_NODE_LEAF) + if (nodes[nr].type == kParseTreeLeafNode) //sciprintf("[%03x]%04x", nr, nodes[nr].content.value); sciprintf("%x", nodes[nr].content.value); else { @@ -518,7 +518,7 @@ void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, i int rbranch = nodes[nr].content.branches[1]; int i; - if (nodes[nr].type == PARSE_TREE_NODE_LEAF) { + if (nodes[nr].type == kParseTreeLeafNode) { sciprintf("vocab_dump_parse_tree: Error: consp is nil for element %03x\n", nr); return; } @@ -529,7 +529,7 @@ void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, i } if (lbranch) { - if (nodes[lbranch].type == PARSE_TREE_NODE_BRANCH) { + if (nodes[lbranch].type == kParseTreeBranchNode) { sciprintf("\n"); for (i = 0; i < blanks; i++) sciprintf(" "); @@ -544,7 +544,7 @@ void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, i }/* else sciprintf ("nil");*/ if (rbranch) { - if (nodes[rbranch].type == PARSE_TREE_NODE_BRANCH) + if (nodes[rbranch].type == kParseTreeBranchNode) _vocab_recursive_ptree_dump(nodes, rbranch, nr, blanks); else sciprintf("%x", nodes[rbranch].content.value); diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h index 9f0d277ef2..ce6d48c570 100644 --- a/engines/sci/vocabulary.h +++ b/engines/sci/vocabulary.h @@ -160,9 +160,10 @@ struct parse_tree_branch_t { int data[10]; }; -#define PARSE_TREE_NODE_LEAF 0 -#define PARSE_TREE_NODE_BRANCH 1 - +enum ParseTypes { + kParseTreeLeafNode = 0, + kParseTreeBranchNode = 1 +}; struct parse_tree_node_t { short type; /* leaf or branch */ diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp index f1429d4261..472e04b5f3 100644 --- a/engines/scumm/boxes.cpp +++ b/engines/scumm/boxes.cpp @@ -369,7 +369,7 @@ void ScummEngine::convertScaleTableToScaleSlot(int slot) { */ // Search for the bend on the left side - m = (resptr[199] - resptr[0]) / 199.0; + m = (resptr[199] - resptr[0]) / 199.0f; for (lowerIdx = 0; lowerIdx < 199 && (resptr[lowerIdx] == 1 || resptr[lowerIdx] == 255); lowerIdx++) { oldM = m; m = (resptr[199] - resptr[lowerIdx+1]) / (float)(199 - (lowerIdx+1)); @@ -383,7 +383,7 @@ void ScummEngine::convertScaleTableToScaleSlot(int slot) { } // Search for the bend on the right side - m = (resptr[199] - resptr[0]) / 199.0; + m = (resptr[199] - resptr[0]) / 199.0f; for (upperIdx = 199; upperIdx > 1 && (resptr[upperIdx] == 1 || resptr[upperIdx] == 255); upperIdx--) { oldM = m; m = (resptr[upperIdx-1] - resptr[0]) / (float)(upperIdx-1); diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 4e4175876b..cf88ded3b8 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -765,6 +765,8 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { dg["preferredtarget"] = res; + dg.setGUIOptions(x->game.guioptions); + detectedGames.push_back(dg); } diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h index 26f6be8fec..9b4ff929e2 100644 --- a/engines/scumm/detection.h +++ b/engines/scumm/detection.h @@ -88,6 +88,11 @@ struct GameSettings { * specific platform. */ Common::Platform platform; + + /** + * Game GUI options. Used to enable/disable certain GUI widgets + */ + uint32 guioptions; }; enum FilenameGenMethod { diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index abdc5b4e91..2ea593c571 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -171,6 +171,10 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {NULL, NULL, UNK} }; +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOMIDI; + // The following table contains information about variants of our various // games. We index into it with help of md5table (from scumm-md5.h), to find // the correct GameSettings for a given game variant. @@ -191,194 +195,197 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { // only a single unique variant. This is used to help the detector quickly // decide whether it has to worry about distinguishing multiple variants or not. static const GameSettings gameVariantsTable[] = { - {"maniac", "Apple II", 0, GID_MANIAC, 0, 0, MDT_PCSPK, 0, Common::kPlatformApple2GS}, - {"maniac", "C64", 0, GID_MANIAC, 0, 0, MDT_PCSPK, 0, Common::kPlatformC64}, - {"maniac", "V1", "v1", GID_MANIAC, 1, 0, MDT_PCSPK, 0, Common::kPlatformPC}, - {"maniac", "V1 Demo", "v1", GID_MANIAC, 1, 0, MDT_PCSPK, GF_DEMO, Common::kPlatformPC}, - {"maniac", "NES", 0, GID_MANIAC, 1, 0, MDT_NONE, 0, Common::kPlatformNES}, - {"maniac", "V2", "v2", GID_MANIAC, 2, 0, MDT_PCSPK, 0, UNK}, - {"maniac", "V2 Demo", "v2", GID_MANIAC, 2, 0, MDT_PCSPK, GF_DEMO, Common::kPlatformPC}, - - {"zak", "V1", "v1", GID_ZAK, 1, 0, MDT_PCSPK, 0, UNK}, - {"zak", "V2", "v2", GID_ZAK, 2, 0, MDT_PCSPK, 0, UNK}, - {"zak", "FM-TOWNS", 0, GID_ZAK, 3, 0, MDT_TOWNS, GF_OLD256 | GF_AUDIOTRACKS, Common::kPlatformFMTowns}, - - {"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, 0, UNK}, - {"indy3", "No Adlib", "ega", GID_INDY3, 3, 0, MDT_PCSPK, 0, UNK}, - {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC}, - {"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns}, - - {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK}, - {"loom", "No Adlib", "ega", GID_LOOM, 3, 0, MDT_PCSPK, 0, UNK}, - {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPCEngine}, - {"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns}, - {"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPC}, - - {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC}, - - {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK}, - {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC}, - {"monkey", "No Adlib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST}, - {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC}, - {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK}, - {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns}, - {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD}, - - {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK}, - - {"atlantis", 0, 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK}, - - {"tentacle", 0, 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - - {"samnmax", 0, 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, + {"maniac", "Apple II", 0, GID_MANIAC, 0, 0, MDT_PCSPK, 0, Common::kPlatformApple2GS, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "C64", 0, GID_MANIAC, 0, 0, MDT_PCSPK, 0, Common::kPlatformC64, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "V1", "v1", GID_MANIAC, 1, 0, MDT_PCSPK, 0, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "V1 Demo", "v1", GID_MANIAC, 1, 0, MDT_PCSPK, GF_DEMO, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "NES", 0, GID_MANIAC, 1, 0, MDT_NONE, 0, Common::kPlatformNES, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "V2", "v2", GID_MANIAC, 2, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"maniac", "V2 Demo", "v2", GID_MANIAC, 2, 0, MDT_PCSPK, GF_DEMO, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"zak", "V1", "v1", GID_ZAK, 1, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"zak", "V2", "v2", GID_ZAK, 2, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"zak", "FM-TOWNS", 0, GID_ZAK, 3, 0, MDT_TOWNS, GF_OLD256 | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"indy3", "No Adlib", "ega", GID_INDY3, 3, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"loom", "No Adlib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, + {"monkey", "No Adlib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI}, + + {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + + {"atlantis", 0, 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"atlantis", "CD" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NONE}, + + {"tentacle", 0, 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"tentacle", "CD", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + + {"samnmax", 0, 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"samnmax", "CD", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, #ifdef ENABLE_SCUMM_7_8 - {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK}, + {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI}, - {"dig", 0, 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK}, + {"dig", 0, 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI}, - {"comi", 0, 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows}, + {"comi", 0, 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO_NOMIDI}, #endif // Humongous Entertainment Scumm Version 6 - {"activity", "", 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"funpack", 0, 0, GID_FUNPACK, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"fbpack", 0, 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, + {"activity", "", 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"funpack", 0, 0, GID_FUNPACK, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"fbpack", 0, 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"brstorm", 0, 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"fbear", "HE 61", 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows}, + {"brstorm", 0, 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"fbear", "HE 61", 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows, GUIO_NOMIDI}, - {"puttmoon", "", 0, GID_PUTTMOON, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"puttmoon", "HE 70", 0, GID_PUTTMOON, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows}, + {"puttmoon", "", 0, GID_PUTTMOON, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"puttmoon", "HE 70", 0, GID_PUTTMOON, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows, GUIO_NOMIDI}, - {"puttputt", "HE 60", 0, GID_HEGAME, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"puttputt", "HE 61", 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, - {"puttputt", "Demo", 0, GID_PUTTDEMO, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, + {"puttputt", "HE 60", 0, GID_HEGAME, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"puttputt", "HE 61", 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, + {"puttputt", "Demo", 0, GID_PUTTDEMO, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, // The following are meant to be generic HE game variants and as such do // not specify a game ID. Make sure that these are last in the table, else // they'll override more specific entries that follow later on. - {"", "HE 70", 0, GID_HEGAME, 6, 70, MDT_NONE, GF_USE_KEY, UNK}, + {"", "HE 70", 0, GID_HEGAME, 6, 70, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, #ifdef ENABLE_HE // HE CUP demos - {"", "HE CUP", 0, GID_HECUP, 6, 200, MDT_NONE, 0, UNK}, + {"", "HE CUP", 0, GID_HECUP, 6, 200, MDT_NONE, 0, UNK, GUIO_NOMIDI | GUIO_NOSPEECH}, // Humongous Entertainment Scumm Version 7.1 // The first version to use 640x480 resolution and wizImages // There are also 7.1 versions of freddemo, airdemo and farmdemo - {"catalog", "", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK}, - {"freddi", "", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK}, + {"catalog", "", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"freddi", "", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 7.2 - {"airport", "", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY, UNK}, + {"airport", "", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Changed o_getResourceSize to cover all resource types - {"farm", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK}, - {"jungle", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK}, - {"puttzoo", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK}, + {"farm", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"jungle", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"puttzoo", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 8.0 ? Scummsrc.80 - {"freddi2", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"pajama", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, + {"freddi2", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"pajama", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, - {"balloon", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"dog", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"maze", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, + {"balloon", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"dog", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"maze", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, - {"water", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, + {"water", "", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // condMaskCode value changed in setUserCondition & setTalkCondition - {"putttime", "", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK}, - {"socks", "", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK}, + {"putttime", "", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"socks", "", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 9.0 ? Scummsys.90 - {"baseball", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, - {"thinkerk", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, - {"thinker1", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, - {"spyfox", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, + {"baseball", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"thinkerk", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"thinker1", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"spyfox", "", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, - {"freddi3", "", 0, GID_FREDDI3, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, - {"freddi3", "HE 99", 0, GID_FREDDI3, 6, 99, MDT_NONE, GF_USE_KEY, UNK}, + {"freddi3", "", 0, GID_FREDDI3, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"freddi3", "HE 99", 0, GID_FREDDI3, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 9.5 ? Scummsys.95 - {"pajama2", "", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK}, - {"chase", "", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK}, + {"pajama2", "", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"chase", "", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 9.8 ? Scummsys.98 // these and later games can easily be identified by the .(a) file instead of a .he1 // and INIB chunk in the .he0 - {"lost", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, + {"lost", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, - {"puttrace", "HE 98", 0, GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, - {"puttrace", "HE 98.5", 0, GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, - {"puttrace", "HE 99", 0, GID_PUTTRACE, 6, 99, MDT_NONE, GF_USE_KEY, UNK}, + {"puttrace", "HE 98", 0, GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"puttrace", "HE 98.5", 0, GID_PUTTRACE, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO_NOMIDI}, + {"puttrace", "HE 99", 0, GID_PUTTRACE, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, - {"bluesabctime", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, - {"BluesBirthday", 0, 0, GID_BIRTHDAY, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, - {"soccer", "", 0, GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, + {"bluesabctime", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"BluesBirthday", 0, 0, GID_BIRTHDAY, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"soccer", "", 0, GID_SOCCER, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, // Global scripts increased to 2048 - {"blues123time", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, - {"freddi4", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, - {"freddi4", "unenc", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_HE_985, UNK}, + {"blues123time", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO_NOMIDI}, + {"freddi4", "", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO_NOMIDI}, + {"freddi4", "unenc", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_HE_985, UNK, GUIO_NOMIDI}, // Humongous Entertainment Scumm Version 9.9 ? Scummsys.99 - {"football", 0, 0, GID_FOOTBALL, 6, 99, MDT_NONE, GF_USE_KEY, UNK}, - {"pajama3", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, - {"puttcircus", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, - {"spyfox2", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, - {"mustard", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, + {"football", 0, 0, GID_FOOTBALL, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"pajama3", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, + {"puttcircus", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, + {"spyfox2", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, + {"mustard", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, // Added the use of fonts - {"FreddisFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, - {"SamsFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, - {"PuttsFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK}, + {"FreddisFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, + {"SamsFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, + {"PuttsFunShop", 0, 0, GID_FUNSHOP, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED, UNK, GUIO_NOMIDI}, // Added 16bit color - {"baseball2001", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"SoccerMLS", 0, 0, GID_SOCCER, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, - {"spyozon", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, + {"baseball2001", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"SoccerMLS", 0, 0, GID_SOCCER, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"spyozon", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, - {"freddicove", "", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, - {"freddicove", "unenc", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, - {"freddicove", "HE 100", 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, + {"freddicove", "", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"freddicove", "unenc", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"freddicove", "HE 100", 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, // Restructured the Scumm engine - {"pjgames", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, + {"pjgames", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, // Uses smacker in external files, for testing only - {"arttime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, - {"readtime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK}, - {"BluesTreasureHunt", 0, 0, GID_TREASUREHUNT, 6, 99, MDT_NONE, GF_HE_LOCALIZED | GF_USE_KEY, UNK}, + {"arttime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"readtime", 0, 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY | GF_HE_LOCALIZED | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"BluesTreasureHunt", 0, 0, GID_TREASUREHUNT, 6, 99, MDT_NONE, GF_HE_LOCALIZED | GF_USE_KEY, UNK, GUIO_NOMIDI}, // Uses bink in external files for logos - {"Baseball2003", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"basketball", 0, 0, GID_BASKETBALL, 6, 100, MDT_NONE, GF_USE_KEY| GF_16BIT_COLOR, UNK}, - {"football2002", 0, 0, GID_FOOTBALL, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"Soccer2004", 0, 0, GID_SOCCER, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, + {"Baseball2003", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"basketball", 0, 0, GID_BASKETBALL, 6, 100, MDT_NONE, GF_USE_KEY| GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"football2002", 0, 0, GID_FOOTBALL, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"Soccer2004", 0, 0, GID_SOCCER, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, // U32 code required, for testing only - {"moonbase", 0, 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"moonbase", "Demo", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR | GF_DEMO, UNK}, + {"moonbase", 0, 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO_NOMIDI}, + {"moonbase", "Demo", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR | GF_DEMO, UNK, GUIO_NOMIDI}, // The following are meant to be generic HE game variants and as such do // not specify a game ID. Make sure that these are last in the table, else // they'll override more specific entries that follow later on. - {"", "HE 71", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 72", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 73", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 80", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 85", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 90", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 95", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 98", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 98.5", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK}, - {"", "HE 99", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY, UNK}, - {"", "HE 100", 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY, UNK}, + {"", "HE 71", 0, GID_HEGAME, 6, 71, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 72", 0, GID_HEGAME, 6, 72, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 73", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 80", 0, GID_HEGAME, 6, 80, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 85", 0, GID_HEGAME, 6, 85, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 90", 0, GID_HEGAME, 6, 90, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 95", 0, GID_HEGAME, 6, 95, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 98", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 98.5", 0, GID_HEGAME, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO_NOMIDI}, + {"", "HE 99", 0, GID_HEGAME, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, + {"", "HE 100", 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY, UNK, GUIO_NOMIDI}, #endif - {NULL, NULL, 0, 0, 0, MDT_NONE, 0, 0, UNK} + {NULL, NULL, 0, 0, 0, MDT_NONE, 0, 0, UNK, 0} }; using Common::UNK_LANG; diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index d47301c974..4574ece6d0 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -577,13 +577,13 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i if (width <= 0 || height <= 0) return; - const byte *src = vs->getPixels(x, top); + const void *src = vs->getPixels(x, top); int m = _textSurfaceMultiplier; int vsPitch; int pitch = vs->pitch; if (_useCJKMode && _textSurfaceMultiplier == 2) { - scale2x(_fmtownsBuf, _screenWidth * m, src, vs->pitch, width, height); + scale2x(_fmtownsBuf, _screenWidth * m, (const byte *)src, vs->pitch, width, height); src = _fmtownsBuf; vsPitch = _screenWidth * m - width * m; @@ -602,7 +602,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i // Compute pointer to the text surface assert(_compositeBuf); - const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m); + const void *text = _textSurface.getBasePtr(x * m, y * m); // The values x, width, etc. are all multiples of 8 at this point, // so loop unrolloing might be a good idea... @@ -693,7 +693,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i } // Finally blit the whole thing to the screen - _system->copyRectToScreen(src, pitch, x, y, width, height); + _system->copyRectToScreen((const byte *)src, pitch, x, y, width, height); } // CGA diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 1b5b467512..022dbc0eb3 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -913,7 +913,7 @@ int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)", entries[c].dib_size, - bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad) + (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) ); image_data = (byte *)malloc(image_size); diff --git a/engines/scumm/he/script_v71he.cpp b/engines/scumm/he/script_v71he.cpp index 316d51b12d..c832d64316 100644 --- a/engines/scumm/he/script_v71he.cpp +++ b/engines/scumm/he/script_v71he.cpp @@ -59,7 +59,7 @@ byte *ScummEngine_v71he::heFindResourceData(uint32 tag, byte *ptr) { byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) { uint32 curpos, totalsize, size; - debugC(DEBUG_RESOURCE, "heFindResource(%s, %lx)", tag2str(tag), searchin); + debugC(DEBUG_RESOURCE, "heFindResource(%s, %p)", tag2str(tag), (const void *)searchin); assert(searchin); searchin += 4; diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 240d3c290d..58d8db91fc 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -38,6 +38,7 @@ MODULE_OBJS := \ player_v1.o \ player_v2.o \ player_v2a.o \ + player_v2cms.o \ player_v3a.o \ resource_v2.o \ resource_v3.o \ diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index 372fcd9e45..f29be071e0 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -1816,9 +1816,8 @@ void ScummEngine::loadFlObject(uint object, uint room) { assert(flob); // Copy object code + object image to floating object - ((uint32 *)flob)[0] = MKID_BE('FLOB'); - ((uint32 *)flob)[1] = TO_BE_32(flob_size); - + WRITE_UINT32(flob, MKID_BE('FLOB')); + WRITE_BE_UINT32(flob + 4, flob_size); memcpy(flob + 8, foir.obcd, obcd_size); memcpy(flob + 8 + obcd_size, foir.obim, obim_size); diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index c6ec85cd88..f59b59b40f 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -467,13 +467,9 @@ void ScummEngine::moveMemInPalRes(int start, int end, byte direction) { } void ScummEngine::palManipulateInit(int resID, int start, int end, int time) { - byte *pal, *target, *between; - byte *string1, *string2, *string3; - int i; - - string1 = getStringAddress(resID); - string2 = getStringAddress(resID + 1); - string3 = getStringAddress(resID + 2); + byte *string1 = getStringAddress(resID); + byte *string2 = getStringAddress(resID + 1); + byte *string3 = getStringAddress(resID + 2); if (!string1 || !string2 || !string3) { error("palManipulateInit(%d,%d,%d,%d): Cannot obtain string resources %d, %d and %d", resID, start, end, time, resID, resID + 1, resID + 2); @@ -493,29 +489,24 @@ void ScummEngine::palManipulateInit(int resID, int start, int end, int time) { if (!_palManipIntermediatePal) _palManipIntermediatePal = (byte *)calloc(0x600, 1); - pal = _currentPalette + start * 3; - target = _palManipPalette + start * 3; - between = _palManipIntermediatePal + start * 6; + byte *pal = _currentPalette + start * 3; + byte *target = _palManipPalette + start * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + start * 6); - for (i = start; i < end; ++i) { + for (int i = start; i < end; ++i) { *target++ = *string1++; *target++ = *string2++; *target++ = *string3++; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; } _palManipCounter = time; } void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) { - byte *pal, *target, *between; const byte *new_pal; - int i; new_pal = getPalettePtr(resID, _roomResource); @@ -530,20 +521,17 @@ void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) if (!_palManipIntermediatePal) _palManipIntermediatePal = (byte *)calloc(0x600, 1); - pal = _currentPalette + start * 3; - target = _palManipPalette + start * 3; - between = _palManipIntermediatePal + start * 6; + byte *pal = _currentPalette + start * 3; + byte *target = _palManipPalette + start * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + start * 6); - for (i = start; i < end; ++i) { + for (int i = start; i < end; ++i) { *target++ = *new_pal++; *target++ = *new_pal++; *target++ = *new_pal++; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; } _palManipCounter = time; @@ -551,26 +539,24 @@ void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) void ScummEngine::palManipulate() { - byte *target, *pal, *between; - int i, j; - if (!_palManipCounter || !_palManipPalette || !_palManipIntermediatePal) return; - target = _palManipPalette + _palManipStart * 3; - pal = _currentPalette + _palManipStart * 3; - between = _palManipIntermediatePal + _palManipStart * 6; + byte *target = _palManipPalette + _palManipStart * 3; + byte *pal = _currentPalette + _palManipStart * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + _palManipStart * 6); - for (i = _palManipStart; i < _palManipEnd; ++i) { - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + for (int i = _palManipStart; i < _palManipEnd; ++i) { + int j; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + between++; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + between++; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; + between++; } setDirtyColors(_palManipStart, _palManipEnd); _palManipCounter--; diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h index cd88d57602..f0e14cdde3 100644 --- a/engines/scumm/player_v2.h +++ b/engines/scumm/player_v2.h @@ -158,6 +158,179 @@ private: void next_freqs(ChannelInfo *channel); }; +/** + * Scumm V2 CMS/Gameblaster MIDI driver. + */ +class Player_V2CMS : public Audio::AudioStream, public MusicEngine { +public: + Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer); + virtual ~Player_V2CMS(); + + virtual void setMusicVolume(int vol); + virtual void startSound(int sound); + virtual void stopSound(int sound); + virtual void stopAllSounds(); + virtual int getMusicTimer() const; + virtual int getSoundStatus(int sound) const; + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return true; } + bool endOfData() const { return false; } + int getRate() const { return _sample_rate; } + +protected: + +#include "common/pack-start.h" // START STRUCT PACKING + struct Voice { + byte attack; + byte decay; + byte sustain; + byte release; + byte octadd; + int16 vibrato; + int16 vibrato2; + int16 noise; + } PACKED_STRUCT; + + struct Voice2 { + byte *amplitudeOutput; + byte *freqOutput; + byte *octaveOutput; + + uint8 channel; + int8 sustainLevel; + int8 attackRate; + uint8 maxAmpl; + int8 decayRate; + int8 sustainRate; + int8 releaseRate; + int8 releaseTime; + int8 vibratoRate; + int8 vibratoDepth; + + int8 curVibratoRate; + int8 curVibratoUnk; + + int8 unkVibratoRate; + int8 unkVibratoDepth; + + int8 unkRate; + int8 unkCount; + + int nextProcessState; + int8 curVolume; + int8 curOctave; + int8 curFreq; + + int8 octaveAdd; + + int8 playingNote; + Voice2 *nextVoice; + + byte chanNumber; + } PACKED_STRUCT; + + struct MusicChip { + byte ampl[4]; + byte freq[4]; + byte octave[2]; + } PACKED_STRUCT; +#include "common/pack-end.h" // END STRUCT PACKING + + Voice _cmsVoicesBase[16]; + Voice2 _cmsVoices[8]; + MusicChip _cmsChips[2]; + + char _tempo; + char _tempoSum; + byte _looping; + byte _octaveMask; + int16 _midiDelay; + Voice2 *_midiChannel[16]; + byte _midiChannelUse[16]; + byte *_midiData; + byte *_midiSongBegin; + + int _loadedMidiSong; + + byte _lastMidiCommand; + uint _outputTableReady; + byte _clkFrequenz; + byte _restart; + byte _curSno; + + void loadMidiData(byte *data, int sound); + void play(); + + void processChannel(Voice2 *channel); + void processRelease(Voice2 *channel); + void processAttack(Voice2 *channel); + void processDecay(Voice2 *channel); + void processSustain(Voice2 *channel); + void processVibrato(Voice2 *channel); + + void playMusicChips(const MusicChip *table); + void playNote(byte *&data); + void clearNote(byte *&data); + void offAllChannels(); + void playVoice(); + void processMidiData(uint ticks); + + Voice2 *getFreeVoice(); + Voice2 *getPlayVoice(byte param); + + // from Player_V2 +protected: + bool _isV3Game; + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + ScummEngine *_vm; + + int _header_len; + + uint32 _sample_rate; + uint32 _next_tick; + uint32 _tick_len; + + int _timer_count[4]; + int _timer_output; + + int _current_nr; + byte *_current_data; + int _next_nr; + byte *_next_data; + byte *_retaddr; + +private: + union ChannelInfo { + channel_data d; + uint16 array[sizeof(channel_data)/2]; + }; + + int _music_timer; + int _music_timer_ctr; + int _ticks_per_music_timer; + + Common::Mutex _mutex; + ChannelInfo _channels[5]; + +protected: + void mutex_up(); + void mutex_down(); + + virtual void nextTick(); + virtual void clear_channel(int i); + virtual void chainSound(int nr, byte *data); + virtual void chainNextSound(); + +private: + void do_mix(int16 *buf, uint len); + + void execute_cmd(ChannelInfo *channel); + void next_freqs(ChannelInfo *channel); +}; + } // End of namespace Scumm #endif diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp new file mode 100644 index 0000000000..d628293d7d --- /dev/null +++ b/engines/scumm/player_v2cms.cpp @@ -0,0 +1,1855 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "engines/engine.h" +#include "scumm/player_v2.h" +#include "scumm/scumm.h" +#include "sound/mididrv.h" +#include "sound/mixer.h" + +namespace Scumm { +#define FREQ_HZ 236 // Don't change! + +#define FIXP_SHIFT 16 +#define MAX_OUTPUT 0x7fff + +#define NG_PRESET 0x0f35 /* noise generator preset */ +#define FB_WNOISE 0x12000 /* feedback for white noise */ +#define FB_PNOISE 0x08000 /* feedback for periodic noise */ + +// CMS/Gameblaster Emulation taken from DosBox + +#define LEFT 0x00 +#define RIGHT 0x01 +#define MAX_OUTPUT 0x7fff +#define MIN_OUTPUT -0x8000 +//#define CMS_BUFFER_SIZE 128 +#define CMS_RATE 22050 + +#define PROCESS_ATTACK 1 +#define PROCESS_RELEASE 2 +#define PROCESS_SUSTAIN 3 +#define PROCESS_DECAY 4 +#define PROCESS_VIBRATO 5 + +/* this structure defines a channel */ +struct saa1099_channel +{ + int frequency; /* frequency (0x00..0xff) */ + int freq_enable; /* frequency enable */ + int noise_enable; /* noise enable */ + int octave; /* octave (0x00..0x07) */ + int amplitude[2]; /* amplitude (0x00..0x0f) */ + int envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */ + + /* vars to simulate the square wave */ + double counter; + double freq; + int level; +}; + +/* this structure defines a noise channel */ +struct saa1099_noise +{ + /* vars to simulate the noise generator output */ + double counter; + double freq; + int level; /* noise polynomal shifter */ +}; + +/* this structure defines a SAA1099 chip */ +struct SAA1099 +{ + int stream; /* our stream */ + int noise_params[2]; /* noise generators parameters */ + int env_enable[2]; /* envelope generators enable */ + int env_reverse_right[2]; /* envelope reversed for right channel */ + int env_mode[2]; /* envelope generators mode */ + int env_bits[2]; /* non zero = 3 bits resolution */ + int env_clock[2]; /* envelope clock mode (non-zero external) */ + int env_step[2]; /* current envelope step */ + int all_ch_enable; /* all channels enable */ + int sync_state; /* sync all channels */ + int selected_reg; /* selected register */ + struct saa1099_channel channels[6]; /* channels */ + struct saa1099_noise noise[2]; /* noise generators */ +}; + +static byte envelope[8][64] = { + /* zero amplitude */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* maximum amplitude */ + {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, }, + /* single decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 } +}; + +static int amplitude_lookup[16] = { + 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, + 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, + 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16, + 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16 +}; + +class CMSEmulator { +public: + CMSEmulator(uint32 sampleRate) { + _sampleRate = sampleRate; + memset(_saa1099, 0, sizeof(SAA1099)*2); + } + + ~CMSEmulator() { } + + void portWrite(int port, int val); + void readBuffer(int16 *buffer, const int numSamples); +private: + uint32 _sampleRate; + + SAA1099 _saa1099[2]; + + void envelope(int chip, int ch); + void update(int chip, int16 *buffer, int length); + void portWriteIntern(int chip, int offset, int data); +}; + +void CMSEmulator::portWrite(int port, int val) { + switch (port) { + case 0x220: + portWriteIntern(0, 1, val); + break; + + case 0x221: + _saa1099[0].selected_reg = val & 0x1f; + if (_saa1099[0].selected_reg == 0x18 || _saa1099[0].selected_reg == 0x19) { + /* clock the envelope channels */ + if (_saa1099[0].env_clock[0]) envelope(0, 0); + if (_saa1099[0].env_clock[1]) envelope(0, 1); + } + break; + + case 0x222: + portWriteIntern(1, 1, val); + break; + + case 0x223: + _saa1099[1].selected_reg = val & 0x1f; + if (_saa1099[1].selected_reg == 0x18 || _saa1099[1].selected_reg == 0x19) { + /* clock the envelope channels */ + if (_saa1099[1].env_clock[0]) envelope(1, 0); + if (_saa1099[1].env_clock[1]) envelope(1, 1); + } + break; + + default: + warning("CMSEmulator got port: 0x%X", port); + break; + } +} + +void CMSEmulator::readBuffer(int16 *buffer, const int numSamples) { + update(0, &buffer[0], numSamples); + update(1, &buffer[0], numSamples); +} + +void CMSEmulator::envelope(int chip, int ch) { + SAA1099 *saa = &_saa1099[chip]; + if (saa->env_enable[ch]) { + int step, mode, mask; + mode = saa->env_mode[ch]; + /* step from 0..63 and then loop in steps 32..63 */ + step = saa->env_step[ch] = ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20); + + mask = 15; + if (saa->env_bits[ch]) + mask &= ~1; /* 3 bit resolution, mask LSB */ + + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = Scumm::envelope[mode][step] & mask; + if (saa->env_reverse_right[ch] & 0x01) { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = (15 - Scumm::envelope[mode][step]) & mask; + } else { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = Scumm::envelope[mode][step] & mask; + } + } else { + /* envelope mode off, set all envelope factors to 16 */ + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = 16; + } +} + +void CMSEmulator::update(int chip, int16 *buffer, int length) { + struct SAA1099 *saa = &_saa1099[chip]; + int j, ch; + + /* if the channels are disabled we're done */ + if (!saa->all_ch_enable) { + /* init output data */ + if (chip == 0) { + memset(buffer, 0, sizeof(int16)*length*2); + } + return; + } + + if (chip == 0) { + memset(buffer, 0, sizeof(int16)*length*2); + } + + for (ch = 0; ch < 2; ch++) { + switch (saa->noise_params[ch]) { + case 0: saa->noise[ch].freq = 31250.0 * 2; break; + case 1: saa->noise[ch].freq = 15625.0 * 2; break; + case 2: saa->noise[ch].freq = 7812.5 * 2; break; + case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; + } + } + + /* fill all data needed */ + for (j = 0; j < length; ++j) { + int output_l = 0, output_r = 0; + + /* for each channel */ + for (ch = 0; ch < 6; ch++) { + if (saa->channels[ch].freq == 0.0) + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / + (511.0 - (double)saa->channels[ch].frequency); + + /* check the actual position in the square wave */ + saa->channels[ch].counter -= saa->channels[ch].freq; + while (saa->channels[ch].counter < 0) { + /* calculate new frequency now after the half wave is updated */ + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / + (511.0 - (double)saa->channels[ch].frequency); + + saa->channels[ch].counter += _sampleRate; + saa->channels[ch].level ^= 1; + + /* eventually clock the envelope counters */ + if (ch == 1 && saa->env_clock[0] == 0) + envelope(chip, 0); + if (ch == 4 && saa->env_clock[1] == 0) + envelope(chip, 1); + } + + /* if the noise is enabled */ + if (saa->channels[ch].noise_enable) { + /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ + if (saa->noise[ch/3].level & 1) { + /* subtract to avoid overflows, also use only half amplitude */ + output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; + output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; + } + } + + /* if the square wave is enabled */ + if (saa->channels[ch].freq_enable) { + /* if the channel level is high */ + if (saa->channels[ch].level & 1) { + output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; + output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; + } + } + } + + for (ch = 0; ch < 2; ch++) { + /* check the actual position in noise generator */ + saa->noise[ch].counter -= saa->noise[ch].freq; + while (saa->noise[ch].counter < 0) { + saa->noise[ch].counter += _sampleRate; + if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) + saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; + else + saa->noise[ch].level <<= 1; + } + } + /* write sound data to the buffer */ + buffer[j*2] += output_l / 6; + buffer[j*2+1] += output_r / 6; + } +} + +void CMSEmulator::portWriteIntern(int chip, int offset, int data) { + SAA1099 *saa = &_saa1099[chip]; + int reg = saa->selected_reg; + int ch; + + switch (reg) { + /* channel i amplitude */ + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + ch = reg & 7; + saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; + saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; + break; + + /* channel i frequency */ + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + ch = reg & 7; + saa->channels[ch].frequency = data & 0xff; + break; + + /* channel i octave */ + case 0x10: + case 0x11: + case 0x12: + ch = (reg - 0x10) << 1; + saa->channels[ch + 0].octave = data & 0x07; + saa->channels[ch + 1].octave = (data >> 4) & 0x07; + break; + + /* channel i frequency enable */ + case 0x14: + saa->channels[0].freq_enable = data & 0x01; + saa->channels[1].freq_enable = data & 0x02; + saa->channels[2].freq_enable = data & 0x04; + saa->channels[3].freq_enable = data & 0x08; + saa->channels[4].freq_enable = data & 0x10; + saa->channels[5].freq_enable = data & 0x20; + break; + + /* channel i noise enable */ + case 0x15: + saa->channels[0].noise_enable = data & 0x01; + saa->channels[1].noise_enable = data & 0x02; + saa->channels[2].noise_enable = data & 0x04; + saa->channels[3].noise_enable = data & 0x08; + saa->channels[4].noise_enable = data & 0x10; + saa->channels[5].noise_enable = data & 0x20; + break; + + /* noise generators parameters */ + case 0x16: + saa->noise_params[0] = data & 0x03; + saa->noise_params[1] = (data >> 4) & 0x03; + break; + + /* envelope generators parameters */ + case 0x18: + case 0x19: + ch = reg - 0x18; + saa->env_reverse_right[ch] = data & 0x01; + saa->env_mode[ch] = (data >> 1) & 0x07; + saa->env_bits[ch] = data & 0x10; + saa->env_clock[ch] = data & 0x20; + saa->env_enable[ch] = data & 0x80; + /* reset the envelope */ + saa->env_step[ch] = 0; + break; + + /* channels enable & reset generators */ + case 0x1c: + saa->all_ch_enable = data & 0x01; + saa->sync_state = data & 0x02; + if (data & 0x02) { + int i; + /* Synch & Reset generators */ + for (i = 0; i < 6; i++) { + saa->channels[i].level = 0; + saa->channels[i].counter = 0.0; + } + } + break; + + default: /* Error! */ + error("CMS Unkown write to reg %x with %x",reg, data); + } +} + +#pragma mark - +#pragma mark - Player_V2CMS +#pragma mark - + +const uint8 note_lengths[] = { + 0, + 0, 0, 2, + 0, 3, 4, + 5, 6, 8, + 9, 12, 16, + 18, 24, 32, + 36, 48, 64, + 72, 96 +}; + +static const uint16 hull_offsets[] = { + 0, 12, 24, 36, 48, 60, + 72, 88, 104, 120, 136, 256, + 152, 164, 180 +}; + +static const int16 hulls[] = { + // hull 0 + 3, -1, 0, 0, 0, 0, 0, 0, + 0, -1, 0, 0, + // hull 1 (staccato) + 3, -1, 0, 32, 0, -1, 0, 0, + 0, -1, 0, 0, + // hull 2 (legato) + 3, -1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + // hull 3 (staccatissimo) + 3, -1, 0, 2, 0, -1, 0, 0, + 0, -1, 0, 0, + // hull 4 + 3, -1, 0, 6, 0, -1, 0, 0, + 0, -1, 0, 0, + // hull 5 + 3, -1, 0, 16, 0, -1, 0, 0, + 0, -1, 0, 0, + // hull 6 + (int16) 60000, -1, -1000, 20, 0, 0, 0, 0, + (int16) 40000, -1, -5000, 5, 0, -1, 0, 0, + // hull 7 + (int16) 50000, -1, 0, 8, 30000, -1, 0, 0, + 28000, -1, -5000, 5, 0, -1, 0, 0, + // hull 8 + (int16) 60000, -1, -2000, 16, 0, 0, 0, 0, + 28000, -1, -6000, 5, 0, -1, 0, 0, + // hull 9 + (int16) 55000, -1, 0, 8, (int16) 35000, -1, 0, 0, + (int16) 40000, -1, -2000, 10, 0, -1, 0, 0, + // hull 10 + (int16) 60000, -1, 0, 4, -2000, 8, 0, 0, + (int16) 40000, -1, -6000, 5, 0, -1, 0, 0, + // hull 12 + 0, -1, 150, 340, -150, 340, 0, -1, + 0, -1, 0, 0, + // hull 13 == 164 + 20000, -1, 4000, 7, 1000, 15, 0, 0, + (int16) 35000, -1, -2000, 15, 0, -1, 0, 0, + + // hull 14 == 180 + (int16) 35000, -1, 500, 20, 0, 0, 0, 0, + (int16) 45000, -1, -500, 60, 0, -1, 0, 0, + + // hull misc = 196 + (int16) 44000, -1, -4400, 10, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 53000, -1, -5300, 10, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 63000, -1, -6300, 10, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 44000, -1, -1375, 32, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 53000, -1, -1656, 32, 0, -1, 0, 0, + 0, -1, 0, 0, + + // hull 11 == 256 + (int16) 63000, -1, -1968, 32, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 44000, -1, - 733, 60, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 53000, -1, - 883, 60, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 63000, -1, -1050, 60, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 44000, -1, - 488, 90, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 53000, -1, - 588, 90, 0, -1, 0, 0, + 0, -1, 0, 0, + + (int16) 63000, -1, - 700, 90, 0, -1, 0, 0, + 0, -1, 0, 0 +}; + +static const uint16 freqmod_lengths[] = { + 0x1000, 0x1000, 0x20, 0x2000, 0x1000 +}; + +static const uint16 freqmod_offsets[] = { + 0, 0x100, 0x200, 0x302, 0x202 +}; + +static const int8 freqmod_table[0x502] = { + 0, 3, 6, 9, 12, 15, 18, 21, + 24, 27, 30, 33, 36, 39, 42, 45, + 48, 51, 54, 57, 59, 62, 65, 67, + 70, 73, 75, 78, 80, 82, 85, 87, + 89, 91, 94, 96, 98, 100, 102, 103, + 105, 107, 108, 110, 112, 113, 114, 116, + 117, 118, 119, 120, 121, 122, 123, 123, + 124, 125, 125, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 125, 125, + 124, 123, 123, 122, 121, 120, 119, 118, + 117, 116, 114, 113, 112, 110, 108, 107, + 105, 103, 102, 100, 98, 96, 94, 91, + 89, 87, 85, 82, 80, 78, 75, 73, + 70, 67, 65, 62, 59, 57, 54, 51, + 48, 45, 42, 39, 36, 33, 30, 27, + 24, 21, 18, 15, 12, 9, 6, 3, + 0, -3, -6, -9, -12, -15, -18, -21, + -24, -27, -30, -33, -36, -39, -42, -45, + -48, -51, -54, -57, -59, -62, -65, -67, + -70, -73, -75, -78, -80, -82, -85, -87, + -89, -91, -94, -96, -98,-100,-102,-103, + -105,-107,-108,-110,-112,-113,-114,-116, + -117,-118,-119,-120,-121,-122,-123,-123, + -124,-125,-125,-126,-126,-126,-126,-126, + -126,-126,-126,-126,-126,-126,-125,-125, + -124,-123,-123,-122,-121,-120,-119,-118, + -117,-116,-114,-113,-112,-110,-108,-107, + -105,-103,-102,-100, -98, -96, -94, -91, + -89, -87, -85, -82, -80, -78, -75, -73, + -70, -67, -65, -62, -59, -57, -54, -51, + -48, -45, -42, -39, -36, -33, -30, -27, + -24, -21, -18, -15, -12, -9, -6, -3, + + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + -128,-127,-126,-125,-124,-123,-122,-121, + -120,-119,-118,-117,-116,-115,-114,-113, + -112,-111,-110,-109,-108,-107,-106,-105, + -104,-103,-102,-101,-100, -99, -98, -97, + -96, -95, -94, -93, -92, -91, -90, -89, + -88, -87, -86, -85, -84, -83, -82, -81, + -80, -79, -78, -77, -76, -75, -74, -73, + -72, -71, -70, -69, -68, -67, -66, -65, + -64, -63, -62, -61, -60, -59, -58, -57, + -56, -55, -54, -53, -52, -51, -50, -49, + -48, -47, -46, -45, -44, -43, -42, -41, + -40, -39, -38, -37, -36, -35, -34, -33, + -32, -31, -30, -29, -28, -27, -26, -25, + -24, -23, -22, -21, -20, -19, -18, -17, + -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1, + + -120, 120, + + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + -120,-120,-120,-120,-120,-120,-120,-120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + + 41, 35, -66,-124, -31, 108, -42, -82, + 82,-112, 73, -15, -15, -69, -23, -21, + -77, -90, -37, 60,-121, 12, 62,-103, + 36, 94, 13, 28, 6, -73, 71, -34, + -77, 18, 77, -56, 67, -69,-117, -90, + 31, 3, 90, 125, 9, 56, 37, 31, + 93, -44, -53, -4,-106, -11, 69, 59, + 19, 13,-119, 10, 28, -37, -82, 50, + 32,-102, 80, -18, 64, 120, 54, -3, + 18, 73, 50, -10, -98, 125, 73, -36, + -83, 79, 20, -14, 68, 64, 102, -48, + 107, -60, 48, -73, 50, 59, -95, 34, + -10, 34,-111, -99, -31,-117, 31, -38, + -80, -54,-103, 2, -71, 114, -99, 73, + 44,-128, 126, -59,-103, -43, -23,-128, + -78, -22, -55, -52, 83, -65, 103, -42, + -65, 20, -42, 126, 45, -36,-114, 102, + -125, -17, 87, 73, 97, -1, 105,-113, + 97, -51, -47, 30, -99,-100, 22, 114, + 114, -26, 29, -16,-124, 79, 74, 119, + 2, -41, -24, 57, 44, 83, -53, -55, + 18, 30, 51, 116, -98, 12, -12, -43, + -44, -97, -44, -92, 89, 126, 53, -49, + 50, 34, -12, -52, -49, -45,-112, 45, + 72, -45,-113, 117, -26, -39, 29, 42, + -27, -64, -9, 43, 120,-127,-121, 68, + 14, 95, 80, 0, -44, 97,-115, -66, + 123, 5, 21, 7, 59, 51,-126, 31, + 24, 112,-110, -38, 100, 84, -50, -79, + -123, 62, 105, 21, -8, 70, 106, 4, + -106, 115, 14, -39, 22, 47, 103, 104, + -44, -9, 74, 74, -48, 87, 104, 118, + -6, 22, -69, 17, -83, -82, 36,-120, + 121, -2, 82, -37, 37, 67, -27, 60, + -12, 69, -45, -40, 40, -50, 11, -11, + -59, 96, 89, 61,-105, 39,-118, 89, + 118, 45, -48, -62, -55, -51, 104, -44, + 73, 106, 121, 37, 8, 97, 64, 20, + -79, 59, 106, -91, 17, 40, -63,-116, + -42, -87, 11,-121,-105,-116, 47, -15, + 21, 29,-102,-107, -63,-101, -31, -64, + 126, -23, -88,-102, -89,-122, -62, -75, + 84, -65,-102, -25, -39, 35, -47, 85, + -112, 56, 40, -47, -39, 108, -95, 102, + 94, 78, -31, 48,-100, -2, -39, 113, + -97, -30, -91, -30, 12,-101, -76, 71, + 101, 56, 42, 70,-119, -87,-126, 121, + 122, 118, 120, -62, 99, -79, 38, -33, + -38, 41, 109, 62, 98, -32,-106, 18, + 52, -65, 57, -90, 63,-119, 94, -15, + 109, 14, -29, 108, 40, -95, 30, 32, + 29, -53, -62, 3, 63, 65, 7,-124, + 15, 20, 5, 101, 27, 40, 97, -55, + -59, -25, 44,-114, 70, 54, 8, -36, + -13, -88,-115, -2, -66, -14, -21, 113, + -1, -96, -48, 59, 117, 6,-116, 126, + -121, 120, 115, 77, -48, -66,-126, -66, + -37, -62, 70, 65, 43,-116, -6, 48, + 127, 112, -16, -89, 84,-122, 50,-107, + -86, 91, 104, 19, 11, -26, -4, -11, + -54, -66, 125, -97,-119,-118, 65, 27, + -3, -72, 79, 104, -10, 114, 123, 20, + -103, -51, -45, 13, -16, 68, 58, -76, + -90, 102, 83, 51, 11, -53, -95, 16 +}; + +static const byte freqTable[] = { + 3, 10, 17, 24, 31, 38, 45, 51, + 58, 65, 71, 77, 83, 90, 96, 102, + 107, 113, 119, 125, 130, 136, 141, 146, + 151, 157, 162, 167, 172, 177, 181, 186, + 191, 195, 200, 204, 209, 213, 217, 221, + 226, 230, 234, 238, 242, 246, 249, 253 +}; + +/*static const byte amplTable[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 % + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 % + 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, // 20 % + 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20, // 30% + 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x40, 0x40, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x20, // 40 % + 0x30, 0x30, 0x40, 0x40, 0x40, 0x50, 0x50, 0x60, + 0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x30, 0x30, // 50% + 0x40, 0x40, 0x50, 0x50, 0x60, 0x60, 0x70, 0x70, + 0x00, 0x00, 0x10, 0x10, 0x20, 0x30, 0x30, 0x40, // 60 % + 0x40, 0x50, 0x60, 0x60, 0x70, 0x70, 0x80, 0x90, + 0x00, 0x00, 0x10, 0x20, 0x20, 0x30, 0x40, 0x40, // 70 % + 0x50, 0x60, 0x70, 0x70, 0x80, 0x90, 0x90, 0xA0, + 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x40, 0x50, // 80 % + 0x60, 0x70, 0x80, 0x80, 0x90, 0xA0, 0xB0, 0xC0, + 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, // 90 % + 0x70, 0x80, 0x90, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // 100 % + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0 +};*/ + +static const byte octaveTable[] = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, + 0x00, 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, + 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, + 0x01, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07, + 0x01, 0x08, 0x01, 0x09, 0x01, 0x0A, 0x01, 0x0B, + 0x02, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, + 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x07, + 0x02, 0x08, 0x02, 0x09, 0x02, 0x0A, 0x02, 0x0B, + 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, + 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, + 0x03, 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, + 0x04, 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, + 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, + 0x04, 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, + 0x05, 0x00, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, + 0x05, 0x04, 0x05, 0x05, 0x05, 0x06, 0x05, 0x07, + 0x05, 0x08, 0x05, 0x09, 0x05, 0x0A, 0x05, 0x0B, + 0x06, 0x00, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, + 0x06, 0x04, 0x06, 0x05, 0x06, 0x06, 0x06, 0x07, + 0x06, 0x08, 0x06, 0x09, 0x06, 0x0A, 0x06, 0x0B, + 0x07, 0x00, 0x07, 0x01, 0x07, 0x02, 0x07, 0x03, + 0x07, 0x04, 0x07, 0x05, 0x07, 0x06, 0x07, 0x07, + 0x07, 0x08, 0x07, 0x09, 0x07, 0x0A, 0x07, 0x0B, + 0x08, 0x00, 0x08, 0x01, 0x08, 0x02, 0x08, 0x03, + 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x08, 0x07, + 0x08, 0x08, 0x08, 0x09, 0x08, 0x0A, 0x08, 0x0B, + 0x09, 0x00, 0x09, 0x01, 0x09, 0x02, 0x09, 0x03, + 0x09, 0x04, 0x09, 0x05, 0x09, 0x06, 0x09, 0x07, + 0x09, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x09, 0x0B, + 0x0A, 0x00, 0x0A, 0x01, 0x0A, 0x02, 0x0A, 0x03, + 0x0A, 0x04, 0x0A, 0x05, 0x0A, 0x06, 0x0A, 0x07, + 0x0A, 0x08, 0x0A, 0x09, 0x0A, 0x0A, 0x0A, 0x0B +}; + +static const byte attackRate[] = { + 0, 2, 4, 7, 14, 26, 48, 82, + 128, 144, 160, 176, 192, 208, 224, 255 +}; + +static const byte decayRate[] = { + 0, 1, 2, 3, 4, 6, 12, 24, + 48, 96, 192, 215, 255, 255, 255, 255 +}; + +static const byte sustainRate[] = { + 255, 180, 128, 96, 80, 64, 56, 48, + 42, 36, 32, 28, 24, 20, 16, 0 +}; + +static const byte releaseRate[] = { + 0, 1, 2, 4, 6, 9, 14, 22, + 36, 56, 80, 100, 120, 140, 160, 255 +}; + +static const uint16 pcjr_freq_table[12] = { + 65472, 61760, 58304, 55040, 52032, 49024, + 46272, 43648, 41216, 38912, 36736, 34624 +}; + +static const byte volumeTable[] = { + 0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22, + 0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF +}; + +static CMSEmulator *g_cmsEmu = 0; + +Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer) { + int i; + + _isV3Game = (scumm->_game.version >= 3); + _vm = scumm; + _mixer = mixer; +// debug("mixer rate: %d", _mixer->getOutputRate()); + _sample_rate = CMS_RATE; + + _header_len = (scumm->_game.features & GF_OLD_BUNDLE) ? 4 : 6; + + // Initialize sound queue + _current_nr = _next_nr = 0; + _current_data = _next_data = 0; + + // Initialize channel code + for (i = 0; i < 4; ++i) + clear_channel(i); + + _next_tick = 0; + _tick_len = (_sample_rate << FIXP_SHIFT) / FREQ_HZ; + + // Initialize V3 music timer + _music_timer_ctr = _music_timer = 0; + _ticks_per_music_timer = 65535; + + setMusicVolume(255); + + _timer_output = 0; + for (i = 0; i < 4; i++) + _timer_count[i] = 0; + + memset(_cmsVoicesBase, 0, sizeof(Voice)*16); + memset(_cmsVoices, 0, sizeof(Voice2)*8); + memset(_cmsChips, 0, sizeof(MusicChip)*2); + _midiDelay = _octaveMask = _looping = _tempo = 0; + _midiData = _midiSongBegin = 0; + _loadedMidiSong = 0; + memset(_midiChannel, 0, sizeof(Voice2*)*16); + memset(_midiChannelUse, 0, sizeof(byte)*16); + + _cmsVoices[0].amplitudeOutput = &(_cmsChips[0].ampl[0]); + _cmsVoices[0].freqOutput = &(_cmsChips[0].freq[0]); + _cmsVoices[0].octaveOutput = &(_cmsChips[0].octave[0]); + _cmsVoices[1].amplitudeOutput = &(_cmsChips[0].ampl[1]); + _cmsVoices[1].freqOutput = &(_cmsChips[0].freq[1]); + _cmsVoices[1].octaveOutput = &(_cmsChips[0].octave[0]); + _cmsVoices[2].amplitudeOutput = &(_cmsChips[0].ampl[2]); + _cmsVoices[2].freqOutput = &(_cmsChips[0].freq[2]); + _cmsVoices[2].octaveOutput = &(_cmsChips[0].octave[1]); + _cmsVoices[3].amplitudeOutput = &(_cmsChips[0].ampl[3]); + _cmsVoices[3].freqOutput = &(_cmsChips[0].freq[3]); + _cmsVoices[3].octaveOutput = &(_cmsChips[0].octave[1]); + _cmsVoices[4].amplitudeOutput = &(_cmsChips[1].ampl[0]); + _cmsVoices[4].freqOutput = &(_cmsChips[1].freq[0]); + _cmsVoices[4].octaveOutput = &(_cmsChips[1].octave[0]); + _cmsVoices[5].amplitudeOutput = &(_cmsChips[1].ampl[1]); + _cmsVoices[5].freqOutput = &(_cmsChips[1].freq[1]); + _cmsVoices[5].octaveOutput = &(_cmsChips[1].octave[0]); + _cmsVoices[6].amplitudeOutput = &(_cmsChips[1].ampl[2]); + _cmsVoices[6].freqOutput = &(_cmsChips[1].freq[2]); + _cmsVoices[6].octaveOutput = &(_cmsChips[1].octave[1]); + _cmsVoices[7].amplitudeOutput = &(_cmsChips[1].ampl[3]); + _cmsVoices[7].freqOutput = &(_cmsChips[1].freq[3]); + _cmsVoices[7].octaveOutput = &(_cmsChips[1].octave[1]); + + // inits the CMS Emulator like in the original + g_cmsEmu = new CMSEmulator(_sample_rate); + static const byte cmsInitData[13*2] = { + 0x1C, 0x02, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1C, 0x01 + }; + + i = 0; + for (int cmsPort = 0x220; i < 2; cmsPort += 2, ++i) { + for (int off = 0; off < 13; ++off) { + g_cmsEmu->portWrite(cmsPort+1, cmsInitData[off*2]); + g_cmsEmu->portWrite(cmsPort, cmsInitData[off*2+1]); + } + } + + _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); +} + +Player_V2CMS::~Player_V2CMS() { + mutex_up(); + _mixer->stopHandle(_soundHandle); + delete g_cmsEmu; + mutex_down(); +} + +void Player_V2CMS::setMusicVolume(int vol) { +} + +void Player_V2CMS::chainSound(int nr, byte *data) { + int offset = _header_len + 10; + + _current_nr = nr; + _current_data = data; + + for (int i = 0; i < 4; i++) { + clear_channel(i); + + _channels[i].d.music_script_nr = nr; + if (data) { + _channels[i].d.next_cmd = READ_LE_UINT16(data + offset + 2 * i); + if (_channels[i].d.next_cmd) { + _channels[i].d.time_left = 1; + } + } + } + _music_timer = 0; +} + +void Player_V2CMS::chainNextSound() { + if (_next_nr) { + chainSound(_next_nr, _next_data); + _next_nr = 0; + _next_data = 0; + } +} + +void Player_V2CMS::stopAllSounds() { + mutex_up(); + for (int i = 0; i < 4; i++) { + clear_channel(i); + } + _next_nr = _current_nr = 0; + _next_data = _current_data = 0; + _midiData = 0; + _midiSongBegin = 0; + _midiDelay = 0; + offAllChannels(); + mutex_down(); +} + +void Player_V2CMS::stopSound(int nr) { + mutex_up(); + if (_next_nr == nr) { + _next_nr = 0; + _next_data = 0; + } + if (_current_nr == nr) { + for (int i = 0; i < 4; i++) { + clear_channel(i); + } + _current_nr = 0; + _current_data = 0; + chainNextSound(); + } + if (_loadedMidiSong == nr) { + _midiData = 0; + _midiSongBegin = 0; + _midiDelay = 0; + offAllChannels(); + } + mutex_down(); +} + +void Player_V2CMS::startSound(int nr) { + byte *data = _vm->getResourceAddress(rtSound, nr); + assert(data); + + if (data[6] == 0x80) { + mutex_up(); + loadMidiData(data, nr); + mutex_down(); + } else { + mutex_up(); + + int cprio = _current_data ? *(_current_data + _header_len) : 0; + int prio = *(data + _header_len); + int nprio = _next_data ? *(_next_data + _header_len) : 0; + + int restartable = *(data + _header_len + 1); + + if (!_current_nr || cprio <= prio) { + int tnr = _current_nr; + int tprio = cprio; + byte *tdata = _current_data; + + chainSound(nr, data); + nr = tnr; + prio = tprio; + data = tdata; + restartable = data ? *(data + _header_len + 1) : 0; + } + + if (!_current_nr) { + nr = 0; + _next_nr = 0; + _next_data = 0; + } + + if (nr != _current_nr + && restartable + && (!_next_nr + || nprio <= prio)) { + + _next_nr = nr; + _next_data = data; + } + + mutex_down(); + } +} + +void Player_V2CMS::loadMidiData(byte *data, int sound) { + memset(_midiChannelUse, 0, sizeof(byte)*16); + + _tempo = data[7]; + _looping = data[8]; + + byte channels = data[14]; + byte curChannel = 0; + byte *voice2 = data + 23; + + for (; channels != 0; ++curChannel, --channels, voice2 += 16) { + if (*(data + 15 + curChannel)) { + byte channel = *(data + 15 + curChannel) - 1; + _midiChannelUse[channel] = 1; + + Voice *voiceDef = &_cmsVoicesBase[channel]; + + byte attackDecay = voice2[10]; + voiceDef->attack = attackRate[attackDecay >> 4]; + voiceDef->decay = decayRate[attackDecay & 0x0F]; + byte sustainRelease = voice2[11]; + voiceDef->sustain = sustainRate[sustainRelease >> 4]; + voiceDef->release = releaseRate[sustainRelease & 0x0F]; + + if (voice2[3] & 0x40) { + voiceDef->vibrato = 0x0301; + if (voice2[13] & 0x40) { + voiceDef->vibrato = 0x0601; + } + } else { + voiceDef->vibrato = 0; + } + + if (voice2[8] & 0x80) { + voiceDef->vibrato2 = 0x0506; + if (voice2[13] & 0x80) { + voiceDef->vibrato2 = 0x050C; + } + } else { + voiceDef->vibrato2 = 0; + } + + if ((voice2[8] & 0x0F) > 1) { + voiceDef->octadd = 0x01; + } else { + voiceDef->octadd = 0x00; + } + } + } + + for (int i = 0, channel = 0; i < 8; ++i, channel += 2) { + _cmsVoices[i].chanNumber = 0xFF; + _cmsVoices[i].curVolume = 0; + _cmsVoices[i].nextVoice = 0; + + _midiChannel[channel] = 0; + } + + _midiDelay = 0; + memset(_cmsChips, 0, sizeof(MusicChip)*2); + _midiData = data + 151; + _midiSongBegin = _midiData + data[9]; + + _loadedMidiSong = sound; +} + +int Player_V2CMS::getSoundStatus(int nr) const { + return _current_nr == nr || _next_nr == nr || _loadedMidiSong == nr; +} + + +void Player_V2CMS::clear_channel(int i) { + ChannelInfo *channel = &_channels[i]; + memset(channel, 0, sizeof(ChannelInfo)); +} + +int Player_V2CMS::getMusicTimer() const { + if (_isV3Game) + return _music_timer; + else + return _channels[0].d.music_timer; +} + +void Player_V2CMS::execute_cmd(ChannelInfo *channel) { + uint16 value; + int16 offset; + uint8 *script_ptr; + ChannelInfo * current_channel; + ChannelInfo * dest_channel; + + current_channel = channel; + + if (channel->d.next_cmd == 0) + goto check_stopped; + script_ptr = &_current_data[channel->d.next_cmd]; + + for (;;) { + uint8 opcode = *script_ptr++; + if (opcode >= 0xf8) { + switch (opcode) { + case 0xf8: // set hull curve + debug(7, "channels[%d]: hull curve %2d", + (uint)(channel - _channels), *script_ptr); + channel->d.hull_curve = hull_offsets[*script_ptr / 2]; + script_ptr++; + break; + + case 0xf9: // set freqmod curve + debug(7, "channels[%d]: freqmod curve %2d", + (uint)(channel - _channels), *script_ptr); + channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4]; + channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4]; + script_ptr++; + break; + + case 0xfd: // clear other channel + value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo); + debug(7, "clear channel %d", value); + script_ptr += 2; + // In Indy3, when traveling to Venice a command is + // issued to clear channel 4. So we introduce a 4th + // channel, which is never used. All OOB accesses are + // mapped to this channel. + // + // The original game had room for 8 channels, but only + // channels 0-3 are read, changes to other channels + // had no effect. + if (value >= ARRAYSIZE (_channels)) + value = 4; + channel = &_channels[value]; + // fall through + + case 0xfa: // clear current channel + if (opcode == 0xfa) + debug(7, "clear channel"); + channel->d.next_cmd = 0; + channel->d.base_freq = 0; + channel->d.freq_delta = 0; + channel->d.freq = 0; + channel->d.volume = 0; + channel->d.volume_delta = 0; + channel->d.inter_note_pause = 0; + channel->d.transpose = 0; + channel->d.hull_curve = 0; + channel->d.hull_offset = 0; + channel->d.hull_counter = 0; + channel->d.freqmod_table = 0; + channel->d.freqmod_offset = 0; + channel->d.freqmod_incr = 0; + channel->d.freqmod_multiplier = 0; + channel->d.freqmod_modulo = 0; + break; + + case 0xfb: // ret from subroutine + debug(7, "ret from sub"); + script_ptr = _retaddr; + break; + + case 0xfc: // call subroutine + offset = READ_LE_UINT16 (script_ptr); + debug(7, "subroutine %d", offset); + script_ptr += 2; + _retaddr = script_ptr; + script_ptr = _current_data + offset; + break; + + case 0xfe: // loop music + opcode = *script_ptr++; + offset = READ_LE_UINT16 (script_ptr); + script_ptr += 2; + debug(7, "loop if %d to %d", opcode, offset); + if (!channel->array[opcode / 2] || --channel->array[opcode/2]) + script_ptr += offset; + break; + + case 0xff: // set parameter + opcode = *script_ptr++; + value = READ_LE_UINT16 (script_ptr); + channel->array[opcode / 2] = value; + debug(7, "channels[%d]: set param %2d = %5d", + (uint)(channel - _channels), opcode, value); + script_ptr += 2; + if (opcode == 14) { + /* tempo var */ + _ticks_per_music_timer = 125; + } + if (opcode == 0) + goto end; + break; + } + } else { // opcode < 0xf8 + for (;;) { + int16 note, octave; + int is_last_note; + dest_channel = &_channels[(opcode >> 5) & 3]; + + if (!(opcode & 0x80)) { + + int tempo = channel->d.tempo; + if (!tempo) + tempo = 1; + channel->d.time_left = tempo * note_lengths[opcode & 0x1f]; + + note = *script_ptr++; + is_last_note = note & 0x80; + note &= 0x7f; + if (note == 0x7f) { + debug(8, "channels[%d]: pause %d", + (uint)(channel - _channels), channel->d.time_left); + goto end; + } + } else { + + channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++; + + if ((opcode & 0x10)) { + debug(8, "channels[%d]: pause %d", + (uint)(channel - _channels), channel->d.time_left); + goto end; + } + + is_last_note = 0; + note = (*script_ptr++) & 0x7f; + } + + debug(8, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s", + (uint)(dest_channel - channel), script_ptr ? (uint)(script_ptr - _current_data - 2) : 0, + note, (signed short) dest_channel->d.transpose, channel->d.time_left, + dest_channel->d.hull_curve, dest_channel->d.freqmod_table, + dest_channel->d.freqmod_incr,dest_channel->d.freqmod_multiplier, + is_last_note ? "last":""); + + uint16 myfreq; + dest_channel->d.time_left = channel->d.time_left; + dest_channel->d.note_length = + channel->d.time_left - dest_channel->d.inter_note_pause; + note += dest_channel->d.transpose; + while (note < 0) + note += 12; + octave = note / 12; + note = note % 12; + dest_channel->d.hull_offset = 0; + dest_channel->d.hull_counter = 1; + if (dest_channel == &_channels[3]) { + dest_channel->d.hull_curve = 196 + note * 12; + myfreq = 384 - 64 * octave; + } else { + myfreq = pcjr_freq_table[note] >> octave; + } + dest_channel->d.freq = dest_channel->d.base_freq = myfreq; + if (is_last_note) + goto end; + opcode = *script_ptr++; + } + } + } + +end: + channel = current_channel; + if (channel->d.time_left) { + channel->d.next_cmd = script_ptr - _current_data; + return; + } + + channel->d.next_cmd = 0; + +check_stopped: + int i; + for (i = 0; i < 4; i++) { + if (_channels[i].d.time_left) + return; + } + + _current_nr = 0; + _current_data = 0; + chainNextSound(); + return; +} + +void Player_V2CMS::next_freqs(ChannelInfo *channel) { + channel->d.volume += channel->d.volume_delta; + channel->d.base_freq += channel->d.freq_delta; + + channel->d.freqmod_offset += channel->d.freqmod_incr; + if (channel->d.freqmod_offset != 0) + if (channel->d.freqmod_offset > channel->d.freqmod_modulo) + channel->d.freqmod_offset -= channel->d.freqmod_modulo; + + channel->d.freq = + (int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)]) + * (int) channel->d.freqmod_multiplier / 256 + + channel->d.base_freq; + + debug(9, "Freq: %d/%d, %d/%d/%d*%d %d", + channel->d.base_freq, (int16)channel->d.freq_delta, + channel->d.freqmod_table, channel->d.freqmod_offset, + channel->d.freqmod_incr, channel->d.freqmod_multiplier, + channel->d.freq); + + if (channel->d.note_length && !--channel->d.note_length) { + channel->d.hull_offset = 16; + channel->d.hull_counter = 1; + } + + if (!--channel->d.time_left) { + execute_cmd(channel); + } + + if (channel->d.hull_counter && !--channel->d.hull_counter) { + for (;;) { + const int16 *hull_ptr = hulls + + channel->d.hull_curve + channel->d.hull_offset / 2; + if (hull_ptr[1] == -1) { + channel->d.volume = hull_ptr[0]; + if (hull_ptr[0] == 0) + channel->d.volume_delta = 0; + channel->d.hull_offset += 4; + } else { + channel->d.volume_delta = hull_ptr[0]; + channel->d.hull_counter = hull_ptr[1]; + channel->d.hull_offset += 4; + break; + } + } + } +} + +void Player_V2CMS::nextTick() { + for (int i = 0; i < 4; i++) { + if (!_channels[i].d.time_left) + continue; + next_freqs(&_channels[i]); + } + if (_music_timer_ctr++ >= _ticks_per_music_timer) { + _music_timer_ctr = 0; + _music_timer++; + } +} + +void Player_V2CMS::processMidiData(uint ticks) { + byte *currentData = _midiData; + byte command = 0x00; + int16 temp = 0; + + if (!_midiDelay) { + while (true) { + if ((command = *currentData++) == 0xFF) { + if ((command = *currentData++) == 0x2F) { + if (_looping == 0) { + currentData = _midiData = _midiSongBegin; + continue; + } + _midiData = _midiSongBegin = 0; + offAllChannels(); + return; + } else { + if (command == 0x58) { + currentData += 6; + } + } + } else { + _lastMidiCommand = command; + if (command < 0x90) { + clearNote(currentData); + } else { + playNote(currentData); + } + } + + temp = command = *currentData++; + if (command & 0x80) { + temp = (command & 0x7F) << 8; + command = *currentData++; + temp |= (command << 1); + temp >>= 1; + } + temp >>= 1; + int lastBit = temp & 1; + temp >>= 1; + temp += lastBit; + + if (temp) + break; + } + _midiData = currentData; + _midiDelay = temp; + } + + _midiDelay -= ticks; + if (_midiDelay < 0) + _midiDelay = 0; + + return; +} + +int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) { + mutex_up(); + uint step = 1; + int len = numSamples/2; + + // maybe this needs a complete rewrite + do { + if (_midiData) { + --_clkFrequenz; + if (!(_clkFrequenz & 0x01)) { + playVoice(); + } + + _tempoSum += _tempo; + // FIXME: _tempoSum is declared as char; on some systems char is unsigned. + // E.g. on OS X. Hence the following check is always false. + // Moral of the story: Use uint8, int8 or any of the other types provided by + // ScummVM if you want to ensure signedness and number of available bits. + if (_tempoSum < 0) { + // this have to be called in the same rate as in the original (I think) + processMidiData(1); + } + } + + if (!(_next_tick >> FIXP_SHIFT) && !_midiData) { + _next_tick += _tick_len; + nextTick(); + play(); + } + + step = len; + if (step > (_next_tick >> FIXP_SHIFT)) + step = (_next_tick >> FIXP_SHIFT); + g_cmsEmu->readBuffer(buffer, step); + buffer += 2 * step; + _next_tick -= step << FIXP_SHIFT; + } while (len -= step); + + mutex_down(); + return numSamples; +} + +void Player_V2CMS::playVoice() { + if (_outputTableReady) { + playMusicChips(_cmsChips); + _outputTableReady = 0; + } + + _octaveMask = 0xF0; + Voice2 *voice =0; + for (int i = 0; i < 8; ++i) { + voice = &_cmsVoices[i]; + _octaveMask = ~_octaveMask; + + if (voice->chanNumber != 0xFF) { + processChannel(voice); + continue; + } + + if (!voice->curVolume) { + *(voice->amplitudeOutput) = 0; + } + + int volume = voice->curVolume - voice->releaseRate; + voice->curVolume = volume; + + if (volume < 0) { + volume = voice->curVolume = 0; + } + + *(voice->amplitudeOutput) = ((volume >> 4) | (volume & 0xF0)) & voice->channel; + ++_outputTableReady; + } +} + +void Player_V2CMS::processChannel(Voice2 *channel) { + ++_outputTableReady; + switch (channel->nextProcessState) { + case PROCESS_RELEASE: + processRelease(channel); + break; + + case PROCESS_ATTACK: + processAttack(channel); + break; + + case PROCESS_DECAY: + processDecay(channel); + break; + + case PROCESS_SUSTAIN: + processSustain(channel); + break; + + case PROCESS_VIBRATO: + processVibrato(channel); + break; + + default: + break; + } +} + +void Player_V2CMS::processRelease(Voice2 *channel) { + channel->curVolume -= channel->releaseRate; + if (channel->curVolume < 0) + channel->curVolume = 0; + processVibrato(channel); +} + +void Player_V2CMS::processAttack(Voice2 *channel) { + channel->curVolume += channel->attackRate; + if (channel->curVolume >= 0) { + if (channel->curVolume <= channel->maxAmpl) + return processVibrato(channel); + } + channel->curVolume = channel->maxAmpl; + channel->nextProcessState = PROCESS_DECAY; + processVibrato(channel); +} + +void Player_V2CMS::processDecay(Voice2 *channel) { + channel->curVolume -= channel->decayRate; + if (channel->curVolume >= 0) { + if (channel->curVolume > channel->sustainRate) + return processVibrato(channel); + } + channel->curVolume = channel->sustainRate; + channel->nextProcessState = PROCESS_SUSTAIN; + processVibrato(channel); +} + +void Player_V2CMS::processSustain(Voice2 *channel) { + if (channel->unkVibratoRate) { + int volume = (int)channel->curVolume + (int)channel->unkRate; + if (volume & 0xFF00) { + volume = ((~volume) >> 8) & 0xFF; + } + channel->curVolume = volume; + --(channel->unkCount); + if (!channel->unkCount) { + channel->unkRate = ~(channel->unkRate); + channel->unkCount = (channel->unkVibratoDepth & 0x0F) << 1; + } + } + processVibrato(channel); +} + +void Player_V2CMS::processVibrato(Voice2 *channel) { + if (channel->vibratoRate) { + uint16 temp = channel->curFreq + channel->curVibratoRate; + channel->curOctave += (temp & 0xFF00) >> 8; + channel->curFreq = temp & 0xFF; + --(channel->curVibratoUnk); + if (!channel->curVibratoUnk) { + channel->curVibratoRate = ~(channel->curVibratoRate); + channel->curVibratoUnk = (channel->vibratoDepth & 0x0F) << 1; + } + } + + byte *output = channel->amplitudeOutput; + *output = ((channel->curVolume >> 4) | (channel->curVolume & 0xF0)) & channel->channel; + output = channel->freqOutput; + *output = channel->curFreq; + output = channel->octaveOutput; + *output = ((((channel->curOctave >> 4) | (channel->curOctave & 0x0F)) & _octaveMask) | ((~_octaveMask) & *output)); +} + +void Player_V2CMS::offAllChannels() { + warning("offAllChannels STUB"); +/* + // after using this sound can not be played anymore (since it would deinit the emulator) + static const byte cmsOffData[10*2] = { + 0x1C, 0x02, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00 + }; + + for (int cmsPort = 0x220, i = 0; i < 2; cmsPort += 2, ++i) { + for (int off = 0; off < 10; ++off) { + g_cmsEmu->portWrite(cmsPort+1, cmsOffData[off*2]); + g_cmsEmu->portWrite(cmsPort, cmsOffData[off*2+1]); + } + }*/ +} + +Player_V2CMS::Voice2 *Player_V2CMS::getFreeVoice() { + Voice2 *curVoice = 0; + Voice2 *selected = 0; + uint8 volume = 0xFF; + + for (int i = 0; i < 8; ++i) { + curVoice = &_cmsVoices[i]; + + if (curVoice->chanNumber == 0xFF) { + if (!curVoice->curVolume) { + selected = curVoice; + break; + } + + if (curVoice->curVolume < volume) { + selected = curVoice; + volume = selected->curVolume; + } + } + } + + if (selected) { + selected->chanNumber = _lastMidiCommand & 0x0F; + + uint8 channel = selected->chanNumber; + Voice2 *oldChannel = _midiChannel[channel]; + _midiChannel[channel] = selected; + selected->nextVoice = oldChannel; + } + + return selected; +} + +void Player_V2CMS::playNote(byte *&data) { + byte channel = _lastMidiCommand & 0x0F; + if (_midiChannelUse[channel]) { + Voice2 *freeVoice = getFreeVoice(); + if (freeVoice) { + Voice *voice = &_cmsVoicesBase[freeVoice->chanNumber]; + freeVoice->attackRate = voice->attack; + freeVoice->decayRate = voice->decay; + freeVoice->sustainRate = voice->sustain; + freeVoice->releaseRate = voice->release; + freeVoice->octaveAdd = voice->octadd; + freeVoice->vibratoRate = freeVoice->curVibratoRate = voice->vibrato; + freeVoice->unkVibratoRate = freeVoice->unkRate = voice->vibrato2; + freeVoice->maxAmpl = 0xFF; + + uint8 rate = freeVoice->attackRate; + uint8 volume = freeVoice->curVolume >> 1; + + if (rate < volume) + rate = volume; + + rate -= freeVoice->attackRate; + freeVoice->curVolume = rate; + freeVoice->playingNote = *data; + int octave = octaveTable[(*data + 3) << 1] + freeVoice->octaveAdd - 3; + if (octave < 0) + octave = 0; + if (octave > 7) + octave = 7; + if (!octave) + ++octave; + freeVoice->curOctave = octave; + freeVoice->curFreq = freqTable[volume << 2]; + freeVoice->curVolume = 0; + freeVoice->nextProcessState = PROCESS_ATTACK; + if (_lastMidiCommand & 1) + freeVoice->channel = 0xF0; + else + freeVoice->channel = 0x0F; + } + } + data += 2; +} + +Player_V2CMS::Voice2 *Player_V2CMS::getPlayVoice(byte param) { + byte channelNum = _lastMidiCommand & 0x0F; + Voice2 *channel = _midiChannel[channelNum]; + + if (channel) { + Voice2 *backUp = 0; + while (true) { + if (channel->playingNote == param) + break; + + backUp = channel; + channel = channel->nextVoice; + if (!channel) + return 0; + } + + Voice2 *backUp2 = channel->nextVoice; + { + Voice2 *temp = backUp; + backUp = channel; + channel = temp; + } + if (channel) { + channel->nextVoice = backUp2; + } else { + _midiChannel[channelNum] = backUp2; + } + channel = backUp; + } + + return channel; +} + +void Player_V2CMS::clearNote(byte *&data) { + Voice2 *voice = getPlayVoice(*data); + if (voice) { + voice->chanNumber = 0xFF; + voice->nextVoice = 0; + voice->nextProcessState = PROCESS_RELEASE; + } + data += 2; +} + +void Player_V2CMS::play() { + _octaveMask = 0xF0; + channel_data *chan = &(_channels[0].d); + + static byte volumeReg[4] = { 0x00, 0x00, 0x00, 0x00 }; + static byte octaveReg[4] = { 0x66, 0x66, 0x66, 0x66 }; + static byte freqReg[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + + static byte freqEnable = 0x3E; + static byte noiseEnable = 0x01; + static byte noiseGen = 0x02; + for (int i = 1; i <= 4; ++i) { + if (chan->time_left) { + uint16 freq = chan->freq; + + if (i == 4) { + if ((freq >> 8) & 0x40) { + noiseGen = freq & 0xFF; + } else { + noiseGen = 3; + freqReg[0] = freqReg[3]; + octaveReg[0] = (octaveReg[0] & 0xF0) | ((octaveReg[1] & 0xF0) >> 4); + } + } else { + if (freq == 0) { + freq = 0xFFC0; + } + + int cmsOct = 2; + int freqOct = 0x8000; + + while (true) { + if (freq >= freqOct) { + break; + } + freqOct >>= 1; + ++cmsOct; + if (cmsOct == 8) { + --cmsOct; + freq = 1024; + break; + } + } + byte oct = cmsOct << 4; + oct |= cmsOct; + + oct &= _octaveMask; + oct |= ((~_octaveMask) & octaveReg[((i & 3) >> 1)]); + octaveReg[((i & 3) >> 1)] = oct; + + freq >>= -(cmsOct-9); + freqReg[(i&3)] = (-(freq-511)) & 0xFF; + } + volumeReg[i & 3] = volumeTable[chan->volume >> 12]; + } else { + volumeReg[i & 3] = 0; + } + chan = &(_channels[i].d); + _octaveMask ^= 0xFF; + } + + // with the high nibble of the volumeReg value + // the right channels amplitude is set + // with the low value the left channels amplitude + g_cmsEmu->portWrite(0x221, 0); + g_cmsEmu->portWrite(0x220, volumeReg[0]); + g_cmsEmu->portWrite(0x221, 1); + g_cmsEmu->portWrite(0x220, volumeReg[1]); + g_cmsEmu->portWrite(0x221, 2); + g_cmsEmu->portWrite(0x220, volumeReg[2]); + g_cmsEmu->portWrite(0x221, 3); + g_cmsEmu->portWrite(0x220, volumeReg[3]); + g_cmsEmu->portWrite(0x221, 8); + g_cmsEmu->portWrite(0x220, freqReg[0]); + g_cmsEmu->portWrite(0x221, 9); + g_cmsEmu->portWrite(0x220, freqReg[1]); + g_cmsEmu->portWrite(0x221, 10); + g_cmsEmu->portWrite(0x220, freqReg[2]); + g_cmsEmu->portWrite(0x221, 11); + g_cmsEmu->portWrite(0x220, freqReg[3]); + g_cmsEmu->portWrite(0x221, 0x10); + g_cmsEmu->portWrite(0x220, octaveReg[0]); + g_cmsEmu->portWrite(0x221, 0x11); + g_cmsEmu->portWrite(0x220, octaveReg[1]); + g_cmsEmu->portWrite(0x221, 0x14); + g_cmsEmu->portWrite(0x220, freqEnable); + g_cmsEmu->portWrite(0x221, 0x15); + g_cmsEmu->portWrite(0x220, noiseEnable); + g_cmsEmu->portWrite(0x221, 0x16); + g_cmsEmu->portWrite(0x220, noiseGen); +} + +void Player_V2CMS::playMusicChips(const MusicChip *table) { + int cmsPort = 0x21E; + + do { + cmsPort += 2; + g_cmsEmu->portWrite(cmsPort+1, 0); + g_cmsEmu->portWrite(cmsPort, table->ampl[0]); + g_cmsEmu->portWrite(cmsPort+1, 1); + g_cmsEmu->portWrite(cmsPort, table->ampl[1]); + g_cmsEmu->portWrite(cmsPort+1, 2); + g_cmsEmu->portWrite(cmsPort, table->ampl[2]); + g_cmsEmu->portWrite(cmsPort+1, 3); + g_cmsEmu->portWrite(cmsPort, table->ampl[3]); + g_cmsEmu->portWrite(cmsPort+1, 8); + g_cmsEmu->portWrite(cmsPort, table->freq[0]); + g_cmsEmu->portWrite(cmsPort+1, 9); + g_cmsEmu->portWrite(cmsPort, table->freq[1]); + g_cmsEmu->portWrite(cmsPort+1, 10); + g_cmsEmu->portWrite(cmsPort, table->freq[2]); + g_cmsEmu->portWrite(cmsPort+1, 11); + g_cmsEmu->portWrite(cmsPort, table->freq[3]); + g_cmsEmu->portWrite(cmsPort+1, 0x10); + g_cmsEmu->portWrite(cmsPort, table->octave[0]); + g_cmsEmu->portWrite(cmsPort+1, 0x11); + g_cmsEmu->portWrite(cmsPort, table->octave[1]); + g_cmsEmu->portWrite(cmsPort+1, 0x14); + g_cmsEmu->portWrite(cmsPort, 0x3F); + g_cmsEmu->portWrite(cmsPort+1, 0x15); + g_cmsEmu->portWrite(cmsPort, 0x00); + ++table; + } while ((cmsPort & 2) == 0); +} + +void Player_V2CMS::mutex_up() { + _mutex.lock(); +} + +void Player_V2CMS::mutex_down() { + _mutex.unlock(); +} +} // end of namespace Scumm diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index a3b1a5be77..8359675032 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -787,8 +787,6 @@ void ResourceManager::setResourceCounter(int type, int idx, byte flag) { #define SAFETY_AREA 2 byte *ResourceManager::createResource(int type, int idx, uint32 size) { - byte *ptr; - debugC(DEBUG_RESOURCE, "_res->createResource(%s,%d,%d)", resTypeFromId(type), idx, size); if (!validateResource("allocating", type, idx)) @@ -807,17 +805,17 @@ byte *ResourceManager::createResource(int type, int idx, uint32 size) { expireResources(size); - ptr = (byte *)calloc(size + sizeof(MemBlkHeader) + SAFETY_AREA, 1); + void *ptr = calloc(size + sizeof(MemBlkHeader) + SAFETY_AREA, 1); if (ptr == NULL) { error("createResource(%s,%d): Out of memory while allocating %d", resTypeFromId(type), idx, size); } _allocatedSize += size; - address[type][idx] = ptr; + address[type][idx] = (byte *)ptr; ((MemBlkHeader *)ptr)->size = size; setResourceCounter(type, idx, 1); - return ptr + sizeof(MemBlkHeader); /* skip header */ + return (byte *)ptr + sizeof(MemBlkHeader); /* skip header */ } ResourceManager::ResourceManager(ScummEngine *vm) { @@ -1378,7 +1376,7 @@ const byte *ResourceIterator::findNext(uint32 tag) { const byte *ScummEngine::findResource(uint32 tag, const byte *searchin) { uint32 curpos, totalsize, size; - debugC(DEBUG_RESOURCE, "findResource(%s, %lx)", tag2str(tag), searchin); + debugC(DEBUG_RESOURCE, "findResource(%s, %p)", tag2str(tag), (const void *)searchin); if (!searchin) { if (_game.heversion >= 70) { diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index fe38bbf82f..c6ed7b71cc 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1596,6 +1596,13 @@ void ScummEngine::setupMusic(int midi) { case MD_PCJR: _musicType = MDT_PCSPK; break; + case MD_CMS: +#if 1 + _musicType = MDT_ADLIB; +#else + _musicType = MDT_CMS; // Still has number of bugs, disable by default +#endif + break; case MD_TOWNS: _musicType = MDT_TOWNS; break; @@ -1650,7 +1657,7 @@ void ScummEngine::setupMusic(int midi) { * automatically when samples need to be generated */ if (!_mixer->isReady()) { warning("Sound mixer initialization failed"); - if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK) { + if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_CMS) { midiDriver = MD_NULL; _musicType = MDT_NONE; warning("MIDI driver depends on sound mixer, switching to null MIDI driver"); @@ -1680,6 +1687,8 @@ void ScummEngine::setupMusic(int midi) { _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); } else if ((_musicType == MDT_PCSPK) && (_game.version > 2 && _game.version <= 4)) { _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); + } else if (_musicType == MDT_CMS) { + _musicEngine = new Player_V2CMS(this, _mixer); } else if (_game.platform == Common::kPlatform3DO && _game.heversion == 61) { // 3DO versions use digital music and sound samples. } else if (_game.version >= 3 && _game.heversion <= 61) { diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 9682e5e1ee..badbb8ba9d 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -128,7 +128,7 @@ enum GameFeatures { }; /* SCUMM Debug Channels */ -void debugC(int level, const char *s, ...); +void debugC(int level, const char *s, ...) GCC_PRINTF(2, 3); enum { DEBUG_GENERAL = 1 << 0, // General debug @@ -528,7 +528,7 @@ protected: void versionDialog(); void scummMenuDialog(); - char displayMessage(const char *altButton, const char *message, ...); + char displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); byte _fastMode; @@ -543,15 +543,13 @@ public: // VAR is a wrapper around scummVar, which attempts to include additional // useful information should an illegal var access be detected. #define VAR(x) scummVar(x, #x, __FILE__, __LINE__) - int32& scummVar(byte var, const char *varName, const char *file, int line) - { + int32& scummVar(byte var, const char *varName, const char *file, int line) { if (var == 0xFF) { error("Illegal access to variable %s in file %s, line %d", varName, file, line); } return _scummVars[var]; } - int32 scummVar(byte var, const char *varName, const char *file, int line) const - { + int32 scummVar(byte var, const char *varName, const char *file, int line) const { if (var == 0xFF) { error("Illegal access to variable %s in file %s, line %d", varName, file, line); } diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp index e39397eded..c1167a57c1 100644 --- a/engines/scumm/smush/imuse_channel.cpp +++ b/engines/scumm/smush/imuse_channel.cpp @@ -158,7 +158,7 @@ void ImuseChannel::decode() { _sbufferSize -= remaining_size; } else { debugC(DEBUG_SMUSH, "impossible ! : %p, %d, %d, %p(%d), %p(%d, %d)", - this, _dataSize, _inData, _tbuffer, _tbufferSize, _sbuffer, _sbufferSize, _srbufferSize); + (const void *)this, _dataSize, _inData, _tbuffer, _tbufferSize, _sbuffer, _sbufferSize, _srbufferSize); byte *old = _tbuffer; int new_size = remaining_size + _tbufferSize; _tbuffer = new byte[new_size]; diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index f1be5e0b17..ad48029bd2 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -1181,7 +1181,7 @@ int ScummEngine::readSoundResource(int idx) { break; } - if ((_musicType == MDT_PCSPK) && pri != 11) + if ((_musicType == MDT_PCSPK || _musicType == MDT_CMS) && pri != 11) pri = -1; debugC(DEBUG_RESOURCE, " tag: %s, total_size=%d, pri=%d", tag2str(tag), size, pri); @@ -1710,7 +1710,7 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, in } else { dw = 500000 * 256 / ticks; } - debugC(DEBUG_SOUND, " ticks = %d, speed = %ld", ticks, dw); + debugC(DEBUG_SOUND, " ticks = %d, speed = %d", ticks, dw); // Write a tempo change Meta event memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4; @@ -2121,6 +2121,19 @@ int ScummEngine::readSoundResourceSmallHeader(int idx) { _fileHandle->read(_res->createResource(rtSound, idx, wa_size + 6), wa_size + 6); } return 1; + } else if (_musicType == MDT_CMS && ad_offs != 0) { + if (_game.features & GF_OLD_BUNDLE) { + _fileHandle->seek(wa_offs + wa_size + 6, SEEK_SET); + byte musType = _fileHandle->readByte(); + + if (musType == 0x80) { + _fileHandle->seek(ad_offs, SEEK_SET); + _fileHandle->read(_res->createResource(rtSound, idx, ad_size), ad_size); + } else { + _fileHandle->seek(wa_offs, SEEK_SET); + _fileHandle->read(_res->createResource(rtSound, idx, wa_size), wa_size); + } + } } else if (ad_offs != 0) { // AD resources have a header, instrument definitions and one MIDI track. // We build an 'ADL ' resource from that: diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp index 631c88ffa6..22487b43a3 100644 --- a/engines/scumm/vars.cpp +++ b/engines/scumm/vars.cpp @@ -706,6 +706,9 @@ void ScummEngine::resetScummVars() { case MDT_PCSPK: VAR(VAR_SOUNDCARD) = 0; break; + case MDT_CMS: + VAR(VAR_SOUNDCARD) = 2; + break; case MDT_ADLIB: VAR(VAR_SOUNDCARD) = 3; break; @@ -724,7 +727,7 @@ void ScummEngine::resetScummVars() { // Value only used by the Macintosh version of Indiana Jones and the Last Crusade else if (_game.platform == Common::kPlatformMacintosh && _game.version == 3) VAR(VAR_VIDEOMODE) = 50; - // Value only used by the Amiga of Monkey Island 2 + // Value only used by the Amiga version of Monkey Island 2 else if (_game.platform == Common::kPlatformAmiga) VAR(VAR_VIDEOMODE) = 82; else if (_renderMode == Common::kRenderCGA) diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp index 764f3de9dd..4b5887da69 100644 --- a/engines/sky/control.cpp +++ b/engines/sky/control.cpp @@ -1115,7 +1115,7 @@ void Control::doAutoSave(void) { outf->finalize(); if (outf->err()) - displayMessage(0, "Unable to write autosave file '%s'. Disk full?", fName, _saveFileMan->popErrorDesc().c_str()); + displayMessage(0, "Unable to write autosave file '%s'. Disk full? (%s)", fName, _saveFileMan->popErrorDesc().c_str()); delete outf; free(saveData); diff --git a/engines/sky/control.h b/engines/sky/control.h index 2a3a229cb3..04ed26fefe 100644 --- a/engines/sky/control.h +++ b/engines/sky/control.h @@ -198,7 +198,7 @@ public: void saveDescriptions(const Common::StringList &list); private: - int displayMessage(const char *altButton, const char *message, ...); + int displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); void initPanel(void); void removePanel(void); diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp index 55c61b8665..1a14703972 100644 --- a/engines/sky/detection.cpp +++ b/engines/sky/detection.cpp @@ -45,21 +45,22 @@ struct SkyVersion { int dataDiskSize; const char *extraDesc; int version; + uint32 guioptions; }; // TODO: Would be nice if Disk::determineGameVersion() used this table, too. static const SkyVersion skyVersions[] = { - { 232, -1, "floppy demo", 272 }, // German - { 243, -1, "pc gamer demo", 109 }, - { 247, -1, "floppy demo", 267 }, // English - { 1404, -1, "floppy", 288 }, - { 1413, -1, "floppy", 303 }, - { 1445, 8830435, "floppy", 348 }, - { 1445, -1, "floppy", 331 }, - { 1711, -1, "cd demo", 365 }, - { 5099, -1, "cd", 368 }, - { 5097, -1, "cd", 372 }, - { 0, 0, 0, 0 } + { 232, -1, "floppy demo", 272, Common::GUIO_NOSPEECH }, // German + { 243, -1, "pc gamer demo", 109, Common::GUIO_NOSPEECH }, + { 247, -1, "floppy demo", 267, Common::GUIO_NOSPEECH }, // English + { 1404, -1, "floppy", 288, Common::GUIO_NOSPEECH }, + { 1413, -1, "floppy", 303, Common::GUIO_NOSPEECH }, + { 1445, 8830435, "floppy", 348, Common::GUIO_NOSPEECH }, + { 1445, -1, "floppy", 331, Common::GUIO_NOSPEECH }, + { 1711, -1, "cd demo", 365, Common::GUIO_NONE }, + { 5099, -1, "cd", 368, Common::GUIO_NONE }, + { 5097, -1, "cd", 372, Common::GUIO_NONE }, + { 0, 0, 0, 0, 0 } }; class SkyMetaEngine : public MetaEngine { @@ -155,6 +156,7 @@ GameList SkyMetaEngine::detectGames(const Common::FSList &fslist) const { char buf[32]; snprintf(buf, sizeof(buf), "v0.0%d %s", sv->version, sv->extraDesc); dg.updateDesc(buf); + dg.setGUIOptions(sv->guioptions); break; } ++sv; diff --git a/engines/sword1/control.h b/engines/sword1/control.h index d6adc61c3a..0193afc7f1 100644 --- a/engines/sword1/control.h +++ b/engines/sword1/control.h @@ -101,7 +101,7 @@ public: } private: - int displayMessage(const char *altButton, const char *message, ...); + int displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); bool convertSaveGame(uint8 slot, char* desc); void showSavegameNames(void); diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index d78c6259f9..b0db320d86 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -37,27 +37,32 @@ #include "engines/metaengine.h" /* Broken Sword 1 */ -static const PlainGameDescriptor sword1FullSettings = - {"sword1", "Broken Sword 1: The Shadow of the Templars"}; -static const PlainGameDescriptor sword1DemoSettings = - {"sword1demo", "Broken Sword 1: The Shadow of the Templars (Demo)"}; -static const PlainGameDescriptor sword1MacFullSettings = - {"sword1mac", "Broken Sword 1: The Shadow of the Templars (Mac)"}; -static const PlainGameDescriptor sword1MacDemoSettings = - {"sword1macdemo", "Broken Sword 1: The Shadow of the Templars (Mac demo)"}; -static const PlainGameDescriptor sword1PSXSettings = - {"sword1psx", "Broken Sword 1: The Shadow of the Templars (PlayStation)"}; +static const PlainGameDescriptorGUIOpts sword1FullSettings = + {"sword1", "Broken Sword 1: The Shadow of the Templars", Common::GUIO_NOMIDI}; +static const PlainGameDescriptorGUIOpts sword1DemoSettings = + {"sword1demo", "Broken Sword 1: The Shadow of the Templars (Demo)", Common::GUIO_NOMIDI}; +static const PlainGameDescriptorGUIOpts sword1MacFullSettings = + {"sword1mac", "Broken Sword 1: The Shadow of the Templars (Mac)", Common::GUIO_NOMIDI}; +static const PlainGameDescriptorGUIOpts sword1MacDemoSettings = + {"sword1macdemo", "Broken Sword 1: The Shadow of the Templars (Mac demo)", Common::GUIO_NOMIDI}; +static const PlainGameDescriptorGUIOpts sword1PSXSettings = + {"sword1psx", "Broken Sword 1: The Shadow of the Templars (PlayStation)", Common::GUIO_NOMIDI}; +static const PlainGameDescriptorGUIOpts sword1PSXDemoSettings = + {"sword1psxdemo", "Broken Sword 1: The Shadow of the Templars (PlayStation demo)", Common::GUIO_NOMIDI}; + // check these subdirectories (if present) -static const char *g_dirNames[] = { "clusters", "speech" }; +static const char *g_dirNames[] = { "clusters", "speech", "english", "italian"}; #define NUM_COMMON_FILES_TO_CHECK 1 #define NUM_PC_FILES_TO_CHECK 3 #define NUM_MAC_FILES_TO_CHECK 4 -#define NUM_PSX_FILES_TO_CHECK 2 +#define NUM_PSX_FILES_TO_CHECK 1 +#define NUM_PSX_DEMO_FILES_TO_CHECK 2 #define NUM_DEMO_FILES_TO_CHECK 1 #define NUM_MAC_DEMO_FILES_TO_CHECK 1 -#define NUM_FILES_TO_CHECK NUM_COMMON_FILES_TO_CHECK + NUM_PC_FILES_TO_CHECK + NUM_MAC_FILES_TO_CHECK + NUM_PSX_FILES_TO_CHECK + NUM_DEMO_FILES_TO_CHECK + NUM_MAC_DEMO_FILES_TO_CHECK + +#define NUM_FILES_TO_CHECK NUM_COMMON_FILES_TO_CHECK + NUM_PC_FILES_TO_CHECK + NUM_MAC_FILES_TO_CHECK + NUM_PSX_FILES_TO_CHECK + NUM_DEMO_FILES_TO_CHECK + NUM_MAC_DEMO_FILES_TO_CHECK + NUM_PSX_DEMO_FILES_TO_CHECK static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to be found "swordres.rif", // Mac, PC and PSX version "general.clu", // PC and PSX version @@ -69,6 +74,7 @@ static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to "paris2.clm", // Mac version (full game only) "cows.mad", // this one should only exist in the demo version "scripts.clm", // Mac version both demo and full game + "train.plx", // PSX version only "speech.dat", // PSX version only "tunes.dat", // PSX version only // the engine needs several more files to work, but checking these should be sufficient @@ -119,6 +125,8 @@ GameList SwordMetaEngine::getSupportedGames() const { games.push_back(sword1DemoSettings); games.push_back(sword1MacFullSettings); games.push_back(sword1MacDemoSettings); + games.push_back(sword1PSXSettings); + games.push_back(sword1PSXDemoSettings); return games; } @@ -133,6 +141,8 @@ GameDescriptor SwordMetaEngine::findGame(const char *gameid) const { return sword1MacDemoSettings; if (0 == scumm_stricmp(gameid, sword1PSXSettings.gameid)) return sword1PSXSettings; + if (0 == scumm_stricmp(gameid, sword1PSXDemoSettings.gameid)) + return sword1PSXDemoSettings; return GameDescriptor(); } @@ -168,6 +178,7 @@ GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const { bool demoFilesFound = true; bool macDemoFilesFound = true; bool psxFilesFound = true; + bool psxDemoFilesFound = true; for (i = 0; i < NUM_COMMON_FILES_TO_CHECK; i++) if (!filesFound[i]) mainFilesFound = false; @@ -186,11 +197,16 @@ GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const { for (j = 0; j < NUM_PSX_FILES_TO_CHECK; i++, j++) if (!filesFound[i]) psxFilesFound = false; + for (j = 0; j < NUM_PSX_DEMO_FILES_TO_CHECK; i++, j++) + if (!filesFound[i] || psxFilesFound) + psxDemoFilesFound = false; if (mainFilesFound && pcFilesFound && demoFilesFound) detectedGames.push_back(sword1DemoSettings); else if (mainFilesFound && pcFilesFound && psxFilesFound) detectedGames.push_back(sword1PSXSettings); + else if (mainFilesFound && pcFilesFound && psxDemoFilesFound) + detectedGames.push_back(sword1PSXDemoSettings); else if (mainFilesFound && pcFilesFound && !psxFilesFound) detectedGames.push_back(sword1FullSettings); else if (mainFilesFound && macFilesFound) diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp index 8b033d9e8d..7e911bd197 100644 --- a/engines/sword1/logic.cpp +++ b/engines/sword1/logic.cpp @@ -524,7 +524,7 @@ int Logic::interpretScript(Object *compact, int id, Header *scriptModule, int sc case IT_PUSHVARIABLE: debug(9, "IT_PUSHVARIABLE: ScriptVar[%d] => %d", scriptCode[pc], _scriptVars[scriptCode[pc]]); varNum = scriptCode[pc++]; - if (SwordEngine::_systemVars.isDemo) { + if (SwordEngine::_systemVars.isDemo && SwordEngine::isPc()) { if (varNum >= 397) // BS1 Demo has different number of script variables varNum++; if (varNum >= 699) @@ -615,7 +615,7 @@ int Logic::interpretScript(Object *compact, int id, Header *scriptModule, int sc case IT_POPVAR: // pop a variable debug(9, "IT_POPVAR: ScriptVars[%d] = %d", scriptCode[pc], stack[stackIdx-1]); varNum = scriptCode[pc++]; - if (SwordEngine::_systemVars.isDemo) { + if (SwordEngine::_systemVars.isDemo && SwordEngine::isPc()) { if (varNum >= 397) // BS1 Demo has different number of script variables varNum++; if (varNum >= 699) diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp index feb48b0750..fb9068dde7 100644 --- a/engines/sword1/music.cpp +++ b/engines/sword1/music.cpp @@ -272,7 +272,7 @@ bool MusicHandle::playPSX(uint16 id, bool loop) { tableFile.close(); - if (size != 0xffffffff) { + if ((size != 0) && (size != 0xffffffff)) { _file.seek(offset, SEEK_SET); _audioSource = new Audio::VagStream(_file.readStream(size), loop); fadeUp(); diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp index 1f2ad04f08..5577c66fc6 100644 --- a/engines/sword1/sound.cpp +++ b/engines/sword1/sound.cpp @@ -225,13 +225,15 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) { warning ("Could not open speech.inf"); return false; } + + uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes uint16 numLines = file.readUint16LE(); uint16 roomOffset = file.readUint16LE(); - file.seek(0x112 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the 0x112 byte header too. + file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too. locIndex = 0xFFFFFFFF; diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index 18a3f2a7c4..3796ceefd6 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -48,7 +48,9 @@ SystemVars SwordEngine::_systemVars; SwordEngine::SwordEngine(OSystem *syst) : Engine(syst) { - if (!scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1demo")) + if (!scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1demo") || + !scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1psxdemo") || + !scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo")) _features = GF_DEMO; else _features = 0; @@ -59,11 +61,14 @@ SwordEngine::SwordEngine(OSystem *syst) Common::File::addDefaultDirectory(_gameDataDir.getChild("SPEECH")); Common::File::addDefaultDirectory(_gameDataDir.getChild("VIDEO")); Common::File::addDefaultDirectory(_gameDataDir.getChild("SMACKSHI")); + Common::File::addDefaultDirectory(_gameDataDir.getChild("ENGLISH"));//PSX Demo + Common::File::addDefaultDirectory(_gameDataDir.getChild("ITALIAN"));//PSX Demo Common::File::addDefaultDirectory(_gameDataDir.getChild("clusters")); Common::File::addDefaultDirectory(_gameDataDir.getChild("music")); Common::File::addDefaultDirectory(_gameDataDir.getChild("speech")); Common::File::addDefaultDirectory(_gameDataDir.getChild("video")); Common::File::addDefaultDirectory(_gameDataDir.getChild("smackshi")); + } SwordEngine::~SwordEngine() { @@ -85,7 +90,8 @@ Common::Error SwordEngine::init() { if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") || 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") ) _systemVars.platform = Common::kPlatformMacintosh; - else if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1psx")) + else if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1psx") || + 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1psxdemo") ) _systemVars.platform = Common::kPlatformPSX; else _systemVars.platform = Common::kPlatformWindows; @@ -321,17 +327,17 @@ const CdFile SwordEngine::_psxCdFileList[] = { // PSX edition has only one cd { "syria.clu", FLAG_CD1 }, { "train.clu", FLAG_CD1 }, { "train.plx", FLAG_CD1 }, - { "compacts.clu", FLAG_CD1 | FLAG_IMMED }, - { "general.clu", FLAG_CD1 | FLAG_IMMED }, - { "maps.clu", FLAG_CD1 }, - { "paris1.clu", FLAG_CD1 }, - { "scripts.clu", FLAG_CD1 | FLAG_IMMED }, - { "swordres.rif", FLAG_CD1 | FLAG_IMMED }, - { "text.clu", FLAG_CD1 }, - { "speech.dat", FLAG_SPEECH1 }, - { "speech.tab", FLAG_SPEECH1 }, - { "speech.inf", FLAG_SPEECH1 }, - { "speech.lis", FLAG_SPEECH1 } + { "compacts.clu", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "general.clu", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "maps.clu", FLAG_CD1 | FLAG_DEMO }, + { "paris1.clu", FLAG_CD1 | FLAG_DEMO}, + { "scripts.clu", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "swordres.rif", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "text.clu", FLAG_CD1 | FLAG_DEMO }, + { "speech.dat", FLAG_SPEECH1 | FLAG_DEMO }, + { "speech.tab", FLAG_SPEECH1 | FLAG_DEMO }, + { "speech.inf", FLAG_SPEECH1 | FLAG_DEMO }, + { "speech.lis", FLAG_SPEECH1 | FLAG_DEMO } }; void SwordEngine::showFileErrorMsg(uint8 type, bool *fileExists) { @@ -439,8 +445,9 @@ void SwordEngine::checkCdFiles(void) { // check if we're running from cd, hdd or if (Common::File::exists(_psxCdFileList[fcnt].name)) { fileExists[fcnt] = true; flagsToBool(foundTypes, _psxCdFileList[fcnt].flags); - isFullVersion = true; - cd2FilesFound = true; + if (!(_psxCdFileList[fcnt].flags & FLAG_DEMO)) + isFullVersion = true; + cd2FilesFound = true; } else { flagsToBool(missingTypes, _psxCdFileList[fcnt].flags); fileExists[fcnt] = false; diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h index 6c336a35ae..4877f99582 100644 --- a/engines/sword1/sword1.h +++ b/engines/sword1/sword1.h @@ -83,6 +83,7 @@ public: static bool isMac() { return _systemVars.platform == Common::kPlatformMacintosh; } static bool isPsx() { return _systemVars.platform == Common::kPlatformPSX; } + static bool isPc() { return _systemVars.platform == Common::kPlatformPC; } protected: // Engine APIs diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h index 2f72b75980..166245c6ef 100644 --- a/engines/sword2/screen.h +++ b/engines/sword2/screen.h @@ -423,8 +423,8 @@ public: void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow); void setSystemPalette(const byte *colors, uint start, uint num); uint8 quickMatch(uint8 r, uint8 g, uint8 b); - int32 fadeUp(float time = 0.75); - int32 fadeDown(float time = 0.75); + int32 fadeUp(float time = 0.75f); + int32 fadeDown(float time = 0.75f); uint8 getFadeStatus(); void dimPalette(bool dim); void waitForFade(); diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index c840a50f0a..cf44b4c99c 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -148,7 +148,7 @@ GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { if (0 == scumm_stricmp(g->detectname, fileName)) { // Match found, add to list of candidates, then abort inner loop. - detectedGames.push_back(GameDescriptor(g->gameid, g->description)); + detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, Common::GUIO_NOMIDI)); break; } } diff --git a/engines/tinsel/actors.h b/engines/tinsel/actors.h index 74a5ba4185..bda0e8bbb3 100644 --- a/engines/tinsel/actors.h +++ b/engines/tinsel/actors.h @@ -137,8 +137,6 @@ int GetActorFilmNumber(int ano); void StoreActorReel(int actor, int column, OBJECT *pObj); void NotPlayingReel(int actor, int filmNumber, int column); bool ActorReelPlaying(int actor, int column); -void SetActorPlayFilm(int ano, SCNHANDLE hFilm); -SCNHANDLE GetActorPlayFilm(int ano); /*----------------------------------------------------------------------*/ @@ -161,8 +159,6 @@ struct Z_POSITIONS { int z; }; -int SaveActors(SAVED_ACTOR *sActorInfo); - void RestoreActorProcess(int id, INT_CONTEXT *pic); int SaveActors(PSAVED_ACTOR sActorInfo); diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index a36c35f10e..3ca8adf30d 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -77,6 +77,9 @@ static const PlainGameDescriptor tinselGames[] = { namespace Tinsel { +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; + static const TinselGameDescription gameDescriptions[] = { // Note: The following is the (hopefully) definitive list of version details: @@ -97,7 +100,8 @@ static const TinselGameDescription gameDescriptions[] = { //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NOSPEECH }, GID_DW1, 0, @@ -115,7 +119,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_DW1, 0, @@ -130,7 +135,8 @@ static const TinselGameDescription gameDescriptions[] = { AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NOSPEECH }, GID_DW1, 0, @@ -148,7 +154,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -172,7 +179,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + GUIO_NONE }, GID_DW1, 0, @@ -194,7 +202,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + GUIO_NONE }, GID_DW1, 0, @@ -216,7 +225,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + GUIO_NONE }, GID_DW1, 0, @@ -238,7 +248,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_DROPLANGUAGE + ADGF_DROPLANGUAGE, + GUIO_NONE }, GID_DW1, 0, @@ -257,7 +268,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -276,7 +288,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::HB_ISR, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -284,21 +297,18 @@ static const TinselGameDescription gameDescriptions[] = { TINSEL_V1, }, - { // UK multilanguage PSX CD + { // Discworld PSX CD { "dw", "CD", { - {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273918}, - {"german.txt", 0, "6e2c0f0655bc3cec5a6b3552164ec984", 263942}, - {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239830}, - {"spanish.txt", 0, "bda9bea9078d1483409082a3e180378a", 236702}, {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, {NULL, 0, NULL, 0} }, Common::EN_ANY, Common::kPlatformPSX, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -320,7 +330,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPSX, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, GID_DW1, 0, @@ -340,7 +351,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -357,7 +369,8 @@ static const TinselGameDescription gameDescriptions[] = { AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW1, 0, @@ -376,7 +389,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_GRB, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -395,7 +409,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::EN_USA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -414,7 +429,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -433,7 +449,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -453,7 +470,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -472,7 +490,8 @@ static const TinselGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -486,13 +505,14 @@ static const TinselGameDescription gameDescriptions[] = { "CD", { {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, "aa8d05f6fade11e6f066d42c302c8e89", 250926923}, + {"english1.smp", 0, NULL, -1}, {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, {NULL, 0, NULL, 0} }, Common::RU_RUS, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, GID_DW2, 0, @@ -521,7 +541,9 @@ static const ADParams detectionParams = { // List of files for file-based fallback detection (optional) 0, // Flags - 0 + 0, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class TinselMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tinsel/palette.cpp b/engines/tinsel/palette.cpp index c544bddbb1..8df9e9a375 100644 --- a/engines/tinsel/palette.cpp +++ b/engines/tinsel/palette.cpp @@ -99,6 +99,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) { bool colorFound = false; uint16 clutEntry = 0; + // Empty the table with color correspondences memset(mapperTable, 0, 16); for (int j = 1; j < 16; j++) { @@ -115,7 +116,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) { uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3); if (psxEquivalent == clutEntry) { - mapperTable[j] = i + 1; + mapperTable[j] = i + 1; // Add entry in the table for the found color colorFound = true; } } diff --git a/engines/tinsel/pdisplay.cpp b/engines/tinsel/pdisplay.cpp index e0262839a2..17e9a3a517 100644 --- a/engines/tinsel/pdisplay.cpp +++ b/engines/tinsel/pdisplay.cpp @@ -55,14 +55,6 @@ extern int newestString; // The overrun counter, in STRRES.C #endif -//----------------- EXTERNAL FUNCTIONS --------------------- - -// in BG.C -extern int BgWidth(void); -extern int BgHeight(void); - - - //----------------- LOCAL DEFINES -------------------- #define LPOSX 295 // X-co-ord of lead actor's position display diff --git a/engines/tinsel/polygons.h b/engines/tinsel/polygons.h index 62ec0422c6..7cb22a1b8a 100644 --- a/engines/tinsel/polygons.h +++ b/engines/tinsel/polygons.h @@ -92,7 +92,6 @@ bool IsPolyCorner(HPOLYGON hPath, int x, int y); int GetScale(HPOLYGON path, int y); int GetBrightness(HPOLYGON hPath, int y); void getNpathNode(HPOLYGON npath, int node, int *px, int *py); -void GetTagTag(HPOLYGON p, SCNHANDLE *hTagText, int *tagx, int *tagy); SCNHANDLE GetPolyFilm(HPOLYGON p); void GetPolyNode(HPOLYGON hp, int *pNodeX, int *pNodeY); SCNHANDLE GetPolyScript(HPOLYGON p); @@ -108,8 +107,6 @@ void DisablePath(int path); void EnablePath(int path); void DisableRefer(int refer); void EnableRefer(int refer); -void DisableBlock(int blockno); -void EnableBlock(int blockno); HPOLYGON GetTagHandle(int tagno); void DisableTag(CORO_PARAM, int tag); void EnableTag(CORO_PARAM, int tag); @@ -152,8 +149,7 @@ bool PolyTagIsWanted(HPOLYGON hp); bool PolyTagFollowsCursor(HPOLYGON hp); SCNHANDLE GetPolyTagHandle(HPOLYGON hp); bool IsTagPolygon(int tagno); -int GetTagPolyId(HPOLYGON hp); -void GetPolyMidBottom( HPOLYGON hp, int *pX, int *pY); +void GetPolyMidBottom(HPOLYGON hp, int *pX, int *pY); int PathCount(void); void MovePolygon(PTYPE ptype, int id, int x, int y); void MovePolygonTo(PTYPE ptype, int id, int x, int y); diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index a07a417723..c6d30fa222 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -41,6 +41,9 @@ #include "sound/mixer.h" #include "sound/adpcm.h" #include "sound/vag.h" +#include "sound/flac.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" #include "gui/message.h" @@ -52,7 +55,9 @@ extern LANGUAGE sampleLanguage; SoundManager::SoundManager(TinselEngine *vm) : //_vm(vm), // TODO: Enable this once global _vm var is gone - _sampleIndex(0), _sampleIndexLen(0) { + _sampleIndex(0), _sampleIndexLen(0), + _soundMode(kVOCMode) + { for (int i = 0; i < kNumChannels; i++) _channels[i].sampleNum = _channels[i].subSample = -1; @@ -68,6 +73,7 @@ SoundManager::~SoundManager() { * @param type type of sound (voice or sfx) * @param handle sound handle */ +// playSample for DiscWorld 1 bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { // Floppy version has no sample file if (_vm->getFeatures() & GF_FLOPPY) @@ -114,7 +120,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound _vm->_mixer->playInputStream(type, &curChan.handle, vagStream); } else { // allocate a buffer - void *sampleBuf = malloc(sampleLen); + byte *sampleBuf = (byte *)malloc(sampleLen); assert(sampleBuf); // read all of the sample @@ -126,10 +132,35 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound //_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volVoice); + Common::MemoryReadStream *compressedStream = + new Common::MemoryReadStream(sampleBuf, sampleLen, true); + Audio::AudioStream *sampleStream = 0; // play it - _vm->_mixer->playRaw(type, &curChan.handle, sampleBuf, sampleLen, 22050, - Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + switch (_soundMode) { + case kMP3Mode: + #ifdef USE_MAD + sampleStream = Audio::makeMP3Stream(compressedStream, true); + #endif + break; + case kVorbisMode: + #ifdef USE_VORBIS + sampleStream = Audio::makeVorbisStream(compressedStream, true); + #endif + break; + case kFlacMode: + #ifdef USE_FLAC + sampleStream = Audio::makeFlacStream(compressedStream, true); + #endif + break; + default: + _vm->_mixer->playRaw(type, &curChan.handle, sampleBuf, sampleLen, 22050, + Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + break; + } + if (sampleStream) { + _vm->_mixer->playInputStream(type, &curChan.handle, sampleStream); + } } if (handle) @@ -138,6 +169,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound return true; } +// playSample for DiscWorld 2 bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int priority, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { @@ -251,10 +283,30 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p if (_sampleStream.read(sampleBuf, sampleLen) != sampleLen) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); - Common::MemoryReadStream *sampleStream = + Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(sampleBuf, sampleLen, true); - Audio::AudioStream *_stream = - makeADPCMStream(sampleStream, true, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); + Audio::AudioStream *sampleStream = 0; + + switch (_soundMode) { + case kMP3Mode: + #ifdef USE_MAD + sampleStream = Audio::makeMP3Stream(compressedStream, true); + #endif + break; + case kVorbisMode: + #ifdef USE_VORBIS + sampleStream = Audio::makeVorbisStream(compressedStream, true); + #endif + break; + case kFlacMode: + #ifdef USE_FLAC + sampleStream = Audio::makeFlacStream(compressedStream, true); + #endif + break; + default: + sampleStream = Audio::makeADPCMStream(compressedStream, true, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); + break; + } // FIXME: Should set this in a different place ;) _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volSound); @@ -269,10 +321,12 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p curChan->priority = priority; curChan->lastStart = g_system->getMillis(); // /---Compression----\ Milis BytesPerSecond - curChan->timeDuration = (((sampleLen * 64) / 25) * 1000) / (22050 * 2); + // not needed and won't work when using MP3/OGG/FLAC anyway + //curChan->timeDuration = (((sampleLen * 64) / 25) * 1000) / (22050 * 2); // Play it - _vm->_mixer->playInputStream(type, &curChan->handle, _stream); + _vm->_mixer->playInputStream(type, &curChan->handle, sampleStream); + _vm->_mixer->setChannelVolume(curChan->handle, sndVol); _vm->_mixer->setChannelBalance(curChan->handle, getPan(x)); @@ -455,6 +509,30 @@ void SoundManager::openSampleFiles(void) { // convert file size to size in DWORDs _sampleIndexLen /= sizeof(uint32); + + // Detect format of soundfile by looking at 1st sample-index + switch (_sampleIndex[0]) { + case MKID_BE(' 3PM'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data"); + _soundMode = kMP3Mode; + break; + + case MKID_BE(' GGO'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data"); + _soundMode = kVorbisMode; + break; + + case MKID_BE('CLAF'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data"); + _soundMode = kFlacMode; + break; + + default: + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected original sound-data"); + break; + } + // Normally the 1st sample-index points to nothing at all + _sampleIndex[0] = 0; } else { char buf[50]; sprintf(buf, CANNOT_FIND_FILE, _vm->getSampleIndex(sampleLanguage)); diff --git a/engines/tinsel/sound.h b/engines/tinsel/sound.h index 15919f8ec5..9bdd037ff0 100644 --- a/engines/tinsel/sound.h +++ b/engines/tinsel/sound.h @@ -58,6 +58,13 @@ protected: }; static const int kNumChannels = kChannelSFX + kNumSFX; + enum SoundMode { + kVOCMode, + kMP3Mode, + kVorbisMode, + kFlacMode + }; + struct Channel { // Sample handle Audio::SoundHandle handle; @@ -87,6 +94,9 @@ protected: /** Number of entries in the sample index */ long _sampleIndexLen; + /** Specifies if the sample-data is compressed and if yes, how */ + SoundMode _soundMode; + /** file stream for sample file */ TinselFile _sampleStream; diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index b73a66b6d3..4b5e0ce450 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -89,8 +89,6 @@ int clRunMode = 0; // in BG.CPP extern void ChangePalette(SCNHANDLE hPal); -extern int BgWidth(void); -extern int BgHeight(void); // in BMV.CPP void PlayBMV(CORO_PARAM, SCNHANDLE hFileStem, int myEscape); @@ -278,7 +276,6 @@ static COLORREF s_talkfontColor = 0; //----------------- FORWARD REFERENCES -------------------- static int HeldObject(void); -void Offset(EXTREME extreme, int x, int y); static void PostTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape); void ResetIdleTime(void); static void SendTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape, bool *result); diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 47602b5862..95541e3287 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -93,10 +93,6 @@ extern void InventoryProcess(CORO_PARAM, const void *); extern void PrimeBackground(); extern SCNHANDLE GetSceneHandle(void); -// In TIMER.CPP -extern void FettleTimers(void); -extern void RebootTimers(void); - //----------------- FORWARD DECLARATIONS --------------------- void SetNewScene(SCNHANDLE scene, int entrance, int transition); @@ -850,19 +846,8 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) Common::File::addDefaultDirectory(_gameDataDir.getChild("dw2")); // Add subfolders needed for psx versions of Discworld 1 - if(TinselV1PSX) { - Common::File::addDefaultDirectory(_gameDataDir.getChild("MIDI")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("SAMPLES")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXAB")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXC")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXDG")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXHL")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXMO")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXP")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXRS")); - Common::File::addDefaultDirectory(_gameDataDir.getChild("GFX").getChild("GFXTW")); - } + if (TinselV1PSX) + SearchMan.addDirectory(_gameDataDir.getPath(), _gameDataDir, 0, 3, true); const GameSettings *g; diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 75bc5c2a6e..efe09ead5e 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -39,6 +39,8 @@ static const PlainGameDescriptor toucheGames[] = { namespace Touche { +using Common::GUIO_NONE; + static const ADGameDescription gameDescriptions[] = { { // retail version "touche", @@ -46,7 +48,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "2af0177f8887e3430f345e6b4d8b1414", 26350211), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // retail version - tracker item #1601818 "touche", @@ -54,7 +57,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "95967f0b51d2e813e99ca00325098340", 26350190), Common::EN_ANY, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // retail version "touche", @@ -62,7 +66,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "1caa20bb4d4fc2ce8eb867b6610082b3", 26558232), Common::FR_FRA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // retail version - tracker item #1598643 "touche", @@ -70,7 +75,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "be2ae6454b3325e410946f2322547cd4", 26625537), Common::DE_DEU, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // retail version - tracker item #1681643 "touche", @@ -78,7 +84,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "64e95ba1decf5a5a60f8fa1840f40c62", 26529523), Common::ES_ESP, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // fan-made translation (http://www.iagtg.net/) - tracker item #1602360 "touche", @@ -86,7 +93,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "1f442331d4b327c3488a9f6ffe9bdd25", 26367792), Common::IT_ITA, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // retail version - tracker item #1800500 "touche", @@ -94,7 +102,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "42d19a0bef65465109020440a9caa228", 26487370), Common::PL_POL, Common::kPlatformPC, - ADGF_NO_FLAGS + ADGF_NO_FLAGS, + GUIO_NONE }, { // demo version "touche", @@ -102,7 +111,8 @@ static const ADGameDescription gameDescriptions[] = { AD_ENTRY1s("touche.dat", "ddaed436445b2e77294ed19e8ae4aa2c", 8720683), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO + ADGF_DEMO, + GUIO_NONE }, AD_TABLE_END_MARKER }; @@ -122,7 +132,9 @@ static const ADParams detectionParams = { 0, // no obsolete targets data "touche", Touche::fileBasedFallback, // file-based detection data to enable not yet known versions to start - kADFlagPrintWarningOnFileBasedFallback + kADFlagPrintWarningOnFileBasedFallback, + // Additional GUI options (for every game} + Common::GUIO_NONE }; class ToucheMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index 29b1e29e5a..dae9f4b39d 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -45,7 +45,8 @@ static const ADGameDescription tuckerGameDescriptions[] = { AD_ENTRY1s("infobar.txt", "f1e42a95972643462b9c3c2ea79d6683", 543), Common::FR_FRA, Common::kPlatformPC, - Tucker::kGameFlagNoSubtitles + Tucker::kGameFlagNoSubtitles, + Common::GUIO_NONE }, { "tucker", @@ -53,7 +54,8 @@ static const ADGameDescription tuckerGameDescriptions[] = { AD_ENTRY1s("infobar.txt", "9c1ddeafc5283b90d1a284bd0924831c", 462), Common::EN_ANY, Common::kPlatformPC, - Tucker::kGameFlagEncodedData + Tucker::kGameFlagEncodedData, + Common::GUIO_NONE }, { "tucker", @@ -62,6 +64,7 @@ static const ADGameDescription tuckerGameDescriptions[] = { Common::ES_ESP, Common::kPlatformPC, Tucker::kGameFlagEncodedData, + Common::GUIO_NONE }, { "tucker", @@ -69,7 +72,8 @@ static const ADGameDescription tuckerGameDescriptions[] = { AD_ENTRY1s("infobrgr.txt", "4df9eb65722418d1a1723508115b146c", 552), Common::DE_DEU, Common::kPlatformPC, - Tucker::kGameFlagEncodedData + Tucker::kGameFlagEncodedData, + Common::GUIO_NONE }, { "tucker", @@ -78,6 +82,7 @@ static const ADGameDescription tuckerGameDescriptions[] = { Common::PL_POL, Common::kPlatformPC, 0, + Common::GUIO_NONE }, { "tucker", @@ -85,7 +90,8 @@ static const ADGameDescription tuckerGameDescriptions[] = { AD_ENTRY1s("infobar.txt", "e548994877ff31ca304f6352ce022a8e", 497), Common::CZ_CZE, Common::kPlatformPC, - Tucker::kGameFlagEncodedData + Tucker::kGameFlagEncodedData, + Common::GUIO_NONE }, { "tucker", @@ -94,6 +100,7 @@ static const ADGameDescription tuckerGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | Tucker::kGameFlagDemo, + Common::GUIO_NONE }, AD_TABLE_END_MARKER }; @@ -106,7 +113,8 @@ static const ADParams detectionParams = { 0, "tucker", 0, - 0 + 0, + Common::GUIO_NONE }; static const ADGameDescription tuckerDemoGameDescription = { @@ -115,7 +123,8 @@ static const ADGameDescription tuckerDemoGameDescription = { AD_ENTRY1(0, 0), Common::EN_ANY, Common::kPlatformPC, - ADGF_DEMO | Tucker::kGameFlagDemo | Tucker::kGameFlagIntroOnly + ADGF_DEMO | Tucker::kGameFlagDemo | Tucker::kGameFlagIntroOnly, + Common::GUIO_NONE }; class TuckerMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp index ec60086abf..9faa2024a6 100644 --- a/engines/tucker/locations.cpp +++ b/engines/tucker/locations.cpp @@ -650,21 +650,17 @@ void TuckerEngine::execData3PostUpdate_locationNum8() { if (_execData3Counter > 30) { _updateLocationYPosTable2[0] = 16; _updateLocationXPosTable2[0] = 264; - } } if (_updateLocationYPosTable2[0] > 0) { const int offset = _updateLocationYPosTable2[0] * 640 + _updateLocationXPosTable2[0]; - _locationBackgroundGfxBuf[offset] = 142; - _locationBackgroundGfxBuf[offset + 640 - 1] = 143; - _locationBackgroundGfxBuf[offset + 640] = 143; - _locationBackgroundGfxBuf[offset + 640 + 1] = 144; - _locationBackgroundGfxBuf[offset + 640 * 2 - 1] = 144; - _locationBackgroundGfxBuf[offset + 640 * 2] = 144; - _locationBackgroundGfxBuf[offset + 640 * 2 + 1] = 145; - _locationBackgroundGfxBuf[offset + 640 * 3 - 1] = 147; - _locationBackgroundGfxBuf[offset + 640 * 3] = 143; - _locationBackgroundGfxBuf[offset + 640 * 3 + 1] = 147; + static const int colorsTable[] = { 143, 143, 144, 144, 144, 145, 147, 143, 147 }; + _locationBackgroundGfxBuf[offset] = 142; + for (int j = 1; j <= 3; ++j) { + for (int i = -1; i <= 1; ++i) { + _locationBackgroundGfxBuf[offset + 640 * j + i] = colorsTable[(j - 1) * 3 + i + 1]; + } + } addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0], 3, 4); _updateLocationYPosTable2[0] += 2; if (_updateLocationYPosTable2[0] > 120) { diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp index 1195fe4894..11c1c78133 100644 --- a/engines/tucker/resource.cpp +++ b/engines/tucker/resource.cpp @@ -218,6 +218,7 @@ void TuckerEngine::openCompressedSoundFile() { int version = _fCompressedSound.readUint16LE(); if (version == kCurrentCompressedSoundDataVersion) { _compressedSoundType = i; + debug(1, "Using compressed sound file '%s'", compressedSoundFilesTable[i].filename); return; } warning("Unhandled version %d for compressed sound file '%s'", version, compressedSoundFilesTable[i].filename); diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index d977813a31..11a535e54a 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -494,13 +494,9 @@ int TuckerEngine::handleSpecialObjectSelectionSequence() { AnimationSequencePlayer::AnimationSequencePlayer(OSystem *system, Audio::Mixer *mixer, Common::EventManager *event, int num) : _system(system), _mixer(mixer), _event(event), _seqNum(num) { memset(_animationPalette, 0, sizeof(_animationPalette)); - _soundSeqDataOffset = 0; _soundSeqDataCount = 0; _soundSeqDataIndex = 0; - _soundsList1Offset = 0; - _soundsList1Count = 0; - _soundsList2Offset = 0; - _soundsList2Count = 0; + _soundSeqData = 0; _offscreenBuffer = (uint8 *)malloc(kScreenWidth * kScreenHeight); _updateScreenWidth = 0; _updateScreenPicture = false; @@ -589,20 +585,9 @@ void AnimationSequencePlayer::syncTime() { } Audio::AudioStream *AnimationSequencePlayer::loadSoundFileAsStream(int index, AnimationSoundType type) { - const char *name = 0; - switch (type) { - case kAnimationSoundType8BitsRAW: - case kAnimationSoundType16BitsRAW: - name = _musicFileNamesTable[index]; - break; - case kAnimationSoundTypeWAV: - case kAnimationSoundTypeLoopingWAV: - name = _audioFileNamesTable[index]; - break; - } Audio::AudioStream *stream = 0; char fileName[64]; - snprintf(fileName, sizeof(fileName), "audio/%s", name); + snprintf(fileName, sizeof(fileName), "audio/%s", _audioFileNamesTable[index]); Common::File f; if (f.open(fileName)) { int size = 0, rate = 0; @@ -637,88 +622,53 @@ Audio::AudioStream *AnimationSequencePlayer::loadSoundFileAsStream(int index, An return stream; } -enum { - kSoundsList_Seq3_4, - kSoundsList_Seq9_10, - kSoundsList_Seq21_20, - kSoundsList_Seq13_14, - kSoundsList_Seq15_16, - kSoundsList_Seq27_28, - kSoundsList_Seq17_18, - kSoundsList_Seq19_20 -}; - void AnimationSequencePlayer::loadSounds(int num) { - static const int soundsList[][8] = { - { 1, 0, 14, 0, 10, 14, 58, 0 }, - { 1, 0, 14, 24, 5, 38, 60, 58 }, - { 1, 0, 14, 43, 9, 57, 48, 118 }, - { 6, 80, 14, 79, 4, 93, 25, 185 }, - { 7, 80, 13, 97, 9, 110, 43, 210 }, - { 10, 80, 11, 119, 0, 0, 11, 253 }, - { 8, 100, 0, 0, 0, 0, 0, 0 }, - { 0, 100, 4, 146, 0, 0, 7, 300 } - }; - int musicIndex = soundsList[num][0]; - int musicVolume = soundsList[num][1]; - _soundsList1Count = soundsList[num][2]; - _soundsList1Offset = soundsList[num][3]; - _soundsList2Count = soundsList[num][4]; - _soundsList2Offset = soundsList[num][5]; - _soundSeqDataCount = soundsList[num][6]; - _soundSeqDataOffset = soundsList[num][7]; - if (musicVolume != 0) { + if (_soundSeqDataList[num].musicVolume != 0) { Audio::AudioStream *s; - if ((s = loadSoundFileAsStream(musicIndex, kAnimationSoundType8BitsRAW)) != 0) { - _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(musicVolume)); + if ((s = loadSoundFileAsStream(_soundSeqDataList[num].musicIndex, kAnimationSoundType8BitsRAW)) != 0) { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(_soundSeqDataList[num].musicVolume)); } } _soundSeqDataIndex = 0; + _soundSeqDataCount = _soundSeqDataList[num].soundSeqDataCount; + _soundSeqData = _soundSeqDataList[num].soundSeqData; } void AnimationSequencePlayer::updateSounds() { Audio::AudioStream *s = 0; - const SoundSequenceData *p = &_soundSeqData[_soundSeqDataOffset + _soundSeqDataIndex]; + const SoundSequenceData *p = &_soundSeqData[_soundSeqDataIndex]; while (_soundSeqDataIndex < _soundSeqDataCount && p->timestamp <= _frameCounter) { switch (p->opcode) { case 0: - if (p->index < _soundsList1Count) { - if ((s = loadSoundFileAsStream(_soundsList1Offset + p->index, kAnimationSoundTypeWAV)) != 0) { - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume)); - } + if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeWAV)) != 0) { + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume)); } break; case 1: - if (p->index < _soundsList1Count) { - if ((s = loadSoundFileAsStream(_soundsList1Offset + p->index, kAnimationSoundTypeLoopingWAV)) != 0) { - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume)); - } + if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeLoopingWAV)) != 0) { + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundsHandle[p->index], s, -1, scaleMixerVolume(p->volume)); } break; case 2: - if (p->index < _soundsList1Count) { - _mixer->stopHandle(_soundsHandle[p->index]); - } + _mixer->stopHandle(_soundsHandle[p->index]); break; case 3: _mixer->stopHandle(_musicHandle); break; case 4: _mixer->stopHandle(_musicHandle); - if ((s = loadSoundFileAsStream(p->index, kAnimationSoundType8BitsRAW)) != 0) { + if ((s = loadSoundFileAsStream(p->num, kAnimationSoundType8BitsRAW)) != 0) { _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(p->volume)); } break; case 5: - if (p->index < _soundsList2Count) { - if ((s = loadSoundFileAsStream(_soundsList2Offset + p->index, kAnimationSoundTypeWAV)) != 0) { - _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, s, -1, scaleMixerVolume(p->volume)); - } + if ((s = loadSoundFileAsStream(p->num, kAnimationSoundTypeWAV)) != 0) { + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, s, -1, scaleMixerVolume(p->volume)); } break; case 6: _mixer->stopHandle(_musicHandle); - if ((s = loadSoundFileAsStream(p->index, kAnimationSoundType16BitsRAW)) != 0) { + if ((s = loadSoundFileAsStream(p->num, kAnimationSoundType16BitsRAW)) != 0) { _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, s, -1, scaleMixerVolume(p->volume)); } break; @@ -796,8 +746,7 @@ uint8 *AnimationSequencePlayer::loadPicture(const char *fileName) { } void AnimationSequencePlayer::getRGBPalette(int index) { - byte rgbPalette[3 * 256]; - memcpy(rgbPalette, _flicPlayer[index].getPalette(), 3 * 256); + const byte *rgbPalette = _flicPlayer[index].getPalette(); for (int i = 0; i < 256; i++) { _animationPalette[i * 4 + 0] = rgbPalette[i * 3 + 0]; _animationPalette[i * 4 + 1] = rgbPalette[i * 3 + 1]; diff --git a/engines/tucker/staticres.cpp b/engines/tucker/staticres.cpp index 62472e2704..b663fb38da 100644 --- a/engines/tucker/staticres.cpp +++ b/engines/tucker/staticres.cpp @@ -246,138 +246,181 @@ const uint8 TuckerEngine::_charWidthCharset2[58] = { 0x13, 0x12, 0x10, 0x11, 0x13, 0x14, 0x14, 0x10, 0x13, 0x10, }; -const SoundSequenceData AnimationSequencePlayer::_soundSeqData[] = { - { 16, 3, 1, 100 }, { 18, 5, 1, 100 }, { 26, 9, 5, 100 }, { 74, 9, 0, 100 }, - { 118, 10, 0, 100 }, { 139, 9, 0, 100 }, { 140, 10, 2, 100 }, { 144, 5, 2, 100 }, - { 146, 3, 2, 100 }, { 147, 9, 2, 100 }, { 148, 2, 1, 100 }, { 156, 0, 1, 50 }, - { 158, 4, 5, 100 }, { 188, 4, 5, 100 }, { 212, 2, 2, 100 }, { 223, 1, 0, 100 }, - { 230, 1, 2, 100 }, { 234, 1, 0, 100 }, { 251, 1, 0, 100 }, { 265, 11, 6, 80 }, - { 293, 5, 1, 80 }, { 295, 12, 6, 80 }, { 343, 13, 6, 110 }, { 373, 14, 6, 80 }, - { 429, 5, 2, 100 }, { 431, 15, 6, 80 }, { 456, 2, 1, 100 }, { 457, 1, 5, 100 }, - { 463, 0, 5, 100 }, { 482, 2, 2, 100 }, { 483, 8, 1, 100 }, { 494, 8, 5, 100 }, - { 507, 7, 5, 100 }, { 511, 7, 5, 100 }, { 522, 13, 1, 100 }, { 547, 6, 5, 100 }, - { 548, 11, 0, 100 }, { 556, 12, 0, 100 }, { 557, 2, 5, 100 }, { 599, 7, 1, 100 }, - { 639, 7, 2, 100 }, { 641, 12, 0, 100 }, { 642, 7, 5, 100 }, { 718, 14, 2, 100 }, - { 719, 1, 2, 100 }, { 720, 2, 2, 100 }, { 721, 3, 2, 100 }, { 722, 4, 2, 100 }, - { 723, 5, 2, 100 }, { 724, 6, 2, 100 }, { 725, 7, 2, 100 }, { 726, 8, 2, 100 }, - { 727, 9, 2, 100 }, { 728, 10, 2, 100 }, { 729, 11, 2, 100 }, { 730, 12, 2, 100 }, - { 731, 0, 2, 100 }, { 732, 13, 2, 100 }, - // count 2,58 - // offset 3,58 - { 2, 0, 3, 100 }, { 3, 2, 0, 100 }, { 3, 5, 1, 20 }, { 6, 25, 6, 80 }, - { 22, 1, 5, 100 }, { 37, 29, 6, 80 }, { 59, 30, 6, 80 }, { 69, 26, 6, 80 }, - { 124, 27, 6, 80 }, { 163, 28, 6, 80 }, { 197, 31, 6, 80 }, { 224, 32, 6, 80 }, - { 306, 33, 6, 80 }, { 350, 34, 6, 80 }, { 388, 8, 0, 100 }, { 389, 6, 1, 100 }, - { 390, 9, 1, 100 }, { 395, 10, 0, 100 }, { 398, 3, 0, 100 }, { 408, 3, 0, 100 }, - { 413, 4, 0, 100 }, { 418, 3, 0, 100 }, { 426, 6, 2, 100 }, { 427, 9, 2, 100 }, - { 430, 35, 6, 80 }, { 472, 36, 6, 80 }, { 514, 9, 1, 100 }, { 515, 7, 0, 100 }, - { 516, 6, 1, 100 }, { 517, 4, 0, 100 }, { 520, 11, 0, 100 }, { 523, 3, 0, 100 }, - { 531, 7, 2, 100 }, { 532, 9, 2, 100 }, { 533, 6, 2, 100 }, { 534, 3, 0, 100 }, - { 535, 37, 6, 80 }, { 553, 38, 6, 80 }, { 569, 39, 6, 80 }, { 588, 40, 6, 80 }, - { 662, 41, 6, 80 }, { 777, 42, 6, 80 }, { 978, 1, 0, 100 }, { 1008, 12, 0, 100 }, - { 1011, 4, 5, 100 }, { 1022, 52, 6, 80 }, { 1039, 3, 5, 100 }, { 1045, 3, 5, 100 }, - { 1051, 3, 5, 100 }, { 1057, 3, 5, 100 }, { 1063, 3, 5, 100 }, { 1066, 3, 5, 40 }, - { 1074, 43, 6, 80 }, { 1256, 44, 6, 80 }, { 1322, 45, 6, 80 }, { 1373, 46, 6, 80 }, - { 1419, 47, 6, 80 }, { 1792, 13, 0, 100 }, { 1793, 0, 5, 100 }, { 1895, 51, 6, 80 }, - // count 3,60 - // offset 4,118 - { 2, 0, 3, 100 }, { 4, 3, 1, 40 }, { 5, 7, 1, 20 }, { 7, 3, 5, 100 }, - { 62, 3, 2, 100 }, { 63, 48, 6, 80 }, { 198, 7, 2, 100 }, { 202, 5, 1, 100 }, - { 203, 16, 6, 80 }, { 211, 1, 5, 100 }, { 216, 0, 1, 40 }, { 217, 5, 2, 100 }, - { 218, 6, 1, 100 }, { 224, 2, 5, 100 }, { 229, 17, 6, 80 }, { 273, 6, 2, 100 }, - { 274, 4, 1, 100 }, { 275, 4, 5, 100 }, { 335, 1, 1, 100 }, { 336, 13, 0, 100 }, - { 339, 11, 0, 100 }, { 358, 0, 5, 100 }, { 364, 24, 4, 100 }, { 397, 7, 5, 100 }, - { 399, 6, 5, 100 }, { 433, 5, 5, 100 }, { 451, 13, 0, 100 }, { 459, 1, 2, 100 }, - { 508, 4, 2, 100 }, { 509, 1, 1, 100 }, { 521, 11, 0, 100 }, { 530, 8, 0, 100 }, - { 537, 9, 0, 100 }, { 557, 8, 5, 100 }, { 578, 5, 5, 100 }, { 602, 13, 0, 100 }, - { 609, 1, 2, 100 }, { 626, 12, 0, 100 }, { 628, 10, 0, 100 }, { 670, 6, 5, 100 }, - { 690, 10, 0, 100 }, { 692, 3, 5, 100 }, { 705, 11, 0, 100 }, { 710, 2, 5, 100 }, - { 714, 9, 0, 100 }, { 720, 9, 2, 100 }, { 721, 7, 5, 100 }, { 725, 0, 5, 100 }, - // count 4,48 - // offset 5,166 - { 3, 8, 0, 100 }, { 43, 11, 0, 100 }, { 68, 5, 1, 100 }, { 100, 5, 2, 100 }, - { 104, 6, 0, 100 }, { 139, 7, 0, 100 }, { 192, 3, 0, 100 }, { 199, 4, 0, 100 }, - { 207, 4, 0, 100 }, { 208, 2, 0, 100 }, { 254, 0, 0, 100 }, { 260, 0, 0, 100 }, - { 266, 0, 0, 100 }, { 272, 0, 0, 100 }, { 276, 0, 0, 100 }, { 282, 1, 0, 100 }, - { 303, 10, 0, 100 }, { 319, 12, 0, 100 }, { 355, 9, 0, 100 }, - // count 5,19 - // offset 6,185 - { 3, 0, 1, 100 }, { 34, 0, 2, 100 }, { 57, 0, 5, 100 }, { 77, 0, 5, 100 }, - { 84, 9, 0, 100 }, { 100, 9, 0, 100 }, { 140, 3, 5, 100 }, { 157, 2, 5, 100 }, - { 158, 1, 0, 100 }, { 204, 1, 5, 100 }, { 220, 2, 1, 100 }, { 235, 7, 0, 100 }, - { 236, 2, 2, 100 }, { 248, 12, 0, 100 }, { 251, 13, 0, 100 }, { 265, 11, 0, 100 }, - { 276, 11, 0, 100 }, { 310, 5, 0, 100 }, { 335, 6, 0, 100 }, { 370, 4, 0, 100 }, - { 373, 8, 0, 100 }, { 378, 8, 0, 100 }, { 434, 10, 0, 100 }, { 453, 3, 0, 100 }, - { 484, 3, 2, 100 }, - // count 6,25 - // offset 7,210 - { 3, 4, 5, 100 }, { 10, 5, 5, 100 }, { 22, 6, 5, 100 }, { 32, 7, 5, 100 }, - { 39, 6, 5, 100 }, { 48, 7, 5, 100 }, { 57, 6, 5, 100 }, { 65, 3, 0, 50 }, - { 102, 4, 0, 50 }, { 151, 2, 5, 50 }, { 205, 3, 5, 100 }, { 218, 0, 5, 100 }, - { 227, 0, 5, 100 }, { 236, 0, 5, 100 }, { 245, 0, 5, 100 }, { 254, 0, 5, 100 }, - { 263, 0, 5, 100 }, { 272, 0, 5, 100 }, { 291, 1, 1, 40 }, { 309, 8, 5, 100 }, - { 360, 8, 5, 100 }, { 384, 2, 1, 60 }, { 398, 10, 0, 100 }, { 440, 2, 2, 100 }, - { 441, 1, 2, 100 }, { 452, 11, 0, 100 }, { 466, 1, 5, 100 }, { 470, 8, 0, 100 }, - { 503, 6, 0, 100 }, { 519, 7, 0, 100 }, { 536, 8, 0, 100 }, { 538, 4, 5, 100 }, - { 549, 5, 5, 100 }, { 558, 4, 5, 100 }, { 568, 5, 5, 100 }, { 578, 4, 5, 100 }, - { 586, 5, 5, 100 }, { 593, 4, 5, 100 }, { 600, 5, 5, 100 }, { 606, 4, 5, 100 }, - { 613, 5, 5, 100 }, { 620, 9, 0, 100 }, { 630, 12, 0, 100 }, - // count 7,43 - // offset 8,253 - { 17, 2, 0, 100 }, { 57, 8, 0, 100 }, { 62, 10, 0, 100 }, { 67, 9, 0, 100 }, - { 74, 3, 1, 100 }, { 87, 3, 2, 100 }, { 85, 0, 0, 100 }, { 138, 5, 0, 100 }, - { 196, 7, 0, 100 }, { 222, 6, 0, 100 }, { 228, 1, 0, 100 }, - // count 8,11 - // offset 9,264 - { 20, 4, 0, 100 }, { 132, 0, 0, 100 }, { 145, 0, 2, 100 }, { 171, 1, 0, 100 }, - { 315, 2, 0, 50 }, { 334, 3, 0, 100 }, { 602, 5, 0, 50 }, { 631, 5, 0, 50 }, - { 660, 5, 0, 50 }, { 767, 5, 0, 50 }, { 795, 5, 0, 50 }, { 824, 5, 0, 50 }, - // count 9,12 - // offset 10,276 - { 4, 8, 1, 100 }, { 5, 6, 0, 100 }, { 47, 8, 2, 100 }, { 125, 8, 1, 100 }, - { 126, 6, 0, 100 }, { 156, 8, 2, 100 }, { 168, 2, 0, 100 }, { 174, 2, 0, 100 }, - { 180, 2, 0, 100 }, { 186, 2, 0, 100 }, { 192, 2, 0, 100 }, { 267, 2, 0, 100 }, - { 273, 2, 0, 100 }, { 279, 2, 0, 100 }, { 285, 2, 0, 100 }, { 291, 2, 0, 100 }, - { 297, 2, 0, 100 }, { 302, 0, 0, 100 }, { 417, 1, 0, 100 }, { 472, 5, 0, 100 }, - { 600, 5, 0, 100 }, { 623, 3, 0, 100 }, { 643, 9, 0, 100 }, { 781, 4, 0, 80 }, - // count 10,24 - // offset 11,300 - { 2, 0, 3, 100 }, { 3, 0, 1, 100 }, { 33, 0, 2, 100 }, { 33, 1, 0, 100 }, - { 53, 2, 1, 100 }, { 78, 2, 2, 100 }, { 80, 0, 4, 100 } - // count 11,7 +static const SoundSequenceData _soundDataSeq3_4[] = { + { 16, 3, 33, 100, 1 }, { 18, 5, 34, 100, 1 }, { 26, 9, 16, 100, 5 }, { 74, 9, 35, 100, 0 }, + { 118, 10, 36, 100, 0 }, { 139, 9, 35, 100, 0 }, { 140, 10, 0, 100, 2 }, { 144, 5, 0, 100, 2 }, + { 146, 3, 0, 100, 2 }, { 147, 9, 0, 100, 2 }, { 148, 2, 30, 100, 1 }, { 156, 0, 103, 50, 1 }, + { 158, 4, 31, 100, 5 }, { 188, 4, 31, 100, 5 }, { 212, 2, 0, 100, 2 }, { 223, 1, 20, 100, 0 }, + { 230, 1, 0, 100, 2 }, { 234, 1, 20, 100, 0 }, { 251, 1, 20, 100, 0 }, { 265, 11, 69, 80, 6 }, + { 293, 5, 34, 80, 1 }, { 295, 12, 76, 80, 6 }, { 343, 13, 87, 110, 6 }, { 373, 14, 97, 80, 6 }, + { 429, 5, 0, 100, 2 }, { 431, 15, 100, 80, 6 }, { 456, 2, 30, 100, 1 }, { 457, 1, 19, 100, 5 }, + { 463, 0, 18, 100, 5 }, { 482, 2, 0, 100, 2 }, { 483, 8, 40, 100, 1 }, { 494, 8, 37, 100, 5 }, + { 507, 7, 17, 100, 5 }, { 511, 7, 17, 100, 5 }, { 522, 13, 21, 100, 1 }, { 547, 6, 49, 100, 5 }, + { 548, 11, 48, 100, 0 }, { 556, 12, 38, 100, 0 }, { 557, 2, 23, 100, 5 }, { 599, 7, 39, 100, 1 }, + { 639, 7, 0, 100, 2 }, { 641, 12, 38, 100, 0 }, { 642, 7, 17, 100, 5 }, { 718, 14, 0, 100, 2 }, + { 719, 1, 0, 100, 2 }, { 720, 2, 0, 100, 2 }, { 721, 3, 0, 100, 2 }, { 722, 4, 0, 100, 2 }, + { 723, 5, 0, 100, 2 }, { 724, 6, 0, 100, 2 }, { 725, 7, 0, 100, 2 }, { 726, 8, 0, 100, 2 }, + { 727, 9, 0, 100, 2 }, { 728, 10, 0, 100, 2 }, { 729, 11, 0, 100, 2 }, { 730, 12, 0, 100, 2 }, + { 731, 0, 0, 100, 2 }, { 732, 13, 0, 100, 2 }, }; -const char *AnimationSequencePlayer::_musicFileNamesTable[] = { +static const SoundSequenceData _soundDataSeq9_10[] = { + { 2, 0, 0, 100, 3 }, { 3, 2, 32, 100, 0 }, { 3, 5, 54, 20, 1 }, { 6, 25, 71, 80, 6 }, + { 22, 1, 18, 100, 5 }, { 37, 29, 75, 80, 6 }, { 59, 30, 77, 80, 6 }, { 69, 26, 72, 80, 6 }, + { 124, 27, 73, 80, 6 }, { 163, 28, 74, 80, 6 }, { 197, 31, 78, 80, 6 }, { 224, 32, 79, 80, 6 }, + { 306, 33, 80, 80, 6 }, { 350, 34, 81, 80, 6 }, { 388, 8, 57, 100, 0 }, { 389, 6, 55, 100, 1 }, + { 390, 9, 58, 100, 1 }, { 395, 10, 59, 100, 0 }, { 398, 3, 52, 100, 0 }, { 408, 3, 52, 100, 0 }, + { 413, 4, 53, 100, 0 }, { 418, 3, 52, 100, 0 }, { 426, 6, 0, 100, 2 }, { 427, 9, 0, 100, 2 }, + { 430, 35, 82, 80, 6 }, { 472, 36, 83, 80, 6 }, { 514, 9, 58, 100, 1 }, { 515, 7, 56, 100, 0 }, + { 516, 6, 55, 100, 1 }, { 517, 4, 53, 100, 0 }, { 520, 11, 60, 100, 0 }, { 523, 3, 52, 100, 0 }, + { 531, 7, 0, 100, 2 }, { 532, 9, 0, 100, 2 }, { 533, 6, 0, 100, 2 }, { 534, 3, 52, 100, 0 }, + { 535, 37, 84, 80, 6 }, { 553, 38, 85, 80, 6 }, { 569, 39, 86, 80, 6 }, { 588, 40, 88, 80, 6 }, + { 662, 41, 89, 80, 6 }, { 777, 42, 90, 80, 6 }, { 978, 1, 22, 100, 0 }, { 1008, 12, 61, 100, 0 }, + { 1011, 4, 15, 100, 5 }, { 1022, 52, 99, 80, 6 }, { 1039, 3, 63, 100, 5 }, { 1045, 3, 63, 100, 5 }, + { 1051, 3, 63, 100, 5 }, { 1057, 3, 63, 100, 5 }, { 1063, 3, 63, 100, 5 }, { 1066, 3, 63, 40, 5 }, + { 1074, 43, 91, 80, 6 }, { 1256, 44, 92, 80, 6 }, { 1322, 45, 93, 80, 6 }, { 1373, 46, 94, 80, 6 }, + { 1419, 47, 95, 80, 6 }, { 1792, 13, 62, 100, 0 }, { 1793, 0, 50, 100, 5 }, { 1895, 51, 98, 80, 6 }, +}; + +static const SoundSequenceData _soundDataSeq21_20[] = { + { 2, 0, 0, 100, 3 }, { 4, 3, 34, 40, 1 }, { 5, 7, 54, 20, 1 }, { 7, 3, 51, 100, 5 }, + { 62, 3, 0, 100, 2 }, { 63, 48, 96, 80, 6 }, { 198, 7, 0, 100, 2 }, { 202, 5, 46, 100, 1 }, + { 203, 16, 101, 80, 6 }, { 211, 1, 41, 100, 5 }, { 216, 0, 103, 40, 1 }, { 217, 5, 0, 100, 2 }, + { 218, 6, 47, 100, 1 }, { 224, 2, 43, 100, 5 }, { 229, 17, 102, 80, 6 }, { 273, 6, 0, 100, 2 }, + { 274, 4, 40, 100, 1 }, { 275, 4, 44, 100, 5 }, { 335, 1, 21, 100, 1 }, { 336, 13, 42, 100, 0 }, + { 339, 11, 28, 100, 0 }, { 358, 0, 25, 100, 5 }, { 364, 24, 70, 100, 4 }, { 397, 7, 49, 100, 5 }, + { 399, 6, 48, 100, 5 }, { 433, 5, 45, 100, 5 }, { 451, 13, 42, 100, 0 }, { 459, 1, 0, 100, 2 }, + { 508, 4, 0, 100, 2 }, { 509, 1, 21, 100, 1 }, { 521, 11, 28, 100, 0 }, { 530, 8, 118, 100, 0 }, + { 537, 9, 26, 100, 0 }, { 557, 8, 106, 100, 5 }, { 578, 5, 45, 100, 5 }, { 602, 13, 42, 100, 0 }, + { 609, 1, 0, 100, 2 }, { 626, 12, 29, 100, 0 }, { 628, 10, 27, 100, 0 }, { 670, 6, 48, 100, 5 }, + { 690, 10, 27, 100, 0 }, { 692, 3, 51, 100, 5 }, { 705, 11, 28, 100, 0 }, { 710, 2, 43, 100, 5 }, + { 714, 9, 26, 100, 0 }, { 720, 9, 0, 100, 2 }, { 721, 7, 49, 100, 5 }, { 725, 0, 25, 100, 5 }, +}; + +static const SoundSequenceData _soundDataSeq13_14[] = { + { 3, 0, 128, 100, 1 }, { 34, 0, 0, 100, 2 }, { 57, 0, 123, 100, 5 }, { 77, 0, 123, 100, 5 }, + { 84, 9, 24, 100, 0 }, { 100, 9, 24, 100, 0 }, { 140, 3, 19, 100, 5 }, { 157, 2, 109, 100, 5 }, + { 158, 1, 129, 100, 0 }, { 204, 1, 114, 100, 5 }, { 220, 2, 107, 100, 1 }, { 235, 7, 113, 100, 0 }, + { 236, 2, 0, 100, 2 }, { 248, 12, 118, 100, 0 }, { 251, 13, 119, 100, 0 }, { 265, 11, 117, 100, 0 }, + { 276, 11, 117, 100, 0 }, { 310, 5, 110, 100, 0 }, { 335, 6, 112, 100, 0 }, { 370, 4, 124, 100, 0 }, + { 373, 8, 127, 100, 0 }, { 378, 8, 127, 100, 0 }, { 434, 10, 120, 100, 0 }, { 453, 3, 108, 100, 0 }, + { 484, 3, 0, 100, 2 }, +}; + +static const SoundSequenceData _soundDataSeq15_16[] = { + { 3, 4, 3, 100, 5 }, { 10, 5, 4, 100, 5 }, { 22, 6, 64, 100, 5 }, { 32, 7, 65, 100, 5 }, + { 39, 6, 64, 100, 5 }, { 48, 7, 65, 100, 5 }, { 57, 6, 64, 100, 5 }, { 65, 3, 67, 50, 0 }, + { 102, 4, 68, 50, 0 }, { 151, 2, 12, 50, 5 }, { 205, 3, 5, 100, 5 }, { 218, 0, 63, 100, 5 }, + { 227, 0, 63, 100, 5 }, { 236, 0, 63, 100, 5 }, { 245, 0, 63, 100, 5 }, { 254, 0, 63, 100, 5 }, + { 263, 0, 63, 100, 5 }, { 272, 0, 63, 100, 5 }, { 291, 1, 54, 40, 1 }, { 309, 8, 6, 100, 5 }, + { 360, 8, 6, 100, 5 }, { 384, 2, 55, 60, 1 }, { 398, 10, 66, 100, 0 }, { 440, 2, 0, 100, 2 }, + { 441, 1, 0, 100, 2 }, { 452, 11, 62, 100, 0 }, { 466, 1, 2, 100, 5 }, { 470, 8, 9, 100, 0 }, + { 503, 6, 7, 100, 0 }, { 519, 7, 8, 100, 0 }, { 536, 8, 9, 100, 0 }, { 538, 4, 3, 100, 5 }, + { 549, 5, 4, 100, 5 }, { 558, 4, 3, 100, 5 }, { 568, 5, 4, 100, 5 }, { 578, 4, 3, 100, 5 }, + { 586, 5, 4, 100, 5 }, { 593, 4, 3, 100, 5 }, { 600, 5, 4, 100, 5 }, { 606, 4, 3, 100, 5 }, + { 613, 5, 4, 100, 5 }, { 620, 9, 10, 100, 0 }, { 630, 12, 11, 100, 0 }, +}; + +static const SoundSequenceData _soundDataSeq27_28[] = { + { 17, 2, 111, 100, 0 }, { 57, 8, 105, 100, 0 }, { 62, 10, 126, 100, 0 }, { 67, 9, 110, 100, 0 }, + { 74, 3, 115, 100, 1 }, { 87, 3, 0, 100, 2 }, { 85, 0, 121, 100, 0 }, { 138, 5, 116, 100, 0 }, + { 196, 7, 125, 100, 0 }, { 222, 6, 122, 100, 0 }, { 228, 1, 129, 100, 0 }, +}; + +static const SoundSequenceData _soundDataSeq19_20[] = { + { 2, 0, 0, 100, 3 }, { 3, 0, 115, 100, 1 }, { 33, 0, 0, 100, 2 }, { 33, 1, 13, 100, 0 }, + { 53, 2, 14, 100, 1 }, { 78, 2, 0, 100, 2 }, { 80, 0, 0, 100, 4 }, +}; + +const SoundSequenceDataList AnimationSequencePlayer::_soundSeqDataList[] = { + { 0, 0, 14, 10, 58, _soundDataSeq3_4 }, + { 0, 0, 14, 5, 60, _soundDataSeq9_10 }, + { 0, 0, 14, 9, 48, _soundDataSeq21_20 }, + { 1, 80, 14, 4, 25, _soundDataSeq13_14 }, + { 1, 80, 13, 9, 43, _soundDataSeq15_16 }, + { 1, 80, 11, 0, 11, _soundDataSeq27_28 }, + { 104, 100, 0, 0, 0, 0 }, + { 0, 100, 4, 0, 7, _soundDataSeq19_20 } +}; + +const char *AnimationSequencePlayer::_audioFileNamesTable[] = { "demomenu.raw", - "introdub.raw", - "introdua.raw", - "demorola.raw", - "democha1.raw", - "icrmusic.raw", - "demorolc.raw", - "demorolc.raw", - "merilogo.raw", - "democha2.raw", "demorolc.raw", + "fx101.wav", + "fx102.wav", + "fx103.wav", + "fx104.wav", + "fx105.wav", + "fx107.wav", + "fx108.wav", + "fx109.wav", + "fx110.wav", + "fx111.wav", + "fx112.wav", + "fx113.wav", + "fx114.wav", + "fx116.wav", + "fx117.wav", + "fx32.wav", + "fx33.wav", + "fx34.wav", + "fx35.wav", + "fx36.wav", + "fx37.wav", + "fx38.wav", + "fx39.wav", + "fx40.wav", + "fx42.wav", + "fx43.wav", + "fx44.wav", + "fx45.wav", + "fx47.wav", + "fx48.wav", + "fx49.wav", + "fx50.wav", + "fx52.wav", + "fx53.wav", + "fx55.wav", + "fx56.wav", + "fx57.wav", + "fx58.wav", + "fx59.wav", + "fx60.wav", + "fx61.wav", + "fx62.wav", + "fx63.wav", + "fx64.wav", + "fx66.wav", + "fx67.wav", + "fx68.wav", + "fx69.wav", + "fx70.wav", + "fx71.wav", + "fx72.wav", + "fx73.wav", + "fx74.wav", + "fx75.wav", + "fx76.wav", + "fx77.wav", + "fx78.wav", + "fx79.wav", + "fx80.wav", + "fx81.wav", + "fx83.wav", + "fx86.wav", + "fx91.wav", + "fx92.wav", + "fx93.wav", + "fx97.wav", + "fx98.wav", "int1.raw", - "int2.raw", - "int3.raw", - "int4.raw", - "int5.raw", - "int6.raw", - "int7.raw", - "int8.raw", - "int9.raw", - "int10.raw", - "int11.raw", - "int12.raw", - "int13.raw", "int14.raw", "int15.raw", "int16.raw", "int17.raw", "int18.raw", "int19.raw", + "int2.raw", "int20.raw", "int21.raw", "int22.raw", @@ -388,6 +431,7 @@ const char *AnimationSequencePlayer::_musicFileNamesTable[] = { "int27.raw", "int28.raw", "int29.raw", + "int3.raw", "int30.raw", "int31.raw", "int32.raw", @@ -397,177 +441,39 @@ const char *AnimationSequencePlayer::_musicFileNamesTable[] = { "int36.raw", "int37.raw", "int38.raw", - "int39.raw", - "int40.raw", + "int4.raw", "int41.raw", - "int42.raw" -}; - -const char *AnimationSequencePlayer::_audioFileNamesTable[] = { - "introdua.wav", - "fx35.wav", - "fx47.wav", - "fx50.wav", - "fx51.wav", - "fx52.wav", - "fx54.wav", - "fx58.wav", - "fx59.wav", - "fx53.wav", - "fx55.wav", - "fx68.wav", - "fx57.wav", - "fx36.wav", - // offset 2,14 - "fx33.wav", - "fx34.wav", - "fx38.wav", - "fx39.wav", - "fx48.wav", - "fx49.wav", - "fx69.wav", - "fx32.wav", - "fx56.wav", - "fx117.wav", - // offset 3,24 - "introdua.wav", - "fx37.wav", - "fx49.wav", - "fx72.wav", - "fx73.wav", - "fx74.wav", - "fx75.wav", - "fx76.wav", - "fx77.wav", - "fx78.wav", - "fx79.wav", - "fx80.wav", - "fx81.wav", - "fx83.wav", - // offset 4,38 - "fx70.wav", - "fx33.wav", - "rdfx12.wav", - "fx86.wav", - "fx116.wav", - // offset 5,43 + "int42.raw", + "int5.raw", + "int6.raw", + "int7.raw", "introdua.wav", - "fx36.wav", - "fx46.wav", - "fx52.wav", - "fx59.wav", - "fx66.wav", - "fx67.wav", - "fx74.wav", - "rdfx26.wav", - "fx42.wav", - "fx43.wav", - "fx44.wav", - "fx45.wav", - "fx61.wav", - // offset 6,57 - "fx40.wav", - "fx60.wav", - "fx62.wav", - "fx71.wav", - "fx63.wav", - "fx64.wav", - "fx68.wav", - "fx69.wav", - "rdfx12.wav", - // offset 7,66 + "merilogo.raw", "rdfx1.wav", - "rdfx2.wav", - "rdfx4.wav", - "rdfx5.wav", - "rdfx6.wav", - "rdfx7.wav", - "rdfx10.wav", - "rdfx11.wav", "rdfx12.wav", - "rdfx19.wav", - "rdfx29.wav", - "rdfx32.wav", - "rdfx35.wav", - // offset 8,79 - "rdfx8.wav", - "rdfx9.wav", "rdfx13.wav", "rdfx14.wav", - "rdfx33.wav", + "rdfx15.wav", "rdfx16.wav", + "rdfx17.wav", "rdfx18.wav", "rdfx20.wav", - "rdfx38.wav", - "fx39.wav", - "rdfx28.wav", + "rdfx21.wav", + "rdfx22.wav", + "rdfx24.wav", "rdfx25.wav", "rdfx26.wav", "rdfx27.wav", - // offset 9,93 - "rdfx31.wav", - "rdfx21.wav", - "rdfx15.wav", - "fx34.wav", - // offset 10,97 - "fx96.wav", - "fx74.wav", - "fx75.wav", - "fx97.wav", - "fx98.wav", - "fx106.wav", - "fx107.wav", - "fx108.wav", - "fx109.wav", - "fx110.wav", - "fx93.wav", - "fx83.wav", - "fx111.wav", - // offset 11,110 - "fx86.wav", - "fx101.wav", - "fx112.wav", - "fx104.wav", - "fx102.wav", - "fx103.wav", - "fx91.wav", - "fx92.wav", - "fx105.wav", - // offset 12,119 + "rdfx28.wav", "rdfx3.wav", - "rdfx9.wav", - "rdfx17.wav", - "rdfx22.wav", - "rdfx23.wav", - "rdfx24.wav", "rdfx30.wav", + "rdfx31.wav", + "rdfx33.wav", "rdfx36.wav", - "rdfx1.wav", - "rdfx16.wav", "rdfx37.wav", - // offset 13,130 - "fx82.wav", - "fx80.wav", - "fx89.wav", - "fx90.wav", - "fx83.wav", - "fx84.wav", - // offset 14,136 - "rdfx2.wav", - "fx85.wav", - "fx86.wav", - "fx87.wav", - "fx88.wav", - "fx99.wav", - "fx98.wav", - "fx97.wav", - "fx96.wav", - "fx100.wav", - // offset 15,146 - "rdfx22.wav", - "fx113.wav", - "fx114.wav", - "fx115.wav" + "rdfx38.wav", + "rdfx8.wav", + "rdfx9.wav", }; } // namespace Tucker diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index cedd9ec723..692335d5ef 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -304,7 +304,7 @@ void TuckerEngine::restart() { _currentGfxBackgroundCounter = 0; _currentGfxBackground = 0; _fadePaletteCounter = 0; - memset(&_currentPalette, 0, sizeof(_currentPalette)); + memset(_currentPalette, 0, sizeof(_currentPalette)); _fullRedrawCounter = 0; _dirtyRectsPrevCount = _dirtyRectsCount = 0; @@ -3395,7 +3395,6 @@ void TuckerEngine::setSelectedObjectKey() { _selectedObject.locationObject_toY2 = _locationObjectsTable[_selectedCharacterNum].toY2; _selectedObject.locationObject_toWalkX2 = _locationObjectsTable[_selectedCharacterNum].toWalkX2; _selectedObject.locationObject_toWalkY2 = _locationObjectsTable[_selectedCharacterNum].toWalkY2; - } } } else { diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index 966900c923..6afccdc4da 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -848,11 +848,32 @@ enum AnimationSoundType { kAnimationSoundTypeLoopingWAV }; +enum { + kSoundsList_Seq3_4, + kSoundsList_Seq9_10, + kSoundsList_Seq21_20, + kSoundsList_Seq13_14, + kSoundsList_Seq15_16, + kSoundsList_Seq27_28, + kSoundsList_Seq17_18, + kSoundsList_Seq19_20 +}; + struct SoundSequenceData { int timestamp; int index; - int opcode; + int num; int volume; + int opcode; +}; + +struct SoundSequenceDataList { + int musicIndex; + int musicVolume; + int soundList1Count; + int soundList2Count; + int soundSeqDataCount; + const SoundSequenceData *soundSeqData; }; class AnimationSequencePlayer { @@ -919,13 +940,9 @@ private: int _updateFuncIndex; ::Graphics::FlicDecoder _flicPlayer[2]; uint8 _animationPalette[256 * 4]; - int _soundsList1Offset; - int _soundsList1Count; - int _soundsList2Offset; - int _soundsList2Count; - int _soundSeqDataOffset; int _soundSeqDataCount; int _soundSeqDataIndex; + const SoundSequenceData *_soundSeqData; uint8 *_offscreenBuffer; int _updateScreenWidth; int _updateScreenPicture; @@ -938,8 +955,7 @@ private: Audio::SoundHandle _sfxHandle; Audio::SoundHandle _musicHandle; - static const SoundSequenceData _soundSeqData[]; - static const char *_musicFileNamesTable[]; + static const SoundSequenceDataList _soundSeqDataList[]; static const char *_audioFileNamesTable[]; }; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index acc2f77357..136a8d55b3 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -37,6 +37,10 @@ namespace Graphics { class VectorRenderer; + +typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &); + + struct DrawStep { struct Color { uint8 r, g, b; @@ -59,7 +63,10 @@ struct DrawStep { kVectorAlignBottom, kVectorAlignTop, kVectorAlignCenter - } xAlign, yAlign; + }; + + VectorAlignment xAlign; + VectorAlignment yAlign; uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */ @@ -68,7 +75,7 @@ struct DrawStep { uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */ - void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ + DrawingFunctionCallback drawingCall; /**< Pointer to drawing function */ Graphics::Surface *blitSrc; }; diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index 9559b59d4a..b77aac37cf 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -144,6 +144,10 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format); } +bool CursorManager::supportsCursorPalettes() { + return g_system->hasFeature(OSystem::kFeatureCursorHasPalette); +} + void CursorManager::disableCursorPalette(bool disable) { if (!g_system->hasFeature(OSystem::kFeatureCursorHasPalette)) return; @@ -154,7 +158,7 @@ void CursorManager::disableCursorPalette(bool disable) { Palette *pal = _cursorPaletteStack.top(); pal->_disabled = disable; - g_system->disableCursorPalette(true); + g_system->disableCursorPalette(disable); } void CursorManager::pushCursorPalette(const byte *colors, uint start, uint num) { diff --git a/graphics/cursorman.h b/graphics/cursorman.h index ab87c9b095..ba11c9ef96 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -40,7 +40,21 @@ public: /** Query whether the mouse cursor is visible. */ bool isVisible(); - /** Show or hide the mouse cursor. */ + /** + * Show or hide the mouse cursor. + * + * This function does not call OSystem::updateScreen, when visible is true. + * This fact might result in a non visible mouse cursor if the caller does + * not call OSystem::updateScreen itself after a showMouse(true) call. + * + * TODO: We might want to reconsider this behavior, it might be confusing + * for the user to call OSystem::updateScreen separately, on the other + * hand OSystem::updateScreen might as well display unwanted changes on + * the screen. Another alternative would be to let the backend worry + * about this on OSystem::showMouse call. + * + * @see OSystem::showMouse. + */ bool showMouse(bool visible); /** @@ -94,6 +108,17 @@ public: void popAllCursors(); /** + * Test whether cursor palettes are supported. + * + * This is just an convenience wrapper for checking for + * OSystem::kFeatureCursorHasPalette to be supported by OSystem. + * + * @see OSystem::kFeatureCursorHasPalette + * @see OSystem::hasFeature + */ + bool supportsCursorPalettes(); + + /** * Enable/Disable the current cursor palette. * * @param disable diff --git a/graphics/font.h b/graphics/font.h index f68a6dd7a6..33962875e7 100644 --- a/graphics/font.h +++ b/graphics/font.h @@ -36,6 +36,7 @@ namespace Graphics { /** Text alignment modes */ enum TextAlign { + kTextAlignInvalid, kTextAlignLeft, //!< Text should be aligned to the left kTextAlignCenter, //!< Text should be centered kTextAlignRight //!< Text should be aligned to the right diff --git a/graphics/iff.cpp b/graphics/iff.cpp index ea6447ac01..902f97499a 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -48,194 +48,179 @@ char *ID2string(Common::IFF_ID id) { namespace Graphics { - -void fillBMHD(BMHD &bitmapHeader, Common::ReadStream &stream) { - - bitmapHeader.width = stream.readUint16BE(); - bitmapHeader.height = stream.readUint16BE(); - bitmapHeader.x = stream.readUint16BE(); - bitmapHeader.y = stream.readUint16BE(); - bitmapHeader.depth = stream.readByte(); - bitmapHeader.masking = stream.readByte(); - bitmapHeader.pack = stream.readByte(); - bitmapHeader.flags = stream.readByte(); - bitmapHeader.transparentColor = stream.readUint16BE(); - bitmapHeader.xAspect = stream.readByte(); - bitmapHeader.yAspect = stream.readByte(); - bitmapHeader.pageWidth = stream.readUint16BE(); - bitmapHeader.pageHeight = stream.readUint16BE(); - +void BMHD::load(Common::ReadStream *stream) { + assert(stream); + stream->read(this, sizeof(BMHD)); + width = FROM_BE_16(width); + height = FROM_BE_16(height); + x = FROM_BE_16(x); + y = FROM_BE_16(y); + transparentColor = FROM_BE_16(transparentColor); + pageWidth = FROM_BE_16(pageWidth); + pageHeight = FROM_BE_16(pageHeight); } -ILBMDecoder::ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { - if (_typeId != ID_ILBM) - error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void ILBMDecoder::loadHeader(Common::ReadStream *stream) { + _header.load(stream); } -void ILBMDecoder::decode() { - - Common::IFFChunk *chunk; - while ((chunk = nextChunk()) != 0) { - switch (chunk->id) { - case ID_BMHD: - readBMHD(*chunk); - break; +void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { + assert(stream); + uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); + assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); - case ID_CMAP: - readCMAP(*chunk); - break; - - case ID_BODY: - readBODY(*chunk); - break; - } + bool packPixels = (mode & ILBM_PACK_PLANES) != 0; + if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { + packPixels = false; } - return; -} + uint32 outPitch = _header.width; + if (packPixels) { + outPitch /= (8 / numPlanes); + } + byte *out = buffer; -void ILBMDecoder::readBMHD(Common::IFFChunk &chunk) { + switch (_header.pack) { + case 1: { // PackBits compressed bitmap + Graphics::PackBitsReadStream packStream(*stream); - fillBMHD(_bitmapHeader, chunk); + // setup a buffer to hold enough data to build a line in the output + uint32 scanlineWidth = ((_header.width + 15)/16) << 1; + byte *scanline = new byte[scanlineWidth * _header.depth]; - _colorCount = 1 << _bitmapHeader.depth; - *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); - _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); + for (uint i = 0; i < _header.height; ++i) { + byte *s = scanline; + for (uint32 j = 0; j < _header.depth; ++j) { + packStream.read(s, scanlineWidth); + s += scanlineWidth; + } -} + planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); + out += outPitch; + } -void ILBMDecoder::readCMAP(Common::IFFChunk &chunk) { - if (*_colors == NULL) { - error("wrong input chunk sequence"); + delete []scanline; + break; } - for (uint32 i = 0; i < _colorCount; i++) { - (*_colors)[i * 3 + 0] = chunk.readByte(); - (*_colors)[i * 3 + 1] = chunk.readByte(); - (*_colors)[i * 3 + 2] = chunk.readByte(); + + default: + // implement other compression types here! + error("only RLE compressed ILBM files are supported"); + break; } } -void ILBMDecoder::readBODY(Common::IFFChunk& chunk) { +void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { + byte pix, ofs, bit; + byte *s; - switch (_bitmapHeader.pack) { - case 0: - error("unpacked ILBM files are not supported"); - break; + uint32 pixels = outPitch; + if (packPlanes) { + pixels *= (8 / nPlanes); + } - case 1: { - uint32 scanWidth = (_bitmapHeader.width + 7) >> 3; - byte *scan = (byte*)malloc(scanWidth); - byte *out = (byte*)_surface->pixels; + for (uint32 x = 0; x < pixels; ++x) { - PackBitsReadStream stream(chunk); + pix = 0; + ofs = x >> 3; + bit = 0x80 >> (x & 7); - for (uint32 i = 0; i < _bitmapHeader.height; i++) { - for (uint32 j = 0; j < _bitmapHeader.depth; j++) { - stream.read(scan, scanWidth); - fillPlane(out, scan, scanWidth, j); + // first build a pixel by scanning all the usable planes in the input + s = in; + for (uint32 plane = 0; plane < nPlanes; ++plane) { + if (s[ofs] & bit) { + pix |= (1 << plane); } - - out += _bitmapHeader.width; + s += inWidth; } - free(scan); - break; - } - - } -} -void ILBMDecoder::fillPlane(byte *out, byte* buf, uint32 width, uint32 plane) { - byte src, idx, set; - byte mask = 1 << plane; - - for (uint32 j = 0; j < _bitmapHeader.width; j++) { - src = buf[j >> 3]; - idx = 7 - (j & 7); - set = src & (1 << idx); - - if (set) - out[j] |= mask; + // then output the pixel according to the requested packing + if (!packPlanes) { + out[x] = pix; + } else + if (nPlanes == 1) { + out[x/8] |= (pix << (x & 7)); + } else + if (nPlanes == 2) { + out[x/4] |= (pix << ((x & 3) << 1)); + } else + if (nPlanes == 4) { + out[x/2] |= (pix << ((x & 1) << 2)); + } } } - - -PBMDecoder::PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { - if (_typeId != ID_PBM) - error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void PBMDecoder::loadHeader(Common::ReadStream *stream) { + _header.load(stream); } -void PBMDecoder::decode() { - Common::IFFChunk *chunk; - while ((chunk = nextChunk()) != 0) { - switch (chunk->id) { - case ID_BMHD: - readBMHD(*chunk); - break; +void PBMDecoder::loadBitmap(byte *buffer, Common::ReadStream *stream) { + uint32 outSize = _header.width * _header.height; - case ID_CMAP: - readCMAP(*chunk); - break; + switch (_header.pack) { + case 0: + stream->read(buffer, outSize); + break; - case ID_BODY: - readBODY(*chunk); - break; + case 1: { + PackBitsReadStream packStream(*stream); + packStream.read(buffer, outSize); + break; } } - - return; } -void PBMDecoder::readBMHD(Common::IFFChunk &chunk) { - fillBMHD(_bitmapHeader, chunk); +struct PBMLoader { + PBMDecoder _decoder; + Surface *_surface; + byte *_colors; - _colorCount = 1 << _bitmapHeader.depth; - *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); - _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); - -} - -void PBMDecoder::readCMAP(Common::IFFChunk &chunk) { - if (*_colors == NULL) { - error("wrong input chunk sequence"); - } - for (uint32 i = 0; i < _colorCount; i++) { - (*_colors)[i * 3 + 0] = chunk.readByte(); - (*_colors)[i * 3 + 1] = chunk.readByte(); - (*_colors)[i * 3 + 2] = chunk.readByte(); + void load(Common::ReadStream &input, Surface &surface, byte *&colors) { + _surface = &surface; + _colors = colors; + Common::IFFParser parser(&input); + Common::Functor1Mem< Common::IFFChunk&, bool, PBMLoader > c(this, &PBMLoader::callback); + parser.parse(c); } -} -void PBMDecoder::readBODY(Common::IFFChunk& chunk) { + bool callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case ID_BMHD: + _decoder.loadHeader(chunk._stream); + break; - uint si = 0; + case ID_CMAP: + if (_colors) { + chunk._stream->read(_colors, chunk._size); + } + break; - switch (_bitmapHeader.pack) { - case 0: - while (!chunk.hasReadAll()) { - ((byte*)_surface->pixels)[si++] = chunk.readByte(); + case ID_BODY: + if (_surface) { + _surface->create(_decoder._header.width, _decoder._header.height, 1); + _decoder.loadBitmap((byte*)_surface->pixels, chunk._stream); + } + return true; // stop the parser } - break; - case 1: { - PackBitsReadStream stream(chunk); - stream.read((byte*)_surface->pixels, _surface->w * _surface->h); - break; + return false; } +}; - } +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors) { + PBMLoader loader; + loader.load(input, surface, colors); } - PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) { } @@ -282,9 +267,4 @@ uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) { } -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors) { - PBMDecoder decoder(input, surface, colors); - decoder.decode(); -} - } diff --git a/graphics/iff.h b/graphics/iff.h index 13b82a673c..fc1b6ceefa 100644 --- a/graphics/iff.h +++ b/graphics/iff.h @@ -52,55 +52,80 @@ struct BMHD { BMHD() { memset(this, 0, sizeof(*this)); } -}; - -// handles ILBM subtype of IFF FORM files -// -class ILBMDecoder : public Common::IFFParser { + void load(Common::ReadStream *stream); +}; -protected: - void readBMHD(Common::IFFChunk &chunk); - void readCMAP(Common::IFFChunk &chunk); - void readBODY(Common::IFFChunk &chunk); - BMHD _bitmapHeader; - uint32 _colorCount; +struct ILBMDecoder { + /** + * ILBM header data, necessary for loadBitmap() + */ + Graphics::BMHD _header; + + /** + * Available decoding modes for loadBitmap(). + */ + enum { + ILBM_UNPACK_PLANES = 0xFF, //!< Decode all bitplanes, and map 1 pixel to 1 byte. + ILBM_PACK_PLANES = 0x100, //!< Request unpacking, used as a mask with below options. + + ILBM_1_PLANES = 1, //!< Decode only the first bitplane, don't pack. + ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, //!< Decode only the first bitplane, pack 8 pixels in 1 byte. + ILBM_2_PLANES = 2, //!< Decode first 2 bitplanes, don't pack. + ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES, //!< Decode first 2 bitplanes, pack 4 pixels in 1 byte. + ILBM_3_PLANES = 3, //!< Decode first 3 bitplanes, don't pack. + ILBM_4_PLANES = 4, //!< Decode first 4 bitplanes, don't pack. + ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES, //!< Decode first 4 bitplanes, pack 2 pixels in 1 byte. + ILBM_5_PLANES = 5, //!< Decode first 5 bitplanes, don't pack. + ILBM_8_PLANES = 8 //!< Decode all 8 bitplanes. + }; + + /** + * Fills the _header member from the given stream. + */ + void loadHeader(Common::ReadStream *stream); + + /** + * Loads and unpacks the ILBM bitmap data from the stream into the buffer. + * The functions assumes the buffer is large enough to contain all data. + * The caller controls how data should be packed by choosing mode from + * the enum above. + */ + void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); + + /** + * Converts from bitplanar to chunky representation. Intended for internal + * usage, but you can be (ab)use it from client code if you know what you + * are doing. + */ + void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); +}; - Surface *_surface; - byte **_colors; - void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane); - -public: - ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); - virtual ~ILBMDecoder() { } - void decode(); -}; // handles PBM subtype of IFF FORM files // -class PBMDecoder : public Common::IFFParser { - -protected: - void readBMHD(Common::IFFChunk &chunk); - void readCMAP(Common::IFFChunk &chunk); - void readBODY(Common::IFFChunk &chunk); - - BMHD _bitmapHeader; - uint32 _colorCount; - - Surface *_surface; - byte **_colors; - -public: - PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); - virtual ~PBMDecoder() { } - void decode(); +struct PBMDecoder { + /** + * PBM header data, necessary for loadBitmap() + */ + Graphics::BMHD _header; + + /** + * Fills the _header member from the given stream. + */ + void loadHeader(Common::ReadStream *stream); + + /** + * Loads and unpacks the PBM bitmap data from the stream into the buffer. + * The functions assumes the buffer is large enough to contain all data. + */ + void loadBitmap(byte *buffer, Common::ReadStream *stream); }; -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors); +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors); /* diff --git a/graphics/video/smk_decoder.cpp b/graphics/video/smk_decoder.cpp index 7c8ec9a855..9db8f0c730 100644 --- a/graphics/video/smk_decoder.cpp +++ b/graphics/video/smk_decoder.cpp @@ -30,7 +30,6 @@ #include "graphics/video/smk_decoder.h" #include "common/archive.h" -#include "common/array.h" #include "common/endian.h" #include "common/util.h" #include "common/stream.h" @@ -50,16 +49,14 @@ enum SmkBlockTypes { /* * class BitStream - * Keeps a two-byte lookahead, so overallocate buf by 2 bytes if - * you want to avoid OOB reads. + * Little-endian bit stream provider. */ class BitStream { public: BitStream(byte *buf, uint32 length) - : _buf(buf), _end(buf+length), _curBit(8) { - _curBytes = *_buf++; - _curBytes |= *_buf++ << 8; + : _buf(buf), _end(buf+length), _bitCount(8) { + _curByte = *_buf++; } bool getBit(); @@ -71,64 +68,63 @@ public: private: byte *_buf; byte *_end; - uint16 _curBytes; - byte _curBit; + byte _curByte; + byte _bitCount; }; bool BitStream::getBit() { - bool v = _curBytes & 1; + if (_bitCount == 0) { + assert(_buf < _end); + _curByte = *_buf++; + _bitCount = 8; + } - _curBytes >>= 1; + bool v = _curByte & 1; - if (--_curBit == 0) { - _curBytes |= *_buf++ << 8; - _curBit = 8; - } + _curByte >>= 1; + --_bitCount; return v; } byte BitStream::getBits8() { - byte v = _curBytes & 0xff; - _curBytes >>= 8; - _curBytes |= *_buf++ << _curBit; + assert(_buf < _end); + + byte v = (*_buf << _bitCount) | _curByte; + _curByte = *_buf++ >> (8 - _bitCount); + return v; } byte BitStream::peek8() const { - return _curBytes & 0xff; + if (_buf == _end) + return _curByte; + + assert(_buf < _end); + return (*_buf << _bitCount) | _curByte; } void BitStream::skip(int n) { assert(n <= 8); - _curBytes >>= n; + _curByte >>= n; - if (_curBit > n) { - _curBit -= n; + if (_bitCount >= n) { + _bitCount -= n; } else { - _curBit = _curBit + 8 - n; - _curBytes |= *_buf++ << _curBit; + assert(_buf < _end); + _bitCount = _bitCount + 8 - n; + _curByte = *_buf++ >> (8 - _bitCount); } } /* * class SmallHuffmanTree * A Huffman-tree to hold 8-bit values. - * Unoptimized since it's only used during smk initialization. */ class SmallHuffmanTree { public: - SmallHuffmanTree(BitStream &bs) : _bs(bs) { - uint32 bit = _bs.getBit(); - assert(bit); - - _tree.reserve(256); - decodeTree(0); - - bit = _bs.getBit(); - assert(!bit); - } + SmallHuffmanTree(BitStream &bs); uint16 getCode(BitStream &bs); private: @@ -136,34 +132,66 @@ private: SMK_NODE = 0x8000 }; - int decodeTree(int length); + uint16 decodeTree(uint32 prefix, int length); + + uint16 _treeSize; + uint16 _tree[511]; + + uint16 _prefixtree[256]; + byte _prefixlength[256]; - Common::Array<uint16> _tree; BitStream &_bs; }; -int SmallHuffmanTree::decodeTree(int length) { +SmallHuffmanTree::SmallHuffmanTree(BitStream &bs) + : _treeSize(0), _bs(bs) { + uint32 bit = _bs.getBit(); + assert(bit); + + for (uint16 i = 0; i < 256; ++i) + _prefixtree[i] = _prefixlength[i] = 0; + + decodeTree(0, 0); + + bit = _bs.getBit(); + assert(!bit); +} + +uint16 SmallHuffmanTree::decodeTree(uint32 prefix, int length) { if (!_bs.getBit()) { // Leaf - uint16 v = _bs.getBits8(); + _tree[_treeSize] = _bs.getBits8(); + + if (length <= 8) { + for (int i = 0; i < 256; i += (1 << length)) { + _prefixtree[prefix | i] = _treeSize; + _prefixlength[prefix | i] = length; + } + } + ++_treeSize; - _tree.push_back(v); return 1; } - _tree.push_back(0); // placeholder for r1 - int t = _tree.size() - 1; + uint16 t = _treeSize++; - int r1 = decodeTree(length + 1); + if (length == 8) { + _prefixtree[prefix] = t; + _prefixlength[prefix] = 8; + } + + uint16 r1 = decodeTree(prefix, length + 1); _tree[t] = (SMK_NODE | r1); - int r2 = decodeTree(length + 1); + uint16 r2 = decodeTree(prefix | (1 << length), length + 1); return r1+r2+1; } uint16 SmallHuffmanTree::getCode(BitStream &bs) { - uint16 *p = &_tree[0]; + byte peek = bs.peek8(); + uint16 *p = &_tree[_prefixtree[peek]]; + bs.skip(_prefixlength[peek]); while (*p & SMK_NODE) { if (bs.getBit()) @@ -177,12 +205,12 @@ uint16 SmallHuffmanTree::getCode(BitStream &bs) { /* * class BigHuffmanTree * A Huffman-tree to hold 16-bit values. - * Contains the beginnings of an optimization. */ class BigHuffmanTree { public: - BigHuffmanTree(BitStream &bs); + BigHuffmanTree(BitStream &bs, int allocSize); + ~BigHuffmanTree(); void reset(); uint32 getCode(BitStream &bs); @@ -191,13 +219,14 @@ private: SMK_NODE = 0x80000000 }; - int decodeTree(uint32 prefix, int length); + uint32 decodeTree(uint32 prefix, int length); - Common::Array<uint32> _tree; - uint32 _last[3]; + uint32 _treeSize; + uint32 *_tree; + uint32 _last[3]; - int _prefixtree[256]; - int _prefixlength[256]; + uint32 _prefixtree[256]; + byte _prefixlength[256]; /* Used during construction */ BitStream &_bs; @@ -206,18 +235,18 @@ private: SmallHuffmanTree *_hiBytes; }; -BigHuffmanTree::BigHuffmanTree(BitStream &bs) +BigHuffmanTree::BigHuffmanTree(BitStream &bs, int allocSize) : _bs(bs) { uint32 bit = _bs.getBit(); if (!bit) { - _tree.push_back(0); + _tree = new uint32[1]; + _tree[0] = 0; _last[0] = _last[1] = _last[2] = 0; return; } - int i; - for (i = 0; i < 256; ++i) - _prefixtree[i] = 0; + for (uint32 i = 0; i < 256; ++i) + _prefixtree[i] = _prefixlength[i] = 0; _loBytes = new SmallHuffmanTree(_bs); _hiBytes = new SmallHuffmanTree(_bs); @@ -228,15 +257,16 @@ BigHuffmanTree::BigHuffmanTree(BitStream &bs) _last[0] = _last[1] = _last[2] = 0xffffffff; - _tree.reserve(256); + _treeSize = 0; + _tree = new uint32[allocSize / 4]; decodeTree(0, 0); bit = _bs.getBit(); assert(!bit); - for (i = 0; i < 3; ++i) { + for (uint32 i = 0; i < 3; ++i) { if (_last[i] == 0xffffffff) { - _tree.push_back(0); - _last[i] = _tree.size() - 1; + _last[i] = _treeSize; + _tree[_treeSize++] = 0; } } @@ -244,11 +274,16 @@ BigHuffmanTree::BigHuffmanTree(BitStream &bs) delete _hiBytes; } +BigHuffmanTree::~BigHuffmanTree() +{ + delete[] _tree; +} + void BigHuffmanTree::reset() { _tree[_last[0]] = _tree[_last[1]] = _tree[_last[2]] = 0; } -int BigHuffmanTree::decodeTree(uint32 prefix, int length) { +uint32 BigHuffmanTree::decodeTree(uint32 prefix, int length) { uint32 bit = _bs.getBit(); if (!bit) { // Leaf @@ -256,50 +291,45 @@ int BigHuffmanTree::decodeTree(uint32 prefix, int length) { uint32 hi = _hiBytes->getCode(_bs); uint32 v = (hi << 8) | lo; - _tree.push_back(v); - int t = _tree.size() - 1; + _tree[_treeSize] = v; if (length <= 8) { - uint32 i; - for (i = 0; i < 256; i += (1 << length)) { - _prefixtree[prefix | i] = t; + for (int i = 0; i < 256; i += (1 << length)) { + _prefixtree[prefix | i] = _treeSize; _prefixlength[prefix | i] = length; } } - int i; - for (i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) { if (_markers[i] == v) { - _last[i] = t; - _tree[t] = 0; + _last[i] = _treeSize; + _tree[_treeSize] = 0; } } + ++_treeSize; return 1; } - _tree.push_back(0); // placeholder for r1 - int t = _tree.size() - 1; + uint32 t = _treeSize++; if (length == 8) { _prefixtree[prefix] = t; _prefixlength[prefix] = 8; } - int r1 = decodeTree(prefix, length + 1); + uint32 r1 = decodeTree(prefix, length + 1); _tree[t] = SMK_NODE | r1; - int r2 = decodeTree(prefix | (1 << length), length + 1); + uint32 r2 = decodeTree(prefix | (1 << length), length + 1); return r1+r2+1; } uint32 BigHuffmanTree::getCode(BitStream &bs) { - uint32 *p = &_tree[0]; - byte peek = bs.peek8(); - p = &_tree[_prefixtree[peek]]; + uint32 *p = &_tree[_prefixtree[peek]]; bs.skip(_prefixlength[peek]); while (*p & SMK_NODE) { @@ -457,18 +487,17 @@ bool SmackerDecoder::loadFile(const char *fileName) { for (i = 0; i < _videoInfo.frameCount; ++i) _frameTypes[i] = _fileStream->readByte(); - Common::Array<byte> huffmanTrees; - huffmanTrees.resize(_header.treesSize + 2); - _fileStream->read(&huffmanTrees[0], _header.treesSize); - huffmanTrees[_header.treesSize] = 0; - huffmanTrees[_header.treesSize + 1] = 0; + byte *huffmanTrees = new byte[_header.treesSize]; + _fileStream->read(huffmanTrees, _header.treesSize); + + BitStream bs(huffmanTrees, _header.treesSize); - BitStream bs(&huffmanTrees[0], _header.treesSize); + _MMapTree = new BigHuffmanTree(bs, _header.mMapSize); + _MClrTree = new BigHuffmanTree(bs, _header.mClrSize); + _FullTree = new BigHuffmanTree(bs, _header.fullSize); + _TypeTree = new BigHuffmanTree(bs, _header.typeSize); - _MMapTree = new BigHuffmanTree(bs); - _MClrTree = new BigHuffmanTree(bs); - _FullTree = new BigHuffmanTree(bs); - _TypeTree = new BigHuffmanTree(bs); + delete[] huffmanTrees; _videoFrameBuffer = (byte *)malloc(2 * _videoInfo.width * _videoInfo.height); memset(_videoFrameBuffer, 0, 2 * _videoInfo.width * _videoInfo.height); @@ -539,11 +568,9 @@ bool SmackerDecoder::decodeNextFrame() { if (_header.audioInfo[i].hasAudio && chunkSize > 0 && i == 0) { // If it's track 0, play the audio data - byte *soundBuffer = new byte[chunkSize + 2]; + byte *soundBuffer = new byte[chunkSize]; _fileStream->read(soundBuffer, chunkSize); - soundBuffer[chunkSize] = 0; - soundBuffer[chunkSize + 1] = 0; if (_header.audioInfo[i].isCompressed) { // Compressed audio (Huffman DPCM encoded) @@ -575,10 +602,8 @@ bool SmackerDecoder::decodeNextFrame() { uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos); - _frameData = (byte *)malloc(frameDataSize + 2); + _frameData = (byte *)malloc(frameDataSize); _fileStream->read(_frameData, frameDataSize); - _frameData[frameDataSize] = 0; - _frameData[frameDataSize + 1] = 0; BitStream bs(_frameData, frameDataSize); diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp index c977ecc3d0..f38f9f5b94 100644 --- a/gui/EditTextWidget.cpp +++ b/gui/EditTextWidget.cpp @@ -30,16 +30,16 @@ namespace GUI { -EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text) - : EditableWidget(boss, x, y - 1, w, h + 2) { +EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd) + : EditableWidget(boss, x, y - 1, w, h + 2, cmd) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; setEditString(text); } -EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text) - : EditableWidget(boss, name) { +EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd) + : EditableWidget(boss, name, cmd) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; @@ -55,8 +55,6 @@ void EditTextWidget::reflowLayout() { _leftPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Left", 0); _rightPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Right", 0); - _font = (ThemeEngine::FontStyle)g_gui.xmlEval()->getVar("EditTextWidget.Font", ThemeEngine::kFontStyleNormal); - EditableWidget::reflowLayout(); } @@ -113,6 +111,7 @@ void EditTextWidget::endEditMode() { void EditTextWidget::abortEditMode() { setEditString(_backupString); + sendCommand(_cmd, 0); releaseFocus(); } diff --git a/gui/EditTextWidget.h b/gui/EditTextWidget.h index 661ba28e1b..5a5823cfb1 100644 --- a/gui/EditTextWidget.h +++ b/gui/EditTextWidget.h @@ -41,8 +41,8 @@ protected: int _rightPadding; public: - EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text); - EditTextWidget(GuiObject *boss, const String &name, const String &text); + EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd = 0); + EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd = 0); void setEditString(const String &str); diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 06cbcdcbd9..07d22973ac 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -33,8 +33,8 @@ namespace GUI { -ListWidget::ListWidget(GuiObject *boss, const String &name) - : EditableWidget(boss, name), CommandSender(boss) { +ListWidget::ListWidget(GuiObject *boss, const String &name, uint32 cmd) + : EditableWidget(boss, name), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; @@ -60,10 +60,12 @@ ListWidget::ListWidget(GuiObject *boss, const String &name) // FIXME: This flag should come from widget definition _editable = true; + + _quickSelect = true; } -ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h) - : EditableWidget(boss, x, y, w, h), CommandSender(boss) { +ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) + : EditableWidget(boss, x, y, w, h), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; @@ -105,11 +107,14 @@ Widget *ListWidget::findWidget(int x, int y) { void ListWidget::setSelected(int item) { assert(item >= -1 && item < (int)_list.size()); + // We only have to do something if the widget is enabled and the selection actually changes if (isEnabled() && _selectedItem != item) { if (_editMode) abortEditMode(); _selectedItem = item; + + // Notify clients that the selection changed. sendCommand(kListSelectionChangedCmd, _selectedItem); _currentPos = _selectedItem - _entriesPerPage / 2; @@ -121,8 +126,13 @@ void ListWidget::setSelected(int item) { void ListWidget::setList(const StringList &list) { if (_editMode && _caretVisible) drawCaret(true); - int size = list.size(); + + // Copy everything + _dataList = list; _list = list; + _filter.clear(); + + int size = list.size(); if (_currentPos >= size) _currentPos = size - 1; if (_currentPos < 0) @@ -133,6 +143,15 @@ void ListWidget::setList(const StringList &list) { scrollBarRecalc(); } +void ListWidget::append(const String &s) { + _dataList.push_back(s); + _list.push_back(s); + + setFilter(_filter, false); + + scrollBarRecalc(); +} + void ListWidget::scrollTo(int item) { int size = _list.size(); if (item >= size) @@ -223,8 +242,6 @@ bool ListWidget::handleKeyDown(Common::KeyState state) { // Quick selection mode: Go to first list item starting with this key // (or a substring accumulated from the last couple key presses). // Only works in a useful fashion if the list entries are sorted. - // TODO: Maybe this should be off by default, and instead we add a - // method "enableQuickSelect()" or so ? uint32 time = getMillis(); if (_quickSelectTime < time) { _quickSelectStr = (char)state.ascii; @@ -233,26 +250,29 @@ bool ListWidget::handleKeyDown(Common::KeyState state) { } _quickSelectTime = time + 300; // TODO: Turn this into a proper constant (kQuickSelectDelay ?) - - // FIXME: This is bad slow code (it scans the list linearly each time a - // key is pressed); it could be much faster. Only of importance if we have - // quite big lists to deal with -- so for now we can live with this lazy - // implementation :-) - int newSelectedItem = 0; - int bestMatch = 0; - bool stop; - for (StringList::const_iterator i = _list.begin(); i != _list.end(); ++i) { - const int match = matchingCharsIgnoringCase(i->c_str(), _quickSelectStr.c_str(), stop); - if (match > bestMatch || stop) { - _selectedItem = newSelectedItem; - bestMatch = match; - if (stop) - break; + if (_quickSelect) { + // FIXME: This is bad slow code (it scans the list linearly each time a + // key is pressed); it could be much faster. Only of importance if we have + // quite big lists to deal with -- so for now we can live with this lazy + // implementation :-) + int newSelectedItem = 0; + int bestMatch = 0; + bool stop; + for (StringList::const_iterator i = _list.begin(); i != _list.end(); ++i) { + const int match = matchingCharsIgnoringCase(i->c_str(), _quickSelectStr.c_str(), stop); + if (match > bestMatch || stop) { + _selectedItem = newSelectedItem; + bestMatch = match; + if (stop) + break; + } + newSelectedItem++; } - newSelectedItem++; - } - scrollToCurrent(); + scrollToCurrent(); + } else { + sendCommand(_cmd, 0); + } } else if (_editMode) { // Class EditableWidget handles all text editing related key presses for us handled = EditableWidget::handleKeyDown(state); @@ -445,6 +465,18 @@ void ListWidget::scrollToCurrent() { _scrollBar->recalc(); } +void ListWidget::scrollToEnd() { + if (_currentPos + _entriesPerPage < (int)_list.size()) { + _currentPos = _list.size() - _entriesPerPage; + } else { + return; + } + + _scrollBar->_currentPos = _currentPos; + _scrollBar->recalc(); + _scrollBar->draw(); +} + void ListWidget::startEditMode() { if (_editable && !_editMode && _selectedItem >= 0) { _editMode = true; @@ -512,4 +544,70 @@ void ListWidget::reflowLayout() { } } +void ListWidget::setFilter(const String &filter, bool redraw) { + // FIXME: This method does not deal correctly with edit mode! + // Until we fix that, let's make sure it isn't called while editing takes place + assert(!_editMode); + + String filt = filter; + filt.toLowercase(); + + if (_filter == filt) // Filter was not changed + return; + + _filter = filt; + + if (_filter.empty()) { + // No filter -> display everything + _list = _dataList; + } else { + // Restrict the list to everything which contains all words in _filter + // as substrings, ignoring case. + + Common::StringTokenizer tok(filter); + String tmp; + int n = 0; + + _list.clear(); + _listIndex.clear(); + + for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) { + tmp = *i; + tmp.toLowercase(); + bool matches = true; + tok.reset(); + while (!tok.empty()) { + if (!tmp.contains(tok.nextToken())) { + matches = false; + break; + } + } + + if (matches) { + _list.push_back(*i); + _listIndex.push_back(n); + } + } + } + + _currentPos = 0; + _selectedItem = -1; + + if (redraw) { + scrollBarRecalc(); + // Redraw the whole dialog. This is annoying, as this might be rather + // expensive when really only the list widget and its scroll bar area + // to be redrawn. However, since the scrollbar might change its + // visibility status, and the list its width, we cannot just redraw + // the two. + // TODO: A more efficient (and elegant?) way to handle this would be to + // introduce a kind of "BoxWidget" or "GroupWidget" which defines a + // rectangular region and subwidgets can be placed within it. + // Such a widget could also (optionally) draw a border (or even different + // kinds of borders) around the objects it groups; and also a 'title' + // (I am borrowing these "ideas" from the NSBox class in Cocoa :). + _boss->draw(); + } +} + } // End of namespace GUI diff --git a/gui/ListWidget.h b/gui/ListWidget.h index 23bcc3c1a7..203cd88fb6 100644 --- a/gui/ListWidget.h +++ b/gui/ListWidget.h @@ -47,12 +47,14 @@ enum { }; /* ListWidget */ -class ListWidget : public EditableWidget, public CommandSender { +class ListWidget : public EditableWidget { public: typedef Common::String String; typedef Common::StringList StringList; protected: StringList _list; + StringList _dataList; + Common::Array<int> _listIndex; bool _editable; bool _editMode; NumberingMode _numberingMode; @@ -73,22 +75,33 @@ protected: int _bottomPadding; int _scrollBarWidth; + String _filter; + bool _quickSelect; + + uint32 _cmd; + public: - ListWidget(GuiObject *boss, const String &name); - ListWidget(GuiObject *boss, int x, int y, int w, int h); + ListWidget(GuiObject *boss, const String &name, uint32 cmd = 0); + ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0); virtual ~ListWidget(); virtual Widget *findWidget(int x, int y); void setList(const StringList &list); - const StringList &getList() const { return _list; } - int getSelected() const { return _selectedItem; } + void append(const String &s); + const StringList &getList() const { return _dataList; } + int getSelected() const { return (_filter.empty() || _selectedItem == -1) ? _selectedItem : _listIndex[_selectedItem]; } void setSelected(int item); const String &getSelectedString() const { return _list[_selectedItem]; } void setNumberingMode(NumberingMode numberingMode) { _numberingMode = numberingMode; } bool isEditable() const { return _editable; } void setEditable(bool editable) { _editable = editable; } void scrollTo(int item); + void scrollToEnd(); + void enableQuickSelect(bool enable) { _quickSelect = enable; } + String getQuickSelectString() const { return _quickSelectStr; } + + void setFilter(const String &filter, bool redraw = true); virtual void handleTickle(); virtual void handleMouseDown(int x, int y, int button, int clickCount); diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 9be652b8d6..cc756a96b6 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -79,10 +79,10 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) _selection = _popUpBoss->_selectedItem; // Calculate real popup dimensions - _x = _popUpBoss->getAbsX() + _popUpBoss->_labelWidth + _popUpBoss->_labelSpacing; + _x = _popUpBoss->getAbsX(); _y = _popUpBoss->getAbsY() - _popUpBoss->_selectedItem * kLineHeight; _h = _popUpBoss->_entries.size() * kLineHeight + 2; - _w = _popUpBoss->_w - kLineHeight + 2 - _popUpBoss->_labelWidth - _popUpBoss->_labelSpacing; + _w = _popUpBoss->_w - kLineHeight + 2; _leftPadding = _popUpBoss->_leftPadding; _rightPadding = _popUpBoss->_rightPadding; @@ -356,13 +356,12 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) { // PopUpWidget // -PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const String &label) - : Widget(boss, name), CommandSender(boss), _label(label), _labelWidth(0) { +PopUpWidget::PopUpWidget(GuiObject *boss, const String &name) + : Widget(boss, name), CommandSender(boss) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_IGNORE_DRAG); _type = kPopUpWidget; _selectedItem = -1; - _labelWidth = g_gui.xmlEval()->getVar("Globals.PopUpWidget.labelWidth"); } void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { @@ -394,10 +393,8 @@ void PopUpWidget::handleMouseWheel(int x, int y, int direction) { } void PopUpWidget::reflowLayout() { - _labelWidth = g_gui.xmlEval()->getVar("Globals.PopUpWidget.labelWidth"); _leftPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Left", 0); _rightPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Right", 0); - _labelSpacing = g_gui.xmlEval()->getVar("Globals.PopUpWidget.labelSpacing", 10); Widget::reflowLayout(); } @@ -435,17 +432,10 @@ void PopUpWidget::setSelectedTag(uint32 tag) { } void PopUpWidget::drawWidget() { - int x = _x + _labelWidth + _labelSpacing; - int w = _w - _labelWidth - _labelSpacing; - - // Draw the label, if any - if (_labelWidth > 0) - g_gui.theme()->drawText(Common::Rect(_x+2,_y+3,_x+2+_labelWidth, _y+3+g_gui.theme()->getFontHeight()), _label, _state, Graphics::kTextAlignRight); - Common::String sel; if (_selectedItem >= 0) sel = _entries[_selectedItem].name; - g_gui.theme()->drawPopUpWidget(Common::Rect(x, _y, x+w, _y+_h), sel, _leftPadding, _state, Graphics::kTextAlignLeft); + g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, _leftPadding, _state, Graphics::kTextAlignLeft); } } // End of namespace GUI diff --git a/gui/PopUpWidget.h b/gui/PopUpWidget.h index 23d5757992..050dc0936d 100644 --- a/gui/PopUpWidget.h +++ b/gui/PopUpWidget.h @@ -55,15 +55,11 @@ protected: EntryList _entries; int _selectedItem; - String _label; - int _labelWidth; - int _leftPadding; int _rightPadding; - int _labelSpacing; public: - PopUpWidget(GuiObject *boss, const String &name, const String &label); + PopUpWidget(GuiObject *boss, const String &name); void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 6041fb8858..a25c111da3 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -50,6 +50,10 @@ namespace GUI { +const char * const ThemeEngine::kImageLogo = "logo.bmp"; +const char * const ThemeEngine::kImageLogoSmall = "logo_small.bmp"; +const char * const ThemeEngine::kImageSearch = "search.bmp"; + struct TextDrawData { const Graphics::Font *_fontPtr; @@ -952,7 +956,7 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s queueDD(dd, r); if (!sel.empty()) { - Common::Rect text(r.left, r.top, r.right - 16, r.bottom); + Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom); queueDDText(getTextData(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); } } @@ -1449,7 +1453,7 @@ void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) { output.clear(); } -void ThemeEngine::listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list, int depth) { +void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return; diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 74af16f09f..f9226a81d8 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -32,7 +32,7 @@ #include "graphics/surface.h" #include "graphics/fontman.h" -#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.4" +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.5" namespace Graphics { struct DrawStep; @@ -123,6 +123,7 @@ protected: public: //! Vertical alignment of the text. enum TextAlignVertical { + kTextAlignVInvalid, kTextAlignVBottom, kTextAlignVCenter, kTextAlignVTop @@ -181,11 +182,10 @@ public: kShadingLuminance //!< Converting colors to luminance for unused areas }; - //! Special image ids for images used in the GUI - enum kThemeImages { - kImageLogo = 0, //!< ScummVM Logo used in the launcher - kImageLogoSmall //!< ScummVM logo used in the GMM - }; + // Special image ids for images used in the GUI + static const char * const kImageLogo; //!< ScummVM logo used in the launcher + static const char * const kImageLogoSmall; //!< ScummVM logo used in the GMM + static const char * const kImageSearch; //!< Search tool image used in the launcher /** * Graphics mode enumeration. @@ -420,13 +420,8 @@ public: return _bitmaps.contains(name) ? _bitmaps[name] : 0; } - const Graphics::Surface *getImageSurface(const kThemeImages n) const { - if (n == kImageLogo) - return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; - else if (n == kImageLogoSmall) - return _bitmaps.contains("logo_small.bmp") ? _bitmaps["logo_small.bmp"] : 0; - - return 0; + const Graphics::Surface *getImageSurface(const Common::String &name) const { + return _bitmaps.contains(name) ? _bitmaps[name] : 0; } /** @@ -534,7 +529,7 @@ private: static Common::String getThemeFile(const Common::String &id); static Common::String getThemeId(const Common::String &filename); - static void listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list, int depth=-1); + static void listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth = -1); protected: OSystem *_system; /** Global system object. */ diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 3729c1b499..8872741228 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -66,19 +66,36 @@ bool ThemeEval::getWidgetData(const Common::String &widget, int16 &x, int16 &y, return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); } +Graphics::TextAlign ThemeEval::getWidgetTextHAlign(const Common::String &widget) { + Common::StringTokenizer tokenizer(widget, "."); + + if (widget.hasPrefix("Dialog.")) + tokenizer.nextToken(); + + Common::String dialogName = "Dialog." + tokenizer.nextToken(); + Common::String widgetName = tokenizer.nextToken(); + + if (!_layouts.contains(dialogName)) + return Graphics::kTextAlignInvalid; + + return _layouts[dialogName]->getWidgetTextHAlign(widgetName); +} -void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled) { +void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled, Graphics::TextAlign align) { int typeW = -1; int typeH = -1; + Graphics::TextAlign typeAlign = Graphics::kTextAlignInvalid; if (!type.empty()) { typeW = getVar("Globals." + type + ".Width", -1); typeH = getVar("Globals." + type + ".Height", -1); + typeAlign = (Graphics::TextAlign)getVar("Globals." + type + ".Align", Graphics::kTextAlignInvalid); } ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name, typeW == -1 ? w : typeW, - typeH == -1 ? h : typeH); + typeH == -1 ? h : typeH, + typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign); _curLayout.top()->addChild(widget); setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0); diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 07242e890e..c484a49564 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -30,6 +30,7 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "common/stack.h" +#include "graphics/font.h" #include "gui/ThemeLayout.h" @@ -76,7 +77,7 @@ public: void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true, int inset = 0); void addLayout(ThemeLayout::LayoutType type, int spacing, bool center = false); - void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true); + void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true, Graphics::TextAlign align = Graphics::kTextAlignLeft); bool addImportedLayout(const Common::String &name); void addSpace(int size); @@ -87,6 +88,8 @@ public: bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h); + Graphics::TextAlign getWidgetTextHAlign(const Common::String &widget); + #ifdef LAYOUT_DEBUG_DIALOG void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { _layouts[LAYOUT_DEBUG_DIALOG]->debugDraw(screen, font); diff --git a/gui/ThemeLayout.cpp b/gui/ThemeLayout.cpp index 3afded5504..3c930db73c 100644 --- a/gui/ThemeLayout.cpp +++ b/gui/ThemeLayout.cpp @@ -70,6 +70,22 @@ bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, return false; } +Graphics::TextAlign ThemeLayout::getWidgetTextHAlign(const Common::String &name) { + if (name.empty()) { + assert(getLayoutType() == kLayoutMain); + return _textHAlign; + } + + Graphics::TextAlign res; + + for (uint i = 0; i < _children.size(); ++i) { + if ((res = _children[i]->getWidgetTextHAlign(name)) != Graphics::kTextAlignInvalid) + return res; + } + + return Graphics::kTextAlignInvalid; +} + int16 ThemeLayoutStacked::getParentWidth() { ThemeLayout *p = _parent; int width = 0; @@ -135,6 +151,14 @@ bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int1 return false; } +Graphics::TextAlign ThemeLayoutWidget::getWidgetTextHAlign(const Common::String &name) { + if (name == _name) { + return _textHAlign; + } + + return Graphics::kTextAlignInvalid; +} + void ThemeLayoutMain::reflowLayout() { assert(_children.size() <= 1); diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h index ac17e5744b..3d367df147 100644 --- a/gui/ThemeLayout.h +++ b/gui/ThemeLayout.h @@ -52,7 +52,8 @@ public: ThemeLayout(ThemeLayout *p) : _parent(p), _x(0), _y(0), _w(-1), _h(-1), - _centered(false), _defaultW(-1), _defaultH(-1) { } + _centered(false), _defaultW(-1), _defaultH(-1), + _textHAlign(Graphics::kTextAlignInvalid) {} virtual ~ThemeLayout() { for (uint i = 0; i < _children.size(); ++i) @@ -90,6 +91,7 @@ protected: void setWidth(int16 width) { _w = width; } void setHeight(int16 height) { _h = height; } + void setTextHAlign(Graphics::TextAlign align) { _textHAlign = align; } virtual LayoutType getLayoutType() = 0; @@ -98,8 +100,12 @@ protected: public: virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + virtual Graphics::TextAlign getWidgetTextHAlign(const Common::String &name); + void importLayout(ThemeLayout *layout); + Graphics::TextAlign getTextHAlign() { return _textHAlign; } + #ifdef LAYOUT_DEBUG_DIALOG void debugDraw(Graphics::Surface *screen, const Graphics::Font *font); @@ -113,6 +119,7 @@ protected: Common::Array<ThemeLayout *> _children; bool _centered; int16 _defaultW, _defaultH; + Graphics::TextAlign _textHAlign; }; class ThemeLayoutMain : public ThemeLayout { @@ -190,12 +197,16 @@ protected: class ThemeLayoutWidget : public ThemeLayout { public: - ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h) : ThemeLayout(p), _name(name) { + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h, Graphics::TextAlign align) : ThemeLayout(p), _name(name) { _w = _defaultW = w; _h = _defaultH = h; + + setTextHAlign(align); } bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + Graphics::TextAlign getWidgetTextHAlign(const Common::String &name); + void reflowLayout() {} #ifdef LAYOUT_DEBUG_DIALOG diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index d0e5528480..8897eef9d7 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -23,17 +23,11 @@ * */ -#include "common/util.h" -#include "common/system.h" -#include "common/events.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/xmlparser.h" - #include "gui/ThemeEngine.h" #include "gui/ThemeEval.h" #include "gui/ThemeParser.h" #include "gui/GuiManager.h" + #include "graphics/VectorRenderer.h" namespace GUI { @@ -62,21 +56,30 @@ static TextData parseTextDataId(const Common::String &name) { return kTextDataNone; } +static Graphics::TextAlign parseTextHAlign(const Common::String &val) { + if (val == "left") + return Graphics::kTextAlignLeft; + else if (val == "right") + return Graphics::kTextAlignRight; + else if (val == "center") + return Graphics::kTextAlignCenter; + else + return Graphics::kTextAlignInvalid; +} -ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { +static GUI::ThemeEngine::TextAlignVertical parseTextVAlign(const Common::String &val) { + if (val == "top") + return GUI::ThemeEngine::kTextAlignVTop; + else if (val == "center") + return GUI::ThemeEngine::kTextAlignVCenter; + else if (val == "bottom") + return GUI::ThemeEngine::kTextAlignVBottom; + else + return GUI::ThemeEngine::kTextAlignVInvalid; +} - _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; - _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; - _drawFunctions["roundedsq"] = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; - _drawFunctions["bevelsq"] = &Graphics::VectorRenderer::drawCallback_BEVELSQ; - _drawFunctions["line"] = &Graphics::VectorRenderer::drawCallback_LINE; - _drawFunctions["triangle"] = &Graphics::VectorRenderer::drawCallback_TRIANGLE; - _drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; - _drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB; - _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; - _drawFunctions["bitmap"] = &Graphics::VectorRenderer::drawCallback_BITMAP; - _drawFunctions["cross"] = &Graphics::VectorRenderer::drawCallback_CROSS; +ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; _theme = parent; @@ -85,8 +88,6 @@ ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { ThemeParser::~ThemeParser() { delete _defaultStepGlobal; delete _defaultStepLocal; - _palette.clear(); - _drawFunctions.clear(); } void ThemeParser::cleanup() { @@ -206,22 +207,10 @@ bool ThemeParser::parserCallback_text(ParserNode *node) { Graphics::TextAlign alignH; GUI::ThemeEngine::TextAlignVertical alignV; - if (node->values["horizontal_align"] == "left") - alignH = Graphics::kTextAlignLeft; - else if (node->values["horizontal_align"] == "right") - alignH = Graphics::kTextAlignRight; - else if (node->values["horizontal_align"] == "center") - alignH = Graphics::kTextAlignCenter; - else + if ((alignH = parseTextHAlign(node->values["horizontal_align"])) == Graphics::kTextAlignInvalid) return parserError("Invalid value for text alignment."); - if (node->values["vertical_align"] == "top") - alignV = GUI::ThemeEngine::kTextAlignVTop; - else if (node->values["vertical_align"] == "center") - alignV = GUI::ThemeEngine::kTextAlignVCenter; - else if (node->values["vertical_align"] == "bottom") - alignV = GUI::ThemeEngine::kTextAlignVBottom; - else + if ((alignV = parseTextVAlign(node->values["vertical_align"])) == GUI::ThemeEngine::kTextAlignVInvalid) return parserError("Invalid value for text alignment."); Common::String id = getParentNode(node)->values["id"]; @@ -271,15 +260,44 @@ bool ThemeParser::parserCallback_color(ParserNode *node) { } +static Graphics::DrawingFunctionCallback getDrawingFunctionCallback(const Common::String &name) { + + if (name == "circle") + return &Graphics::VectorRenderer::drawCallback_CIRCLE; + if (name == "square") + return &Graphics::VectorRenderer::drawCallback_SQUARE; + if (name == "roundedsq") + return &Graphics::VectorRenderer::drawCallback_ROUNDSQ; + if (name == "bevelsq") + return &Graphics::VectorRenderer::drawCallback_BEVELSQ; + if (name == "line") + return &Graphics::VectorRenderer::drawCallback_LINE; + if (name == "triangle") + return &Graphics::VectorRenderer::drawCallback_TRIANGLE; + if (name == "fill") + return &Graphics::VectorRenderer::drawCallback_FILLSURFACE; + if (name == "tab") + return &Graphics::VectorRenderer::drawCallback_TAB; + if (name == "void") + return &Graphics::VectorRenderer::drawCallback_VOID; + if (name == "bitmap") + return &Graphics::VectorRenderer::drawCallback_BITMAP; + if (name == "cross") + return &Graphics::VectorRenderer::drawCallback_CROSS; + + return 0; +} + + bool ThemeParser::parserCallback_drawstep(ParserNode *node) { Graphics::DrawStep *drawstep = newDrawStep(); Common::String functionName = node->values["func"]; - if (_drawFunctions.contains(functionName) == false) - return parserError("%s is not a valid drawing function name", functionName.c_str()); + drawstep->drawingCall = getDrawingFunctionCallback(functionName); - drawstep->drawingCall = _drawFunctions[functionName]; + if (drawstep->drawingCall == 0) + return parserError("%s is not a valid drawing function name", functionName.c_str()); if (!parseDrawStep(node, drawstep, true)) return false; @@ -566,7 +584,14 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return parserError("Corrupted height value in key for %s", var.c_str()); } - _theme->getEvaluator()->addWidget(var, width, height, node->values["type"], enabled); + Graphics::TextAlign alignH = Graphics::kTextAlignLeft; + + if (node->values.contains("textalign")) { + if((alignH = parseTextHAlign(node->values["textalign"])) == Graphics::kTextAlignInvalid) + return parserError("Invalid value for text alignment."); + } + + _theme->getEvaluator()->addWidget(var, width, height, node->values["type"], enabled, alignH); } return true; @@ -783,6 +808,15 @@ bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String _theme->getEvaluator()->setVar(var + "Padding.Bottom", paddingB); } + + if (node->values.contains("textalign")) { + Graphics::TextAlign alignH = Graphics::kTextAlignLeft; + + if((alignH = parseTextHAlign(node->values["textalign"])) == Graphics::kTextAlignInvalid) + return parserError("Invalid value for text alignment."); + + _theme->getEvaluator()->setVar(var + "Align", alignH); + } return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 520b319a06..e261b6b842 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -27,7 +27,6 @@ #define THEME_PARSER_H #include "common/scummsys.h" -#include "common/system.h" #include "common/xmlparser.h" namespace GUI { @@ -35,8 +34,6 @@ namespace GUI { class ThemeEngine; class ThemeParser : public Common::XMLParser { - typedef void (Graphics::VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &); - public: ThemeParser(ThemeEngine *parent); @@ -169,6 +166,7 @@ protected: XML_PROP(pos, false) XML_PROP(padding, false) XML_PROP(resolution, false) + XML_PROP(textalign, false) KEY_END() KEY_END() @@ -195,6 +193,7 @@ protected: XML_PROP(height, false) XML_PROP(type, false) XML_PROP(enabled, false) + XML_PROP(textalign, false) KEY_END() XML_KEY(space) @@ -247,8 +246,6 @@ protected: Graphics::DrawStep *_defaultStepGlobal; Graphics::DrawStep *_defaultStepLocal; - Common::HashMap<Common::String, DrawingFunctionCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _drawFunctions; - struct PaletteColor { uint8 r, g, b; }; diff --git a/gui/console.h b/gui/console.h index ae38d1d690..52c3394184 100644 --- a/gui/console.h +++ b/gui/console.h @@ -143,7 +143,7 @@ public: void handleKeyDown(Common::KeyState state); void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); - int printf(const char *format, ...); + int printf(const char *format, ...) GCC_PRINTF(2, 3); int vprintf(const char *format, va_list argptr); #undef putchar void putchar(int c); diff --git a/gui/credits.h b/gui/credits.h index 4bfd788172..869adec827 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -61,6 +61,7 @@ static const char *credits[] = { "C1""Cinematique evo 2", "C0""Vincent Hamm", "C2""original CruisE engine author", +"C0""Paul Gilbert", "", "C1""FOTAQ", "C0""Gregory Montoir", diff --git a/gui/debugger.cpp b/gui/debugger.cpp index c32b68f3de..181403484b 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -39,7 +39,7 @@ Debugger::Debugger() { _isAttached = false; _errStr = NULL; _firstTime = true; - _debuggerDialog = new GUI::ConsoleDialog(1.0, 0.67F); + _debuggerDialog = new GUI::ConsoleDialog(1.0f, 0.67f); _debuggerDialog->setInputCallback(debuggerInputCallback, this); _debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this); diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 964ef35b77..5e3a9a1927 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -92,10 +92,7 @@ void Dialog::open() { w = w->_next; } - if (w) { - w->receivedFocus(); - _focusedWidget = w; - } + setFocusWidget(w); } void Dialog::close() { @@ -123,6 +120,18 @@ void Dialog::reflowLayout() { GuiObject::reflowLayout(); } +void Dialog::setFocusWidget(Widget *widget) { + // The focus will change. Tell the old focused widget (if any) + // that it lost the focus. + releaseFocus(); + + // Tell the new focused widget (if any) that it just gained the focus. + if (widget) + widget->receivedFocus(); + + _focusedWidget = widget; +} + void Dialog::releaseFocus() { if (_focusedWidget) { _focusedWidget->lostFocus(); @@ -165,15 +174,7 @@ void Dialog::handleMouseDown(int x, int y, int button, int clickCount) { // If the click occured inside a widget which is not the currently // focused one, change the focus to that widget. if (w && w != _focusedWidget && w->wantsFocus()) { - // The focus will change. Tell the old focused widget (if any) - // that it lost the focus. - releaseFocus(); - - // Tell the new focused widget (if any) that it just gained the focus. - if (w) - w->receivedFocus(); - - _focusedWidget = w; + setFocusWidget(w); } if (w) diff --git a/gui/dialog.h b/gui/dialog.h index 018677d82b..dcc7d6fe27 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -63,6 +63,8 @@ public: bool isVisible() const { return _visible; } void releaseFocus(); + void setFocusWidget(Widget *widget); + Widget *getFocusWidget() { return _focusedWidget; } virtual void reflowLayout(); diff --git a/gui/editable.cpp b/gui/editable.cpp index 38dcb1ecf5..232873ffe3 100644 --- a/gui/editable.cpp +++ b/gui/editable.cpp @@ -28,13 +28,13 @@ namespace GUI { -EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h) - : Widget(boss, x, y, w, h) { +EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) + : Widget(boss, x, y, w, h), CommandSender(boss), _cmd(cmd) { init(); } -EditableWidget::EditableWidget(GuiObject *boss, const String &name) - : Widget(boss, name) { +EditableWidget::EditableWidget(GuiObject *boss, const String &name, uint32 cmd) + : Widget(boss, name), CommandSender(boss), _cmd(cmd) { init(); } @@ -109,6 +109,8 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) { _caretPos--; _editString.deleteChar(_caretPos); dirty = true; + + sendCommand(_cmd, 0); } forcecaret = true; break; @@ -116,6 +118,8 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) { if (_caretPos < (int)_editString.size()) { _editString.deleteChar(_caretPos); dirty = true; + + sendCommand(_cmd, 0); } forcecaret = true; break; @@ -146,6 +150,8 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) { _caretPos++; dirty = true; forcecaret = true; + + sendCommand(_cmd, 0); } else { handled = false; } diff --git a/gui/editable.h b/gui/editable.h index f01a4a5da2..363ba7b9f6 100644 --- a/gui/editable.h +++ b/gui/editable.h @@ -36,12 +36,14 @@ namespace GUI { * Base class for widgets which need to edit text, like ListWidget and * EditTextWidget. */ -class EditableWidget : public Widget { +class EditableWidget : public Widget, public CommandSender { public: typedef Common::String String; protected: String _editString; + uint32 _cmd; + bool _caretVisible; uint32 _caretTime; int _caretPos; @@ -53,8 +55,8 @@ protected: ThemeEngine::FontStyle _font; public: - EditableWidget(GuiObject *boss, int x, int y, int w, int h); - EditableWidget(GuiObject *boss, const String &name); + EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0); + EditableWidget(GuiObject *boss, const String &name, uint32 cmd = 0); virtual ~EditableWidget(); void init(); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index de58fe463d..da49c1ccfd 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -64,7 +64,9 @@ enum { kRemoveGameCmd = 'REMG', kLoadGameCmd = 'LOAD', kQuitCmd = 'QUIT', - + kSearchCmd = 'SRCH', + kListSearchCmd = 'LSSR', + kSearchClearCmd = 'SRCL', kCmdGlobalGraphicsOverride = 'OGFX', kCmdGlobalAudioOverride = 'OSFX', @@ -133,7 +135,9 @@ protected: StaticTextWidget *_extraPathWidget; StaticTextWidget *_savePathWidget; + StaticTextWidget *_langPopUpDesc; PopUpWidget *_langPopUp; + StaticTextWidget *_platformPopUpDesc; PopUpWidget *_platformPopUp; CheckboxWidget *_globalGraphicsOverride; @@ -173,7 +177,8 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description); // Language popup - _langPopUp = new PopUpWidget(tab, "GameOptions_Game.Lang", "Language:"); + _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", "Language:"); + _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup"); _langPopUp->appendEntry("<default>"); _langPopUp->appendEntry(""); const Common::LanguageDescription *l = Common::g_languages; @@ -182,7 +187,8 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // Platform popup - _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.Platform", "Platform:"); + _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", "Platform:"); + _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup"); _platformPopUp->appendEntry("<default>"); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; @@ -225,6 +231,9 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); + if (_guioptions & Common::GUIO_NOMIDI) + _globalMIDIOverride->setEnabled(false); + addMIDIControls(tab, "GameOptions_MIDI."); // @@ -504,9 +513,22 @@ LauncherDialog::LauncherDialog() _removeButton = new ButtonWidget(this, "Launcher.RemoveGameButton", "Remove Game", kRemoveGameCmd, 'R'); + // Search box + _searchDesc = 0; +#ifndef DISABLE_FANCY_THEMES + _searchPic = 0; + if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) { + _searchPic = new GraphicsWidget(this, "Launcher.SearchPic"); + _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch)); + } else +#endif + _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:"); + + _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, kSearchCmd); + _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", kSearchClearCmd, 0); // Add list with game titles - _list = new ListWidget(this, "Launcher.GameList"); + _list = new ListWidget(this, "Launcher.GameList", kListSearchCmd); _list->setEditable(false); _list->setNumberingMode(kListNumberingOff); @@ -630,10 +652,21 @@ void LauncherDialog::addGame() { "This could potentially add a huge number of games.", "Yes", "No"); if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) { MassAddDialog massAddDlg(_browser->getResult()); + + if (_list->getSelected() != -1) { + // Save current game position, so on cancel cursor will move back + ConfMan.set("temp_selection", _domains[_list->getSelected()], ConfigManager::kApplicationDomain); + } + massAddDlg.runModal(); // Update the ListWidget and force a redraw updateListing(); + + // Set cursor to first detected game + selectGame(ConfMan.get("temp_selection", ConfigManager::kApplicationDomain)); + ConfMan.removeKey("temp_selection", ConfigManager::kApplicationDomain); + draw(); } @@ -652,68 +685,77 @@ void LauncherDialog::addGame() { // 3) Display the 'Edit' dialog for that item, letting the user specify // an alternate description (to distinguish multiple versions of the // game, e.g. 'Monkey German' and 'Monkey English') and set default - // options for that game. - - if (_browser->runModal() > 0) { - // User made his choice... - Common::FSNode dir(_browser->getResult()); - Common::FSList files; - if (!dir.getChildren(files, Common::FSNode::kListAll)) { - MessageDialog alert("ScummVM couldn't open the specified directory!"); - alert.runModal(); - return; - } + // options for that game + // 4) If no game is found in the specified directory, return to the + // dialog. - // ...so let's determine a list of candidates, games that - // could be contained in the specified directory. - GameList candidates(EngineMan.detectGames(files)); - - int idx; - if (candidates.empty()) { - // No game was found in the specified directory - MessageDialog alert("ScummVM could not find any game in the specified directory!"); - alert.runModal(); - idx = -1; - } else if (candidates.size() == 1) { - // Exact match - idx = 0; - } else { - // Display the candidates to the user and let her/him pick one - StringList list; - for (idx = 0; idx < (int)candidates.size(); idx++) - list.push_back(candidates[idx].description()); - - ChooserDialog dialog("Pick the game:"); - dialog.setList(list); - idx = dialog.runModal(); - } - if (0 <= idx && idx < (int)candidates.size()) { - GameDescriptor result = candidates[idx]; + bool looping; + do { + looping = false; - // TODO: Change the detectors to set "path" ! - result["path"] = dir.getPath(); - - Common::String domain = addGameToConf(result); + if (_browser->runModal() > 0) { + // User made his choice... + Common::FSNode dir(_browser->getResult()); + Common::FSList files; + if (!dir.getChildren(files, Common::FSNode::kListAll)) { + MessageDialog alert("ScummVM couldn't open the specified directory!"); + alert.runModal(); + return; + } - // Display edit dialog for the new entry - EditGameDialog editDialog(domain, result.description()); - if (editDialog.runModal() > 0) { - // User pressed OK, so make changes permanent + // ...so let's determine a list of candidates, games that + // could be contained in the specified directory. + GameList candidates(EngineMan.detectGames(files)); - // Write config to disk - ConfMan.flushToDisk(); + int idx; + if (candidates.empty()) { + // No game was found in the specified directory + MessageDialog alert("ScummVM could not find any game in the specified directory!"); + alert.runModal(); + idx = -1; - // Update the ListWidget, select the new item, and force a redraw - updateListing(); - selectGame(editDialog.getDomain()); - draw(); + looping = true; + } else if (candidates.size() == 1) { + // Exact match + idx = 0; } else { - // User aborted, remove the the new domain again - ConfMan.removeGameDomain(domain); + // Display the candidates to the user and let her/him pick one + StringList list; + for (idx = 0; idx < (int)candidates.size(); idx++) + list.push_back(candidates[idx].description()); + + ChooserDialog dialog("Pick the game:"); + dialog.setList(list); + idx = dialog.runModal(); } + if (0 <= idx && idx < (int)candidates.size()) { + GameDescriptor result = candidates[idx]; + + // TODO: Change the detectors to set "path" ! + result["path"] = dir.getPath(); + Common::String domain = addGameToConf(result); + + // Display edit dialog for the new entry + EditGameDialog editDialog(domain, result.description()); + if (editDialog.runModal() > 0) { + // User pressed OK, so make changes permanent + + // Write config to disk + ConfMan.flushToDisk(); + + // Update the ListWidget, select the new item, and force a redraw + updateListing(); + selectGame(editDialog.getDomain()); + draw(); + } else { + // User aborted, remove the the new domain again + ConfMan.removeGameDomain(domain); + } + + } } - } + } while (looping); } Common::String addGameToConf(const GameDescriptor &result) { @@ -831,6 +873,14 @@ void LauncherDialog::loadGame(int item) { } void LauncherDialog::handleKeyDown(Common::KeyState state) { + if (state.keycode == Common::KEYCODE_TAB) { + // Toggle between the game list and the quick search field. + if (getFocusWidget() == _searchWidget) { + setFocusWidget(_list); + } else if (getFocusWidget() == _list) { + setFocusWidget(_searchWidget); + } + } Dialog::handleKeyDown(state); updateButtons(); } @@ -885,6 +935,13 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat setResult(-1); close(); break; + case kSearchCmd: + _list->setFilter(_searchWidget->getEditString()); + break; + case kSearchClearCmd: + _searchWidget->setEditString(""); + _list->setFilter(""); + break; default: Dialog::handleCommand(sender, cmd, data); } @@ -904,8 +961,15 @@ void LauncherDialog::updateButtons() { _removeButton->setEnabled(enable); _removeButton->draw(); } - if (enable != _loadButton->isEnabled()) { - _loadButton->setEnabled(enable); + + int item = _list->getSelected(); + bool en = enable; + + if (item >= 0) + en = !(Common::checkGameGUIOption(Common::GUIO_NOLAUNCHLOAD, ConfMan.get("guioptions", _domains[item]))); + + if (en != _loadButton->isEnabled()) { + _loadButton->setEnabled(en); _loadButton->draw(); } @@ -946,6 +1010,29 @@ void LauncherDialog::reflowLayout() { _logo = 0; } } + + if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) { + if (!_searchPic) + _searchPic = new GraphicsWidget(this, "Launcher.SearchPic"); + _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch)); + + if (_searchDesc) { + removeWidget(_searchDesc); + _searchDesc->setNext(0); + delete _searchDesc; + _searchDesc = 0; + } + } else { + if (!_searchDesc) + _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:"); + + if (_searchPic) { + removeWidget(_searchPic); + _searchPic->setNext(0); + delete _searchPic; + _searchPic = 0; + } + } #endif _w = g_system->getOverlayWidth(); diff --git a/gui/launcher.h b/gui/launcher.h index b9a76c80ca..d482f26faf 100644 --- a/gui/launcher.h +++ b/gui/launcher.h @@ -34,6 +34,7 @@ class BrowserDialog; class ListWidget; class GraphicsWidget; class SaveLoadChooser; +class EditTextWidget; Common::String addGameToConf(const GameDescriptor &result); @@ -50,6 +51,7 @@ public: virtual void handleKeyUp(Common::KeyState state); protected: + EditTextWidget *_searchWidget; ListWidget *_list; ButtonWidget *_addButton; Widget *_startButton; @@ -58,11 +60,16 @@ protected: Widget *_removeButton; #ifndef DISABLE_FANCY_THEMES GraphicsWidget *_logo; + GraphicsWidget *_searchPic; #endif + StaticTextWidget *_searchDesc; + ButtonWidget *_searchClearButton; StringList _domains; BrowserDialog *_browser; SaveLoadChooser *_loadDialog; + String _search; + virtual void reflowLayout(); void updateListing(); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 1b1f3f7ff0..4e43d342cb 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -32,6 +32,7 @@ #include "gui/massadd.h" #include "gui/GuiManager.h" #include "gui/widget.h" +#include "gui/ListWidget.h" namespace GUI { @@ -65,6 +66,8 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) _dirProgressText(0), _gameProgressText(0) { + Common::StringList l; + // The dir we start our scan at _scanStack.push(startDir); @@ -80,6 +83,11 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) _dirProgressText->setAlign(Graphics::kTextAlignCenter); _gameProgressText->setAlign(Graphics::kTextAlignCenter); + _list = new ListWidget(this, "MassAdd.GameList"); + _list->setEditable(false); + _list->setNumberingMode(kListNumberingOff); + _list->setList(l); + _okButton = new ButtonWidget(this, "MassAdd.Ok", "OK", kOkCmd, Common::ASCII_RETURN); _okButton->setEnabled(false); @@ -110,30 +118,40 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) } } -struct GameDescLess { +struct GameTargetLess { bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { return x.preferredtarget().compareToIgnoreCase(y.preferredtarget()) < 0; } }; +struct GameDescLess { + bool operator()(const GameDescriptor &x, const GameDescriptor &y) const { + return x.description().compareToIgnoreCase(y.description()) < 0; + } +}; + void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { // FIXME: It's a really bad thing that we use two arbitrary constants if (cmd == kOkCmd) { // Sort the detected games. This is not strictly necessary, but nice for // people who want to edit their config file by hand after a mass add. - sort(_games.begin(), _games.end(), GameDescLess()); + sort(_games.begin(), _games.end(), GameTargetLess()); // Add all the detected games to the config - for (GameList::const_iterator iter = _games.begin(); iter != _games.end(); ++iter) { + for (GameList::iterator iter = _games.begin(); iter != _games.end(); ++iter) { printf(" Added gameid '%s', desc '%s'\n", (*iter)["gameid"].c_str(), (*iter)["description"].c_str()); - addGameToConf(*iter); + (*iter)["gameid"] = addGameToConf(*iter); } // Write everything to disk ConfMan.flushToDisk(); + // And scroll to first detected game + sort(_games.begin(), _games.end(), GameDescLess()); + ConfMan.set("temp_selection", _games.front().gameid()); + close(); } else if (cmd == kCancelCmd) { // User cancelled, so we don't do anything and just leave. @@ -196,6 +214,8 @@ void MassAddDialog::handleTickle() { } result["path"] = path; _games.push_back(result); + + _list->append(result.description()); } @@ -231,6 +251,10 @@ void MassAddDialog::handleTickle() { _gameProgressText->setLabel(buf); } + if (_games.size() > 0) { + _list->scrollToEnd(); + } + drawDialog(); } diff --git a/gui/massadd.h b/gui/massadd.h index c2a0eff2ba..106b285a64 100644 --- a/gui/massadd.h +++ b/gui/massadd.h @@ -60,6 +60,8 @@ private: Widget *_okButton; StaticTextWidget *_dirProgressText; StaticTextWidget *_gameProgressText; + + ListWidget *_list; }; diff --git a/gui/options.cpp b/gui/options.cpp index 415d7ca357..5991a204e9 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -119,11 +119,17 @@ void OptionsDialog::init() { _speechVolumeDesc = 0; _speechVolumeSlider = 0; _speechVolumeLabel = 0; + _muteCheckbox = 0; _subToggleDesc = 0; _subToggleButton = 0; _subSpeedDesc = 0; _subSpeedSlider = 0; _subSpeedLabel = 0; + + // Retrieve game GUI options + _guioptions = 0; + if (ConfMan.hasKey("guioptions", _domain)) + _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain)); } void OptionsDialog::open() { @@ -132,6 +138,11 @@ void OptionsDialog::open() { // Reset result value setResult(0); + // Retrieve game GUI options + _guioptions = 0; + if (ConfMan.hasKey("guioptions", _domain)) + _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain)); + // Graphic options if (_fullscreenCheckbox) { _gfxPopUp->setSelected(0); @@ -240,12 +251,19 @@ void OptionsDialog::open() { vol = ConfMan.getInt("speech_volume", _domain); _speechVolumeSlider->setValue(vol); _speechVolumeLabel->setValue(vol); + + bool val = false; + if (ConfMan.hasKey("mute", _domain)) { + val = ConfMan.getBool("mute", _domain); + } else { + ConfMan.setBool("mute", false); + } + _muteCheckbox->setState(val); } // Subtitle options if (_subToggleButton) { - int speed; - int sliderMaxValue = _subSpeedSlider->getMaxValue(); + int speed; int sliderMaxValue = _subSpeedSlider->getMaxValue(); _subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain)); _subToggleButton->setLabel(_subModeDesc[_subMode]); @@ -300,10 +318,12 @@ void OptionsDialog::close() { ConfMan.setInt("music_volume", _musicVolumeSlider->getValue(), _domain); ConfMan.setInt("sfx_volume", _sfxVolumeSlider->getValue(), _domain); ConfMan.setInt("speech_volume", _speechVolumeSlider->getValue(), _domain); + ConfMan.setBool("mute", _muteCheckbox->getState(), _domain); } else { ConfMan.removeKey("music_volume", _domain); ConfMan.removeKey("sfx_volume", _domain); ConfMan.removeKey("speech_volume", _domain); + ConfMan.removeKey("mute", _domain); } } @@ -467,7 +487,9 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data void OptionsDialog::setGraphicSettingsState(bool enabled) { _enableGraphicSettings = enabled; + _gfxPopUpDesc->setEnabled(enabled); _gfxPopUp->setEnabled(enabled); + _renderModePopUpDesc->setEnabled(enabled); _renderModePopUp->setEnabled(enabled); #ifndef SMALL_SCREEN_DEVICE _fullscreenCheckbox->setEnabled(enabled); @@ -478,12 +500,18 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) { void OptionsDialog::setAudioSettingsState(bool enabled) { _enableAudioSettings = enabled; + _midiPopUpDesc->setEnabled(enabled); _midiPopUp->setEnabled(enabled); + _oplPopUpDesc->setEnabled(enabled); _oplPopUp->setEnabled(enabled); + _outputRatePopUpDesc->setEnabled(enabled); _outputRatePopUp->setEnabled(enabled); } void OptionsDialog::setMIDISettingsState(bool enabled) { + if (_guioptions & Common::GUIO_NOMIDI) + enabled = false; + _enableMIDISettings = enabled; _soundFontButton->setEnabled(enabled); @@ -503,34 +531,63 @@ void OptionsDialog::setMIDISettingsState(bool enabled) { } void OptionsDialog::setVolumeSettingsState(bool enabled) { + bool ena; + _enableVolumeSettings = enabled; - _musicVolumeDesc->setEnabled(enabled); - _musicVolumeSlider->setEnabled(enabled); - _musicVolumeLabel->setEnabled(enabled); - _sfxVolumeDesc->setEnabled(enabled); - _sfxVolumeSlider->setEnabled(enabled); - _sfxVolumeLabel->setEnabled(enabled); - _speechVolumeDesc->setEnabled(enabled); - _speechVolumeSlider->setEnabled(enabled); - _speechVolumeLabel->setEnabled(enabled); + ena = enabled; + if (_guioptions & Common::GUIO_NOMUSIC) + ena = false; + + _musicVolumeDesc->setEnabled(ena); + _musicVolumeSlider->setEnabled(ena); + _musicVolumeLabel->setEnabled(ena); + + ena = enabled; + if (_guioptions & Common::GUIO_NOSFX) + ena = false; + + _sfxVolumeDesc->setEnabled(ena); + _sfxVolumeSlider->setEnabled(ena); + _sfxVolumeLabel->setEnabled(ena); + + ena = enabled; + if (_guioptions & Common::GUIO_NOSPEECH) + ena = false; + + _speechVolumeDesc->setEnabled(ena); + _speechVolumeSlider->setEnabled(ena); + _speechVolumeLabel->setEnabled(ena); + + _muteCheckbox->setEnabled(enabled); } void OptionsDialog::setSubtitleSettingsState(bool enabled) { + bool ena; _enableSubtitleSettings = enabled; - _subToggleButton->setEnabled(enabled); - _subToggleDesc->setEnabled(enabled); - _subSpeedDesc->setEnabled(enabled); - _subSpeedSlider->setEnabled(enabled); - _subSpeedLabel->setEnabled(enabled); + ena = enabled; + if ((_guioptions & Common::GUIO_NOSUBTITLES) || (_guioptions & Common::GUIO_NOSPEECH)) + ena = false; + + _subToggleButton->setEnabled(ena); + _subToggleDesc->setEnabled(ena); + + ena = enabled; + if (_guioptions & Common::GUIO_NOSUBTITLES) + ena = false; + + _subSpeedDesc->setEnabled(ena); + _subSpeedSlider->setEnabled(ena); + _subSpeedLabel->setEnabled(ena); } void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); // The GFX mode popup - _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:"); + _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", "Graphics mode:"); + _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup"); _gfxPopUp->appendEntry("<default>"); _gfxPopUp->appendEntry(""); @@ -540,7 +597,8 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { } // RenderMode popup - _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode:"); + _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", "Render mode:"); + _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup"); _renderModePopUp->appendEntry("<default>", Common::kRenderDefault); _renderModePopUp->appendEntry(""); const Common::RenderModeDescription *rm = Common::g_renderModes; @@ -559,7 +617,8 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { // The MIDI mode popup & a label - _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:"); + _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", "Music driver:"); + _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup"); // Populate it const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); @@ -569,7 +628,8 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { } // The OPL emulator popup & a label - _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup", "AdLib emulator:"); + _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", "AdLib emulator:"); + _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup"); // Populate it const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable(); @@ -579,7 +639,8 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { } // Sample rate settings - _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate:"); + _outputRatePopUpDesc = new StaticTextWidget(boss, prefix + "auSampleRatePopupDesc", "Output rate:"); + _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup"); for (int i = 0; outputRateLabels[i]; i++) { _outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]); @@ -640,6 +701,9 @@ void OptionsDialog::addVolumeControls(GuiObject *boss, const String &prefix) { _musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); _musicVolumeLabel->setFlags(WIDGET_CLEARBG); + _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", "Mute All", 0, 0); + + _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", "SFX volume:"); _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", kSfxVolumeChanged); _sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%"); @@ -658,6 +722,11 @@ void OptionsDialog::addVolumeControls(GuiObject *boss, const String &prefix) { } int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { + if (_guioptions & Common::GUIO_NOSUBTITLES) + return 0; // Speech only + if (_guioptions & Common::GUIO_NOSPEECH) + return 2; // Subtitles only + if (!subtitles && !speech_mute) // Speech only return 0; else if (subtitles && !speech_mute) // Speech and subtitles @@ -740,12 +809,14 @@ GlobalOptionsDialog::GlobalOptionsDialog() _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); - _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.Renderer", "GUI Renderer:"); + _rendererPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.RendererPopupDesc", "GUI Renderer:"); + _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.RendererPopup"); for (uint i = 1; i < GUI::ThemeEngine::_rendererModesSize; ++i) _rendererPopUp->appendEntry(GUI::ThemeEngine::_rendererModes[i].name, GUI::ThemeEngine::_rendererModes[i].mode); - _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:"); + _autosavePeriodPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopupDesc", "Autosave:"); + _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopup"); for (int i = 0; savePeriodLabels[i]; i++) { _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]); diff --git a/gui/options.h b/gui/options.h index 53fc5e2d01..13803aee77 100644 --- a/gui/options.h +++ b/gui/options.h @@ -91,17 +91,22 @@ private: // Graphics controls // bool _enableGraphicSettings; + StaticTextWidget *_gfxPopUpDesc; PopUpWidget *_gfxPopUp; CheckboxWidget *_fullscreenCheckbox; CheckboxWidget *_aspectCheckbox; + StaticTextWidget *_renderModePopUpDesc; PopUpWidget *_renderModePopUp; // // Audio controls // bool _enableAudioSettings; + StaticTextWidget *_midiPopUpDesc; PopUpWidget *_midiPopUp; + StaticTextWidget *_oplPopUpDesc; PopUpWidget *_oplPopUp; + StaticTextWidget *_outputRatePopUpDesc; PopUpWidget *_outputRatePopUp; // @@ -145,6 +150,14 @@ private: StaticTextWidget *_speechVolumeDesc; SliderWidget *_speechVolumeSlider; StaticTextWidget *_speechVolumeLabel; + + CheckboxWidget *_muteCheckbox; + +protected: + // + // Game GUI options + // + uint32 _guioptions; }; @@ -173,7 +186,9 @@ protected: // Misc controls // StaticTextWidget *_curTheme; + StaticTextWidget *_rendererPopUpDesc; PopUpWidget *_rendererPopUp; + StaticTextWidget *_autosavePeriodPopUpDesc; PopUpWidget *_autosavePeriodPopUp; }; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index ddb8127d77..d2fe7dade5 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -329,14 +329,17 @@ "<def var='Line.Height' value='16' /> " "<def var='Font.Height' value='16' /> " "<def var='About.OuterBorder' value='80'/> " -"<def var='PopUpWidget.labelSpacing' value='10' /> " -"<def var='PopUpWidget.labelWidth' value='110' /> " "<def var='Layout.Spacing' value='8' /> " "<def var='ShowLauncherLogo' value='0'/> " "<def var='ShowGlobalMenuLogo' value='0'/> " +"<def var='ShowSearchPic' value='0'/> " "<def var='ScummSaveLoad.ExtInfo.Visible' value='1'/> " +"<def var='KeyMapper.Spacing' value='10'/> " +"<def var='KeyMapper.LabelWidth' value='100'/> " +"<def var='KeyMapper.ButtonWidth' value='80'/> " "<widget name='OptionsLabel' " "size='110,Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='SmallLabel' " "size='24,Globals.Line.Height' " @@ -385,6 +388,22 @@ "<widget name='Version' " "height='Globals.Line.Height' " "/> " +"<layout type='horizontal' spacing='5' padding='10,0,0,0'> " +"<widget name='SearchDesc' " +"width='60' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='Search' " +"width='150' " +"height='Globals.Line.Height' " +"/> " +"<widget name='SearchClearButton' " +"height='Globals.Line.Height' " +"width='Globals.Line.Height' " +"/> " +"<space /> " +"</layout> " "<widget name='GameList'/> " "<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='LoadGameButton' " @@ -456,12 +475,22 @@ "</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'> " +"<widget name='grModePopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='grModePopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='grRenderPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='grRenderPopup' " "type='PopUp' " "/> " +"</layout> " "<widget name='grAspectCheckbox' " "type='Checkbox' " "/> " @@ -472,16 +501,31 @@ "</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'> " +"<widget name='auMidiPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auMidiPopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='auOPLPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auOPLPopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='auSampleRatePopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auSampleRatePopup' " "type='PopUp' " "/> " -"<layout type='horizontal' padding='0,0,0,0'> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " @@ -490,7 +534,7 @@ "height='Globals.Slider.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -504,7 +548,8 @@ "</layout> " "</dialog> " "<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<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' " @@ -539,10 +584,16 @@ "/> " "</layout> " "</layout> " +"<layout type='vertical' padding='24,0,24,0' center='true'> " +"<widget name='vcMuteCheckbox' " +"type='Checkbox' " +"/> " +"</layout> " +"</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'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='mcFontButton' " "type='Button' " "/> " @@ -579,7 +630,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' " "/> " @@ -587,7 +638,7 @@ "height='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' " "/> " @@ -595,7 +646,7 @@ "height='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' " "/> " @@ -615,7 +666,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' " "/> " @@ -623,12 +674,22 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<widget name='Renderer' " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='RendererPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='RendererPopup' " "type='PopUp' " "/> " -"<widget name='AutosavePeriod' " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='AutosavePeriodPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='AutosavePeriodPopup' " "type='PopUp' " "/> " +"</layout> " "<widget name='KeysButton' " "type='Button' " "/> " @@ -706,7 +767,7 @@ "</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='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Id' " "type='OptionsLabel' " "/> " @@ -714,7 +775,7 @@ "type='PopUp' " "/> " "</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='Name' " "type='OptionsLabel' " "/> " @@ -722,17 +783,27 @@ "type='PopUp' " "/> " "</layout> " -"<widget name='Lang' " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='LangPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='LangPopup' " "type='PopUp' " "/> " -"<widget name='Platform' " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='PlatformPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='PlatformPopup' " "type='PopUp' " "/> " "</layout> " +"</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='16' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Savepath' " "type='Button' " "/> " @@ -740,7 +811,7 @@ "height='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' " "/> " @@ -748,7 +819,7 @@ "height='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' " "/> " @@ -830,7 +901,9 @@ "</layout> " "</dialog> " "<dialog name='ScummConfig' overlays='screen_center'> " -"<layout type='vertical' padding='8,8,8,8' center='true'> " +"<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'> " "<widget name='vcMusicText' " "type='OptionsLabel' " @@ -864,7 +937,16 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"</layout> " +"<layout type='vertical' padding='24,24,24,24' center='true'> " +"<widget name='vcMuteCheckbox' " +"type='Checkbox' " +"width='80' " +"/> " +"</layout> " +"</layout> " +"<space size='8' /> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " @@ -873,7 +955,7 @@ "height='Globals.Slider.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -885,7 +967,7 @@ "/> " "</layout> " "<space size='60'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='Keys' " "type='Button' " "/> " @@ -959,7 +1041,10 @@ "width='250' " "height='Globals.Line.Height' " "/> " -"<space size='32' /> " +"<widget name='GameList' " +"width='480' " +"height='250' " +"/> " "<layout type='horizontal' padding='8,8,8,8'> " "<widget name='Ok' " "type='Button' " @@ -970,18 +1055,41 @@ "</layout> " "</layout> " "</dialog> " +"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> " +"<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='400' " +"height='Globals.Line.Height' " +"/> " +"</layout> " +"<widget name='KeymapArea' " +"width='600' " +"height='280' " +"/> " +"<widget name='Close' " +"type='Button' " +"/> " +"</layout> " +"</dialog> " "</layout_info> " "<layout_info resolution='320xY,256x240,Xx272'> " "<globals> " "<def var='Line.Height' value='12' /> " "<def var='Font.Height' value='10' /> " "<def var='About.OuterBorder' value='10'/> " -"<def var='PopUpWidget.labelSpacing' value='6' /> " -"<def var='PopUpWidget.labelWidth' value='100' /> " "<def var='Layout.Spacing' value='8'/> " "<def var='ShowLauncherLogo' value='0'/> " "<def var='ShowGlobalMenuLogo' value='0'/> " +"<def var='ShowSearchPic' value='0'/> " "<def var='ScummSaveLoad.ExtInfo.Visible' value='0'/> " +"<def var='KeyMapper.Spacing' value='5'/> " +"<def var='KeyMapper.LabelWidth' value='80'/> " +"<def var='KeyMapper.ButtonWidth' value='60'/> " "<widget name='Button' " "size='72,16' " "/> " @@ -990,6 +1098,7 @@ "/> " "<widget name='OptionsLabel' " "size='110,Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='SmallLabel' " "size='18,Globals.Line.Height' " @@ -1029,6 +1138,22 @@ "<widget name='Version' " "height='Globals.Line.Height' " "/> " +"<layout type='horizontal' spacing='5' padding='10,0,0,0'> " +"<widget name='SearchDesc' " +"width='50' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='Search' " +"width='150' " +"height='Globals.Line.Height' " +"/> " +"<widget name='SearchClearButton' " +"height='Globals.Line.Height' " +"width='Globals.Line.Height' " +"/> " +"<space /> " +"</layout> " "<widget name='GameList'/> " "<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='LoadGameButton' " @@ -1099,12 +1224,22 @@ "</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'> " +"<widget name='grModePopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='grModePopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='grRenderPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='grRenderPopup' " "type='PopUp' " "/> " +"</layout> " "<widget name='grAspectCheckbox' " "type='Checkbox' " "/> " @@ -1115,16 +1250,31 @@ "</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'> " +"<widget name='auMidiPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auMidiPopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='auOPLPopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auOPLPopup' " "type='PopUp' " "/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='auSampleRatePopupDesc' " +"type='OptionsLabel' " +"/> " "<widget name='auSampleRatePopup' " "type='PopUp' " "/> " -"<layout type='horizontal' padding='0,0,0,0'> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " @@ -1133,7 +1283,7 @@ "height='Globals.Slider.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -1148,7 +1298,7 @@ "</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'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcMusicText' " "type='OptionsLabel' " "/> " @@ -1159,7 +1309,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' " "/> " @@ -1170,7 +1320,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' " "/> " @@ -1181,11 +1331,17 @@ "type='SmallLabel' " "/> " "</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<space size='110' /> " +"<widget name='vcMuteCheckbox' " +"type='Checkbox' " +"/> " +"</layout> " "</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'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " "<widget name='mcFontButton' " "type='Button' " "/> " @@ -1206,7 +1362,7 @@ "<widget name='mcGSCheckbox' " "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' " "/> " @@ -1266,12 +1422,26 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<widget name='Renderer' " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='RendererPopupDesc' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='RendererPopup' " "type='PopUp' " "/> " -"<widget name='AutosavePeriod' " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='AutosavePeriodPopupDesc' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='AutosavePeriodPopup' " "type='PopUp' " "/> " +"</layout> " "<widget name='KeysButton' " "type='Button' " "/> " @@ -1349,32 +1519,48 @@ "</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='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='Id' " "width='35' " "height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='Domain' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='Name' " "width='35' " "height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='Desc' " "type='PopUp' " "/> " "</layout> " "<space size='8'/> " -"<widget name='Lang' " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='LangPopupDesc' " +"width='60' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='LangPopup' " "type='PopUp' " "/> " -"<widget name='Platform' " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='PlatformPopupDesc' " +"width='60' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='PlatformPopup' " "type='PopUp' " "/> " "</layout> " +"</layout> " "</dialog> " "<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> " "<layout type='vertical' padding='16,16,16,16'> " @@ -1484,7 +1670,7 @@ "</dialog> " "<dialog name='ScummConfig' overlays='screen_center'> " "<layout type='vertical' padding='8,8,8,8'> " -"<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' " "/> " @@ -1495,7 +1681,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' " "/> " @@ -1506,7 +1692,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' " "/> " @@ -1517,7 +1703,15 @@ "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'> " +"<space size='110' /> " +"<widget name='vcMuteCheckbox' " +"type='Checkbox' " +"width='80' " +"/> " +"</layout> " +"<space size='4' /> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " @@ -1526,7 +1720,7 @@ "height='Globals.Slider.Height' " "/> " "</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='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -1604,7 +1798,10 @@ "width='240' " "height='Globals.Line.Height' " "/> " -"<space size='16' /> " +"<widget name='GameList' " +"width='280' " +"height='100' " +"/> " "<layout type='horizontal' padding='4,4,4,4'> " "<widget name='Ok' " "type='Button' " @@ -1615,4 +1812,25 @@ "</layout> " "</layout> " "</dialog> " +"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> " +"<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='150' " +"height='Globals.Line.Height' " +"/> " +"</layout> " +"<widget name='KeymapArea' " +"width='300' " +"height='120' " +"/> " +"<widget name='Close' " +"type='Button' " +"/> " +"</layout> " +"</dialog> " "</layout_info> " diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differindex 798f4d292f..cd686aaf1e 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC index c35f4c0a25..0593de00d4 100644 --- a/gui/themes/scummclassic/THEMERC +++ b/gui/themes/scummclassic/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.4:ScummVM Classic Theme:No Author]
\ No newline at end of file +[SCUMMVM_STX0.5:ScummVM Classic Theme:No Author] diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index bb7fdc20a2..0256fc7dd6 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -29,17 +29,21 @@ <def var = 'Font.Height' value = '16' /> <def var = 'About.OuterBorder' value = '80'/> - <def var = 'PopUpWidget.labelSpacing' value = '10' /> - <def var = 'PopUpWidget.labelWidth' value = '110' /> <def var = 'Layout.Spacing' value = '8' /> <def var = 'ShowLauncherLogo' value = '0'/> <def var = 'ShowGlobalMenuLogo' value = '0'/> + <def var = 'ShowSearchPic' value = '0'/> <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '1'/> + <def var = 'KeyMapper.Spacing' value = '10'/> + <def var = 'KeyMapper.LabelWidth' value = '100'/> + <def var = 'KeyMapper.ButtonWidth' value = '80'/> + <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' + textalign = 'right' /> <widget name = 'SmallLabel' size = '24, Globals.Line.Height' @@ -92,6 +96,22 @@ <widget name = 'Version' height = 'Globals.Line.Height' /> + <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <widget name = 'SearchDesc' + width = '60' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'Search' + width = '150' + height = 'Globals.Line.Height' + /> + <widget name = 'SearchClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + <space /> + </layout> <widget name = 'GameList'/> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'LoadGameButton' @@ -166,12 +186,22 @@ <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'grModePopup' - type = 'PopUp' - /> - <widget name = 'grRenderPopup' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'grModePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grModePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'grRenderPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + </layout> <widget name = 'grAspectCheckbox' type = 'Checkbox' /> @@ -183,16 +213,31 @@ <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'auMidiPopup' - type = 'PopUp' - /> - <widget name = 'auOPLPopup' - type = 'PopUp' - /> - <widget name = 'auSampleRatePopup' - type = 'PopUp' - /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auMidiPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auOPLPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auOPLPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auSampleRatePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -201,7 +246,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -216,38 +261,45 @@ </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'> - <widget name = 'vcMusicText' - type = 'OptionsLabel' - /> - <widget name = 'vcMusicSlider' - type = 'Slider' - /> - <widget name = 'vcMusicLabel' - type = 'SmallLabel' - /> + <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' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> - <widget name = 'vcSfxText' - type = 'OptionsLabel' - /> - <widget name = 'vcSfxSlider' - type = 'Slider' - /> - <widget name = 'vcSfxLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> - <widget name = 'vcSpeechText' - type = 'OptionsLabel' - /> - <widget name = 'vcSpeechSlider' - type = 'Slider' - /> - <widget name = 'vcSpeechLabel' - type = 'SmallLabel' + <layout type = 'vertical' padding = '24, 0, 24, 0' center = 'true'> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' /> </layout> </layout> @@ -255,7 +307,7 @@ <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'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'mcFontButton' type = 'Button' /> @@ -293,7 +345,7 @@ <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' /> @@ -301,7 +353,7 @@ height = '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' /> @@ -309,7 +361,7 @@ height = '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' /> @@ -330,7 +382,7 @@ <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' /> @@ -338,12 +390,22 @@ height = 'Globals.Line.Height' /> </layout> - <widget name = 'Renderer' - type = 'PopUp' - /> - <widget name = 'AutosavePeriod' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'RendererPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'RendererPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'AutosavePeriodPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'AutosavePeriodPopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -428,7 +490,7 @@ <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 = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'Id' type = 'OptionsLabel' /> @@ -436,7 +498,7 @@ type = 'PopUp' /> </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 = 'Name' type = 'OptionsLabel' /> @@ -444,18 +506,28 @@ type = 'PopUp' /> </layout> - <widget name = 'Lang' - type = 'PopUp' - /> - <widget name = 'Platform' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'LangPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'LangPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'PlatformPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'PlatformPopup' + type = 'PopUp' + /> + </layout> </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 = '16' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'Savepath' type = 'Button' /> @@ -463,7 +535,7 @@ height = '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' /> @@ -471,7 +543,7 @@ height = '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' /> @@ -556,41 +628,53 @@ </dialog> <dialog name = 'ScummConfig' overlays = 'screen_center'> - <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcMusicText' - type = 'OptionsLabel' - /> - <widget name = 'vcMusicSlider' - type = 'Slider' - /> - <widget name = 'vcMusicLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcSfxText' - type = 'OptionsLabel' - /> - <widget name = 'vcSfxSlider' - type = 'Slider' - /> - <widget name = 'vcSfxLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcSpeechText' - type = 'OptionsLabel' - /> - <widget name = 'vcSpeechSlider' - type = 'Slider' - /> - <widget name = 'vcSpeechLabel' - type = 'SmallLabel' - /> + <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'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + + <layout type = 'vertical' padding = '24, 24, 24, 24' center = 'true'> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + width = '80' <!-- FIXME: Why this is needed? --> + /> + </layout> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = '8' /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -599,7 +683,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -611,7 +695,7 @@ /> </layout> <space size = '60'/> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'Keys' type = 'Button' /> @@ -688,7 +772,10 @@ width = '250' height = 'Globals.Line.Height' /> - <space size = '32' /> + <widget name = 'GameList' + width = '480' + height = '250' + /> <layout type = 'horizontal' padding = '8, 8, 8, 8'> <widget name = 'Ok' type = 'Button' @@ -699,4 +786,25 @@ </layout> </layout> </dialog> + <dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'> + <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 = '400' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'KeymapArea' + width = '600' + height = '280' + /> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </dialog> </layout_info> diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx index c144f0bad3..d4a92b831e 100644 --- a/gui/themes/scummclassic/classic_layout_lowres.stx +++ b/gui/themes/scummclassic/classic_layout_lowres.stx @@ -29,15 +29,19 @@ <def var = 'Font.Height' value = '10' /> <def var = 'About.OuterBorder' value = '10'/> - <def var = 'PopUpWidget.labelSpacing' value = '6' /> - <def var = 'PopUpWidget.labelWidth' value = '100' /> <def var = 'Layout.Spacing' value = '8'/> <def var = 'ShowLauncherLogo' value = '0'/> <def var = 'ShowGlobalMenuLogo' value = '0'/> + <def var = 'ShowSearchPic' value = '0'/> + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> + <def var = 'KeyMapper.Spacing' value = '5'/> + <def var = 'KeyMapper.LabelWidth' value = '80'/> + <def var = 'KeyMapper.ButtonWidth' value = '60'/> + <widget name = 'Button' size = '72, 16' /> @@ -48,6 +52,7 @@ <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' + textalign = 'right' /> <widget name = 'SmallLabel' size = '18, Globals.Line.Height' @@ -88,6 +93,22 @@ <widget name = 'Version' height = 'Globals.Line.Height' /> + <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <widget name = 'SearchDesc' + width = '50' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'Search' + width = '150' + height = 'Globals.Line.Height' + /> + <widget name = 'SearchClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + <space /> + </layout> <widget name = 'GameList'/> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'LoadGameButton' @@ -163,12 +184,22 @@ <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'grModePopup' - type = 'PopUp' - /> - <widget name = 'grRenderPopup' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'grModePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grModePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'grRenderPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + </layout> <widget name = 'grAspectCheckbox' type = 'Checkbox' /> @@ -180,16 +211,31 @@ <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'auMidiPopup' - type = 'PopUp' - /> - <widget name = 'auOPLPopup' - type = 'PopUp' - /> - <widget name = 'auSampleRatePopup' - type = 'PopUp' - /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auMidiPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auOPLPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auOPLPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auSampleRatePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -198,7 +244,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -214,7 +260,7 @@ <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'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'vcMusicText' type = 'OptionsLabel' /> @@ -225,7 +271,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' /> @@ -236,7 +282,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' /> @@ -247,12 +293,18 @@ type = 'SmallLabel' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <space size = '110' /> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + /> + </layout> </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'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> <widget name = 'mcFontButton' type = 'Button' /> @@ -273,7 +325,7 @@ <widget name = 'mcGSCheckbox' 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' /> @@ -335,12 +387,26 @@ height = 'Globals.Line.Height' /> </layout> - <widget name = 'Renderer' - type = 'PopUp' - /> - <widget name = 'AutosavePeriod' + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'RendererPopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'RendererPopup' type = 'PopUp' - /> + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'AutosavePeriodPopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'AutosavePeriodPopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -425,31 +491,47 @@ <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 = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'Id' width = '35' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'Domain' type = 'PopUp' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'Name' width = '35' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'Desc' type = 'PopUp' /> </layout> <space size = '8'/> - <widget name = 'Lang' - type = 'PopUp' - /> - <widget name = 'Platform' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'LangPopupDesc' + width = '60' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'LangPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'PlatformPopupDesc' + width = '60' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'PlatformPopup' + type = 'PopUp' + /> + </layout> </layout> </dialog> @@ -564,7 +646,7 @@ <dialog name = 'ScummConfig' overlays = 'screen_center'> <layout type = 'vertical' padding = '8, 8, 8, 8'> - <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' /> @@ -575,7 +657,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' /> @@ -586,7 +668,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' /> @@ -597,7 +679,15 @@ 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'> + <space size = '110' /> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + width = '80' + /> + </layout> + <space size = '4' /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -606,7 +696,7 @@ height = 'Globals.Slider.Height' /> </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 = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -687,7 +777,10 @@ width = '240' height = 'Globals.Line.Height' /> - <space size = '16' /> + <widget name = 'GameList' + width = '280' + height = '100' + /> <layout type = 'horizontal' padding = '4, 4, 4, 4'> <widget name = 'Ok' type = 'Button' @@ -698,4 +791,25 @@ </layout> </layout> </dialog> + <dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'> + <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 = '150' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'KeymapArea' + width = '300' + height = '120' + /> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </dialog> </layout_info> diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex a67b11f244..a133723d99 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC index e5a1ec0ec1..32b51c573d 100644 --- a/gui/themes/scummmodern/THEMERC +++ b/gui/themes/scummmodern/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.4:ScummVM Modern Theme:No Author]
\ No newline at end of file +[SCUMMVM_STX0.5:ScummVM Modern Theme:No Author] diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx index 473bb3dfa0..b0bba89bfe 100644 --- a/gui/themes/scummmodern/scummmodern_gfx.stx +++ b/gui/themes/scummmodern/scummmodern_gfx.stx @@ -62,7 +62,7 @@ rgb = '251, 241, 206' /> <color name = 'blandyellow' - rgb = '246, 224, 139' + rgb = '248, 228, 152' /> <!-- Others --> @@ -84,6 +84,9 @@ <color name = 'lightgray' rgb = '210, 200, 170' /> + <color name = 'lightgray2' + rgb = '231, 223, 189' + /> <color name = 'paleyellow' rgb = '247, 228, 166' /> @@ -94,7 +97,9 @@ <bitmap filename = 'cursor.bmp'/> <bitmap filename = 'cursor_small.bmp'/> <bitmap filename = 'checkbox.bmp'/> + <bitmap filename = 'checkbox_empty.bmp'/> <bitmap filename = 'logo_small.bmp'/> + <bitmap filename = 'search.bmp'/> </bitmaps> <fonts> @@ -153,7 +158,7 @@ <!-- Load screen --> <drawdata id = 'special_bg' cache = 'false'> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' fill = 'gradient' stroke = '0' gradient_start = 'darkorange' @@ -294,7 +299,7 @@ <drawdata id = 'widget_slider' cache = 'false'> <drawstep func = 'roundedsq' stroke = '0' - radius = '4' + radius = '5' fill = 'foreground' fg_color = 'paleyellow' bevel = '1' @@ -306,7 +311,7 @@ <drawdata id = 'slider_full' cache = 'false'> <drawstep func = 'roundedsq' stroke = '1' - radius = '4' + radius = '5' fill = 'gradient' fg_color = '123, 112, 56' gradient_start = 'brightred' @@ -318,7 +323,7 @@ <drawdata id = 'slider_hover' cache = 'false'> <drawstep func = 'roundedsq' stroke = '1' - radius = '4' + radius = '5' fill = 'gradient' fg_color = '123, 112, 56' gradient_start = 'brightpink' @@ -330,7 +335,7 @@ <drawdata id = 'slider_disabled' cache = 'false'> <drawstep func = 'roundedsq' stroke = '1' - radius = '4' + radius = '5' fill = 'gradient' fg_color = '123, 112, 56' gradient_start = 'darkenedbrightred' @@ -341,9 +346,9 @@ <!-- Idle popup --> <drawdata id = 'popup_idle' cache = 'false'> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' stroke = '1' - fg_color = 'lightgray' + fg_color = 'lightgray2' fill = 'background' bg_color = 'xtrabrightred' shadow = '2' @@ -366,7 +371,7 @@ <!-- Disabled popup --> <drawdata id = 'popup_disabled' cache = 'false'> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' fill = 'foreground' fg_color = 'darkgray' shadow = '2' @@ -391,7 +396,7 @@ <drawstep func = 'roundedsq' stroke = '1' fg_color = 'lightgray' - radius = '4' + radius = '5' fill = 'gradient' gradient_start = 'blandyellow' gradient_end = 'xtrabrightred' @@ -416,7 +421,7 @@ <drawdata id = 'widget_textedit' cache = 'false'> <drawstep func = 'roundedsq' fill = 'foreground' - radius = '4' + radius = '5' fg_color = 'paleyellow' shadow = '0' bevel = '1' @@ -464,7 +469,7 @@ horizontal_align = 'center' /> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' stroke = '1' fill = 'gradient' shadow = '0' @@ -483,7 +488,7 @@ horizontal_align = 'center' /> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' stroke = '1' fill = 'gradient' shadow = '0' @@ -502,7 +507,7 @@ horizontal_align = 'center' /> <drawstep func = 'roundedsq' - radius = '4' + radius = '5' stroke = '1' fill = 'gradient' shadow = '0' @@ -520,13 +525,8 @@ vertical_align = 'top' horizontal_align = 'left' /> - <drawstep func = 'roundedsq' - fill = 'none' - radius = '4' - fg_color = 'black' - shadow = '0' - bevel = '1' - bevel_color = 'shadowcolor' + <drawstep func = 'bitmap' + file = 'checkbox_empty.bmp' /> </drawdata> @@ -547,13 +547,8 @@ vertical_align = 'top' horizontal_align = 'left' /> - <drawstep func = 'roundedsq' - fill = 'foreground' - radius = '4' - fg_color = 'paleyellow' - shadow = '0' - bevel = '1' - bevel_color = 'shadowcolor' + <drawstep func = 'bitmap' + file = 'checkbox_empty.bmp' /> </drawdata> diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index 736fce87f2..8c13217c65 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -37,20 +37,20 @@ <def var = 'ListWidget.hlLeftPadding' value = '0'/> <def var = 'ListWidget.hlRightPadding' value = '0'/> - <def var = 'PopUpWidget.labelSpacing' value = '10' /> - <def var = 'PopUpWidget.labelWidth' value = '110' /> <def var = 'ShowLauncherLogo' value = '1'/> <def var = 'ShowGlobalMenuLogo' value = '1'/> + <def var = 'ShowSearchPic' value = '1'/> <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '1'/> - <def var = 'KeyRemapper.Spacing' value = '10'/> - <def var = 'KeyRemapper.LabelWidth' value = '100'/> - <def var = 'KeyRemapper.ButtonWidth' value = '80'/> + <def var = 'KeyMapper.Spacing' value = '10'/> + <def var = 'KeyMapper.LabelWidth' value = '100'/> + <def var = 'KeyMapper.ButtonWidth' value = '80'/> <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' + textalign = 'right' /> <widget name = 'SmallLabel' size = '24, Globals.Line.Height' @@ -105,6 +105,21 @@ width = '283' height = '80' /> + <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <widget name = 'SearchPic' + width = '16' + height = '17' + /> + <widget name = 'Search' + width = '150' + height = 'Globals.Line.Height' + /> + <widget name = 'SearchClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + <space /> + </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0'> <widget name = 'GameList'/> <layout type = 'vertical' padding = '10, 0, 0, 0'> @@ -181,12 +196,22 @@ <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'grModePopup' - type = 'PopUp' - /> - <widget name = 'grRenderPopup' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'grModePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grModePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'grRenderPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + </layout> <widget name = 'grAspectCheckbox' type = 'Checkbox' /> @@ -198,16 +223,31 @@ <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'auMidiPopup' - type = 'PopUp' - /> - <widget name = 'auOPLPopup' - type = 'PopUp' - /> - <widget name = 'auSampleRatePopup' - type = 'PopUp' - /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auMidiPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auOPLPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auOPLPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auSampleRatePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -216,7 +256,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -231,38 +271,45 @@ </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'> - <widget name = 'vcMusicText' - type = 'OptionsLabel' - /> - <widget name = 'vcMusicSlider' - type = 'Slider' - /> - <widget name = 'vcMusicLabel' - type = 'SmallLabel' - /> + <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' spacing = '10' center = 'true'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> - <widget name = 'vcSfxText' - type = 'OptionsLabel' - /> - <widget name = 'vcSfxSlider' - type = 'Slider' - /> - <widget name = 'vcSfxLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> - <widget name = 'vcSpeechText' - type = 'OptionsLabel' - /> - <widget name = 'vcSpeechSlider' - type = 'Slider' - /> - <widget name = 'vcSpeechLabel' - type = 'SmallLabel' + <layout type = 'vertical' padding = '24, 0, 24, 0' center = 'true'> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' /> </layout> </layout> @@ -270,7 +317,7 @@ <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'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'mcFontButton' type = 'Button' /> @@ -291,7 +338,7 @@ <widget name = 'mcGSCheckbox' type = 'Checkbox' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'mcMidiGainText' type = 'OptionsLabel' /> @@ -308,7 +355,7 @@ <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' /> @@ -316,7 +363,7 @@ height = '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' /> @@ -324,7 +371,7 @@ height = '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' /> @@ -332,7 +379,7 @@ height = '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 = 'PluginsButton' type = 'Button' /> @@ -345,7 +392,7 @@ <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' /> @@ -353,12 +400,22 @@ height = 'Globals.Line.Height' /> </layout> - <widget name = 'Renderer' - type = 'PopUp' - /> - <widget name = 'AutosavePeriod' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'RendererPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'RendererPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'AutosavePeriodPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'AutosavePeriodPopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -443,7 +500,7 @@ <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 = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'Id' type = 'OptionsLabel' /> @@ -451,7 +508,7 @@ type = 'PopUp' /> </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 = 'Name' type = 'OptionsLabel' /> @@ -459,12 +516,22 @@ type = 'PopUp' /> </layout> - <widget name = 'Lang' - type = 'PopUp' - /> - <widget name = 'Platform' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'LangPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'LangPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'PlatformPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'PlatformPopup' + type = 'PopUp' + /> + </layout> </layout> </dialog> @@ -571,41 +638,53 @@ </dialog> <dialog name = 'ScummConfig' overlays = 'screen_center'> - <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcMusicText' - type = 'OptionsLabel' - /> - <widget name = 'vcMusicSlider' - type = 'Slider' - /> - <widget name = 'vcMusicLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcSfxText' - type = 'OptionsLabel' - /> - <widget name = 'vcSfxSlider' - type = 'Slider' - /> - <widget name = 'vcSfxLabel' - type = 'SmallLabel' - /> - </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> - <widget name = 'vcSpeechText' - type = 'OptionsLabel' - /> - <widget name = 'vcSpeechSlider' - type = 'Slider' - /> - <widget name = 'vcSpeechLabel' - type = 'SmallLabel' - /> + <layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '8' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + + <layout type = 'vertical' padding = '24, 24, 24, 24' center = 'true'> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + width = '80' <!-- FIXME: Why this is needed? --> + /> + </layout> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = '8' /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -614,7 +693,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -626,7 +705,7 @@ /> </layout> <space size = '60'/> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <widget name='Keys' type='Button' /> @@ -703,7 +782,14 @@ width = '250' height = 'Globals.Line.Height' /> - <space size = '32' /> + <widget name = 'GameProgressText' + width = '250' + height = 'Globals.Line.Height' + /> + <widget name = 'GameList' + width = '480' + height = '250' + /> <layout type = 'horizontal' padding = '8, 8, 8, 8'> <widget name = 'Ok' type = 'Button' @@ -715,15 +801,21 @@ </layout> </dialog> - <dialog name = 'KeyRemapper' overlays = 'screen_center' shading = 'dim'> - <layout type = 'vertical' padding = '8, 8, 32, 8' center = 'true'> - <widget name = 'Popup' - type = 'PopUp' - width = '600' - /> + <dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'> + <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 = '400' + height = 'Globals.Line.Height' + /> + </layout> <widget name = 'KeymapArea' width = '600' - height = '378' + height = '280' /> <widget name = 'Close' type = 'Button' diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx index bf19b48485..13346a1d6f 100644 --- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx +++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx @@ -29,11 +29,11 @@ <def var = 'Font.Height' value = '10' /> <def var = 'About.OuterBorder' value = '10'/> - <def var = 'PopUpWidget.labelSpacing' value = '6' /> - <def var = 'PopUpWidget.labelWidth' value = '100' /> <def var = 'ShowLauncherLogo' value = '0'/> <def var = 'ShowGlobalMenuLogo' value = '0'/> + <def var = 'ShowSearchPic' value = '0'/> + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> <widget name = 'Button' @@ -44,8 +44,13 @@ size = '85, 12' /> + <def var = 'KeyMapper.Spacing' value = '5'/> + <def var = 'KeyMapper.LabelWidth' value = '80'/> + <def var = 'KeyMapper.ButtonWidth' value = '60'/> + <widget name = 'OptionsLabel' - size = '110, Globals.Line.Height' + size = '100, Globals.Line.Height' + textalign = 'right' /> <widget name = 'SmallLabel' size = '18, Globals.Line.Height' @@ -86,6 +91,22 @@ <widget name = 'Version' height = 'Globals.Line.Height' /> + <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <widget name = 'SearchDesc' + width = '50' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'Search' + width = '150' + height = 'Globals.Line.Height' + /> + <widget name = 'SearchClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + <space /> + </layout> <widget name = 'GameList'/> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'> <widget name = 'LoadGameButton' @@ -161,12 +182,22 @@ <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'grModePopup' - type = 'PopUp' - /> - <widget name = 'grRenderPopup' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'grModePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grModePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'grRenderPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + </layout> <widget name = 'grAspectCheckbox' type = 'Checkbox' /> @@ -178,16 +209,31 @@ <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> - <widget name = 'auMidiPopup' - type = 'PopUp' - /> - <widget name = 'auOPLPopup' - type = 'PopUp' - /> - <widget name = 'auSampleRatePopup' - type = 'PopUp' - /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auMidiPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auOPLPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auOPLPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auSampleRatePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -196,7 +242,7 @@ height = 'Globals.Slider.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -245,12 +291,18 @@ type = 'SmallLabel' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8' center = 'true'> + <space size = '105' /> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + /> + </layout> </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'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> <widget name = 'mcFontButton' type = 'Button' /> @@ -271,7 +323,7 @@ <widget name = 'mcGSCheckbox' type = 'Checkbox' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' center = 'true'> <widget name = 'mcMidiGainText' type = 'OptionsLabel' /> @@ -288,7 +340,7 @@ <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 = '16' center = 'true'> <widget name = 'SaveButton' type = 'Button' /> @@ -296,7 +348,7 @@ height = 'Globals.Line.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> <widget name = 'ThemeButton' type = 'Button' /> @@ -304,7 +356,7 @@ height = 'Globals.Line.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> <widget name = 'ExtraButton' type = 'Button' /> @@ -312,7 +364,7 @@ height = 'Globals.Line.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> <widget name = 'PluginsButton' type = 'Button' /> @@ -325,7 +377,7 @@ <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 = '16' center = 'true'> <widget name = 'ThemeButton' type = 'Button' /> @@ -333,12 +385,24 @@ height = 'Globals.Line.Height' /> </layout> - <widget name = 'Renderer' - type = 'PopUp' - /> - <widget name = 'AutosavePeriod' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'RendererPopupDesc' + width = '80' + height = 'Globals.Line.Height' + /> + <widget name = 'RendererPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'AutosavePeriodPopupDesc' + width = '80' + height = 'Globals.Line.Height' + /> + <widget name = 'AutosavePeriodPopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -423,31 +487,47 @@ <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 = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'Id' width = '35' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'Domain' type = 'PopUp' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'Name' width = '35' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'Desc' type = 'PopUp' /> </layout> <space size = '8'/> - <widget name = 'Lang' - type = 'PopUp' - /> - <widget name = 'Platform' - type = 'PopUp' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'LangPopupDesc' + width = '60' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'LangPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'PlatformPopupDesc' + width = '60' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'PlatformPopup' + type = 'PopUp' + /> + </layout> </layout> </dialog> @@ -555,7 +635,7 @@ <dialog name = 'ScummConfig' overlays = 'screen_center'> <layout type = 'vertical' padding = '8, 8, 8, 8'> - <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' /> @@ -566,7 +646,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' /> @@ -577,7 +657,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' /> @@ -588,7 +668,15 @@ 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'> + <space size = '100' /> + <widget name = 'vcMuteCheckbox' + type = 'Checkbox' + width = '80' + /> + </layout> + <space size = '4' /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> @@ -597,7 +685,7 @@ height = 'Globals.Slider.Height' /> </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 = 'subSubtitleSpeedDesc' type = 'OptionsLabel' /> @@ -678,7 +766,10 @@ width = '240' height = 'Globals.Line.Height' /> - <space size = '16' /> + <widget name = 'GameList' + width = '280' + height = '100' + /> <layout type = 'horizontal' padding = '4, 4, 4, 4'> <widget name = 'Ok' type = 'Button' @@ -689,4 +780,25 @@ </layout> </layout> </dialog> + <dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'> + <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 = '150' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'KeymapArea' + width = '300' + height = '120' + /> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </dialog> </layout_info> diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py index 4a03c89799..4a03c89799 100644..100755 --- a/gui/themes/scummtheme.py +++ b/gui/themes/scummtheme.py diff --git a/gui/widget.cpp b/gui/widget.cpp index 12da012c7b..e4b37dc3c2 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -192,7 +192,7 @@ StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, _type = kStaticTextWidget; _label = text; - _align = (Graphics::TextAlign)g_gui.xmlEval()->getVar(name + ".Align", Graphics::kTextAlignLeft); + _align = g_gui.xmlEval()->getWidgetTextHAlign(name); } void StaticTextWidget::setValue(int value) { @@ -16,7 +16,7 @@ install: all $(INSTALL) -d "$(DESTDIR)$(PREFIX)/share/pixmaps/" $(INSTALL) -c -m 644 "$(srcdir)/icons/scummvm.xpm" "$(DESTDIR)$(PREFIX)/share/pixmaps/scummvm.xpm" $(INSTALL) -d "$(DESTDIR)$(PREFIX)/share/doc/scummvm/" - $(INSTALL) -c -m 644 "$(srcdir)/AUTHORS" "$(srcdir)/COPYING" "$(srcdir)/COPYING.LGPL" "$(srcdir)/COPYRIGHT" "$(srcdir)/NEWS" "$(srcdir)/README" "$(DESTDIR)$(PREFIX)/share/doc/scummvm/" + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) "$(DESTDIR)$(PREFIX)/share/doc/scummvm/" $(INSTALL) -d "$(DESTDIR)$(DATADIR)/scummvm/" $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) "$(DESTDIR)$(DATADIR)/scummvm/" ifdef DYNAMIC_MODULES @@ -48,7 +48,7 @@ bundle: scummvm-static $(srcdir)/dists/macosx/Info.plist echo "APPL????" > $(bundle_name)/Contents/PkgInfo cp $(srcdir)/dists/macosx/Info.plist $(bundle_name)/Contents/ cp $(srcdir)/icons/scummvm.icns $(bundle_name)/Contents/Resources/ - cp $(srcdir)/dists/pred.dic $(bundle_name)/Contents/Resources/ + cp $(DIST_FILES_DOCS) $(bundle_name)/ cp $(DIST_FILES_THEMES) $(bundle_name)/Contents/Resources/ cp $(DIST_FILES_ENGINEDATA) $(bundle_name)/Contents/Resources/ $(srcdir)/tools/credits.pl --rtf > $(bundle_name)/Contents/Resources/Credits.rtf @@ -60,13 +60,9 @@ bundle: scummvm-static $(srcdir)/dists/macosx/Info.plist iphonebundle: iphone $(srcdir)/dists/iphone/Info.plist mkdir -p $(bundle_name) cp $(srcdir)/dists/iphone/Info.plist $(bundle_name)/ - cp $(srcdir)/dists/pred.dic $(bundle_name)/ + cp $(DIST_FILES_DOCS) $(bundle_name)/ cp $(DIST_FILES_THEMES) $(bundle_name)/ cp $(DIST_FILES_ENGINEDATA) $(bundle_name)/ - cp $(srcdir)/AUTHORS $(bundle_name)/ - cp $(srcdir)/COPYING $(bundle_name)/ - cp $(srcdir)/COPYING.LGPL $(bundle_name)/ - cp $(srcdir)/COPYRIGHT $(bundle_name)/ cp scummvm $(bundle_name)/ScummVM cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/icon.png cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/Default.png @@ -156,7 +152,6 @@ scummvmico.o: $(srcdir)/icons/scummvm.ico win32dist: $(EXECUTABLE) mkdir -p $(WIN32PATH) $(STRIP) $(EXECUTABLE) -o $(WIN32PATH)/$(EXECUTABLE) - cp $(srcdir)/dists/pred.dic $(WIN32PATH) cp $(DIST_FILES_THEMES) $(WIN32PATH) cp $(DIST_FILES_ENGINEDATA) $(WIN32PATH) cp $(srcdir)/AUTHORS $(WIN32PATH)/AUTHORS.txt @@ -180,7 +175,6 @@ aos4dist: $(EXECUTABLE) cp icons/scummvm.info $(AOS4PATH)/$(EXECUTABLE)_SVN.info cp $(DIST_FILES_THEMES) $(AOS4PATH)/themes/ cp $(DIST_FILES_ENGINEDATA) $(AOS4PATH)/extras/ - cp $(srcdir)/dists/pred.dic $(AOS4PATH)/extras/ cp $(srcdir)/AUTHORS $(AOS4PATH)/AUTHORS.txt cp $(srcdir)/COPYING $(AOS4PATH)/COPYING.txt cp $(srcdir)/COPYING.LGPL $(AOS4PATH)/COPYING.LGPL.txt @@ -188,4 +182,26 @@ aos4dist: $(EXECUTABLE) cp $(srcdir)/NEWS $(AOS4PATH)/NEWS.txt cp $(srcdir)/README $(AOS4PATH)/README.txt -.PHONY: deb bundle osxsnap win32dist install uninstall +# +# Wii/Gamecube specific +# + +# Special target to create a Wii snapshot +wiidist: $(EXECUTABLE) + $(MKDIR) wiidist/scummvm +ifeq ($(GAMECUBE),1) + $(DEVKITPPC)/bin/elf2dol $(EXECUTABLE) wiidist/scummvm/scummvm.dol +else + $(STRIP) $(EXECUTABLE) -o wiidist/scummvm/boot.elf + $(CP) $(srcdir)/dists/wii/icon.png wiidist/scummvm/ + sed "s/@REVISION@/$(VER_SVNREV)/;s/@TIMESTAMP@/`date +%Y%m%d%H%M%S`/" < $(srcdir)/dists/wii/meta.xml > wiidist/scummvm/meta.xml +endif + sed 's/$$/\r/' < $(srcdir)/dists/wii/READMII > wiidist/scummvm/READMII.txt + for i in $(DIST_FILES_DOCS); do sed 's/$$/\r/' < $$i > wiidist/scummvm/`basename $$i`.txt; done + $(CP) $(DIST_FILES_THEMES) wiidist/scummvm/ +ifneq ($(DIST_FILES_ENGINEDATA),) + $(CP) $(DIST_FILES_ENGINEDATA) wiidist/scummvm/ +endif + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip wiidist/scummvm/ + +.PHONY: deb bundle osxsnap win32dist wiidist install uninstall diff --git a/sound/iff.cpp b/sound/iff.cpp index de380276bb..1df58b178c 100644 --- a/sound/iff.cpp +++ b/sound/iff.cpp @@ -26,58 +26,81 @@ #include "sound/iff.h" #include "sound/audiostream.h" #include "sound/mixer.h" +#include "common/func.h" namespace Audio { - -void A8SVXDecoder::readVHDR(Common::IFFChunk &chunk) { - _header.oneShotHiSamples = chunk.readUint32BE(); - _header.repeatHiSamples = chunk.readUint32BE(); - _header.samplesPerHiCycle = chunk.readUint32BE(); - _header.samplesPerSec = chunk.readUint16BE(); - _header.octaves = chunk.readByte(); - _header.compression = chunk.readByte(); - _header.volume = chunk.readUint32BE(); +void Voice8Header::load(Common::ReadStream &stream) { + stream.read(this, sizeof(Voice8Header)); + oneShotHiSamples = FROM_BE_32(oneShotHiSamples); + repeatHiSamples = FROM_BE_32(repeatHiSamples); + samplesPerHiCycle = FROM_BE_32(samplesPerHiCycle); + samplesPerSec = FROM_BE_16(samplesPerSec); + volume = FROM_BE_32(volume); } -void A8SVXDecoder::readBODY(Common::IFFChunk &chunk) { - switch (_header.compression) { - case 0: - _dataSize = chunk.size; - _data = (int8*)malloc(_dataSize); - chunk.read(_data, _dataSize); - break; - case 1: - warning("compressed IFF audio is not supported"); - break; - } - -} +struct A8SVXLoader { + Voice8Header _header; + int8 *_data; + uint32 _dataSize; + void load(Common::ReadStream &input) { + Common::IFFParser parser(&input); + Common::Functor1Mem< Common::IFFChunk&, bool, A8SVXLoader > c(this, &A8SVXLoader::callback); + parser.parse(c); + } -A8SVXDecoder::A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize) : - IFFParser(input), _header(header), _data(data), _dataSize(dataSize) { - if (_typeId != ID_8SVX) - error("unknown audio format"); -} + bool callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case ID_VHDR: + _header.load(*chunk._stream); + break; -void A8SVXDecoder::decode() { + case ID_BODY: + _dataSize = chunk._size; + _data = (int8*)malloc(_dataSize); + assert(_data); + loadData(chunk._stream); + return true; + } - Common::IFFChunk *chunk; + return false; + } - while ((chunk = nextChunk()) != 0) { - switch (chunk->id) { - case ID_VHDR: - readVHDR(*chunk); + void loadData(Common::ReadStream *stream) { + switch (_header.compression) { + case 0: + stream->read(_data, _dataSize); break; - case ID_BODY: - readBODY(*chunk); + case 1: + // implement other formats here + error("compressed IFF audio is not supported"); break; } + + } +}; + + +AudioStream *make8SVXStream(Common::ReadStream &input, bool loop) { + A8SVXLoader loader; + loader.load(input); + + uint32 loopStart = 0, loopEnd = 0, flags = 0; + if (loop) { + // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and + // repeatHiSamples fields + loopStart = 0; + loopEnd = loader._header.oneShotHiSamples + loader._header.repeatHiSamples; + flags |= Audio::Mixer::FLAG_LOOP; } + + flags |= Audio::Mixer::FLAG_AUTOFREE; + + return Audio::makeLinearInputStream((byte *)loader._data, loader._dataSize, loader._header.samplesPerSec, flags, loopStart, loopEnd); } } diff --git a/sound/iff.h b/sound/iff.h index 2bc8b51b82..82106cb75e 100644 --- a/sound/iff.h +++ b/sound/iff.h @@ -32,6 +32,7 @@ #define SOUND_IFF_H #include "common/iff_container.h" +#include "sound/audiostream.h" namespace Audio { @@ -47,34 +48,12 @@ struct Voice8Header { Voice8Header() { memset(this, 0, sizeof(Voice8Header)); } -}; - - -/* - A8SVX decoder reads 8SVX subtype of IFF files. - - TODO: make a factory function for this kind of stream? - */ -class A8SVXDecoder : public Common::IFFParser { - -protected: - Voice8Header &_header; - int8* &_data; - uint32 &_dataSize; -protected: - void readVHDR(Common::IFFChunk &chunk); - void readBODY(Common::IFFChunk &chunk); - -public: - A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize); - void decode(); + void load(Common::ReadStream &stream); }; +AudioStream *make8SVXStream(Common::ReadStream &stream, bool loop); -/* - TODO: Implement a parser for AIFF subtype. - */ } diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index 85d6994992..11c11c35d4 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -88,6 +88,7 @@ static const MidiDriverDescription s_musicDrivers[] = { {"adlib", "AdLib", MD_ADLIB, MDT_ADLIB}, {"pcspk", "PC Speaker", MD_PCSPK, MDT_PCSPK}, {"pcjr", "IBM PCjr", MD_PCJR, MDT_PCSPK}, + {"cms", "Creative Music System", MD_CMS, MDT_CMS}, {"towns", "FM Towns", MD_TOWNS, MDT_TOWNS}, #if defined(UNIX) {"timidity", "TiMidity", MD_TIMIDITY, MDT_MIDI}, @@ -236,6 +237,7 @@ MidiDriver *MidiDriver::createMidi(int midiDriver) { // outside the MidiDriver architecture, so // don't create anything for now. case MD_PCSPK: + case MD_CMS: case MD_PCJR: return NULL; #ifdef USE_FLUIDSYNTH diff --git a/sound/mididrv.h b/sound/mididrv.h index 700fd01f6b..bf2b804e16 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -80,6 +80,7 @@ enum MidiDriverType { // "Fake" MIDI devices MD_ADLIB, MD_PCSPK, + MD_CMS, MD_PCJR, MD_TOWNS, MD_TIMIDITY @@ -98,10 +99,11 @@ enum MidiDriverType { enum MidiDriverFlags { MDT_NONE = 0, MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR - MDT_ADLIB = 1 << 1, // Adlib: Maps to MD_ADLIB - MDT_TOWNS = 1 << 2, // FM-TOWNS: Maps to MD_TOWNS - MDT_MIDI = 1 << 3, // Real MIDI - MDT_PREFER_MIDI = 1 << 4 // Real MIDI output is preferred + MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS + MDT_ADLIB = 1 << 2, // Adlib: Maps to MD_ADLIB + MDT_TOWNS = 1 << 3, // FM-TOWNS: Maps to MD_TOWNS + MDT_MIDI = 1 << 4, // Real MIDI + MDT_PREFER_MIDI = 1 << 5 // Real MIDI output is preferred }; /** diff --git a/sound/softsynth/mt32/partial.cpp b/sound/softsynth/mt32/partial.cpp index 02610798dc..871eff03d2 100644 --- a/sound/softsynth/mt32/partial.cpp +++ b/sound/softsynth/mt32/partial.cpp @@ -35,9 +35,9 @@ // powf, resulting in a linker error because of multiple definitions. // Hence we re-define them here. The only potential drawback is that it // might be a little bit slower this way. -#define powf pow -#define floorf floor -#define fabsf fabs +#define powf(x,y) ((float)pow(x,y)) +#define floorf(x) ((float)floorf(x)) +#define fabsf(x) ((float)fabs(x)) #endif #define FIXEDPOINT_UDIV(x, y, point) (((x) << (point)) / ((y))) @@ -504,10 +504,10 @@ Bit16s *Partial::mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) { a = ((float)*buf1) / 8192.0f; b = ((float)*buf2) / 8192.0f; a = (a * b) + a; - if (a>1.0) - a = 1.0; - if (a<-1.0) - a = -1.0; + if (a > 1.0f) + a = 1.0f; + if (a < -1.0f) + a = -1.0f; *buf1 = (Bit16s)(a * 8192.0f); buf1++; buf2++; @@ -537,10 +537,10 @@ Bit16s *Partial::mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) { a = ((float)*buf1) / 8192.0f; b = ((float)*buf2) / 8192.0f; a *= b; - if (a>1.0) - a = 1.0; - if (a<-1.0) - a = -1.0; + if (a > 1.0f) + a = 1.0f; + if (a < -1.0f) + a = -1.0f; *buf1 = (Bit16s)(a * 8192.0f); buf1++; buf2++; diff --git a/sound/softsynth/mt32/synth.cpp b/sound/softsynth/mt32/synth.cpp index bedae241b3..547b2bb9b3 100644 --- a/sound/softsynth/mt32/synth.cpp +++ b/sound/softsynth/mt32/synth.cpp @@ -35,9 +35,9 @@ // powf, resulting in a linker error because of multiple definitions. // Hence we re-define them here. The only potential drawback is that it // might be a little bit slower this way. -#define powf pow -#define floorf floor -#define fabsf fabs +#define powf(x,y) ((float)pow(x,y)) +#define floorf(x) ((float)floorf(x)) +#define fabsf(x) ((float)fabs(x)) #endif namespace MT32Emu { diff --git a/sound/softsynth/mt32/synth.h b/sound/softsynth/mt32/synth.h index 9d57c8d3cd..3fc303d322 100644 --- a/sound/softsynth/mt32/synth.h +++ b/sound/softsynth/mt32/synth.h @@ -22,7 +22,7 @@ #ifndef MT32EMU_SYNTH_H #define MT32EMU_SYNTH_H -#include <stdarg.h> +#include "common/scummsys.h" class revmodel; @@ -256,7 +256,7 @@ protected: int report(ReportType type, const void *reportData); File *openFile(const char *filename, File::OpenMode mode); void closeFile(File *file); - void printDebug(const char *fmt, ...); + void printDebug(const char *fmt, ...) GCC_PRINTF(2, 3); public: static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum); diff --git a/sound/softsynth/mt32/tables.cpp b/sound/softsynth/mt32/tables.cpp index bf35db776a..16fc4f71e5 100644 --- a/sound/softsynth/mt32/tables.cpp +++ b/sound/softsynth/mt32/tables.cpp @@ -35,9 +35,9 @@ // powf, resulting in a linker error because of multiple definitions. // Hence we re-define them here. The only potential drawback is that it // might be a little bit slower this way. -#define powf pow -#define floorf floor -#define fabsf fabs +#define powf(x,y) ((float)pow(x,y)) +#define floorf(x) ((float)floorf(x)) +#define fabsf(x) ((float)fabs(x)) #endif #define FIXEDPOINT_MAKE(x, point) ((Bit32u)((1 << point) * x)) @@ -730,7 +730,7 @@ Tables::Tables() { bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune) { if (sampleRate <= 0.0f) { - synth->printDebug("Bad sampleRate (%d <= 0.0f)", sampleRate); + synth->printDebug("Bad sampleRate (%f <= 0.0f)", sampleRate); return false; } if (initialisedSampleRate == 0.0f) { diff --git a/sound/vorbis.cpp b/sound/vorbis.cpp index 9658f8f257..8b8bb8f649 100644 --- a/sound/vorbis.cpp +++ b/sound/vorbis.cpp @@ -60,7 +60,7 @@ static size_t read_stream_wrap(void *ptr, size_t size, size_t nmemb, void *datas static int seek_stream_wrap(void *datasource, ogg_int64_t offset, int whence) { Common::SeekableReadStream *stream = (Common::SeekableReadStream *)datasource; - stream->seek(offset, whence); + stream->seek((int32)offset, whence); return stream->pos(); } diff --git a/test/common/hashmap.h b/test/common/hashmap.h index c62f909f95..6476005eaf 100644 --- a/test/common/hashmap.h +++ b/test/common/hashmap.h @@ -108,5 +108,48 @@ class HashMapTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS(container2[323], 32); } + void test_collision() { + // NB: The usefulness of this example depends strongly on the + // specific hashmap implementation. + // It is constructed to insert multiple colliding elements. + Common::HashMap<int, int> h; + h[5] = 1; + h[32+5] = 1; + h[64+5] = 1; + h[128+5] = 1; + TS_ASSERT(h.contains(5)); + TS_ASSERT(h.contains(32+5)); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h.erase(32+5); + TS_ASSERT(h.contains(5)); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h.erase(5); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h[32+5] = 1; + TS_ASSERT(h.contains(32+5)); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h[5] = 1; + TS_ASSERT(h.contains(5)); + TS_ASSERT(h.contains(32+5)); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h.erase(5); + TS_ASSERT(h.contains(32+5)); + TS_ASSERT(h.contains(64+5)); + TS_ASSERT(h.contains(128+5)); + h.erase(64+5); + TS_ASSERT(h.contains(32+5)); + TS_ASSERT(h.contains(128+5)); + h.erase(128+5); + TS_ASSERT(h.contains(32+5)); + h.erase(32+5); + TS_ASSERT(h.empty()); + } + + // TODO: Add test cases for iterators, find, ... }; diff --git a/test/common/str.h b/test/common/str.h index 1e92dc0b7f..bf0db98b09 100644 --- a/test/common/str.h +++ b/test/common/str.h @@ -190,6 +190,9 @@ class StringTestSuite : public CxxTest::TestSuite TS_ASSERT_EQUALS(str.contains("haha"), true); TS_ASSERT_EQUALS(str.contains("hahb"), false); TS_ASSERT_EQUALS(str.contains("test"), true); + + TS_ASSERT_EQUALS(str.contains('/'), true); + TS_ASSERT_EQUALS(str.contains('x'), false); } void test_toLowercase() { diff --git a/tools/credits.pl b/tools/credits.pl index 949f8ef1fa..cfc328f070 100755 --- a/tools/credits.pl +++ b/tools/credits.pl @@ -524,6 +524,7 @@ begin_credits("Credits"); begin_section("Cinematique evo 2"); add_person("Vincent Hamm", "yazoo", "original CruisE engine author"); + add_person("Paul Gilbert", "dreammaster", ""); end_section(); begin_section("FOTAQ"); # Flight of the Amazon Queen diff --git a/tools/update-version.pl b/tools/update-version.pl index dda4fcbcf9..ec0249c872 100755 --- a/tools/update-version.pl +++ b/tools/update-version.pl @@ -35,6 +35,7 @@ my @subs_files = qw( dists/redhat/scummvm.spec dists/scummvm.rc dists/slackware/scummvm.SlackBuild + dists/wii/meta.xml backends/platform/psp/README.PSP ); |