diff options
author | Norbert Lange | 2009-07-01 14:45:24 +0000 |
---|---|---|
committer | Norbert Lange | 2009-07-01 14:45:24 +0000 |
commit | abef70f4e14f495b20097cb46411d1fafbafdd53 (patch) | |
tree | 27462f82f352b303ac059dd275466930c88b2de6 | |
parent | 3b94e2488df9a699a899727515ac69af6a0a1a6e (diff) | |
parent | f9298ff40310149779b37ccdecc873afba7adf2f (diff) | |
download | scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.gz scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.tar.bz2 scummvm-rg350-abef70f4e14f495b20097cb46411d1fafbafdd53.zip |
Merging in changes from trunk
svn-id: r41989
319 files changed, 16938 insertions, 16958 deletions
@@ -57,6 +57,7 @@ ScummVM Team Cinematique evo 2: Vincent Hamm - original CruisE engine author + Paul Gilbert FOTAQ: Gregory Montoir diff --git a/Makefile.common b/Makefile.common index 6e9062592e..251711301f 100644 --- a/Makefile.common +++ b/Makefile.common @@ -208,6 +208,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) @@ -237,6 +239,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,12 +4,12 @@ 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 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. @@ -26,72 +26,74 @@ For a more comprehensive changelog for the latest experimental SVN code, see: 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: @@ -109,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. @@ -134,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). @@ -441,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: diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index 8b0a5c2e36..0440acdd0a 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -39,17 +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); - _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyRemapper.PopupDesc", "Keymap:"); - _kmPopUp = new GUI::PopUpWidget(this, "KeyRemapper.Popup"); + _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() { @@ -138,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/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/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/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/sdl.cpp b/backends/platform/sdl/sdl.cpp index 343a1ac6f4..52355f60cc 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -397,13 +397,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()); } @@ -489,7 +496,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/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index 452f730110..6a8a46df07 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -472,6 +472,7 @@ bool OSystem_SDL_Symbian::remapKey(SDL_Event &ev, Common::Event &event) { void OSystem_SDL_Symbian::setWindowCaption(const char *caption) { OSystem_SDL::setWindowCaption(caption); check_mappings(); +FIXME: move check_mappings() call to engineInit() & engineDone() } void OSystem_SDL_Symbian::check_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 differindex c58c26fc5f..9311b2a902 100644 --- a/backends/vkeybd/packs/vkeybd_default.zip +++ b/backends/vkeybd/packs/vkeybd_default.zip diff --git a/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp b/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp Binary files differindex 27a450f2d2..3270bf21e4 100644 --- a/backends/vkeybd/packs/vkeybd_default/lowercase320x240.bmp +++ 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 differindex 3df2a58b83..610f0844d0 100644 --- a/backends/vkeybd/packs/vkeybd_default/lowercase640x480.bmp +++ b/backends/vkeybd/packs/vkeybd_default/lowercase640x480.bmp diff --git a/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml index aba31b1096..982c4f45ef 100644 --- a/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml +++ b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml @@ -76,6 +76,8 @@ <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"> @@ -151,6 +153,8 @@ <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="" /> @@ -223,6 +227,8 @@ <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> 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/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/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..fa613782cf 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,6 +376,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { } _size = 0; + _deleted = 0; } template<class Key, class Val, class HashFunc, class EqualFunc> @@ -374,6 +389,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) { // allocate a new array _size = 0; + _deleted = 0; _mask = newCapacity - 1; _storage = new Node *[newCapacity]; assert(_storage != NULL); @@ -381,7 +397,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 +406,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 +428,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 +446,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 +456,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; + } - if (_storage[ctr] == NULL) { + ctr = (5 * ctr + perturb + 1) & _mask; + +#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 +556,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/system.h b/common/system.h index 5b72dab7c1..5b3c208661 100644 --- a/common/system.h +++ b/common/system.h @@ -148,6 +148,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, @@ -662,10 +666,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; /** @@ -830,6 +849,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. */ //@{ @@ -875,13 +897,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) {} @@ -891,6 +911,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 ff665468af..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} }; diff --git a/common/util.h b/common/util.h index ea4d280fbc..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) }; @@ -1115,6 +1115,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" ;; @@ -1307,8 +1311,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 */" @@ -1325,10 +1331,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 */" @@ -1925,7 +1934,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 49f5b542ef..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,10 +359,10 @@ RelativePath="..\..\engines\gob\palanim.h"> </File> <File - RelativePath="..\..\engines\gob\parse.cpp"> + RelativePath="..\..\engines\gob\expression.cpp"> </File> <File - RelativePath="..\..\engines\gob\parse.h"> + 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/scummvm.vcproj b/dists/msvc7/scummvm.vcproj index 90a1f5655d..aee0ca2032 100644 --- a/dists/msvc7/scummvm.vcproj +++ b/dists/msvc7/scummvm.vcproj @@ -1082,6 +1082,9 @@ RelativePath="..\..\graphics\imagedec.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 b955f2951f..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,10 +373,10 @@ RelativePath="..\..\engines\gob\palanim.h"> </File> <File - RelativePath="..\..\engines\gob\parse.cpp"> + RelativePath="..\..\engines\gob\expression.cpp"> </File> <File - RelativePath="..\..\engines\gob\parse.h"> + 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/scummvm.vcproj b/dists/msvc71/scummvm.vcproj index 5bfd240fc6..aa9e3b9066 100644 --- a/dists/msvc71/scummvm.vcproj +++ b/dists/msvc71/scummvm.vcproj @@ -1096,6 +1096,9 @@ RelativePath="..\..\graphics\imagedec.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 dd95afb3f7..3df12a8403 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,11 +507,11 @@ > </File> <File - RelativePath="..\..\engines\gob\parse.cpp" + RelativePath="..\..\engines\gob\expression.cpp" > </File> <File - RelativePath="..\..\engines\gob\parse.h" + 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/scummvm.vcproj b/dists/msvc8/scummvm.vcproj index f25cfa11ff..a88167c0b0 100644 --- a/dists/msvc8/scummvm.vcproj +++ b/dists/msvc8/scummvm.vcproj @@ -1473,6 +1473,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 84622328fb..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,11 +508,11 @@ > </File> <File - RelativePath="..\..\engines\gob\parse.cpp" + RelativePath="..\..\engines\gob\expression.cpp" > </File> <File - RelativePath="..\..\engines\gob\parse.h" + 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/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index a2ff0d45a9..6bbc21f9e4 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1478,6 +1478,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/dists/wii/meta.xml.in b/dists/wii/meta.xml.in new file mode 100644 index 0000000000..7df9f6d350 --- /dev/null +++ b/dists/wii/meta.xml.in @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<app version="1"> + <name>ScummVM</name> + <coder>The ScummVM Team</coder> + <version>@VERSION@@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! + +Some of the adventures ScummVM supports include Adventure Soft's Simon the Sorcerer 1 and 2; Revolution's Beneath A Steel Sky, Broken Sword 1 and Broken Sword 2; Flight of the Amazon Queen; Wyrmkeep's Inherit the Earth; Coktel Vision's Gobliiins; Westwood Studios' The Legend of Kyrandia and games based on LucasArts' SCUMM (Script Creation Utility for Maniac Mansion) system such as Monkey Island, Day of the Tentacle, Sam and Max and more.</long_description> +</app> + diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 0676c0f8e4..e373dd3e6d 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -729,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: diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index aef236ce64..bf4622bc08 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -198,7 +198,9 @@ int AgiEngine::mainCycle() { // In AGI Mouse emulation mode we must update the mouse-related // vars in every interpreter cycle. - if (getFeatures() & GF_AGIMOUSE) { + // + // 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; } diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 302951b69b..910f6e0e55 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -168,6 +168,9 @@ using Common::GUIO_NONE; #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) @@ -222,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 @@ -279,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), @@ -297,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), @@ -316,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), @@ -350,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), @@ -371,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), @@ -392,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), @@ -408,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), @@ -420,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), @@ -437,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), @@ -471,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), @@ -499,8 +559,14 @@ 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) - GAME_P("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1, Common::kPlatformCoCo3), + // 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), @@ -550,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), @@ -568,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"), @@ -630,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"), @@ -777,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"), @@ -805,6 +883,7 @@ 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"), @@ -826,6 +905,7 @@ static const AGIGameDescription gameDescriptions[] = { 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"), diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index a620788de2..97255097bc 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -1520,7 +1520,8 @@ cmd(print_at_v) { } 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; diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index b0856f6ddf..fb73c6b71f 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -367,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: { @@ -411,6 +411,8 @@ void SoundMgr::startSound(int resnum, int flag) { 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++) @@ -418,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(); @@ -474,6 +477,8 @@ int SoundMgr::initSound() { case SOUND_EMU_APPLE2GS: _disabledMidi = !loadInstruments(); break; + case SOUND_EMU_COCO3: + break; } report("Initializing sound:\n"); @@ -819,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; @@ -875,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(); 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/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 910c5cd5a6..d23e772306 100644 --- a/engines/agos/charset-fontdata.cpp +++ b/engines/agos/charset-fontdata.cpp @@ -2105,9 +2105,9 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { w = getFeebleFontSize(chr); if (_language == Common::PL_POL) - src = feeble_windowFont + (chr - 32) * 13; - else 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/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/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 f59dee53df..4764d5a474 100644 --- a/engines/cine/pal.h +++ b/engines/cine/pal.h @@ -73,16 +73,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 { @@ -135,7 +127,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/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/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..938e823fe9 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(); 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 a0a8cce970..879fad0210 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -209,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..d151950c5e 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; @@ -926,8 +929,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/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 ede90af333..0229bb7515 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -123,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) { diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index af64a53b60..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"}, @@ -84,6 +85,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { namespace Gob { using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; using Common::GUIO_NONE; static const GOBGameDescription gameDescriptions[] = { @@ -95,7 +97,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -109,7 +111,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesEGA, @@ -123,7 +125,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -137,7 +139,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -151,7 +153,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -165,7 +167,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -179,7 +181,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -193,7 +195,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -207,7 +209,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -221,7 +223,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -235,7 +237,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -249,7 +251,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -263,7 +265,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -277,7 +279,63 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -291,7 +349,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -305,7 +363,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -319,7 +377,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -333,7 +391,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -347,7 +405,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -361,7 +419,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -375,7 +433,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -389,7 +447,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -403,7 +461,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -417,13 +475,13 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, 0, 0, 0 }, - { + { // Supplied by Hkz on #scummvm { "gob1", "", @@ -435,7 +493,151 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -453,7 +655,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesAdlib, @@ -467,7 +669,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -481,7 +683,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -495,7 +697,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -509,7 +711,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -527,7 +729,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -545,7 +747,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -559,7 +761,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -573,7 +775,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -587,7 +789,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -601,7 +803,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -615,7 +817,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -629,7 +831,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -643,7 +845,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -657,7 +859,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -671,7 +873,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -685,7 +887,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -699,7 +901,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -713,7 +915,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -727,7 +929,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -741,7 +943,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -755,7 +957,77 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -769,7 +1041,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -783,7 +1055,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -797,7 +1069,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -811,7 +1083,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -829,7 +1101,43 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -847,7 +1155,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -865,7 +1173,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -879,7 +1187,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -893,7 +1201,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -907,7 +1215,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -925,7 +1233,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -943,7 +1251,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -957,7 +1265,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesNone, @@ -971,7 +1279,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -985,7 +1293,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -999,7 +1307,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1013,7 +1321,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1027,7 +1335,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1041,7 +1349,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1055,7 +1363,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1069,7 +1377,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWeen, kFeaturesAdlib, @@ -1083,7 +1391,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1097,7 +1405,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAtariST, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1111,7 +1419,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1125,7 +1433,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1139,7 +1447,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1153,7 +1461,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1167,7 +1475,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -1181,7 +1489,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1195,7 +1503,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1209,7 +1517,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1223,7 +1531,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1237,7 +1545,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib | kFeaturesEGA, @@ -1255,7 +1563,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesNone, @@ -1269,7 +1577,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -1283,7 +1591,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1297,7 +1605,7 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1311,7 +1619,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1325,7 +1633,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1339,7 +1647,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1357,7 +1665,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1371,7 +1679,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1385,7 +1693,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1399,7 +1707,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1413,7 +1721,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1427,7 +1735,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1441,7 +1749,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1455,7 +1763,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1469,7 +1777,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1483,7 +1791,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1497,7 +1805,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1511,7 +1819,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1525,7 +1833,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -1536,10 +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, - GUIO_NOSPEECH + 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, @@ -1553,7 +1889,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES }, kGameTypeFascination, kFeaturesCD, @@ -1567,7 +1903,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1581,14 +1917,13 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, "intro.stk", 0, 0 }, - //Provided by Sanguine - { + { // Supplied by sanguine { "fascination", "VGA 3 disks edition", @@ -1596,7 +1931,21 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -1610,7 +1959,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesAdlib, @@ -1624,7 +1973,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1638,7 +1987,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1652,7 +2001,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1666,7 +2015,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -1680,7 +2029,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1694,7 +2043,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -1708,7 +2057,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1722,7 +2071,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -1736,7 +2085,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1750,7 +2099,7 @@ static const GOBGameDescription gameDescriptions[] = { HB_ISR, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1764,7 +2113,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1782,7 +2131,43 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -1800,7 +2185,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1814,7 +2199,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1828,7 +2213,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1842,7 +2227,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1856,7 +2241,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1870,7 +2255,7 @@ static const GOBGameDescription gameDescriptions[] = { RU_RUS, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1884,7 +2269,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1898,7 +2283,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -1912,7 +2297,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1926,7 +2311,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformAmiga, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesNone, @@ -1940,7 +2325,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1954,7 +2339,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1968,7 +2353,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1982,7 +2367,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -1996,7 +2381,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -2010,7 +2395,63 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -2024,7 +2465,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2038,7 +2479,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2052,7 +2493,7 @@ static const GOBGameDescription gameDescriptions[] = { UNK_LANG, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2066,7 +2507,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_DEMO, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2084,7 +2525,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -2098,7 +2539,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2112,7 +2553,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2126,7 +2567,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2140,7 +2581,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2154,7 +2595,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesCD, @@ -2168,7 +2609,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2182,7 +2623,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2196,7 +2637,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib, @@ -2210,7 +2651,63 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformWindows, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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, @@ -2237,7 +2734,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeInca2, kFeaturesAdlib | kFeaturesBATDemo, @@ -2251,7 +2748,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2265,7 +2762,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2279,7 +2776,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2293,7 +2790,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2307,7 +2804,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2321,7 +2818,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2335,7 +2832,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2349,7 +2846,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2363,7 +2860,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2377,7 +2874,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2391,7 +2888,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2405,7 +2902,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2419,7 +2916,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2433,7 +2930,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2447,7 +2944,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2461,7 +2958,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2475,7 +2972,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2489,7 +2986,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2503,7 +3000,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2517,7 +3014,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_GRB, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2531,7 +3028,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2545,7 +3042,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2559,7 +3056,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2573,7 +3070,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2587,7 +3084,7 @@ static const GOBGameDescription gameDescriptions[] = { PL_POL, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -2605,7 +3102,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640 | kFeaturesSCNDemo, @@ -2619,7 +3116,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2633,7 +3130,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2647,7 +3144,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, kFeatures640, @@ -2661,7 +3158,21 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + 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, @@ -2717,7 +3228,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_USA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2731,7 +3242,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2745,7 +3256,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2759,7 +3270,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeatures640, @@ -2786,7 +3297,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2796,7 +3307,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2804,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}, @@ -2814,7 +3325,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2822,7 +3333,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2832,7 +3343,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2840,7 +3351,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, @@ -2855,7 +3366,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2863,7 +3374,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, @@ -2873,7 +3384,7 @@ static const GOBGameDescription gameDescriptions[] = { EN_ANY, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2881,7 +3392,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, @@ -2895,7 +3406,7 @@ static const GOBGameDescription gameDescriptions[] = { IT_ITA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2903,7 +3414,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "archi", + "playtoons1", "Non-Interactive Demo", { {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, @@ -2916,7 +3427,7 @@ static const GOBGameDescription gameDescriptions[] = { ES_ESP, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640 | kFeaturesSCNDemo, @@ -2924,7 +3435,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "spirou", + "playtoons2", "", { {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, @@ -2934,7 +3445,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2942,7 +3453,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "spirou", + "playtoons2", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -2952,7 +3463,7 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2960,7 +3471,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, @@ -2970,7 +3481,25 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "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, @@ -2978,8 +3507,8 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", - "Pack mes histoires animées", + "playtoons3", + "Pack mes histoires anim\xE9""es", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, @@ -2988,7 +3517,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -2996,7 +3525,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "chato", + "playtoons3", "", { {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, @@ -3006,7 +3535,26 @@ static const GOBGameDescription gameDescriptions[] = { DE_DEU, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + + { + { + "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, @@ -3014,7 +3562,7 @@ static const GOBGameDescription gameDescriptions[] = { }, { { - "wakan", + "playtoons5", "", { {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, @@ -3024,7 +3572,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3042,11 +3590,29 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + 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 }, { { @@ -3054,12 +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, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -3073,7 +3640,7 @@ static const GOBGameDescription gameDescriptions[] = { FR_FRA, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NONE }, kGameTypeAdibou4, kFeatures640, @@ -3207,7 +3774,7 @@ static const GOBGameDescription gameDescriptions[] = { { { "adibouunknown", - "ADIBÙ 2 Ambiente", + "ADIB\xD9 2 Ambiente", AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), IT_ITA, kPlatformPC, @@ -3221,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}, @@ -3239,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}, @@ -3320,7 +3887,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesNone, @@ -3334,7 +3901,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob1, kFeaturesCD, @@ -3348,7 +3915,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3362,7 +3929,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesAdlib, @@ -3376,7 +3943,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob2, kFeaturesCD, @@ -3390,7 +3957,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBargon, kFeaturesNone, @@ -3404,7 +3971,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesAdlib, @@ -3418,7 +3985,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGob3, kFeaturesCD, @@ -3432,7 +3999,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, kFeatures640, @@ -3446,7 +4013,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3460,7 +4027,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformMacintosh, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesAdlib, @@ -3474,7 +4041,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeLostInTime, kFeaturesCD, @@ -3488,7 +4055,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NONE + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, kFeaturesCD, @@ -3496,13 +4063,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "archi", + "playtoons1", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3510,13 +4077,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "spirou", + "playtoons2", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3524,13 +4091,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "chato", + "playtoons3", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3538,13 +4105,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "manda", + "playtoons4", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3552,13 +4119,13 @@ static const GOBGameDescription fallbackDescs[] = { }, { { - "wakan", + "playtoons5", "unknown", AD_ENTRY1(0, 0), UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoon, kFeatures640, @@ -3572,7 +4139,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytnCk, kFeatures640, @@ -3586,7 +4153,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, kFeatures640, @@ -3600,7 +4167,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, kFeaturesNone, @@ -3614,7 +4181,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeGeisha, kFeaturesNone, @@ -3628,7 +4195,7 @@ static const GOBGameDescription fallbackDescs[] = { UNK_LANG, kPlatformPC, ADGF_NO_FLAGS, - GUIO_NOSPEECH + GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdibou4, kFeatures640, diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 8619e08e8b..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" @@ -389,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); @@ -401,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') diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index de71f20142..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" @@ -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; @@ -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: diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 4bb8120e3a..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" @@ -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; SurfaceDescPtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; + Resource *resource; // Always assigned to -1 in Game::loadTotFile() int16 someHandle = -1; @@ -705,6 +707,11 @@ 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: @@ -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,7 +788,7 @@ 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, 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 09addc3900..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)); @@ -533,27 +406,17 @@ void Game::start(void) { 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 ad24d7d9c6..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(); + } + } } } @@ -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 e9656efa32..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; } @@ -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 005d65815f..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,15 +110,12 @@ Global::Global(GobEngine *vm) : _vm(vm) { _pPaletteDesc = 0; - _setAllPalette = false; + _setAllPalette = false; _dontSetPalette = false; _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 9f12f4ded6..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; @@ -117,9 +132,6 @@ public: 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 1de6245297..e534464cce 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -47,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" @@ -102,12 +101,12 @@ void PauseDialog::handleKeyDown(Common::KeyState state) { 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; @@ -121,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"); @@ -248,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; @@ -332,7 +331,6 @@ bool GobEngine::initGameParts() { _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); _sound = new Sound(this); - _parse = new Parse(this); switch (_gameType) { case kGameTypeGeisha: @@ -465,6 +463,8 @@ bool GobEngine::initGameParts() { break; } + _inter->setupOpcodes(); + if (is640()) { _video->_surfWidth = _width = 640; _video->_surfHeight = _video->_splitHeight1 = _height = 480; @@ -495,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 43e2270354..5d1cb3ecf2 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -52,7 +52,6 @@ class Inter; class Map; class Mult; class PalAnim; -class Parse; class Scenery; class Util; class SaveLoad; @@ -128,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, @@ -197,7 +196,6 @@ public: Map *_map; Mult *_mult; PalAnim *_palAnim; - Parse *_parse; Scenery *_scenery; Inter *_inter; SaveLoad *_saveLoad; diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 8bf9536286..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" @@ -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,19 +172,17 @@ 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); 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 412c3f2673..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(); @@ -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(); @@ -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,35 +528,11 @@ 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(); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 54ca32fa9e..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_assign), - 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::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) (); -} - -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)); - - if ((i > 4) || (j > 15)) { - warning("unimplemented opcodeFunc: %d.%d", i, j); - return false; - } - - 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); +void Inter_Bargon::setupOpcodesDraw() { + Inter_v2::setupOpcodesDraw(); } -const char *Inter_Bargon::getOpcodeDrawDesc(byte i) { - return _opcodesDrawBargon[i].desc; +void Inter_Bargon::setupOpcodesFunc() { + Inter_v2::setupOpcodesFunc(); } -const char *Inter_Bargon::getOpcodeFuncDesc(byte i, byte j) { - if ((i > 4) || (j > 15)) - return ""; +void Inter_Bargon::setupOpcodesGob() { + OPCODEGOB( 1, oBargon_intro0); + OPCODEGOB( 2, oBargon_intro1); + OPCODEGOB( 3, oBargon_intro2); + OPCODEGOB( 4, oBargon_intro3); - return _opcodesFuncBargon[i*16 + j].desc; -} + OPCODEGOB( 5, oBargon_intro4); + OPCODEGOB( 6, oBargon_intro5); + OPCODEGOB( 7, oBargon_intro6); + OPCODEGOB( 8, oBargon_intro7); -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) { diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp index bd0b0a94c6..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(o1_assign), - 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 ace5a7a3be..d5d5fcad9a 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_assign), - 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; @@ -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); @@ -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, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, + _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_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 token; + 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_assign(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,7 +1037,7 @@ 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; } @@ -1533,28 +1045,30 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { if (!allZero) { _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(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,14 +1423,14 @@ 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]) return false; @@ -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 3107fcf9bc..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_assign), - 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 " @@ -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"); @@ -1589,49 +1042,46 @@ void Inter_v2::o2_resetImdFrontSurf() { } bool Inter_v2::o2_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - - savedPos = _vm->_global->_inter_execPtr; - varOff = _vm->_parse->parseVarIndex(); + 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 6819b369b8..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_assign), - 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; } diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index 6ab55d70af..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_assign), - 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(); @@ -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 cb5b28cb67..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_assign), - 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); @@ -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,40 +235,36 @@ 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"))) { @@ -859,9 +276,7 @@ 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"))) { @@ -873,9 +288,7 @@ 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"))) { @@ -887,9 +300,7 @@ 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"))) { @@ -901,9 +312,7 @@ 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"))) { @@ -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 f40314f87e..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_assign), - 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, index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); - _vm->_video->drawPackedSprite(dataBuf, width, height, + _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_assign(OpFuncParams ¶ms) { - byte *savedPos; - int16 varOff; - int16 token; - int16 result; - byte loopCount; - uint16 var_6, var_A; + 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 22a5cd37b9..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,10 +44,12 @@ MODULE_OBJS := \ mult_v1.o \ mult_v2.o \ palanim.o \ - parse.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 1670c26ea5..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" @@ -251,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) @@ -265,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_v1.cpp b/engines/gob/mult_v1.cpp index e2c16674c9..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() { diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index d9b5be0847..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; @@ -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 0fa46097a3..0000000000 --- a/engines/gob/parse.cpp +++ /dev/null @@ -1,1499 +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; -} - -int16 Parse::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; -} - -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; -} - -int16 Parse::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::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::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; - } -} - -} // End of namespace Gob diff --git a/engines/gob/parse.h b/engines/gob/parse.h deleted file mode 100644 index 01f5762b6d..0000000000 --- a/engines/gob/parse.h +++ /dev/null @@ -1,128 +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); - - int16 parseVarIndex(uint16 *arg_0 = 0, uint16 *arg_4 = 0); - int16 parseValExpr(byte stopToken = 99); - int16 parseExpr(byte stopToken, byte *resultPtr); - - Parse(GobEngine *vm); - virtual ~Parse() {} - -private: - 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); - - int16 getOffset(int16 arg_0, byte arg_2, uint32 arg_3, uint16 arg_7, uint16 arg_9); - int cmpHelper(byte *operPtr, int32 *valPtr); -}; - -} // End of namespace Gob - -#endif // GOB_PARSE_H 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.h b/engines/gob/save/savefile.h index 989a37277e..615be8e0f2 100644 --- a/engines/gob/save/savefile.h +++ b/engines/gob/save/savefile.h @@ -163,7 +163,7 @@ public: bool readPalette(const byte *palette); /** Read a sprite into the part. */ bool readSprite(const SurfaceDesc &sprite); - + /** Read size bytes of raw data into the sprite. */ bool readSpriteRaw(const byte *data, uint32 size); 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 71750509b4..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,9 +185,7 @@ 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; @@ -193,17 +193,16 @@ int16 Scenery::loadStatic(char search) { _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); - _vm->_draw->_destSurface = sprIndex; - _vm->_draw->_spriteLeft = sprResId; + _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; @@ -522,22 +518,21 @@ int16 Scenery::loadAnim(char search) { ; _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->_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 e1148dacb9..b0e7691c07 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -331,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 3d7520fe69..0a76ee40ab 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -76,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/videoplayer.cpp b/engines/gob/videoplayer.cpp index e82805d6ac..6c07d22333 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -201,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; } diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 8d0e466bba..14f1c6463c 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -48,8 +48,6 @@ static const PlainGameDescriptor groovieGames[] = { {0, 0} }; -using Common::GUIO_NONE; - static const GroovieGameDescription gameDescriptions[] = { // The 7th Guest DOS English @@ -57,7 +55,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -67,7 +65,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("script.grv", "6e30b54b1f3bc2262cdcf7961db2ae67", 17191), - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -81,7 +79,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "intro.gjd", 0, NULL, 31711554}, { NULL, 0, NULL, 0} }, - Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieT7G, 0 }, @@ -92,7 +90,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE }, kGroovieV2, 1 }, @@ -102,7 +100,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "Demo", AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70), - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 1 }, @@ -112,7 +110,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "Making Of", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 2 }, @@ -122,7 +120,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "clandestiny", "Trailer", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD }, kGroovieV2, 3 }, @@ -132,7 +130,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "clandestiny", "", AD_ENTRY1s("disk.1", "f79fc1515174540fef6a34132efc4c53", 76), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -142,7 +140,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "unclehenry", "", AD_ENTRY1s("disk.1", "0e1b1d3cecc4fc7efa62a968844d1f7a", 72), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -152,7 +150,7 @@ static const GroovieGameDescription gameDescriptions[] = { { "tlc", "", AD_ENTRY1s("disk.1", "32a1afa68478f1f9d2b25eeea427f2e3", 84), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NOMIDI }, kGroovieV2, 1 }, @@ -179,7 +177,7 @@ static const ADParams detectionParams = { // Flags kADFlagUseExtraAsHint, // Additional GUI options (for every game} - Common::GUIO_NOMIDI + Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX }; diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 6e18b86062..e2315459d4 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -264,6 +264,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/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 e0c2c0aa77..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(); 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..3989062506 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; 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 af8bc6aa97..5e03f3d9bb 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -28,6 +28,14 @@ #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 { @@ -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); @@ -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; } @@ -1773,7 +1814,7 @@ int LoLEngine::clickedAutomap(Button *button) { displayAutomap(); gui_drawPlayField(); - setPaletteBrightness(_screen->_currentPalette, _brightness, _lampEffect); + setPaletteBrightness(_screen->getPalette(0), _brightness, _lampEffect); return 1; } @@ -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 c4d804c14d..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); } @@ -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 e75a13c870..c0ddd0c860 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -477,7 +477,7 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec r = getNearestPartyMemberFromPos(x, y); 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 d9fc8f9d66..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: @@ -594,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; } @@ -629,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 3461fa5da9..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; @@ -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]; @@ -561,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); } @@ -591,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; @@ -639,6 +632,15 @@ 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) { @@ -661,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) @@ -714,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); @@ -729,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]); @@ -754,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); @@ -808,9 +850,6 @@ void LoLEngine::startup() { _loadSuppFilesFlag = 1; - _txt->setAnimParameters("<MORE>", 10, 31, 0); - _txt->setAnimFlag(true); - _sound->loadSfxFile("LORESFX"); setMouseCursorToItemInHand(); @@ -822,12 +861,6 @@ void LoLEngine::startupNew() { _compassDirection = _compassDirectionIndex = -1; _lastMouseRegion = -1; - - /* - _unk5 = 1; - _unk6 = 1; - _unk7 = 1 - _unk8 = 1*/ _currentLevel = 1; giveCredits(41, 0); @@ -858,6 +891,12 @@ void LoLEngine::runLoop() { _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; @@ -865,7 +904,7 @@ void LoLEngine::runLoop() { _timer->update(); - //checkFloatingPointerRegions(); + checkFloatingPointerRegions(); gui_updateInput(); update(); @@ -884,6 +923,55 @@ void LoLEngine::runLoop() { } } +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(); @@ -1095,7 +1183,7 @@ void LoLEngine::updatePortraitSpeechAnim() { f -= 5; f += 7; - if (_speechFlag) { + if (speechEnabled()) { if (snd_updateCharacterSpeech() == 2) _updatePortraitSpeechAnimDuration = 2; else @@ -1233,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; @@ -1421,7 +1509,7 @@ void LoLEngine::gui_specialSceneSuspendControls(int controlMode) { _specialSceneFlag = 1; _currentControlMode = controlMode; calcCharPortraitXpos(); - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { @@ -1431,7 +1519,7 @@ void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { } _updateFlags &= 0xfffe; _specialSceneFlag = 0; - //checkMouseRegions(); + checkFloatingPointerRegions(); } void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { @@ -1450,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; } @@ -1584,15 +1672,16 @@ 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 && (_flagsTable[31] & 0x08)) { brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8); @@ -1606,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() { @@ -1790,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); } @@ -1919,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); @@ -2120,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 && !(_flagsTable[52] & 0x04)) { - uint8 *sc = _screen->_currentPalette; - uint8 *dc = _screen->getPalette(2); + uint8 *sc = _screen->getPalette(0).getData(); + uint8 *dc = _screen->getPalette(2).getData(); for (int i = 1; i < 768; i++) SWAP(sc[i], dc[i]); + _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; @@ -2148,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; @@ -2174,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) { @@ -2241,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; } @@ -2417,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"); @@ -2495,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; @@ -2509,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"); @@ -2541,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"); @@ -2570,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"); @@ -2646,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()) @@ -2671,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); @@ -2734,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"); @@ -2742,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); @@ -2754,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; @@ -2771,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); } @@ -2799,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) { @@ -2871,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()) @@ -3282,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) { @@ -3499,16 +3650,16 @@ void LoLEngine::restoreSwampPalette() { 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); } @@ -3529,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"); @@ -3579,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"); @@ -3681,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); @@ -3848,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; @@ -3932,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++; @@ -3942,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++; } @@ -3951,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 45795a7cab..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; @@ -772,11 +781,12 @@ 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); @@ -862,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; @@ -905,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]; @@ -1303,7 +1313,6 @@ private: // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); - uint8 getRandomNumberSpecial(); uint8 _compassBroken; uint8 _drainMagic; @@ -1349,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); diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 79665068f6..ecd6bbe450 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -29,6 +29,7 @@ #include "graphics/thumbnail.h" #include "kyra/kyra_v1.h" +#include "kyra/util.h" #define CURRENT_SAVE_VERSION 16 @@ -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/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 0236e4fa7d..945495517f 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -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; + _screen->loadPalette("SWAMPICE.COL", _screen->getPalette(2)); + _screen->getPalette(2).copy(_screen->getPalette(0), 128); if (_flagsTable[52] & 0x04) { - uint8 *pal0 = _screen->_currentPalette; - uint8 *pal2 = _screen->getPalette(2); + 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); @@ -548,14 +544,14 @@ void LoLEngine::updateLampStatus() { 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); } } } @@ -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) @@ -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 2b3a9366e6..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,12 +2663,13 @@ void Screen::setMouseCursor(int x, int y, const byte *shape) { _system->updateScreen(); } -uint8 *Screen::getPalette(int num) { - assert(num >= 0 && num < (_vm->gameFlags().platform == Common::kPlatformAmiga ? 6 : 4)); - if (num == 0) - return _currentPalette; +Palette &Screen::getPalette(int num) { + assert(num >= 0 && (uint)num < _palettes.size()); + return *_palettes[num]; +} - 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) { @@ -2685,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); @@ -2702,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); @@ -2738,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 @@ -2967,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); @@ -3139,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 1691c73a90..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); @@ -275,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]; @@ -287,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 3f3aef72fe..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,10 +923,10 @@ 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; @@ -936,7 +934,7 @@ bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, u uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int numTabs) { if (!src1) - src1 = _screenPalette; + src1 = _screenPalette->getData(); uint8 *p1 = dst; uint8 *p2 = src1; @@ -949,14 +947,14 @@ uint8 *Screen_LoL::generateFadeTable(uint8 *dst, uint8 *src1, uint8 *src2, int n 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++) { - int val = (((int8)*p3++ * t) >> 8) + (int8)*p2++; + int16 val = (((int8)*p3++ * t) >> 8) + (int8)*p2++; *dst++ = (uint8)val; } } @@ -972,6 +970,45 @@ 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 017af4ba48..db355977f8 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -70,14 +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); @@ -92,6 +92,9 @@ public: uint8 *_grayOverlay; int _fadeFlag; + // PC98 specific + static void convertPC98Gfx(uint8 *data, int w, int h, int pitch); + private: LoLEngine *_vm; @@ -106,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 a4e014e8c1..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); 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 3d57b23181..a606419722 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -609,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; @@ -663,7 +663,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) { case 12: return _drainMagic; case 13: - return _speechFlag; + return getVolume(kVolumeSpeech) - 2; default: break; } @@ -864,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; @@ -876,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; } @@ -1276,7 +1276,7 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) { 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); + releaseMonsterShapes(i); return 0; } @@ -1399,17 +1399,17 @@ int LoLEngine::olol_playEndSequence(EMCState *script){ if (_characters[0].id == -9) c = 1; else if (_characters[0].id == -5) - c = 3; + c = 3; else if (_characters[0].id == -1) c = 2; while (snd_updateCharacterSpeech()) delay(_tickLength); - + _eventList.clear(); _screen->hideMouse(); - memset(_screen->getPalette(1), 0, 768); - + _screen->getPalette(1).clear(); + showOutro(c, (_monsterDifficulty == 2)); quitGame(); @@ -1428,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; } @@ -1994,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; } @@ -2095,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); @@ -2126,55 +2134,65 @@ int LoLEngine::olol_paletteFlash(EMCState *script) { int LoLEngine::olol_restoreMagicShroud(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_restoreMagicShroud(%p)", (const void *)script); - WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen); + 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; - _screen->loadPalette("LITEPAL1.COL", tpal1); + _res->loadFileToBuf("LITEPAL1.COL", tpal1, 768); tpal2 = _screen->generateFadeTable(tpal3, 0, tpal1, 21); - _screen->loadPalette("LITEPAL2.COL", tpal2); + _res->loadFileToBuf("LITEPAL2.COL", tpal2, 768); tpal4 = tpal2; tpal2 += 768; - _screen->loadPalette("LITEPAL3.COL", tpal1); + _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); + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); - _screen->setScreenPalette(tpal3); + + 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(tpal3, 300); + _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); + mov->displayFrame(i, 0, 0, 0, 0, 0, 0); _screen->updateScreen(); if (i == 22 || i == 24 || i == 28 || i == 32) { snd_playSoundEffect(131, -1); - _screen->setScreenPalette(tpal3); + + pal.copy(tpal3, 0, 256); + _screen->setScreenPalette(pal); tpal3 += 768; } delayUntil(etime); } mov->close(); - delete mov; + delete mov; delete[] fadeTab; _screen->showMouse(); @@ -2297,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; @@ -2375,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: @@ -2383,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; @@ -2395,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; @@ -2405,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; @@ -2511,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; @@ -2547,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; } @@ -2566,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); } @@ -2852,7 +2868,7 @@ void LoLEngine::setupOpcodeTable() { // 0xA8 OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_drinkBezelCup); Opcode(olol_changeItemTypeOrFlag); // 0xAC 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 849a325560..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); @@ -803,25 +802,24 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { 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); @@ -856,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); @@ -865,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; @@ -895,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]; @@ -906,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(); @@ -1042,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; @@ -1062,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; @@ -1129,7 +1127,7 @@ 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; diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index 3f87036849..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) { @@ -304,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 732a8bb2ca..8cee1dc5fc 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -784,7 +784,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) { default: return m->damageReceived ? 5 : m->currentSubFrame; } - + break; default: break; @@ -1092,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..06c13e1fef 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(); @@ -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/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 26638b8172..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) { @@ -137,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)) { @@ -200,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) { @@ -220,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) @@ -239,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; @@ -266,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; @@ -311,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) { @@ -334,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; } @@ -347,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; @@ -376,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) { @@ -384,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; @@ -448,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 && !(_flags & WF_NO_LAST_FRAME)) - frameStep = -1; - else - frameCount = diffCount; - } else { - frameCount = _numFrames - _currentFrame + frameNum; - if (frameCount >= diffCount || (_flags & WF_NO_LAST_FRAME)) { - 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 fdceca1cd8..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,12 +74,12 @@ 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, @@ -104,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); @@ -116,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; } @@ -128,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/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/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 4816f87a20..2f2fbc5243 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -55,15 +55,6 @@ int g_debug_seeking = 0; // Stepping forward until some special condition is met int g_debug_seek_special = 0; // Used for special seeks int g_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth -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 -}; - Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; @@ -152,11 +143,17 @@ 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)); @@ -165,7 +162,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { 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)); @@ -174,7 +173,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)); @@ -225,6 +226,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"); @@ -310,12 +317,12 @@ 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(" step - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); - DebugPrintf(" step_event - Steps forward until a SCI event is received.\n"); - DebugPrintf(" step_ret - Steps forward until ret is called on the current execution stack level.\n"); - DebugPrintf(" step_global - Steps until the global variable with the specified index is modified.\n"); - DebugPrintf(" step_callk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\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"); @@ -324,8 +331,8 @@ bool Console::cmdHelp(int argc, const char **argv) { 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"); @@ -334,8 +341,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"); diff --git a/engines/sci/console.h b/engines/sci/console.h index c45202de16..22b5505bf2 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -35,6 +35,15 @@ namespace Sci { class SciEngine; struct List; +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 +}; + // Refer to the "addresses" command on how to pass address parameters int parse_reg_t(EngineState *s, const char *str, reg_t *dest); int printObject(EngineState *s, reg_t pos); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index ac5268dd4c..bdf2c7c72a 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -953,9 +953,9 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954}, {"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - 0, + GF_SCI0_SCI1VOCAB, SCI_VERSION_AUTODETECT, - SCI_VERSION_01 + SCI_VERSION_0 }, // King's Quest 1 SCI Remake - English DOS (from the King's Quest Collection) @@ -969,7 +969,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {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) @@ -2504,6 +2504,32 @@ static const struct SciGameDescription SciGameDescriptions[] = { 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 @@ -3085,6 +3111,32 @@ static const struct SciGameDescription SciGameDescriptions[] = { 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", { 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/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 baf45d80c7..eafc6dbd4d 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -945,7 +945,11 @@ bool Kernel::loadKernelNames() { switch (_resmgr->_sciVersion) { case SCI_VERSION_0: case SCI_VERSION_01: - vocab_get_knames0(_resmgr, _kernelNames); + // HACK: The KQ1 demo requires the SCI1 vocabulary. + if (((SciEngine*)g_engine)->getFlags() & GF_SCI0_SCI1VOCAB) + vocab_get_knames1(_resmgr, _kernelNames); + else + vocab_get_knames0(_resmgr, _kernelNames); break; case SCI_VERSION_01_VGA: case SCI_VERSION_01_VGA_ODD: diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 27d9df059d..46913a5b39 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -69,16 +69,17 @@ 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; @@ -104,18 +105,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(); /** @@ -127,8 +128,10 @@ private: ResourceManager *_resmgr; // 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,61 +181,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 */ - +/** + * 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)))) @@ -249,50 +253,59 @@ int _find_view_priority(EngineState *s, int y); /******************** 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/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index a26c2dbcb1..2856c76aa3 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -621,10 +621,14 @@ 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 = (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; @@ -636,7 +640,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); @@ -1570,7 +1574,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)); @@ -1584,7 +1588,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; @@ -1593,7 +1597,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; @@ -1620,8 +1624,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; @@ -1641,7 +1645,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 ; @@ -2524,10 +2528,10 @@ 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) @@ -3287,7 +3291,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"); diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index b742c93a52..bb27589d84 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -975,49 +975,42 @@ 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 (argv[0].toUint16()) { case kSciAudioWPlay: - case kSciAudioPlay: - s->_sound._audioResource->stop(); - - if (argc == 2) { // KQ5CD, KQ6 floppy - Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(argv[1].toUint16(), 65535, &sampleLen); - - if (audioStream) - mixer->playInputStream(Audio::Mixer::kSpeechSoundType, s->_sound._audioResource->getAudioHandle(), audioStream); - } else if (argc == 6) { // SQ4CD or newer - // Make a BE number - uint32 audioNumber = (((argv[2].toUint16() & 0xFF) << 24) & 0xFF000000) | - (((argv[3].toUint16() & 0xFF) << 16) & 0x00FF0000) | - (((argv[4].toUint16() & 0xFF) << 8) & 0x0000FF00) | - ( (argv[5].toUint16() & 0xFF) & 0x000000FF); - - Audio::AudioStream *audioStream = s->_sound._audioResource->getAudioStream(audioNumber, argv[1].toUint16(), &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(argv[1].toUint16()); + s->_sound.setAudioRate(argv[1].toUint16()); break; case kSciAudioVolume: mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, argv[1].toUint16()); @@ -1027,7 +1020,7 @@ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) { // In SCI1.1: tests for digital audio support return make_reg(0, 1); } else { - s->_sound._audioResource->setAudioLang(argv[1].toSint16()); + s->resmgr->setAudioLanguage(argv[1].toSint16()); } break; default: @@ -1042,8 +1035,10 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) { case kSciAudioSyncStart: { ResourceId id; - if (s->_sound._soundSync) - s->resmgr->unlockResource(s->_sound._soundSync); + if (s->_sound._syncResource) { + s->resmgr->unlockResource(s->_sound._syncResource); + s->_sound._syncResource = NULL; + } // Load sound sync resource and lock it if (argc == 3) { @@ -1056,10 +1051,11 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } - s->_sound._soundSync = (ResourceSync *)s->resmgr->findResource(id, 1); + s->_sound._syncResource = s->resmgr->findResource(id, 1); - if (s->_sound._soundSync) { - s->_sound._soundSync->startSync(s, argv[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 @@ -1067,20 +1063,32 @@ reg_t kDoSync(EngineState *s, int funct_nr, int argc, reg_t *argv) { } 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 = NULL; + if (s->_sound._syncResource) { + s->resmgr->unlockResource(s->_sound._syncResource); + s->_sound._syncResource = NULL; } break; default: - warning("kDoSync: Unhandled case %d", argv[0].toUint16()); + warning("DoSync: Unhandled subfunction %d", argv[0].toUint16()); } return s->r_acc; 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 f800695df5..50c43a0e88 100644 --- a/engines/sci/engine/memobj.h +++ b/engines/sci/engine/memobj.h @@ -502,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/script.cpp b/engines/sci/engine/script.cpp index a0bfdeddc9..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) { diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 63e99ad122..11c38052db 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -26,24 +26,9 @@ // 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 { @@ -63,13 +48,13 @@ static int *p_var_max; // May be NULL even in valid state! extern const char *selector_name(EngineState *s, int selector); -int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) { +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; } @@ -86,7 +71,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; } @@ -257,7 +242,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod 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, *p_objp); sciprintf(" (%s)", selector_name(s, prop_id)); } @@ -342,8 +327,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod 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) { -// TODO: disabled till this is moved in console.cpp -#if 0 // Do we support a separate console? int old_debugstate = g_debugstate_valid; @@ -412,7 +395,6 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * // OK, found whatever we were looking for } } -#endif g_debugstate_valid = (g_debug_step_running == 0); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 98fbd8bad7..2227167673 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -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 e35530700e..e618077d54 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -126,4 +126,73 @@ uint16 EngineState::currentRoomNumber() const { 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 0b84c0ef3c..cbd0b0cfbb 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -193,7 +193,7 @@ int script_error(EngineState *s, const char *file, int line, const char *reason) } #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\""); @@ -1550,7 +1550,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select 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) diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index dfbbc39780..a3fabbe44b 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -198,7 +198,11 @@ 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. @@ -287,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; @@ -307,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); @@ -342,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 - * (ObjVarRef& ) 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, const ObjVarRef& 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, ObjVarRef *varp, 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 -** (ObjVarRef *) *varp: A reference to 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. -** *varindex 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/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.h b/engines/sci/gfx/gfx_driver.h index b74511de77..f7cbd0b6c2 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -38,171 +38,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, int bytespp); - /* Attempts to initialize a specific graphics mode - ** Parameters: (int x int) xres, yres: Horizontal and vertical scaling - ** factors - ** (int) bytespp: Any of GFX_COLOR_MODE_*. GFX_COLOR_MODE_INDEX - ** implies color index mode. - ** 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]; } @@ -212,7 +243,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.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 d03c5e9519..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,6 +257,7 @@ 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 */ @@ -265,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; @@ -293,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 */ @@ -324,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); @@ -334,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 */ @@ -353,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 */ @@ -366,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 3922b21db2..6b7724a6bd 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -36,7 +36,7 @@ namespace Sci { #define GFX_DEBUG /* General output macros */ -# define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error +#define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error /***********************/ /*** Data structures ***/ @@ -50,32 +50,35 @@ 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 */ uint32 red_mask, green_mask, blue_mask, alpha_mask; short red_shift, green_shift, blue_shift, alpha_shift; - - /* 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. */ - }; @@ -84,16 +87,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 */ }; @@ -104,11 +107,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; @@ -120,11 +127,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); } @@ -133,10 +145,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)); } @@ -150,86 +165,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, @@ -240,16 +264,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 */ }; @@ -260,18 +284,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.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.h b/engines/sci/gfx/gfx_widgets.h index bd884ffbb4..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, const ObjVarRef& under_bitsp, int signal, const ObjVarRef& 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.h b/engines/sci/gfx/operations.h index d559d3b6d2..491b485da0 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,640 @@ 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, - int xfact = 1, int yfact = 1, gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX); -/* 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 -** (gfx_color_mode_t) bpp: Bytes per pixel to initialize with, or -** 0 (GFX_COLOR_MODE_AUTO) to auto-detect -** (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] bpp Bytes per pixel to initialize with, or 0 + * (GFX_COLOR_MODE_AUTO) to auto-detect + * @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, int xfact = 1, int yfact = 1, + gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX); + +/** + * 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 762cb7b55d..5ee2665b50 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; diff --git a/engines/sci/gfx/res_view.cpp b/engines/sci/gfx/res_view.cpp index f282369e15..b30c57f38d 100644 --- a/engines/sci/gfx/res_view.cpp +++ b/engines/sci/gfx/res_view.cpp @@ -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 5edf1b7145..3c377e8ef2 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", @@ -217,7 +210,7 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { return loadPatch(res, file); } -bool ResourceManager::loadFromAudioVolume(Resource *res, Common::File &file) { +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))) { @@ -243,6 +236,21 @@ bool ResourceManager::loadFromAudioVolume(Resource *res, Common::File &file) { 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; @@ -292,7 +300,10 @@ void ResourceManager::loadResource(Resource *res) { file->seek(res->file_offset, SEEK_SET); if (res->source->source_type == kSourceAudioVolume) { - loadFromAudioVolume(res, *file); + if (_sciVersion < SCI_VERSION_1_1) + loadFromAudioVolumeSCI1(res, *file); + else + loadFromAudioVolumeSCI11(res, *file); } else { int error = decompress(res, file); if (error) { @@ -436,8 +447,11 @@ void ResourceManager::scanNewSources() { else readResourceMapSCI1(source); break; + case kSourceExtAudioMap: + readAudioMapSCI1(source); + break; case kSourceIntMap: - readMap(source); + readAudioMapSCI11(source); break; default: break; @@ -460,6 +474,7 @@ ResourceManager::ResourceManager(int version, int maxMemory) { _LRU.clear(); _resMap.clear(); _sciVersion = version; + _audioMapSCI1 = NULL; addAppropriateSources(); @@ -607,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 @@ -659,6 +669,8 @@ Resource *ResourceManager::findResource(ResourceId id, 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; @@ -671,8 +683,6 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) { addToLRU(retval); } - freeOldResources(retval->status == kResStatusAllocated); - if (retval->data) return retval; else { @@ -695,7 +705,7 @@ void ResourceManager::unlockResource(Resource *res) { addToLRU(res); } - freeOldResources(0); + freeOldResources(); } int ResourceManager::detectMapVersion() { @@ -871,15 +881,7 @@ 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); @@ -1042,15 +1044,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { 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->id = resId; res->source = getVolume(map, volume_nr); @@ -1064,11 +1058,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { 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; - if ((resId.type == kResourceTypeSync) || (resId.type == kResourceTypeSync36)) - res = new ResourceSync; - else - res = new Resource; + Resource *res = new Resource; _resMap.setVal(resId, res); res->id = resId; res->source = src; @@ -1077,6 +1067,22 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 } } +void ResourceManager::removeAudioResource(ResourceId resId) { + // Remove resource, unless it was loaded from a patch + if (_resMap.contains(resId)) { + Resource *res = _resMap.getVal(resId); + + 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()); + } + } + } +} + // Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): // ========= // 6-byte entries: @@ -1112,7 +1118,7 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 // w syncSize (iff seq has bit 7 set) // w syncAscSize (iff seq has bit 6 set) -int ResourceManager::readMap(ResourceSource *map) { +int ResourceManager::readAudioMapSCI11(ResourceSource *map) { bool isEarly = true; uint32 offset = 0; Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); @@ -1197,6 +1203,103 @@ int ResourceManager::readMap(ResourceSource *map) { return 0; } +// AUDIOnnn.MAP contains 10-byte entries: +// w nEntry +// dw offset+volume (as in resource.map) +// dw size +// ending with 10 0xFFs + +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(); + + if (file.ioFailed()) { + warning("Error while reading %s", map->location_name.c_str()); + return SCI_ERROR_RESMAP_NOT_FOUND; + } + + if (n == 0xffff) + break; + + 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 { + warning("Failed to find audio volume %i", volume_nr); + } + } + + 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; + } + + 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, uint32&szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes @@ -1328,325 +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); - } -} - -// 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; -} - -// 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* 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; - Sci::Resource* audioRes = NULL; - - // Try to load from resource manager - if (volume == 65535) - audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio, audioNumber), false); - else - audioRes = _resMgr->findResource(ResourceId(kResourceTypeAudio36, volume, audioNumber), false); - - if (audioRes) { - 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; - } - - 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 fc3f37f25c..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,7 +131,6 @@ struct ResourceSource { Common::String location_name; // FIXME: Replace by FSNode ? int volume_number; ResourceSource *associated_map; - ResourceSource *next; }; class ResourceManager; @@ -270,6 +264,8 @@ public: */ Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1); + void setAudioLanguage(int language); + protected: int _maxMemory; //!< Config option: Maximum total byte number allocated Common::List<ResourceSource *> _sources; @@ -278,6 +274,7 @@ protected: Common::List<Resource *> _LRU; //!< Last Resource Used list 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. @@ -325,11 +322,13 @@ protected: void loadResource(Resource *res); bool loadPatch(Resource *res, Common::File &file); bool loadFromPatchFile(Resource *res); - bool loadFromAudioVolume(Resource *res, Common::File &file); - 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(); @@ -337,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 SCI1.1 MAP resources + * Reads SCI1.1 audio map resources + * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ - int readMap(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 ---*/ @@ -368,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 f58d729bf6..9b277b058f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -158,7 +158,8 @@ Common::Error SciEngine::run() { if (flags & GF_SCI0_OLD || flags & GF_SCI0_OLDGFXFUNCS || - flags & GF_SCI0_OLDGETTIME) { + flags & GF_SCI0_OLDGETTIME || + flags & GF_SCI0_SCI1VOCAB) { error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set"); } } else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) { @@ -170,7 +171,8 @@ Common::Error SciEngine::run() { if (flags & GF_SCI0_OLD || flags & GF_SCI0_OLDGFXFUNCS || - flags & GF_SCI0_OLDGETTIME) { + flags & GF_SCI0_OLDGETTIME || + flags & GF_SCI0_SCI1VOCAB) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set"); } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 91f491fe71..18b1b93a92 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -108,6 +108,11 @@ enum SciGameFlags { ** Older SCI versions had simpler code for GetTime() */ GF_SCI0_OLDGETTIME = (1 << 2), + + /* Applies to any game that requires the SCI1 kernel vocab + ** Some games (such as the King's Quest I demo) require the default kernel vocab table. + */ + GF_SCI0_SCI1VOCAB = (1 << 3), // ---------------------------------------------------------------------------- @@ -118,18 +123,18 @@ enum SciGameFlags { /* ** Used to distinguish SCI1 EGA games */ - GF_SCI1_EGA = (1 << 3), + GF_SCI1_EGA = (1 << 4), /* 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 << 5), /* 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 << 6) }; class SciEngine : public Engine { diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index e37007bf8e..9bf7730fc9 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -348,11 +348,13 @@ SfxState::SfxState() { _flags = 0; _song = NULL; _suspended = 0; - _soundSync = 0; - _audioResource = 0; + _syncResource = NULL; + _audioRate = 11025; } SfxState::~SfxState() { + if (_syncResource) + _resMgr->unlockResource(_syncResource); } @@ -526,7 +528,7 @@ void SfxState::updateSingleSong() { debugMessage += " none\n"; } - debugC(2, kDebugLevelSound, debugMessage.c_str()); + debugC(2, kDebugLevelSound, "%s", debugMessage.c_str()); _song = newsong; thawTime(); /* Recover song delay time */ @@ -641,8 +643,8 @@ void SfxState::sfx_init(ResourceManager *resmgr, int flags) { _songlib._lib = 0; _song = NULL; _flags = flags; - _soundSync = NULL; - _audioResource = NULL; + _syncResource = NULL; + _syncOffset = 0; player = NULL; @@ -676,6 +678,8 @@ void SfxState::sfx_init(ResourceManager *resmgr, int flags) { delete player; player = NULL; } + + _resMgr = resmgr; } void SfxState::sfx_exit() { @@ -689,12 +693,6 @@ void SfxState::sfx_exit() { g_system->getMixer()->stopAll(); _songlib.freeSounds(); - - // Delete audio resources for CD talkie games - if (_audioResource) { - delete _audioResource; - _audioResource = 0; - } } void SfxState::sfx_suspend(bool suspend) { @@ -1004,4 +1002,187 @@ void SfxState::sfx_all_stop() { 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; + 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 5db56bd864..e7eba85c99 100644 --- a/engines/sci/sfx/core.h +++ b/engines/sci/sfx/core.h @@ -50,8 +50,9 @@ public: // FIXME, make private 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(); @@ -164,6 +165,15 @@ public: 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(); @@ -173,8 +183,12 @@ protected: 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/scumm/actor.cpp b/engines/scumm/actor.cpp index cf90094112..88c258a2e6 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -1348,6 +1348,22 @@ void ScummEngine::processActors() { } } } + } else if (_game.heversion >= 90) { + for (int j = 0; j < numactors; ++j) { + for (int i = 0; i < numactors; ++i) { + int sc_actor1 = _sortedActors[j]->_layer; + int sc_actor2 = _sortedActors[i]->_layer; + if (sc_actor1 < sc_actor2) { + SWAP(_sortedActors[i], _sortedActors[j]); + } else if (sc_actor1 == sc_actor2) { + sc_actor1 = _sortedActors[j]->getPos().y; + sc_actor2 = _sortedActors[i]->getPos().y; + if (sc_actor1 < sc_actor2) { + SWAP(_sortedActors[i], _sortedActors[j]); + } + } + } + } } else { for (int j = 0; j < numactors; ++j) { for (int i = 0; i < numactors; ++i) { diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index 665782bf36..fe0904d632 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -420,8 +420,7 @@ void ScummEngine_v100he::o100_actorOps() { a->_needRedraw = true; break; case 59: - // HE games use reverse order of layering, so we adjust - a->_layer = -pop(); + a->_layer = pop(); a->_needRedraw = true; break; case 63: diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp index bb209e78d1..64c63baa9d 100644 --- a/engines/scumm/he/script_v72he.cpp +++ b/engines/scumm/he/script_v72he.cpp @@ -770,8 +770,7 @@ void ScummEngine_v72he::o72_actorOps() { a->setTalkCondition(k); break; case 43: // HE 90+ - // HE games use reverse order of layering, so we adjust - a->_layer = -pop(); + a->_layer = pop(); a->_needRedraw = true; break; case 64: diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp index caae659766..22487b43a3 100644 --- a/engines/scumm/vars.cpp +++ b/engines/scumm/vars.cpp @@ -727,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/sword1/music.cpp b/engines/sword1/music.cpp index 9f602aca2c..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 && size) { + 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 306d23db57..5577c66fc6 100644 --- a/engines/sword1/sound.cpp +++ b/engines/sword1/sound.cpp @@ -226,14 +226,14 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) { return false; } - uint16 numRooms = file.readUint16LE(); // Number of rooms + 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(2 + numRooms * 4 + 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/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 863848bee1..a3cd0bc7b7 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -297,15 +297,11 @@ 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} }, 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/tinsel.cpp b/engines/tinsel/tinsel.cpp index 47602b5862..1a08fd2420 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -850,19 +850,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/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 fe5f653b94..2e71b548bc 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -129,6 +129,10 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale); } +bool CursorManager::supportsCursorPalettes() { + return g_system->hasFeature(OSystem::kFeatureCursorHasPalette); +} + void CursorManager::disableCursorPalette(bool disable) { if (!g_system->hasFeature(OSystem::kFeatureCursorHasPalette)) return; @@ -139,7 +143,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 bc38466eda..f019e37b04 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -36,7 +36,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); /** @@ -88,6 +102,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/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/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 4628ec436b..166b11afe3 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -1447,7 +1447,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 a8e63098fb..fd2d9c65fd 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -529,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/ThemeParser.cpp b/gui/ThemeParser.cpp index 2e7e2d3214..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 { @@ -86,19 +80,6 @@ static GUI::ThemeEngine::TextAlignVertical parseTextVAlign(const Common::String ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { - - _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; - _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; _theme = parent; @@ -107,8 +88,6 @@ ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { ThemeParser::~ThemeParser() { delete _defaultStepGlobal; delete _defaultStepLocal; - _palette.clear(); - _drawFunctions.clear(); } void ThemeParser::cleanup() { @@ -281,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; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 7c9d39030b..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); @@ -249,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/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/themes/default.inc b/gui/themes/default.inc index d23c7ff060..d2fe7dade5 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -334,9 +334,9 @@ "<def var='ShowGlobalMenuLogo' value='0'/> " "<def var='ShowSearchPic' value='0'/> " "<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' " @@ -1055,7 +1055,7 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='KeyRemapper' overlays='screen_center' shading='dim'> " +"<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' " @@ -1087,9 +1087,9 @@ "<def var='ShowGlobalMenuLogo' value='0'/> " "<def var='ShowSearchPic' value='0'/> " "<def var='ScummSaveLoad.ExtInfo.Visible' value='0'/> " -"<def var='KeyRemapper.Spacing' value='5'/> " -"<def var='KeyRemapper.LabelWidth' value='80'/> " -"<def var='KeyRemapper.ButtonWidth' value='60'/> " +"<def var='KeyMapper.Spacing' value='5'/> " +"<def var='KeyMapper.LabelWidth' value='80'/> " +"<def var='KeyMapper.ButtonWidth' value='60'/> " "<widget name='Button' " "size='72,16' " "/> " @@ -1812,7 +1812,7 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='KeyRemapper' overlays='screen_center' shading='dim'> " +"<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' " diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differindex 9f2701fcd0..cd686aaf1e 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index 567b0f0d9e..0256fc7dd6 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -37,9 +37,9 @@ <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' @@ -786,7 +786,7 @@ </layout> </layout> </dialog> - <dialog name = 'KeyRemapper' overlays = 'screen_center' shading = 'dim'> + <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' diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx index 809ceccf9f..d4a92b831e 100644 --- a/gui/themes/scummclassic/classic_layout_lowres.stx +++ b/gui/themes/scummclassic/classic_layout_lowres.stx @@ -38,9 +38,9 @@ <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> - <def var = 'KeyRemapper.Spacing' value = '5'/> - <def var = 'KeyRemapper.LabelWidth' value = '80'/> - <def var = 'KeyRemapper.ButtonWidth' value = '60'/> + <def var = 'KeyMapper.Spacing' value = '5'/> + <def var = 'KeyMapper.LabelWidth' value = '80'/> + <def var = 'KeyMapper.ButtonWidth' value = '60'/> <widget name = 'Button' size = '72, 16' @@ -791,7 +791,7 @@ </layout> </layout> </dialog> - <dialog name = 'KeyRemapper' overlays = 'screen_center' shading = 'dim'> + <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' diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex 8a1739adb5..a133723d99 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index d3cd048f1d..8c13217c65 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -44,9 +44,9 @@ <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' @@ -801,7 +801,7 @@ </layout> </dialog> - <dialog name = 'KeyRemapper' overlays = 'screen_center' shading = 'dim'> + <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' diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx index 6f7f25db20..13346a1d6f 100644 --- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx +++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx @@ -44,9 +44,9 @@ size = '85, 12' /> - <def var = 'KeyRemapper.Spacing' value = '5'/> - <def var = 'KeyRemapper.LabelWidth' value = '80'/> - <def var = 'KeyRemapper.ButtonWidth' value = '60'/> + <def var = 'KeyMapper.Spacing' value = '5'/> + <def var = 'KeyMapper.LabelWidth' value = '80'/> + <def var = 'KeyMapper.ButtonWidth' value = '60'/> <widget name = 'OptionsLabel' size = '100, Globals.Line.Height' @@ -780,7 +780,7 @@ </layout> </layout> </dialog> - <dialog name = 'KeyRemapper' overlays = 'screen_center' shading = 'dim'> + <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' @@ -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/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/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 ); |